{"id":13479495,"url":"https://github.com/fregante/webext-options-sync","last_synced_at":"2025-05-16T04:06:44.946Z","repository":{"id":39648710,"uuid":"77394895","full_name":"fregante/webext-options-sync","owner":"fregante","description":"Helps you manage and autosave your extension's options.","archived":false,"fork":false,"pushed_at":"2024-11-17T11:05:17.000Z","size":234,"stargazers_count":155,"open_issues_count":1,"forks_count":12,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-08T15:04:39.194Z","etag":null,"topics":["webext","webextensions"],"latest_commit_sha":null,"homepage":"https://npm.im/webext-options-sync","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fregante.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-26T16:25:02.000Z","updated_at":"2025-01-28T07:53:18.000Z","dependencies_parsed_at":"2024-01-05T20:50:21.287Z","dependency_job_id":"f648b14b-7b24-404a-a7c6-d81591a108aa","html_url":"https://github.com/fregante/webext-options-sync","commit_stats":{"total_commits":192,"total_committers":12,"mean_commits":16.0,"dds":"0.40104166666666663","last_synced_commit":"cca7ea38211a3e3f3d42edff53afa9d30d0d8001"},"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fregante%2Fwebext-options-sync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fregante%2Fwebext-options-sync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fregante%2Fwebext-options-sync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fregante%2Fwebext-options-sync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fregante","download_url":"https://codeload.github.com/fregante/webext-options-sync/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464896,"owners_count":22075570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["webext","webextensions"],"created_at":"2024-07-31T16:02:17.573Z","updated_at":"2025-05-16T04:06:39.936Z","avatar_url":"https://github.com/fregante.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Libraries and Frameworks"],"sub_categories":[],"readme":"# webext-options-sync [![](https://img.shields.io/npm/v/webext-options-sync.svg)](https://www.npmjs.com/package/webext-options-sync)\n\n\u003e Helps you manage and autosave your extension's options.\n\nMain features:\n\n- Define your default options\n- Add autoload and autosave to your options `\u003cform\u003e`\n- Run migrations on update\n- Import/export helpers\n\nThis also lets you very easily have [separate options for each domain](https://github.com/fregante/webext-options-sync-per-domain) with the help of `webext-options-sync-per-domain`.\n\n## Install\n\nYou can download the [standalone bundle](https://bundle.fregante.com/?pkg=webext-options-sync\u0026global=OptionsSync) and include it in your `manifest.json`.\n\nOr use `npm`:\n\n```sh\nnpm install webext-options-sync\n```\n\n```js\nimport OptionsSync from 'webext-options-sync';\n```\n\nThe [browser-extension-template](https://github.com/notlmn/browser-extension-template) repo includes a complete setup with ES Modules, based on the advanced usage below.\n\n## Usage\n\nThis module requires the `storage` permission in `manifest.json`:\n\n```json\n{\n\t\"name\": \"My Cool Extension\",\n\t\"permissions\": [\n\t\t\"storage\"\n\t]\n}\n```\n\n### Simple usage\n\nYou can set and get your options from any context (background, content script, etc):\n\n```js\n/* global OptionsSync */\nconst optionsStorage = new OptionsSync();\n\nawait optionsStorage.set({showStars: 10});\n\nconst options = await optionsStorage.getAll();\n// {showStars: 10}\n```\n\n**Note:** `OptionsSync` relies on `chrome.storage.sync`, so its [limitations](https://developer.chrome.com/docs/extensions/reference/api/storage?hl=en#property-sync) apply, both the size limit and the type of data stored (which must be compatible with JSON).\n\n### Advanced usage\n\nIt's suggested to create an `options-storage.js` file with your defaults and possible migrations, and import it where needed:\n\n```js\n/* global OptionsSync */\nwindow.optionsStorage = new OptionsSync({\n\tdefaults: {\n\t\tcolorString: 'green',\n\t\tanyBooleans: true,\n\t\tnumbersAreFine: 9001\n\t},\n\n\t// List of functions that are called when the extension is updated\n\tmigrations: [\n\t\t(savedOptions, currentDefaults) =\u003e {\n\t\t\t// Perhaps it was renamed\n\t\t\tif (savedOptions.colour) {\n\t\t\t\tsavedOptions.color = savedOptions.colour;\n\t\t\t\tdelete savedOptions.colour;\n\t\t\t}\n\t\t},\n\n\t\t// Integrated utility that drops any properties that don't appear in the defaults\n\t\tOptionsSync.migrations.removeUnused\n\t]\n});\n```\n\nInclude this file as a background script: it's where the `defaults` are set for the first time and where the `migrations` are run. This example also includes it in the content script, if you need it there:\n\n```json\n{\n\t\"background\": {\n\t\t\"scripts\": [\n\t\t\t\"webext-options-sync.js\",\n\t\t\t\"options-storage.js\",\n\t\t\t\"background.js\"\n\t\t]\n\t},\n\t\"content_scripts\": [\n\t\t{\n\t\t\t\"matches\": [\n\t\t\t\t\"https://www.google.com/*\",\n\t\t\t],\n\t\t\t\"js\": [\n\t\t\t\t\"webext-options-sync.js\",\n\t\t\t\t\"options-storage.js\",\n\t\t\t\t\"content.js\"\n\t\t\t]\n\t\t}\n\t]\n}\n```\n\nThen you can use it this way from the `background` or `content.js`:\n\n```js\n/* global optionsStorage */\nasync function init () {\n\tconst {colorString} = await optionsStorage.getAll();\n\tdocument.body.style.background = colorString;\n}\n\ninit();\n```\n\nAnd also enable autosaving in your options page:\n\n```html\n\u003c!-- Your options.html --\u003e\n\u003cform\u003e\n\t\u003clabel\u003eColor: \u003cinput name=\"colorString\"/\u003e\u003c/label\u003e\u003cbr\u003e\n\t\u003clabel\u003eShow: \u003cinput type=\"checkbox\" name=\"anyBooleans\"/\u003e\u003c/label\u003e\u003cbr\u003e\n\t\u003clabel\u003eStars: \u003cinput name=\"numbersAreFine\"/\u003e\u003c/label\u003e\u003cbr\u003e\n\u003c/form\u003e\n\n\u003cscript src=\"webext-options-sync.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"options-storage.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"options.js\"\u003e\u003c/script\u003e\n```\n\n```js\n// Your options.js file\n/* global optionsStorage */\n\noptionsStorage.syncForm(document.querySelector('form'));\n```\n\n### Form autosave and autoload\n\nWhen using the `syncForm` method, `OptionsSync` will serialize the form using [dom-form-serializer](https://github.com/jefersondaniel/dom-form-serializer), which uses the `name` attribute as `key` for your options. Refer to its readme for more info on the structure of the data.\n\nAny user changes to the form are automatically saved into `chrome.storage.sync` after 300ms (debounced). It listens to `input` events.\n\n#### Input validation\n\nIf your form fields have any [validation attributes](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation#Validation-related_attributes) they will not be saved until they become valid.\n\n\u003cdetails\u003e\n\nSince autosave and validation is silent, you should inform the user of invalid fields, possibly via CSS by using the `:invalid` selector:\n\n```css\n/* Style the element */\ninput:invalid {\n\tcolor: red;\n\tborder: 1px solid red;\n}\n\n/* Or display a custom error message */\ninput:invalid ~ .error-message {\n\tdisplay: block;\n}\n```\n\n\u003c/details\u003e\n\n## API\n\n#### const optionsStorage = new OptionsSync(setup?)\n\nReturns an instance linked to the chosen storage. It will also run any migrations if it's called in the background.\n\n##### setup\n\nType: `object`\n\nOptional. It should follow this format:\n\n```js\n{\n\tdefaults: { // recommended\n\t\tcolor: 'blue'\n\t},\n\tmigrations: [ // optional\n\t\tsavedOptions =\u003e {\n\t\t\tif(savedOptions.oldStuff) {\n\t\t\t\tdelete savedOptions.oldStuff\n\t\t\t}\n\t\t}\n\t],\n}\n```\n\n###### defaults\n\nType: `object`\n\nA map of default options as strings or booleans. The keys will have to match the options form fields' `name` attributes.\n\n###### migrations\n\nType: `array`\n\nA list of functions to run in the `background` when the extension is updated. Example:\n\n```js\n{\n\tmigrations: [\n\t\t(options, defaults) =\u003e {\n\t\t\t// Change the `options`\n\t\t\tif(options.oldStuff) {\n\t\t\t\tdelete options.oldStuff\n\t\t\t}\n\n\t\t\t// No return needed\n\t\t},\n\n\t\t// Integrated utility that drops any properties that don't appear in the defaults\n\t\tOptionsSync.migrations.removeUnused\n\t],\n}\n```\n\n\u003e [!NOTE]\n\u003e The `options` argument will always include the `defaults` as well as any options that were saved before the update.\n\n###### storageName\n\nType: `string`\nDefault: `'options'`\n\nThe key used to store data in `chrome.storage.sync`\n\n###### logging\n\nType: `boolean`\nDefault: `true`\n\nWhether info and warnings (on sync, updating form, etc.) should be logged to the console or not.\n\n###### storageType\n\nType: `'local' | 'sync'`\nDefault: `sync`\n\nWhat storage area type to use (sync storage vs local storage). Sync storage is used by default.\n\n**Considerations for selecting which option to use:**\n\n- Sync is default as it's likely more convenient for users.\n- Firefox requires [`browser_specific_settings.gecko.id`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings) for the `sync` storage to work locally.\n- Sync storage is subject to much tighter [quota limitations](https://developer.chrome.com/docs/extensions/reference/storage/#property-sync), and may cause privacy concerns if the data being stored is confidential.\n\n#### optionsStorage.set(options)\n\nThis will merge the existing options with the object provided.\n\n**Note:** Any values specified in `default` are not saved into the storage, to save space, but they will still appear when using `getAll`. You just have to make sure to always specify the same `defaults` object in every context (this happens automatically in the [Advanced usage](#advanced-usage) above.)\n\n##### options\n\nType: `object`\nDefault: `{}`\nExample: `{color: red}`\n\nA map of default options as strings, booleans, numbers and anything accepted by [dom-form-serializer](https://github.com/jefersondaniel/dom-form-serializer)’s `deserialize` function.\n\n#### optionsStorage.setAll(options)\n\nThis will override **all** the options stored with your `options`.\n\n#### optionsStorage.getAll()\n\nThis returns a Promise that will resolve with all the options.\n\n#### optionsStorage.onChanged(callback, signal?)\n\nListens to changes in the storage and calls the callback when the options are changed. The callback is called with the new and old options.\n\n##### callback\n\nType: `(newOptions: object, oldOptions: object) =\u003e void`\n\n##### signal\n\nType: `AbortSignal`\n\nIf provided, the callback will be removed when the signal is aborted.\n\n#### optionsStorage.syncForm(form)\n\nAny defaults or saved options will be loaded into the `\u003cform\u003e` and any change will automatically be saved via `chrome.storage.sync`. It also looks for any buttons with `js-import` or `js-export` classes that when clicked will allow the user to export and import the options to a JSON file.\n\n- `options-sync:save-success`: Fired on the edited field when the form is saved.\n- `options-sync:save-error`: Fired on the edited field when the form is not saved due to an error. The error is passed as the `detail` property.\n\nSaving can fail when the storage quota is exceeded for example. You should handle this case and display a message to the user.\n\n##### form\n\nType: `HTMLFormElement`, `string`\n\nIt's the `\u003cform\u003e` that needs to be synchronized or a CSS selector (one element). The form fields' `name` attributes will have to match the option names.\n\n#### optionsStorage.stopSyncForm()\n\nRemoves any listeners added by `syncForm`.\n\n#### optionsStorage.exportToFile()\n\nOpens the browser’s \"save file\" dialog to export options to a JSON file. If your form has a `.js-export` element, this listener will be attached automatically.\n\n#### optionsStorage.importFromFile()\n\nOpens the browser’s file picker to import options from a previously-saved JSON file. If your form has a `.js-import` element, this listener will be attached automatically.\n\n## Related\n\n- [webext-options-sync-per-domain](https://github.com/fregante/webext-options-sync-per-domain) - Wrapper for `webext-options-sync` to have different options for each domain your extension supports.\n- [webext-storage-cache](https://github.com/fregante/webext-storage-cache) - Map-like promised cache storage with expiration.\n- [webext-dynamic-content-scripts](https://github.com/fregante/webext-dynamic-content-scripts) - Automatically registers your content_scripts on domains added via permission.request.\n- [Awesome-WebExtensions](https://github.com/fregante/Awesome-WebExtensions) - A curated list of awesome resources for WebExtensions development.\n- [More…](https://github.com/fregante/webext-fun)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffregante%2Fwebext-options-sync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffregante%2Fwebext-options-sync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffregante%2Fwebext-options-sync/lists"}