svelte-settings
Version:
> [!WARNING] > This project is a work in progress. Do not use it in any of your projects yet.
75 lines (74 loc) • 3.15 kB
JavaScript
import { extractDefaults } from './extractDefaults.js';
import { select } from './utils/stores.js';
import { getDeep, mergeDeep, setDeep } from './deep.js';
import { writable, get } from 'svelte/store';
import { persisted } from 'svelte-persisted-store';
import { mergeOptions } from './options.js';
export { default as SettingsView } from './components/SettingsView.svelte';
export * as migration from './utils/migration.js';
export { performMigrations } from './migrate.js';
/**
* Creates an instance of svelte-settings following the given blueprint.
* Should only be called once, as this initializes the settings and creates a store for it.
* Having multiple instances would break reactivity.
* You can re-export the initialized settings for use in your app.
*/
export function useSettings(blueprint, options) {
const settingsOverrides = persisted('settings', {});
const settingsDefaults = extractDefaults(blueprint);
const settingsStore = writable(mergeDeep(structuredClone(settingsDefaults), get(settingsOverrides)));
const settings = {
subscribe: settingsStore.subscribe,
// set: settingsWritable.set,
// update: settingsWritable.update,
select: (selector, isEqual) => select(settingsStore, selector, isEqual),
readSetting,
writeSetting,
resetSetting,
defaults: settingsDefaults,
blueprint,
options: mergeOptions(options),
};
return settings;
function writeSetting(path, value) {
console.info(`Writing setting: ${path} = ${JSON.stringify(value)}`);
settingsStore.update((s) => {
setDeep(s, path, value);
return s;
});
setDeep(settingsOverrides, path, value);
settingsOverrides.update((s) => {
setDeep(s, path, value);
return s;
});
}
function readSetting(path) {
console.debug(`Reading setting: ${path}`);
const valueOverride = getDeep(get(settingsOverrides), path);
if (valueOverride !== undefined) {
console.debug(`Read changed setting: ${path} = ${JSON.stringify(valueOverride)}`);
return { value: valueOverride, changed: true };
}
const value = getDeep(get(settingsStore), path);
console.debug(`Read default setting: ${path} = ${JSON.stringify(value)}`);
return { value: value, changed: false };
}
function resetSetting(path) {
console.debug(`Resetting setting: ${path}`);
const defaultValue = getDeep(settingsDefaults, path);
settingsStore.update((s) => {
setDeep(s, path, defaultValue);
return s;
});
settingsOverrides.update((s) => {
// deleteDeep(s, path)
setDeep(s, path, undefined);
return s;
});
console.info(`Reset setting: ${path} to ${JSON.stringify(defaultValue)}`);
return defaultValue;
}
// NOTE: building an object where every setting is a Writable would not help:
// it can neither be accessed as $settings.a nor as settings.$a,
// so creating a variable for it is necessary anyways
}