Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fregante/webext-options-sync
Helps you manage and autosave your extension's options.
https://github.com/fregante/webext-options-sync
webext webextensions
Last synced: 6 days ago
JSON representation
Helps you manage and autosave your extension's options.
- Host: GitHub
- URL: https://github.com/fregante/webext-options-sync
- Owner: fregante
- License: mit
- Created: 2016-12-26T16:25:02.000Z (almost 8 years ago)
- Default Branch: main
- Last Pushed: 2024-11-17T11:05:17.000Z (27 days ago)
- Last Synced: 2024-12-01T05:04:58.124Z (13 days ago)
- Topics: webext, webextensions
- Language: TypeScript
- Homepage: https://npm.im/webext-options-sync
- Size: 229 KB
- Stars: 153
- Watchers: 4
- Forks: 12
- Open Issues: 1
-
Metadata Files:
- Readme: readme.md
- License: license
Awesome Lists containing this project
- Awesome-WebExtensions - webext-options-sync - Helps you manage and autosave your extension's options. (Libraries and Frameworks)
README
# webext-options-sync [![](https://img.shields.io/npm/v/webext-options-sync.svg)](https://www.npmjs.com/package/webext-options-sync)
> Helps you manage and autosave your extension's options.
Main features:
- Define your default options
- Add autoload and autosave to your options ``
- Run migrations on update
- Import/export helpersThis 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`.
## Install
You can download the [standalone bundle](https://bundle.fregante.com/?pkg=webext-options-sync&global=OptionsSync) and include it in your `manifest.json`.
Or use `npm`:
```sh
npm install webext-options-sync
``````js
import OptionsSync from 'webext-options-sync';
```The [browser-extension-template](https://github.com/notlmn/browser-extension-template) repo includes a complete setup with ES Modules, based on the advanced usage below.
## Usage
This module requires the `storage` permission in `manifest.json`:
```json
{
"name": "My Cool Extension",
"permissions": [
"storage"
]
}
```### Simple usage
You can set and get your options from any context (background, content script, etc):
```js
/* global OptionsSync */
const optionsStorage = new OptionsSync();await optionsStorage.set({showStars: 10});
const options = await optionsStorage.getAll();
// {showStars: 10}
```**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).
### Advanced usage
It's suggested to create an `options-storage.js` file with your defaults and possible migrations, and import it where needed:
```js
/* global OptionsSync */
window.optionsStorage = new OptionsSync({
defaults: {
colorString: 'green',
anyBooleans: true,
numbersAreFine: 9001
},// List of functions that are called when the extension is updated
migrations: [
(savedOptions, currentDefaults) => {
// Perhaps it was renamed
if (savedOptions.colour) {
savedOptions.color = savedOptions.colour;
delete savedOptions.colour;
}
},// Integrated utility that drops any properties that don't appear in the defaults
OptionsSync.migrations.removeUnused
]
});
```Include 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:
```json
{
"background": {
"scripts": [
"webext-options-sync.js",
"options-storage.js",
"background.js"
]
},
"content_scripts": [
{
"matches": [
"https://www.google.com/*",
],
"js": [
"webext-options-sync.js",
"options-storage.js",
"content.js"
]
}
]
}
```Then you can use it this way from the `background` or `content.js`:
```js
/* global optionsStorage */
async function init () {
const {colorString} = await optionsStorage.getAll();
document.body.style.background = colorString;
}init();
```And also enable autosaving in your options page:
```html
Color:
Show:
Stars:```
```js
// Your options.js file
/* global optionsStorage */optionsStorage.syncForm(document.querySelector('form'));
```### Form autosave and autoload
When 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.
Any user changes to the form are automatically saved into `chrome.storage.sync` after 300ms (debounced). It listens to `input` events.
#### Input validation
If 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.
Since autosave and validation is silent, you should inform the user of invalid fields, possibly via CSS by using the `:invalid` selector:
```css
/* Style the element */
input:invalid {
color: red;
border: 1px solid red;
}/* Or display a custom error message */
input:invalid ~ .error-message {
display: block;
}
```## API
#### const optionsStorage = new OptionsSync(setup?)
Returns an instance linked to the chosen storage. It will also run any migrations if it's called in the background.
##### setup
Type: `object`
Optional. It should follow this format:
```js
{
defaults: { // recommended
color: 'blue'
},
migrations: [ // optional
savedOptions => {
if(savedOptions.oldStuff) {
delete savedOptions.oldStuff
}
}
],
}
```###### defaults
Type: `object`
A map of default options as strings or booleans. The keys will have to match the options form fields' `name` attributes.
###### migrations
Type: `array`
A list of functions to run in the `background` when the extension is updated. Example:
```js
{
migrations: [
(options, defaults) => {
// Change the `options`
if(options.oldStuff) {
delete options.oldStuff
}// No return needed
},// Integrated utility that drops any properties that don't appear in the defaults
OptionsSync.migrations.removeUnused
],
}
```> [!NOTE]
> The `options` argument will always include the `defaults` as well as any options that were saved before the update.###### storageName
Type: `string`
Default: `'options'`The key used to store data in `chrome.storage.sync`
###### logging
Type: `boolean`
Default: `true`Whether info and warnings (on sync, updating form, etc.) should be logged to the console or not.
###### storageType
Type: `'local' | 'sync'`
Default: `sync`What storage area type to use (sync storage vs local storage). Sync storage is used by default.
**Considerations for selecting which option to use:**
- Sync is default as it's likely more convenient for users.
- 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.
- 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.#### optionsStorage.set(options)
This will merge the existing options with the object provided.
**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.)
##### options
Type: `object`
Default: `{}`
Example: `{color: red}`A 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.
#### optionsStorage.setAll(options)
This will override **all** the options stored with your `options`.
#### optionsStorage.getAll()
This returns a Promise that will resolve with all the options.
#### optionsStorage.onChanged(callback, signal?)
Listens to changes in the storage and calls the callback when the options are changed. The callback is called with the new and old options.
##### callback
Type: `(newOptions: object, oldOptions: object) => void`
##### signal
Type: `AbortSignal`
If provided, the callback will be removed when the signal is aborted.
#### optionsStorage.syncForm(form)
Any defaults or saved options will be loaded into the `` 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.
- `options-sync:save-success`: Fired on the edited field when the form is saved.
- `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.Saving can fail when the storage quota is exceeded for example. You should handle this case and display a message to the user.
##### form
Type: `HTMLFormElement`, `string`
It's the `` that needs to be synchronized or a CSS selector (one element). The form fields' `name` attributes will have to match the option names.
#### optionsStorage.stopSyncForm()
Removes any listeners added by `syncForm`.
#### optionsStorage.exportToFile()
Opens 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.
#### optionsStorage.importFromFile()
Opens 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.
## Related
- [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.
- [webext-storage-cache](https://github.com/fregante/webext-storage-cache) - Map-like promised cache storage with expiration.
- [webext-dynamic-content-scripts](https://github.com/fregante/webext-dynamic-content-scripts) - Automatically registers your content_scripts on domains added via permission.request.
- [Awesome-WebExtensions](https://github.com/fregante/Awesome-WebExtensions) - A curated list of awesome resources for WebExtensions development.
- [More…](https://github.com/fregante/webext-fun)