From 05c26d789e581dd1200904cefe4502c05e3169d3 Mon Sep 17 00:00:00 2001 From: Sander Hahn Date: Fri, 10 May 2019 18:56:54 +0200 Subject: [PATCH] typescript version of store --- .gitignore | 2 +- package.json | 3 +- rollup.config.js | 31 ++++++++++- src/store.ts | 130 +++++++++++++++++++++++++++++++++++++++++++++++ store.mjs | 85 ------------------------------- tsconfig.json | 3 +- 6 files changed, 165 insertions(+), 89 deletions(-) create mode 100644 src/store.ts delete mode 100644 store.mjs diff --git a/.gitignore b/.gitignore index 06671edc2b..7aa75b29f4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ node_modules /compiler.js /index.js /internal.* -/store.js +/store.* /easing.js /motion.* /transition.js diff --git a/package.json b/package.json index ccbedde168..e0364bfa3a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "dev": "rollup -cw", "pretest": "npm run build", "posttest": "agadoo src/internal/index.js", - "prepublishOnly": "export PUBLISH=true && npm run lint && npm test" + "prepublishOnly": "export PUBLISH=true && npm run lint && npm test", + "tsd": "tsc -d src/store.ts --outDir ." }, "repository": { "type": "git", diff --git a/rollup.config.js b/rollup.config.js index f7b2d07d4b..0d19e59d4a 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -87,8 +87,37 @@ export default [ external: id => id.startsWith('svelte/') }, + /* store.mjs */ + { + input: `src/store.ts`, + output: [ + { + file: `store.mjs`, + format: 'esm', + paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') + }, + { + file: `store.js`, + format: 'cjs', + paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') + } + ], + plugins: [ + is_publish + ? typescript({ + include: 'src/**', + exclude: 'src/internal/**', + typescript: require('typescript') + }) + : sucrase({ + transforms: ['typescript'] + }) + ], + external: id => id.startsWith('svelte/') + }, + // everything else - ...['index', 'store', 'easing', 'transition', 'animate'].map(name => ({ + ...['index', 'easing', 'transition', 'animate'].map(name => ({ input: `${name}.mjs`, output: { file: `${name}.js`, diff --git a/src/store.ts b/src/store.ts new file mode 100644 index 0000000000..e27059a4d7 --- /dev/null +++ b/src/store.ts @@ -0,0 +1,130 @@ +import { run_all, noop, safe_not_equal } from './internal/utils'; + +type Subscriber = (value: T) => void; + +type Unsubscriber = () => void; + +type Updater = (value: T) => T; + +type Invalidater = (value?: T) => void; + +type StartStopNotifier = (set: Subscriber) => Unsubscriber | void; + +export interface ReadableStore { + subscribe(run: Subscriber, invalidate?: Invalidater): Unsubscriber; +} + +export interface WritableStore extends ReadableStore { + set(value: T): void; + update(updater: Updater): void; +} + +type SubscribeInvalidateTuple = [Subscriber, Invalidater]; + +export function readable(value: T, start: StartStopNotifier): ReadableStore { + return { + subscribe: writable(value, start).subscribe, + }; +} + +export function writable(value: T, start: StartStopNotifier = noop): WritableStore { + let stop: Unsubscriber; + const subscribers: Array> = []; + + function set(new_value: T): void { + if (safe_not_equal(value, new_value)) { + value = new_value; + if (!stop) { + return; // not ready + } + subscribers.forEach((s) => s[1]()); + subscribers.forEach((s) => s[0](value)); + } + } + + function update(fn: Updater): void { + set(fn(value)); + } + + function subscribe(run: Subscriber, invalidate: Invalidater = noop): Unsubscriber { + const subscriber: SubscribeInvalidateTuple = [run, invalidate]; + subscribers.push(subscriber); + if (subscribers.length === 1) { + stop = start(set) || noop; + } + run(value); + + return () => { + const index = subscribers.indexOf(subscriber); + if (index !== -1) { + subscribers.splice(index, 1); + } + if (subscribers.length === 0) { + stop(); + } + }; + } + + return { set, update, subscribe }; +} + +export function derived( + stores: ReadableStore | Array>, + fn: (values: T | T[], set?: Subscriber) => T | Unsubscriber | void, + initial_value: T): ReadableStore { + + const single = !Array.isArray(stores); + const stores_array: Array> = single + ? [stores as ReadableStore] + : stores as Array>; + + const auto = fn.length < 2; + + return readable(initial_value, (set) => { + let inited = false; + const values: T[] = []; + + let pending = 0; + let cleanup = noop; + + const sync = () => { + if (pending) { + return; + } + cleanup(); + const result = fn(single ? values[0] : values, set); + if (auto) { + set(result as T); + } else { + cleanup = result as Unsubscriber || noop; + } + }; + + const unsubscribers = stores_array.map((store, i) => store.subscribe( + (value) => { + values[i] = value; + pending &= ~(1 << i); + if (inited) { + sync(); + } + }, + () => { + pending |= (1 << i); + }), + ); + + inited = true; + sync(); + + return function stop() { + run_all(unsubscribers); + cleanup(); + }; + }); +} + +export function get(store: ReadableStore): T { + let value: T | undefined; + store.subscribe((_: T) => value = _)(); + return value as T; +} diff --git a/store.mjs b/store.mjs deleted file mode 100644 index 624ede3dde..0000000000 --- a/store.mjs +++ /dev/null @@ -1,85 +0,0 @@ -import { run_all, noop, get_store_value, safe_not_equal } from './internal'; - -export function readable(value, start) { - return { - subscribe: writable(value, start).subscribe - }; -} - -export function writable(value, start = noop) { - let stop; - const subscribers = []; - - function set(new_value) { - if (safe_not_equal(value, new_value)) { - value = new_value; - if (!stop) return; // not ready - subscribers.forEach(s => s[1]()); - subscribers.forEach(s => s[0](value)); - } - } - - function update(fn) { - set(fn(value)); - } - - function subscribe(run, invalidate = noop) { - const subscriber = [run, invalidate]; - subscribers.push(subscriber); - if (subscribers.length === 1) stop = start(set) || noop; - run(value); - - return () => { - const index = subscribers.indexOf(subscriber); - if (index !== -1) subscribers.splice(index, 1); - if (subscribers.length === 0) stop(); - }; - } - - return { set, update, subscribe }; -} - -export function derived(stores, fn, initial_value) { - const single = !Array.isArray(stores); - if (single) stores = [stores]; - - const auto = fn.length < 2; - let value = {}; - - return readable(initial_value, set => { - let inited = false; - const values = []; - - let pending = 0; - let cleanup = noop; - - const sync = () => { - if (pending) return; - cleanup(); - const result = fn(single ? values[0] : values, set); - if (auto) set(result); - else cleanup = result || noop; - }; - - const unsubscribers = stores.map((store, i) => store.subscribe( - value => { - values[i] = value; - pending &= ~(1 << i); - if (inited) sync(); - }, - () => { - pending |= (1 << i); - }) - ); - - inited = true; - sync(); - - return function stop() { - run_all(unsubscribers); - cleanup(); - }; - }); -} - -export { get_store_value as get }; diff --git a/tsconfig.json b/tsconfig.json index fdb7367e05..5da2d13a01 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,8 @@ "allowJs": true, "lib": ["es5", "es6", "dom"], "importHelpers": true, - "moduleResolution": "node" + "moduleResolution": "node", + "strict": true }, "include": [ "src"