Compare commits

..

11 Commits

Author SHA1 Message Date
GitHub Actions 5fa5fd01cb chore(release): v0.2.5 2023-07-20 16:19:32 +00:00
Aaron Klinker de16423e02 Add hanging-process reporter to CI to diagnose hung processes 2023-07-20 11:13:55 -05:00
Aaron Klinker aa4c0449e9 Fix failing tests 2023-07-20 11:13:55 -05:00
Aaron Klinker 9d00eb2466 chore: Update templates to wxt@0.2 2023-07-20 11:13:55 -05:00
Aaron Klinker 9ac756fb43 ci: Validate project templates 2023-07-20 11:13:55 -05:00
Aaron Klinker f195aa429c Fix type error 2023-07-20 10:40:03 -05:00
Aaron Klinker ca20a210ea feat: Include background script in dev mode if user doesn't define one 2023-07-20 10:38:53 -05:00
Aaron Klinker 547fee0e0e feat: Auto-import from subdirectories 2023-07-20 09:54:44 -05:00
Aaron Klinker 54b18cc66e fix: Properly load entrypoints that reference import.meta 2023-07-20 09:43:16 -05:00
Aaron Klinker d8c190365a fix: Don't crash when generating types in dev mode 2023-07-20 09:06:32 -05:00
Aaron Klinker b625f41919 Update changelog 2023-07-20 09:06:32 -05:00
18 changed files with 200 additions and 23 deletions
+49 -2
View File
@@ -7,7 +7,8 @@ on:
- main
jobs:
validate:
wxt:
name: WXT
runs-on: ubuntu-20.04
steps:
- name: Checkout
@@ -45,4 +46,50 @@ jobs:
working-directory: demo
- name: Tests
run: pnpm test:coverage
run: pnpm test:coverage --reporter=default --reporter=hanging-process
project-templates:
name: Project Templates
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup PNPM
uses: pnpm/action-setup@v2
with:
version: 8
- name: Setup NodeJS
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
- name: Validate Vanilla
working-directory: templates/vanilla
run: |
npm i
npm run build
npm run compile
- name: Validate Vue
working-directory: templates/vue
run: |
npm i
npm run build
npm run compile
- name: Validate React
working-directory: templates/react
run: |
npm i
npm run build
npm run compile
- name: Validate Svelte
working-directory: templates/svelte
run: |
npm i
npm run build
npm run check
+26 -2
View File
@@ -1,5 +1,31 @@
# Changelog
## v0.2.5
[compare changes](https://github.com/aklinker1/wxt/compare/v0.2.4...v0.2.5)
### 🚀 Enhancements
- Auto-import from subdirectories ([547fee0](https://github.com/aklinker1/wxt/commit/547fee0))
- Include background script in dev mode if user doesn't define one ([ca20a21](https://github.com/aklinker1/wxt/commit/ca20a21))
### 🩹 Fixes
- Don't crash when generating types in dev mode ([d8c1903](https://github.com/aklinker1/wxt/commit/d8c1903))
- Properly load entrypoints that reference `import.meta` ([54b18cc](https://github.com/aklinker1/wxt/commit/54b18cc))
### 🏡 Chore
- Update templates to wxt@0.2 ([9d00eb2](https://github.com/aklinker1/wxt/commit/9d00eb2))
### 🤖 CI
- Validate project templates ([9ac756f](https://github.com/aklinker1/wxt/commit/9ac756f))
### ❤️ Contributors
- Aaron Klinker
## v0.2.4
[compare changes](https://github.com/aklinker1/wxt/compare/v0.2.3...v0.2.4)
@@ -24,7 +50,6 @@
### ❤️ Contributors
- Aaron
- Aaron Klinker
## v0.2.2
@@ -158,7 +183,6 @@
### ❤️ Contributors
- Aaron
- Aaron Klinker
## v0.1.2
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "wxt",
"type": "module",
"version": "0.2.4",
"version": "0.2.5",
"description": "Next gen framework for developing web extensions",
"engines": {
"node": ">=18.16.0",
+6 -2
View File
@@ -39,7 +39,7 @@ export async function buildInternal(
const entrypoints = await findEntrypoints(config);
const groups = groupEntrypoints(entrypoints);
const { output } = await rebuild(config, groups);
const { output } = await rebuild(config, groups, undefined);
// Post-build
config.logger.success(
@@ -70,7 +70,11 @@ export async function rebuild(
): Promise<{ output: BuildOutput; manifest: Manifest.WebExtensionManifest }> {
// Update types directory with new files and types
const allEntrypoints = await findEntrypoints(config);
await generateTypesDir(allEntrypoints, config);
await generateTypesDir(allEntrypoints, config).catch((err) => {
config.logger.warn('Failed to update .wxt directory:', err);
// Throw the error if doing a regular build, don't for dev mode.
if (config.command === 'build') throw err;
});
// Build and merge the outputs
const newOutput = await buildEntrypoints(entrypointGroups, config);
@@ -29,6 +29,7 @@ describe('findEntrypoints', () => {
root: '/',
entrypointsDir: resolve('/src/entrypoints'),
outDir: resolve('.output'),
command: 'build',
});
it.each<[string, string, PopupEntrypoint]>([
@@ -210,10 +211,10 @@ describe('findEntrypoints', () => {
},
],
])(
'should find and load content script entrypoint config from %s',
'should find and load background entrypoint config from %s',
async (path, expected) => {
const options: ContentScriptEntrypoint['options'] = {
matches: ['<all_urls>'],
const options: BackgroundEntrypoint['options'] = {
type: 'module',
};
globMock.mockResolvedValueOnce([path]);
importTsFileMock.mockResolvedValue(options);
@@ -226,6 +227,24 @@ describe('findEntrypoints', () => {
},
);
it("should include a virtual background script so dev reloading works when there isn't a background entrypoint defined by the user", async () => {
globMock.mockResolvedValueOnce([]);
const entrypoints = await findEntrypoints({
...config,
command: 'serve',
});
expect(entrypoints).toHaveLength(1);
expect(entrypoints[0]).toEqual({
type: 'background',
inputPath: 'virtual:user-background',
name: 'background',
options: {},
outputDir: config.outDir,
});
});
it.each<[string, GenericEntrypoint]>([
// Sandbox
[
+21 -5
View File
@@ -16,9 +16,10 @@ import JSON5 from 'json5';
import { importTsFile } from '../utils/importTsFile';
import glob from 'fast-glob';
import { getEntrypointName } from '../utils/entrypoints';
import { VIRTUAL_NOOP_BACKGROUND_MODULE_ID } from '../vite-plugins/noopBackground';
/**
* Return entrypoints and their configuration by looking through the
* Return entrypoints and their configuration by looking through the project's files.
*/
export async function findEntrypoints(
config: InternalConfig,
@@ -33,6 +34,7 @@ export async function findEntrypoints(
const existingNames: Record<string, Entrypoint | undefined> = {};
const entrypoints: Entrypoint[] = [];
let hasBackground = false;
await Promise.all(
relativePaths.map(async (relativePath) => {
const path = resolve(config.entrypointsDir, relativePath);
@@ -63,6 +65,7 @@ export async function findEntrypoints(
break;
case 'background':
entrypoint = await getBackgroundEntrypoint(config, path);
hasBackground = true;
break;
case 'content-script':
entrypoint = await getContentScriptEntrypoint(
@@ -95,6 +98,11 @@ export async function findEntrypoints(
existingNames[entrypoint.name] = entrypoint;
}),
);
if (config.command === 'serve' && !hasBackground) {
entrypoints.push(
await getBackgroundEntrypoint(config, VIRTUAL_NOOP_BACKGROUND_MODULE_ID),
);
}
return entrypoints;
}
@@ -195,10 +203,17 @@ async function getBackgroundEntrypoint(
config: InternalConfig,
path: string,
): Promise<BackgroundEntrypoint> {
const { main: _, ...options } =
await importTsFile<BackgroundScriptDefintition>(path, config);
if (options == null) {
throw Error('Background script does not have a default export');
let options: Omit<BackgroundScriptDefintition, 'main'> = {};
if (path !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
const defaultExport = await importTsFile<BackgroundScriptDefintition>(
path,
config,
);
if (defaultExport == null) {
throw Error('Background script does not have a default export');
}
const { main: _, ...moduleOptions } = defaultExport;
options = moduleOptions;
}
return {
type: 'background',
@@ -257,6 +272,7 @@ const PATH_GLOB_TO_TYPE_MAP: Record<string, Entrypoint['type'] | 'ignored'> = {
'devtools/index.html': 'devtools',
'background.ts': 'background',
[VIRTUAL_NOOP_BACKGROUND_MODULE_ID]: 'background',
'content.ts?(x)': 'content-script',
'content/index.ts?(x)': 'content-script',
+29 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { kebabCaseAlphanumeric } from '../strings';
import { kebabCaseAlphanumeric, removeImportStatements } from '../strings';
describe('String utils', () => {
describe('kebabCaseAlphanumeric', () => {
@@ -14,4 +14,32 @@ describe('String utils', () => {
expect(kebabCaseAlphanumeric(input)).toBe(expected);
});
});
describe('removeImportStatements', () => {
it('should remove all import formats', () => {
const imports = `
import { registerGithubService, createGithubApi } from "@/utils/github";
import {
registerGithubService,
createGithubApi
} from "@/utils/github";
import{ registerGithubService, createGithubApi }from "@/utils/github";
import GitHub from "@/utils/github";
import "@/utils/github";
import '@/utils/github';
import"@/utils/github"
import'@/utils/github';
`;
expect(removeImportStatements(imports).trim()).toEqual('');
});
it('should not remove import.meta or inline import statements', () => {
const imports = `
import.meta.env.DEV
const a = await import("example");
import("example");
`;
expect(removeImportStatements(imports)).toEqual(imports);
});
});
});
+1 -1
View File
@@ -13,7 +13,7 @@ export function getUnimportOptions(
],
presets: [{ package: 'wxt/client' }],
warn: config.logger.warn,
dirs: ['components', 'composables', 'hooks', 'utils'],
dirs: ['./components/*', './composables/*', './hooks/*', './utils/*'],
};
return mergeConfig(
+1
View File
@@ -142,6 +142,7 @@ export async function getInternalConfig(
);
finalConfig.vite.plugins.push(plugins.devServerGlobals(finalConfig));
finalConfig.vite.plugins.push(plugins.tsconfigPaths(finalConfig));
finalConfig.vite.plugins.push(plugins.noopBackground());
finalConfig.vite.define ??= {};
getGlobals(finalConfig).forEach((global) => {
+2 -1
View File
@@ -5,6 +5,7 @@ import fs from 'fs-extra';
import { resolve } from 'path';
import transform from 'jiti/dist/babel';
import { getUnimportOptions } from './auto-imports';
import { removeImportStatements } from './strings';
/**
* Get the value from the default export of a `path`.
@@ -36,7 +37,7 @@ export async function importTsFile<T>(
await unimport.init();
const text = await fs.readFile(path, 'utf-8');
const textNoImports = text.replace(/import.*[\n;]/gm, '');
const textNoImports = removeImportStatements(text);
const { code } = await unimport.injectImports(textNoImports);
config.logger.debug(
['Text:', text, 'No imports:', textNoImports, 'Code:', code].join('\n'),
+11
View File
@@ -4,3 +4,14 @@ export function kebabCaseAlphanumeric(str: string): string {
.replace(/[^a-z0-9-\s]/g, '') // Remove all non-alphanumeric, non-hyphen characters
.replace(/\s+/g, '-'); // Replace spaces with hyphens
}
/**
* Removes import statements from the top of a file. Keeps import.meta and inline, async `import()`
* calls.
*/
export function removeImportStatements(text: string): string {
return text.replace(
/(import\s?[{\w][\s\S]*?from\s?["'][\s\S]*?["'];?|import\s?["'][\s\S]*?["'];?)/gm,
'',
);
}
+1
View File
@@ -5,3 +5,4 @@ export * from './multipageMove';
export * from './unimport';
export * from './virtualEntrypoint';
export * from './tsconfigPaths';
export * from './noopBackground';
+24
View File
@@ -0,0 +1,24 @@
import { Plugin } from 'vite';
/**
* In dev mode, if there's not a background script listed, we need to add one.
*
* This define's a virtual module that is basically just a noop.
*/
export function noopBackground(): Plugin {
const virtualModuleId = VIRTUAL_NOOP_BACKGROUND_MODULE_ID;
const resolvedVirtualModuleId = '\0' + virtualModuleId;
return {
name: 'wxt:noop-background',
resolveId(id) {
if (id === virtualModuleId) return resolvedVirtualModuleId;
},
load(id) {
if (id === resolvedVirtualModuleId) {
return `import { defineBackground } from 'wxt/client';\nexport default defineBackground(() => void 0)`;
}
},
};
}
export const VIRTUAL_NOOP_BACKGROUND_MODULE_ID = 'virtual:user-background';
+2 -1
View File
@@ -59,8 +59,9 @@ export async function createServer(
await fileChangedMutex.runExclusive(async () => {
const fileChanges = changeQueue.splice(0, changeQueue.length);
const changes = detectDevChanges(fileChanges, server.currentOutput);
if (fileChanges.length === 0) return;
const changes = detectDevChanges(fileChanges, server.currentOutput);
if (changes.type === 'no-change') return;
// Log the entrypoints that were effected
+1 -1
View File
@@ -21,6 +21,6 @@
"@types/react-dom": "^18.2.6",
"@vitejs/plugin-react": "^4.0.3",
"typescript": "^5.1.6",
"wxt": "^0.1.3"
"wxt": "^0.2.0"
}
}
+1 -1
View File
@@ -18,6 +18,6 @@
"svelte-check": "^3.4.6",
"tslib": "^2.6.0",
"typescript": "^5.1.6",
"wxt": "^0.1.5"
"wxt": "^0.2.0"
}
}
+1 -1
View File
@@ -14,6 +14,6 @@
},
"devDependencies": {
"typescript": "^5.1.6",
"wxt": "^0.1.3"
"wxt": "^0.2.0"
}
}
+1 -1
View File
@@ -19,6 +19,6 @@
"@vitejs/plugin-vue": "^4.2.3",
"typescript": "^5.1.6",
"vue-tsc": "^1.8.4",
"wxt": "^0.1.3"
"wxt": "^0.2.0"
}
}