From c77773eb2081231b350e1f8e0702d383fa400d44 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 13 Jun 2024 12:20:09 -0500 Subject: [PATCH] feat(modules): Add new `addImportPreset` helper function (#720) --- packages/wxt/src/__tests__/modules.test.ts | 48 +++++++++++++++++++++- packages/wxt/src/modules.ts | 45 +++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/packages/wxt/src/__tests__/modules.test.ts b/packages/wxt/src/__tests__/modules.test.ts index 7e527728..d1e2e522 100644 --- a/packages/wxt/src/__tests__/modules.test.ts +++ b/packages/wxt/src/__tests__/modules.test.ts @@ -1,5 +1,5 @@ import { fakeWxt } from '~/core/utils/testing/fake-objects'; -import { addViteConfig } from '../modules'; +import { addImportPreset, addViteConfig } from '../modules'; import { describe, it, expect } from 'vitest'; import { createHooks } from 'hookable'; @@ -37,4 +37,50 @@ describe('Module Utilities', () => { expect(actual).toEqual(expected); }); }); + + describe('addImportPreset', () => { + it('should add the import to the config', async () => { + const preset = 'vue'; + const wxt = fakeWxt({ hooks: createHooks() }); + + addImportPreset(wxt, preset); + await wxt.hooks.callHook('ready', wxt); + + expect(wxt.config.imports && wxt.config.imports.presets).toContain( + preset, + ); + }); + + it('should not add duplicate presets', async () => { + const preset = 'vue'; + const wxt = fakeWxt({ + hooks: createHooks(), + config: { + imports: { + presets: ['vue', 'react'], + }, + }, + }); + + addImportPreset(wxt, preset); + await wxt.hooks.callHook('ready', wxt); + + expect(wxt.config.imports && wxt.config.imports.presets).toHaveLength(2); + }); + + it("should not enable imports if they've been disabled", async () => { + const preset = 'vue'; + const wxt = fakeWxt({ + hooks: createHooks(), + config: { + imports: false, + }, + }); + + addImportPreset(wxt, preset); + await wxt.hooks.callHook('ready', wxt); + + expect(wxt.config.imports).toBe(false); + }); + }); }); diff --git a/packages/wxt/src/modules.ts b/packages/wxt/src/modules.ts index e18c996e..3f70ba02 100644 --- a/packages/wxt/src/modules.ts +++ b/packages/wxt/src/modules.ts @@ -13,6 +13,7 @@ import type { import * as vite from 'vite'; import glob from 'fast-glob'; import { resolve } from 'node:path'; +import type { UnimportOptions } from 'unimport'; // Re-export to prevent TS2742 type errors export { WxtModule }; @@ -126,8 +127,50 @@ export function addViteConfig( * addWxtPlugin(wxt, "wxt-module-analytics/client-plugin"); * }); */ -export function addWxtPlugin(wxt: Wxt, plugin: string) { +export function addWxtPlugin(wxt: Wxt, plugin: string): void { wxt.hooks.hook('ready', (wxt) => { wxt.config.plugins.push(plugin); }); } + +/** + * Add an Unimport preset ([built-in](https://github.com/unjs/unimport?tab=readme-ov-file#built-in-presets), + * [custom](https://github.com/unjs/unimport?tab=readme-ov-file#custom-presets), + * or [auto-scanned](https://github.com/unjs/unimport?tab=readme-ov-file#exports-auto-scan)), + * to the project's list of auto-imported utilities. + * + * Some things to note: + * - This function will only de-duplicate built-in preset names. It will not + * stop you adding duplicate custom or auto-scanned presets. + * - If the project has disabled imports, this function has no effect. + * + * @param wxt The wxt instance provided by the module's setup function. + * @param preset The preset to add to the project. + * + * @example + * export default defineWxtModule((wxt) => { + * // Built-in preset: + * addImportPreset(wxt, "vue"); + * // Custom preset: + * addImportPreset(wxt, { + * from: "vue", + * imports: ["ref", "reactive", ...], + * }); + * // Auto-scanned preset: + * addImportPreset(wxt, { package: "vue" }); + * }); + */ +export function addImportPreset( + wxt: Wxt, + preset: UnimportOptions['presets'][0], +): void { + wxt.hooks.hook('ready', (wxt) => { + if (!wxt.config.imports) return; + + wxt.config.imports.presets ??= []; + // De-dupelicate built-in named presets + if (wxt.config.imports.presets.includes(preset)) return; + + wxt.config.imports.presets.push(preset); + }); +}