diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5d181bb..2132400 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,8 +13,8 @@ jobs:
Lint:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
node-version: 16
- name: install
@@ -25,7 +25,7 @@ jobs:
Test:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: install
run: npm ci || npm install
- name: build
@@ -36,7 +36,7 @@ jobs:
Build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: install
run: npm ci || npm install
- name: build
diff --git a/.github/workflows/esm-lint.yml b/.github/workflows/esm-lint.yml
index 0205cd9..f5802fd 100644
--- a/.github/workflows/esm-lint.yml
+++ b/.github/workflows/esm-lint.yml
@@ -4,6 +4,7 @@ env:
# FILE GENERATED WITH: npx ghat fregante/ghatemplates/esm-lint
# SOURCE: https://github.com/fregante/ghatemplates
+# OPTIONS: {"exclude":["jobs.Rollup"]}
name: ESM
on:
@@ -18,19 +19,19 @@ jobs:
Pack:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- run: npm install
- run: npm run build --if-present
- run: npm pack --dry-run
- run: npm pack | tail -1 | xargs -n1 tar -xzf
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
path: package
Webpack:
runs-on: ubuntu-latest
needs: Pack
steps:
- - uses: actions/download-artifact@v2
+ - uses: actions/download-artifact@v3
- run: npm install ./artifact
- run: echo "${{ env.IMPORT_TEXT }} '${{ env.NPM_MODULE_NAME }}'" > index.js
- run: webpack --entry ./index.js
@@ -39,35 +40,37 @@ jobs:
runs-on: ubuntu-latest
needs: Pack
steps:
- - uses: actions/download-artifact@v2
+ - uses: actions/download-artifact@v3
- run: npm install ./artifact
- run: echo "${{ env.IMPORT_TEXT }} '${{ env.NPM_MODULE_NAME }}'" > index.js
- - run: npx parcel build index.js
+ - run: npx parcel@2 build index.js
- run: cat dist/index.js
- Rollup:
+ Vite:
runs-on: ubuntu-latest
needs: Pack
steps:
- - uses: actions/download-artifact@v2
- - run: npm install ./artifact rollup@2 @rollup/plugin-node-resolve
- - run: echo "${{ env.IMPORT_TEXT }} '${{ env.NPM_MODULE_NAME }}'" > index.js
- - run: npx rollup -p node-resolve index.js
- Snowpack:
+ - uses: actions/download-artifact@v3
+ - run: npm install ./artifact
+ - run: >-
+ echo '' > index.html
+ - run: npx vite build
+ - run: cat dist/assets/*
+ esbuild:
runs-on: ubuntu-latest
needs: Pack
steps:
- - uses: actions/download-artifact@v2
+ - uses: actions/download-artifact@v3
- run: echo '{}' > package.json
- run: echo "${{ env.IMPORT_TEXT }} '${{ env.NPM_MODULE_NAME }}'" > index.js
- run: npm install ./artifact
- - run: npx snowpack@2 build
- - run: cat build/web_modules/$NPM_MODULE_NAME.js
+ - run: npx esbuild --bundle index.js
TypeScript:
runs-on: ubuntu-latest
needs: Pack
steps:
- - uses: actions/download-artifact@v2
- - run: npm install ./artifact
+ - uses: actions/download-artifact@v3
+ - run: npm install ./artifact && npm install @types/estree
- run: echo "${{ env.IMPORT_TEXT }} '${{ env.NPM_MODULE_NAME }}'" > index.ts
- run: tsc index.ts
- run: cat index.js
@@ -75,8 +78,8 @@ jobs:
runs-on: ubuntu-latest
needs: Pack
steps:
- - uses: actions/download-artifact@v2
- - uses: actions/setup-node@v1
+ - uses: actions/download-artifact@v3
+ - uses: actions/setup-node@v3
with:
node-version: 14.x
- run: echo "${{ env.IMPORT_TEXT }} '${{ env.NPM_MODULE_NAME }}'" > index.mjs
diff --git a/globals.d.ts b/globals.d.ts
index 5db4dca..6b388a1 100644
--- a/globals.d.ts
+++ b/globals.d.ts
@@ -1,18 +1,14 @@
-declare module 'dom-form-serializer/lib/serialize' {
+declare module 'dom-form-serializer/dist/dom-form-serializer.mjs' {
import {JsonObject} from 'type-fest';
- export default function serialize(
+ export function serialize(
element: HTMLFormElement,
options: {
include?: string[];
}
): JSONValue;
-}
-
-declare module 'dom-form-serializer/lib/deserialize' {
- import {JsonObject} from 'type-fest';
- export default function deserialize(
+ export function deserialize(
element: HTMLFormElement,
serializedData: JsonObject,
options?: {
diff --git a/index.ts b/index.ts
index 3d1d18d..3ae4dcf 100644
--- a/index.ts
+++ b/index.ts
@@ -1,34 +1,28 @@
import {debounce} from 'throttle-debounce';
-import serialize from 'dom-form-serializer/lib/serialize';
-import deserialize from 'dom-form-serializer/lib/deserialize';
+import chromeP from 'webext-polyfill-kinda';
import {isBackground} from 'webext-detect-page';
-import {compressToEncodedURIComponent, decompressFromEncodedURIComponent} from 'lz-string';
+import {serialize, deserialize} from 'dom-form-serializer/dist/dom-form-serializer.mjs';
+import LZString from 'lz-string';
+
+// eslint-disable-next-line @typescript-eslint/naming-convention -- CJS in ESM imports
+const {compressToEncodedURIComponent, decompressFromEncodedURIComponent} = LZString;
async function shouldRunMigrations(): Promise {
+ const self = await chromeP.management?.getSelf();
+
+ // Always run migrations during development #25
+ if (self?.installType === 'development') {
+ return true;
+ }
+
return new Promise(resolve => {
- const callback = (installType: string): void => {
- // Always run migrations during development #25
- if (installType === 'development') {
- resolve(true);
- return;
- }
+ // Run migrations when the extension is installed or updated
+ chrome.runtime.onInstalled.addListener(() => {
+ resolve(true);
+ });
- // Run migrations when the extension is installed or updated
- chrome.runtime.onInstalled.addListener(() => {
- resolve(true);
- });
-
- // If `onInstalled` isn't fired, then migrations should not be run
- setTimeout(resolve, 500, false);
- };
-
- if (chrome.management?.getSelf) {
- chrome.management.getSelf(({installType}) => {
- callback(installType);
- });
- } else {
- callback('unknown');
- }
+ // If `onInstalled` isn't fired, then migrations should not be run
+ setTimeout(resolve, 500, false);
});
}
@@ -113,8 +107,6 @@ class OptionsSync {
this.storageName = storageName;
this.defaults = defaults;
this.storageType = storageType;
- this._handleFormInput = debounce(300, this._handleFormInput.bind(this));
- this._handleStorageChangeOnForm = this._handleStorageChangeOnForm.bind(this);
if (!logging) {
this._log = () => {};
@@ -123,8 +115,8 @@ class OptionsSync {
this._migrations = this._runMigrations(migrations);
}
- get storage(): chrome.storage.StorageArea {
- return chrome.storage[this.storageType];
+ get storage(): chromeP.storage.StorageArea {
+ return chromeP.storage[this.storageType];
}
/**
@@ -198,29 +190,14 @@ class OptionsSync {
}
private async _getAll(): Promise {
- return new Promise((resolve, reject) => {
- this.storage.get(this.storageName, result => {
- if (chrome.runtime.lastError) {
- reject(chrome.runtime.lastError);
- } else {
- resolve(this._decode(result[this.storageName]));
- }
- });
- });
+ const result = await this.storage.get(this.storageName);
+ return this._decode(result[this.storageName]);
}
private async _setAll(newOptions: UserOptions): Promise {
this._log('log', 'Saving options', newOptions);
- return new Promise((resolve, reject) => {
- this.storage.set({
- [this.storageName]: this._encode(newOptions),
- }, () => {
- if (chrome.runtime.lastError) {
- reject(chrome.runtime.lastError);
- } else {
- resolve();
- }
- });
+ await this.storage.set({
+ [this.storageName]: this._encode(newOptions),
});
}
@@ -266,7 +243,8 @@ class OptionsSync {
}
}
- private async _handleFormInput({target}: Event): Promise {
+ // eslint-disable-next-line @typescript-eslint/member-ordering -- Needs to be near _handleFormSubmit
+ private readonly _handleFormInput = debounce(300, async ({target}: Event): Promise => {
const field = target as HTMLInputElement;
if (!field.name) {
return;
@@ -276,7 +254,7 @@ class OptionsSync {
field.form!.dispatchEvent(new CustomEvent('options-sync:form-synced', {
bubbles: true,
}));
- }
+ });
private _handleFormSubmit(event: Event): void {
event.preventDefault();
@@ -312,7 +290,7 @@ class OptionsSync {
return serialize(form, {include});
}
- private _handleStorageChangeOnForm(changes: Record, areaName: string): void {
+ private readonly _handleStorageChangeOnForm = (changes: Record, areaName: string): void => {
if (
areaName === this.storageType
&& changes[this.storageName]
@@ -320,7 +298,7 @@ class OptionsSync {
) {
this._updateForm(this._form!, this._decode(changes[this.storageName].newValue));
}
- }
+ };
}
export default OptionsSync;
diff --git a/package.json b/package.json
index 0bd4910..308d324 100644
--- a/package.json
+++ b/package.json
@@ -16,16 +16,15 @@
"author": "Federico Brigante (https://fregante.com)",
"type": "module",
"main": "index.js",
- "module": "index.js",
"files": [
"index.js",
"index.d.ts"
],
"scripts": {
- "build": "rollup -c",
- "prepack": "rollup -c",
+ "build": "tsc",
+ "prepack": "tsc",
"test": "run-p build ava xo",
- "watch": "rollup -c --watch",
+ "watch": "tsc --watch",
"ava": "ava",
"xo": "xo"
},
@@ -35,39 +34,35 @@
"webextensions"
],
"rules": {
- "@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-return": "off",
- "@typescript-eslint/no-unsafe-member-access": "off",
- "@typescript-eslint/no-duplicate-imports": "off",
"@typescript-eslint/no-dynamic-delete": "off",
- "@typescript-eslint/no-empty-function": "off",
- "import/no-duplicates": "off",
- "import/no-unassigned-import": "off"
+ "@typescript-eslint/no-empty-function": "off"
}
},
+ "ava": {
+ "require": [
+ "./test/_env.js"
+ ]
+ },
"dependencies": {
- "webext-detect-page": "^4.0.0"
+ "dom-form-serializer": "^2.0.0",
+ "lz-string": "^1.4.4",
+ "throttle-debounce": "^5.0.0",
+ "webext-detect-page": "^4.0.1",
+ "webext-polyfill-kinda": "^0.10.0"
},
"devDependencies": {
- "@rollup/plugin-commonjs": "^21.0.1",
- "@rollup/plugin-node-resolve": "^13.1.3",
- "@rollup/plugin-typescript": "^8.3.0",
- "@sindresorhus/tsconfig": "^2.0.0",
- "@types/chrome": "0.0.176",
- "@types/estree": "^0.0.50",
+ "@sindresorhus/tsconfig": "^3.0.1",
+ "@types/chrome": "0.0.193",
+ "@types/firefox-webext-browser": "^94.0.1",
"@types/lz-string": "^1.3.34",
- "@types/throttle-debounce": "^2.1.0",
- "ava": "^4.0.1",
- "dom-form-serializer": "^2.0.0",
- "lz-string": "^1.4.4",
+ "@types/throttle-debounce": "^5.0.0",
+ "ava": "^4.3.1",
"npm-run-all": "^4.1.5",
- "rollup": "^2.63.0",
- "rollup-plugin-terser": "^7.0.2",
- "sinon": "^12.0.1",
+ "sinon": "^14.0.0",
"sinon-chrome": "^3.0.1",
- "throttle-debounce": "^3.0.1",
- "type-fest": "^2.9.0",
- "typescript": "^4.5.4",
- "xo": "^0.47.0"
+ "type-fest": "^2.17.0",
+ "typescript": "^4.7.4",
+ "xo": "^0.51.0"
}
}
diff --git a/rollup.config.js b/rollup.config.js
deleted file mode 100644
index e1238a2..0000000
--- a/rollup.config.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import typescript from '@rollup/plugin-typescript';
-import {terser} from 'rollup-plugin-terser';
-import commonjs from '@rollup/plugin-commonjs';
-import resolve from '@rollup/plugin-node-resolve';
-
-const config = {
- input: 'index.ts',
- output: {
- format: 'esm',
- dir: '.',
- },
- external: [
- // These are `type: module` packages so they don't need to be bundled
- 'webext-detect-page',
- ],
- plugins: [
- resolve(),
- commonjs(),
- typescript({
- outDir: '.',
- }),
- terser({
- toplevel: true,
- output: {
- comments: false,
- beautify: true,
- },
- mangle: false,
- compress: {
- join_vars: false, // eslint-disable-line camelcase
- booleans: false,
- expression: false,
- sequences: false,
- },
- }),
- ],
-};
-
-export default config;
diff --git a/test/_fixtures.js b/test/_env.js
similarity index 100%
rename from test/_fixtures.js
rename to test/_env.js
diff --git a/test/index.js b/test/index.js
index 50d5750..c8315e8 100644
--- a/test/index.js
+++ b/test/index.js
@@ -1,4 +1,3 @@
-import './_fixtures.js';
import test from 'ava';
import lzString from 'lz-string';
import OptionsSync from '../index.js';
diff --git a/tsconfig.json b/tsconfig.json
index 47a7f4d..6680c65 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,8 @@
{
"extends": "@sindresorhus/tsconfig/tsconfig.json",
"compilerOptions": {
- "target": "es2020"
+ "target": "es2020",
+ "outDir": "."
},
"files": [
"globals.d.ts",