sigmx 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +173 -0
- package/dist/auto.d.ts +1 -0
- package/dist/auto.js +7 -0
- package/dist/auto.js.map +7 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +26 -0
- package/dist/cli.js.map +7 -0
- package/dist/core/csp.d.ts +7 -0
- package/dist/core/csp.js +20 -0
- package/dist/core/csp.js.map +7 -0
- package/dist/core/engine.d.ts +10 -0
- package/dist/core/engine.js +200 -0
- package/dist/core/engine.js.map +7 -0
- package/dist/core/expr.d.ts +12 -0
- package/dist/core/expr.js +94 -0
- package/dist/core/expr.js.map +7 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.js +46 -0
- package/dist/core/index.js.map +7 -0
- package/dist/core/signals.d.ts +42 -0
- package/dist/core/signals.js +195 -0
- package/dist/core/signals.js.map +7 -0
- package/dist/core/store.d.ts +32 -0
- package/dist/core/store.js +185 -0
- package/dist/core/store.js.map +7 -0
- package/dist/core/types.d.ts +101 -0
- package/dist/core/types.js +1 -0
- package/dist/core/types.js.map +7 -0
- package/dist/kernel/compile.d.ts +16 -0
- package/dist/kernel/compile.js +96 -0
- package/dist/kernel/compile.js.map +7 -0
- package/dist/kernel/contracts.d.ts +121 -0
- package/dist/kernel/contracts.js +1 -0
- package/dist/kernel/contracts.js.map +7 -0
- package/dist/kernel/index.d.ts +20 -0
- package/dist/kernel/index.js +54 -0
- package/dist/kernel/index.js.map +7 -0
- package/dist/kernel/precompile.d.ts +25 -0
- package/dist/kernel/precompile.js +111 -0
- package/dist/kernel/precompile.js.map +7 -0
- package/dist/kernel/precompiled.d.ts +11 -0
- package/dist/kernel/precompiled.js +13 -0
- package/dist/kernel/precompiled.js.map +7 -0
- package/dist/kernel/reactive.d.ts +42 -0
- package/dist/kernel/reactive.js +201 -0
- package/dist/kernel/reactive.js.map +7 -0
- package/dist/kernel/runtime.d.ts +11 -0
- package/dist/kernel/runtime.js +210 -0
- package/dist/kernel/runtime.js.map +7 -0
- package/dist/kernel/scan.d.ts +42 -0
- package/dist/kernel/scan.js +68 -0
- package/dist/kernel/scan.js.map +7 -0
- package/dist/kernel/state.d.ts +32 -0
- package/dist/kernel/state.js +186 -0
- package/dist/kernel/state.js.map +7 -0
- package/dist/kernel/strict-csp.d.ts +7 -0
- package/dist/kernel/strict-csp.js +20 -0
- package/dist/kernel/strict-csp.js.map +7 -0
- package/dist/lib/casing.d.ts +7 -0
- package/dist/lib/casing.js +16 -0
- package/dist/lib/casing.js.map +7 -0
- package/dist/lib/objects.d.ts +9 -0
- package/dist/lib/objects.js +26 -0
- package/dist/lib/objects.js.map +7 -0
- package/dist/lib/schedule.d.ts +14 -0
- package/dist/lib/schedule.js +51 -0
- package/dist/lib/schedule.js.map +7 -0
- package/dist/lib/sse.d.ts +10 -0
- package/dist/lib/sse.js +55 -0
- package/dist/lib/sse.js.map +7 -0
- package/dist/plugins/actions/clipboard.d.ts +2 -0
- package/dist/plugins/actions/clipboard.js +11 -0
- package/dist/plugins/actions/clipboard.js.map +7 -0
- package/dist/plugins/actions/fit.d.ts +2 -0
- package/dist/plugins/actions/fit.js +14 -0
- package/dist/plugins/actions/fit.js.map +7 -0
- package/dist/plugins/actions/intl.d.ts +2 -0
- package/dist/plugins/actions/intl.js +21 -0
- package/dist/plugins/actions/intl.js.map +7 -0
- package/dist/plugins/actions/peek.d.ts +2 -0
- package/dist/plugins/actions/peek.js +6 -0
- package/dist/plugins/actions/peek.js.map +7 -0
- package/dist/plugins/actions/setAll.d.ts +2 -0
- package/dist/plugins/actions/setAll.js +11 -0
- package/dist/plugins/actions/setAll.js.map +7 -0
- package/dist/plugins/actions/toggleAll.d.ts +2 -0
- package/dist/plugins/actions/toggleAll.js +11 -0
- package/dist/plugins/actions/toggleAll.js.map +7 -0
- package/dist/plugins/attributes/attr.d.ts +2 -0
- package/dist/plugins/attributes/attr.js +20 -0
- package/dist/plugins/attributes/attr.js.map +7 -0
- package/dist/plugins/attributes/bind.d.ts +6 -0
- package/dist/plugins/attributes/bind.js +81 -0
- package/dist/plugins/attributes/bind.js.map +7 -0
- package/dist/plugins/attributes/class.d.ts +2 -0
- package/dist/plugins/attributes/class.js +22 -0
- package/dist/plugins/attributes/class.js.map +7 -0
- package/dist/plugins/attributes/computed.d.ts +2 -0
- package/dist/plugins/attributes/computed.js +20 -0
- package/dist/plugins/attributes/computed.js.map +7 -0
- package/dist/plugins/attributes/customValidity.d.ts +2 -0
- package/dist/plugins/attributes/customValidity.js +14 -0
- package/dist/plugins/attributes/customValidity.js.map +7 -0
- package/dist/plugins/attributes/effect.d.ts +2 -0
- package/dist/plugins/attributes/effect.js +12 -0
- package/dist/plugins/attributes/effect.js.map +7 -0
- package/dist/plugins/attributes/indicator.d.ts +2 -0
- package/dist/plugins/attributes/indicator.js +20 -0
- package/dist/plugins/attributes/indicator.js.map +7 -0
- package/dist/plugins/attributes/init.d.ts +2 -0
- package/dist/plugins/attributes/init.js +14 -0
- package/dist/plugins/attributes/init.js.map +7 -0
- package/dist/plugins/attributes/jsonSignals.d.ts +2 -0
- package/dist/plugins/attributes/jsonSignals.js +15 -0
- package/dist/plugins/attributes/jsonSignals.js.map +7 -0
- package/dist/plugins/attributes/matchMedia.d.ts +2 -0
- package/dist/plugins/attributes/matchMedia.js +19 -0
- package/dist/plugins/attributes/matchMedia.js.map +7 -0
- package/dist/plugins/attributes/on.d.ts +5 -0
- package/dist/plugins/attributes/on.js +28 -0
- package/dist/plugins/attributes/on.js.map +7 -0
- package/dist/plugins/attributes/onIntersect.d.ts +2 -0
- package/dist/plugins/attributes/onIntersect.js +28 -0
- package/dist/plugins/attributes/onIntersect.js.map +7 -0
- package/dist/plugins/attributes/onInterval.d.ts +2 -0
- package/dist/plugins/attributes/onInterval.js +18 -0
- package/dist/plugins/attributes/onInterval.js.map +7 -0
- package/dist/plugins/attributes/onRaf.d.ts +1 -0
- package/dist/plugins/attributes/onRaf.js +19 -0
- package/dist/plugins/attributes/onRaf.js.map +7 -0
- package/dist/plugins/attributes/onResize.d.ts +1 -0
- package/dist/plugins/attributes/onResize.js +17 -0
- package/dist/plugins/attributes/onResize.js.map +7 -0
- package/dist/plugins/attributes/onSignalPatch.d.ts +5 -0
- package/dist/plugins/attributes/onSignalPatch.js +35 -0
- package/dist/plugins/attributes/onSignalPatch.js.map +7 -0
- package/dist/plugins/attributes/persist.d.ts +6 -0
- package/dist/plugins/attributes/persist.js +16 -0
- package/dist/plugins/attributes/persist.js.map +7 -0
- package/dist/plugins/attributes/queryString.d.ts +5 -0
- package/dist/plugins/attributes/queryString.js +54 -0
- package/dist/plugins/attributes/queryString.js.map +7 -0
- package/dist/plugins/attributes/ref.d.ts +2 -0
- package/dist/plugins/attributes/ref.js +13 -0
- package/dist/plugins/attributes/ref.js.map +7 -0
- package/dist/plugins/attributes/replaceUrl.d.ts +1 -0
- package/dist/plugins/attributes/replaceUrl.js +11 -0
- package/dist/plugins/attributes/replaceUrl.js.map +7 -0
- package/dist/plugins/attributes/scrollIntoView.d.ts +2 -0
- package/dist/plugins/attributes/scrollIntoView.js +19 -0
- package/dist/plugins/attributes/scrollIntoView.js.map +7 -0
- package/dist/plugins/attributes/show.d.ts +2 -0
- package/dist/plugins/attributes/show.js +19 -0
- package/dist/plugins/attributes/show.js.map +7 -0
- package/dist/plugins/attributes/signals.d.ts +2 -0
- package/dist/plugins/attributes/signals.js +13 -0
- package/dist/plugins/attributes/signals.js.map +7 -0
- package/dist/plugins/attributes/style.d.ts +2 -0
- package/dist/plugins/attributes/style.js +25 -0
- package/dist/plugins/attributes/style.js.map +7 -0
- package/dist/plugins/attributes/text.d.ts +1 -0
- package/dist/plugins/attributes/text.js +13 -0
- package/dist/plugins/attributes/text.js.map +7 -0
- package/dist/plugins/attributes/viewTransition.d.ts +1 -0
- package/dist/plugins/attributes/viewTransition.js +11 -0
- package/dist/plugins/attributes/viewTransition.js.map +7 -0
- package/dist/plugins/directives/attribute-sync.d.ts +2 -0
- package/dist/plugins/directives/attribute-sync.js +20 -0
- package/dist/plugins/directives/attribute-sync.js.map +7 -0
- package/dist/plugins/directives/boost.d.ts +6 -0
- package/dist/plugins/directives/boost.js +35 -0
- package/dist/plugins/directives/boost.js.map +7 -0
- package/dist/plugins/directives/busy-flag.d.ts +2 -0
- package/dist/plugins/directives/busy-flag.js +21 -0
- package/dist/plugins/directives/busy-flag.js.map +7 -0
- package/dist/plugins/directives/class-toggle.d.ts +2 -0
- package/dist/plugins/directives/class-toggle.js +22 -0
- package/dist/plugins/directives/class-toggle.js.map +7 -0
- package/dist/plugins/directives/cloak.d.ts +5 -0
- package/dist/plugins/directives/cloak.js +11 -0
- package/dist/plugins/directives/cloak.js.map +7 -0
- package/dist/plugins/directives/collapse.d.ts +5 -0
- package/dist/plugins/directives/collapse.js +42 -0
- package/dist/plugins/directives/collapse.js.map +7 -0
- package/dist/plugins/directives/declare.d.ts +2 -0
- package/dist/plugins/directives/declare.js +13 -0
- package/dist/plugins/directives/declare.js.map +7 -0
- package/dist/plugins/directives/derive.d.ts +2 -0
- package/dist/plugins/directives/derive.js +20 -0
- package/dist/plugins/directives/derive.js.map +7 -0
- package/dist/plugins/directives/element-ref.d.ts +2 -0
- package/dist/plugins/directives/element-ref.js +13 -0
- package/dist/plugins/directives/element-ref.js.map +7 -0
- package/dist/plugins/directives/event-listener.d.ts +5 -0
- package/dist/plugins/directives/event-listener.js +28 -0
- package/dist/plugins/directives/event-listener.js.map +7 -0
- package/dist/plugins/directives/frame-loop.d.ts +1 -0
- package/dist/plugins/directives/frame-loop.js +19 -0
- package/dist/plugins/directives/frame-loop.js.map +7 -0
- package/dist/plugins/directives/html.d.ts +2 -0
- package/dist/plugins/directives/html.js +13 -0
- package/dist/plugins/directives/html.js.map +7 -0
- package/dist/plugins/directives/inline-style.d.ts +2 -0
- package/dist/plugins/directives/inline-style.js +25 -0
- package/dist/plugins/directives/inline-style.js.map +7 -0
- package/dist/plugins/directives/mask.d.ts +7 -0
- package/dist/plugins/directives/mask.js +47 -0
- package/dist/plugins/directives/mask.js.map +7 -0
- package/dist/plugins/directives/media-query.d.ts +2 -0
- package/dist/plugins/directives/media-query.js +19 -0
- package/dist/plugins/directives/media-query.js.map +7 -0
- package/dist/plugins/directives/on-mount.d.ts +2 -0
- package/dist/plugins/directives/on-mount.js +14 -0
- package/dist/plugins/directives/on-mount.js.map +7 -0
- package/dist/plugins/directives/patch-listener.d.ts +5 -0
- package/dist/plugins/directives/patch-listener.js +35 -0
- package/dist/plugins/directives/patch-listener.js.map +7 -0
- package/dist/plugins/directives/remove-me.d.ts +2 -0
- package/dist/plugins/directives/remove-me.js +13 -0
- package/dist/plugins/directives/remove-me.js.map +7 -0
- package/dist/plugins/directives/scroll-to.d.ts +2 -0
- package/dist/plugins/directives/scroll-to.js +19 -0
- package/dist/plugins/directives/scroll-to.js.map +7 -0
- package/dist/plugins/directives/size-watch.d.ts +1 -0
- package/dist/plugins/directives/size-watch.js +17 -0
- package/dist/plugins/directives/size-watch.js.map +7 -0
- package/dist/plugins/directives/state-dump.d.ts +2 -0
- package/dist/plugins/directives/state-dump.js +15 -0
- package/dist/plugins/directives/state-dump.js.map +7 -0
- package/dist/plugins/directives/storage-sync.d.ts +6 -0
- package/dist/plugins/directives/storage-sync.js +16 -0
- package/dist/plugins/directives/storage-sync.js.map +7 -0
- package/dist/plugins/directives/teleport.d.ts +5 -0
- package/dist/plugins/directives/teleport.js +19 -0
- package/dist/plugins/directives/teleport.js.map +7 -0
- package/dist/plugins/directives/text-content.d.ts +1 -0
- package/dist/plugins/directives/text-content.js +13 -0
- package/dist/plugins/directives/text-content.js.map +7 -0
- package/dist/plugins/directives/timer.d.ts +2 -0
- package/dist/plugins/directives/timer.js +18 -0
- package/dist/plugins/directives/timer.js.map +7 -0
- package/dist/plugins/directives/transition-name.d.ts +1 -0
- package/dist/plugins/directives/transition-name.js +11 -0
- package/dist/plugins/directives/transition-name.js.map +7 -0
- package/dist/plugins/directives/transition.d.ts +5 -0
- package/dist/plugins/directives/transition.js +40 -0
- package/dist/plugins/directives/transition.js.map +7 -0
- package/dist/plugins/directives/trap.d.ts +5 -0
- package/dist/plugins/directives/trap.js +48 -0
- package/dist/plugins/directives/trap.js.map +7 -0
- package/dist/plugins/directives/tween.d.ts +6 -0
- package/dist/plugins/directives/tween.js +58 -0
- package/dist/plugins/directives/tween.js.map +7 -0
- package/dist/plugins/directives/two-way-bind.d.ts +6 -0
- package/dist/plugins/directives/two-way-bind.js +82 -0
- package/dist/plugins/directives/two-way-bind.js.map +7 -0
- package/dist/plugins/directives/url-params.d.ts +13 -0
- package/dist/plugins/directives/url-params.js +76 -0
- package/dist/plugins/directives/url-params.js.map +7 -0
- package/dist/plugins/directives/url-replace.d.ts +1 -0
- package/dist/plugins/directives/url-replace.js +11 -0
- package/dist/plugins/directives/url-replace.js.map +7 -0
- package/dist/plugins/directives/validity.d.ts +2 -0
- package/dist/plugins/directives/validity.js +14 -0
- package/dist/plugins/directives/validity.js.map +7 -0
- package/dist/plugins/directives/viewport.d.ts +2 -0
- package/dist/plugins/directives/viewport.js +28 -0
- package/dist/plugins/directives/viewport.js.map +7 -0
- package/dist/plugins/directives/visibility.d.ts +2 -0
- package/dist/plugins/directives/visibility.js +19 -0
- package/dist/plugins/directives/visibility.js.map +7 -0
- package/dist/plugins/directives/watch.d.ts +2 -0
- package/dist/plugins/directives/watch.js +12 -0
- package/dist/plugins/directives/watch.js.map +7 -0
- package/dist/plugins/functions/bulk-set.d.ts +2 -0
- package/dist/plugins/functions/bulk-set.js +11 -0
- package/dist/plugins/functions/bulk-set.js.map +7 -0
- package/dist/plugins/functions/bulk-toggle.d.ts +2 -0
- package/dist/plugins/functions/bulk-toggle.js +11 -0
- package/dist/plugins/functions/bulk-toggle.js.map +7 -0
- package/dist/plugins/functions/confirm.d.ts +2 -0
- package/dist/plugins/functions/confirm.js +6 -0
- package/dist/plugins/functions/confirm.js.map +7 -0
- package/dist/plugins/functions/copy-text.d.ts +2 -0
- package/dist/plugins/functions/copy-text.js +11 -0
- package/dist/plugins/functions/copy-text.js.map +7 -0
- package/dist/plugins/functions/dispatch.d.ts +2 -0
- package/dist/plugins/functions/dispatch.js +9 -0
- package/dist/plugins/functions/dispatch.js.map +7 -0
- package/dist/plugins/functions/locale-format.d.ts +2 -0
- package/dist/plugins/functions/locale-format.js +21 -0
- package/dist/plugins/functions/locale-format.js.map +7 -0
- package/dist/plugins/functions/range-map.d.ts +2 -0
- package/dist/plugins/functions/range-map.js +14 -0
- package/dist/plugins/functions/range-map.js.map +7 -0
- package/dist/plugins/functions/request.d.ts +30 -0
- package/dist/plugins/functions/request.js +152 -0
- package/dist/plugins/functions/request.js.map +7 -0
- package/dist/plugins/functions/untracked-read.d.ts +2 -0
- package/dist/plugins/functions/untracked-read.js +6 -0
- package/dist/plugins/functions/untracked-read.js.map +7 -0
- package/dist/plugins/functions/websocket.d.ts +11 -0
- package/dist/plugins/functions/websocket.js +35 -0
- package/dist/plugins/functions/websocket.js.map +7 -0
- package/dist/plugins/index.d.ts +52 -0
- package/dist/plugins/index.js +108 -0
- package/dist/plugins/index.js.map +7 -0
- package/dist/plugins/server-events/apply-elements.d.ts +2 -0
- package/dist/plugins/server-events/apply-elements.js +62 -0
- package/dist/plugins/server-events/apply-elements.js.map +7 -0
- package/dist/plugins/server-events/apply-state.d.ts +2 -0
- package/dist/plugins/server-events/apply-state.js +18 -0
- package/dist/plugins/server-events/apply-state.js.map +7 -0
- package/dist/plugins/server-events/morph.d.ts +12 -0
- package/dist/plugins/server-events/morph.js +124 -0
- package/dist/plugins/server-events/morph.js.map +7 -0
- package/dist/presets/all.d.ts +3 -0
- package/dist/presets/all.js +112 -0
- package/dist/presets/all.js.map +7 -0
- package/dist/presets/essentials.d.ts +3 -0
- package/dist/presets/essentials.js +18 -0
- package/dist/presets/essentials.js.map +7 -0
- package/dist/presets/minimal.d.ts +3 -0
- package/dist/presets/minimal.js +9 -0
- package/dist/presets/minimal.js.map +7 -0
- package/dist/sigmx.auto.js +5 -0
- package/dist/sigmx.standalone.js +1 -0
- package/dist/standalone.d.ts +1 -0
- package/dist/standalone.js +8 -0
- package/dist/standalone.js.map +7 -0
- package/dist/utils/object.d.ts +9 -0
- package/dist/utils/object.js +26 -0
- package/dist/utils/object.js.map +7 -0
- package/dist/utils/text.d.ts +7 -0
- package/dist/utils/text.js +15 -0
- package/dist/utils/text.js.map +7 -0
- package/dist/utils/timing.d.ts +14 -0
- package/dist/utils/timing.js +58 -0
- package/dist/utils/timing.js.map +7 -0
- package/dist/vite.d.ts +42 -0
- package/dist/vite.js +79 -0
- package/dist/vite.js.map +7 -0
- package/package.json +111 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/expr.ts"],
|
|
4
|
+
"sourcesContent": ["// Expression compiler. Signals need no rewriting: the body runs inside `with (scope)`, where\n// `$count`, `$user.name` and `$` resolve through the store's scope proxy. Only `@action(` is\n// rewritten, into a call on the per-evaluation actions object.\n\nexport type Compiler = (params: string[], body: string) => (...args: any[]) => any\n\n/** Default compiler: `new Function`. Not usable under a strict CSP; see `cspCompiler`. */\nexport const functionCompiler: Compiler = (params, body) => Function(...params, body) as (...args: any[]) => any\n\nconst cache = new Map<string, (...args: any[]) => any>()\n\nconst isIdent = (c: string): boolean => /[A-Za-z0-9_$]/.test(c)\n\n/** Walk source text, skipping string, template and comment contents; `emit` receives code chars. */\nconst scan = (src: string, onCode: (c: string, i: number) => number | void): void => {\n let i = 0\n const n = src.length\n while (i < n) {\n const c = src[i]\n const next = src[i + 1]\n if (c === '\"' || c === \"'\" || c === '`') {\n let j = i + 1\n while (j < n && src[j] !== c) j += src[j] === '\\\\' ? 2 : 1\n onCode(src.slice(i, j + 1), i)\n i = j + 1\n } else if (c === '/' && next === '/') {\n const j = src.indexOf('\\n', i)\n i = j < 0 ? n : j\n } else if (c === '/' && next === '*') {\n const j = src.indexOf('*/', i + 2)\n i = j < 0 ? n : j + 2\n } else {\n const skip = onCode(c, i)\n i += skip || 1\n }\n }\n}\n\n/** Replace `@name(` with `__a.name(` outside strings and comments. */\nexport const rewriteActions = (src: string): string => {\n let out = ''\n scan(src, (c, i) => {\n if (c === '@') {\n let j = i + 1\n while (j < src.length && isIdent(src[j])) j++\n let k = j\n while (k < src.length && /\\s/.test(src[k])) k++\n if (j > i + 1 && src[k] === '(') {\n out += `__a.${src.slice(i + 1, j)}(`\n return k + 1 - i\n }\n }\n out += c\n })\n return out\n}\n\n/** Split on top-level semicolons. */\nexport const splitStatements = (src: string): string[] => {\n const parts: string[] = []\n let depth = 0\n let start = 0\n scan(src, (c, i) => {\n if (c.length > 1) return\n if ('([{'.includes(c)) depth++\n else if (')]}'.includes(c)) depth--\n else if (c === ';' && !depth) {\n parts.push(src.slice(start, i))\n start = i + 1\n }\n })\n parts.push(src.slice(start))\n return parts.filter((p) => p.trim())\n}\n\n/**\n * Compile an expression to `(scope, actions, ...params) => any`. With `returns`, the value of the\n * last statement is returned, so `$a = 1; $a * 2` works. Compiled functions are cached by source.\n */\nexport const compile = (\n compiler: Compiler,\n src: string,\n params: string[],\n returns: boolean,\n): ((...args: any[]) => any) => {\n const key = `${+returns}|${params.join()}|${src}`\n const hit = cache.get(key)\n if (hit) return hit\n const code = rewriteActions(src.trim())\n const make = (body: string) => compiler(['$', '__a', ...params], `with($){${body}\\n}`)\n let fn: (...args: any[]) => any\n if (!returns) {\n fn = make(code)\n } else {\n try {\n fn = make(`return(${code}\\n)`)\n } catch {\n const parts = splitStatements(code)\n const last = parts.pop() ?? ''\n try {\n fn = make(`${parts.join(';')};return(${last}\\n)`)\n } catch {\n fn = make(code)\n }\n }\n }\n cache.set(key, fn)\n return fn\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { createSigmx, parseAttr } from './engine.js';
|
|
2
|
+
export { compile, functionCompiler, rewriteActions, splitStatements } from './expr.js';
|
|
3
|
+
export type { Compiler } from './expr.js';
|
|
4
|
+
export { Computed, Signal, batch, computed, effect, flush, onSettled, signal, untracked } from './signals.js';
|
|
5
|
+
export { createStore } from './store.js';
|
|
6
|
+
export type { Patch, Store } from './store.js';
|
|
7
|
+
export type * from './types.js';
|
|
8
|
+
export { expand, isPlain, toPredicate } from '../utils/object.js';
|
|
9
|
+
export type { Filter } from '../utils/object.js';
|
|
10
|
+
export { camel, kebab, pascal, recase, snake } from '../utils/text.js';
|
|
11
|
+
export { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../utils/timing.js';
|
|
12
|
+
import type { ActionPlugin, AttributePlugin, HandlerPlugin } from './types.js';
|
|
13
|
+
/** Type a plugin definition. Pure: registration is `createSigmx({ plugins })` or `sigmx.use()`. */
|
|
14
|
+
export declare const attribute: (p: Omit<AttributePlugin, "type">) => AttributePlugin;
|
|
15
|
+
export declare const action: (p: Omit<ActionPlugin, "type">) => ActionPlugin;
|
|
16
|
+
export declare const handler: (p: Omit<HandlerPlugin, "type">) => HandlerPlugin;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createSigmx, parseAttr } from "./engine.js";
|
|
2
|
+
import { compile, functionCompiler, rewriteActions, splitStatements } from "./expr.js";
|
|
3
|
+
import { Computed, Signal, batch, computed, effect, flush, onSettled, signal, untracked } from "./signals.js";
|
|
4
|
+
import { createStore } from "./store.js";
|
|
5
|
+
import { expand, isPlain, toPredicate } from "../utils/object.js";
|
|
6
|
+
import { camel, kebab, pascal, recase, snake } from "../utils/text.js";
|
|
7
|
+
import { debounce, delay, throttle, toMs, withTiming, withViewTransition } from "../utils/timing.js";
|
|
8
|
+
const attribute = (p) => ({ type: "attribute", ...p });
|
|
9
|
+
const action = (p) => ({ type: "action", ...p });
|
|
10
|
+
const handler = (p) => ({ type: "handler", ...p });
|
|
11
|
+
export {
|
|
12
|
+
Computed,
|
|
13
|
+
Signal,
|
|
14
|
+
action,
|
|
15
|
+
attribute,
|
|
16
|
+
batch,
|
|
17
|
+
camel,
|
|
18
|
+
compile,
|
|
19
|
+
computed,
|
|
20
|
+
createSigmx,
|
|
21
|
+
createStore,
|
|
22
|
+
debounce,
|
|
23
|
+
delay,
|
|
24
|
+
effect,
|
|
25
|
+
expand,
|
|
26
|
+
flush,
|
|
27
|
+
functionCompiler,
|
|
28
|
+
handler,
|
|
29
|
+
isPlain,
|
|
30
|
+
kebab,
|
|
31
|
+
onSettled,
|
|
32
|
+
parseAttr,
|
|
33
|
+
pascal,
|
|
34
|
+
recase,
|
|
35
|
+
rewriteActions,
|
|
36
|
+
signal,
|
|
37
|
+
snake,
|
|
38
|
+
splitStatements,
|
|
39
|
+
throttle,
|
|
40
|
+
toMs,
|
|
41
|
+
toPredicate,
|
|
42
|
+
untracked,
|
|
43
|
+
withTiming,
|
|
44
|
+
withViewTransition
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/index.ts"],
|
|
4
|
+
"sourcesContent": ["export { createSigmx, parseAttr } from './engine.js'\nexport { compile, functionCompiler, rewriteActions, splitStatements } from './expr.js'\nexport type { Compiler } from './expr.js'\nexport { Computed, Signal, batch, computed, effect, flush, onSettled, signal, untracked } from './signals.js'\nexport { createStore } from './store.js'\nexport type { Patch, Store } from './store.js'\nexport type * from './types.js'\nexport { expand, isPlain, toPredicate } from '../utils/object.js'\nexport type { Filter } from '../utils/object.js'\nexport { camel, kebab, pascal, recase, snake } from '../utils/text.js'\nexport { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../utils/timing.js'\n\nimport type { ActionPlugin, AttributePlugin, HandlerPlugin } from './types.js'\n\n/** Type a plugin definition. Pure: registration is `createSigmx({ plugins })` or `sigmx.use()`. */\nexport const attribute = (p: Omit<AttributePlugin, 'type'>): AttributePlugin => ({ type: 'attribute', ...p })\nexport const action = (p: Omit<ActionPlugin, 'type'>): ActionPlugin => ({ type: 'action', ...p })\nexport const handler = (p: Omit<HandlerPlugin, 'type'>): HandlerPlugin => ({ type: 'handler', ...p })\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,aAAa,iBAAiB;AACvC,SAAS,SAAS,kBAAkB,gBAAgB,uBAAuB;AAE3E,SAAS,UAAU,QAAQ,OAAO,UAAU,QAAQ,OAAO,WAAW,QAAQ,iBAAiB;AAC/F,SAAS,mBAAmB;AAG5B,SAAS,QAAQ,SAAS,mBAAmB;AAE7C,SAAS,OAAO,OAAO,QAAQ,QAAQ,aAAa;AACpD,SAAS,UAAU,OAAO,UAAU,MAAM,YAAY,0BAA0B;AAKzE,MAAM,YAAY,CAAC,OAAuD,EAAE,MAAM,aAAa,GAAG,EAAE;AACpG,MAAM,SAAS,CAAC,OAAiD,EAAE,MAAM,UAAU,GAAG,EAAE;AACxF,MAAM,UAAU,CAAC,OAAmD,EAAE,MAAM,WAAW,GAAG,EAAE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
interface Tracker {
|
|
2
|
+
_deps: Map<Signal<any>, number>;
|
|
3
|
+
_invalidate(): void;
|
|
4
|
+
}
|
|
5
|
+
export declare class Signal<T> {
|
|
6
|
+
/** @internal */ _v: T;
|
|
7
|
+
/** @internal */ _ver: number;
|
|
8
|
+
/** @internal */ _subs: Set<Tracker>;
|
|
9
|
+
constructor(v: T);
|
|
10
|
+
get value(): T;
|
|
11
|
+
set value(x: T);
|
|
12
|
+
/** Read without subscribing. */
|
|
13
|
+
peek(): T;
|
|
14
|
+
/** Notify subscribers without replacing the value (after mutating an array or object in place). */
|
|
15
|
+
bump(): void;
|
|
16
|
+
}
|
|
17
|
+
export declare class Computed<T> extends Signal<T> implements Tracker {
|
|
18
|
+
_deps: Map<Signal<any>, number>;
|
|
19
|
+
/** @internal */ _dirty: boolean;
|
|
20
|
+
/** @internal */ _fn: () => T;
|
|
21
|
+
constructor(fn: () => T);
|
|
22
|
+
/** @internal */ _refresh(): void;
|
|
23
|
+
get value(): T;
|
|
24
|
+
set value(_: T);
|
|
25
|
+
peek(): T;
|
|
26
|
+
_invalidate(): void;
|
|
27
|
+
}
|
|
28
|
+
export declare const signal: <T>(value: T) => Signal<T>;
|
|
29
|
+
export declare const computed: <T>(fn: () => T) => Computed<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Run `fn` now and again whenever a signal it read changes. Effects created inside another
|
|
32
|
+
* effect are disposed when the parent re-runs. Returns a disposer.
|
|
33
|
+
*/
|
|
34
|
+
export declare const effect: (fn: () => void, onError?: (e: unknown) => void) => (() => void);
|
|
35
|
+
/** Coalesce many writes into one round of effect runs. */
|
|
36
|
+
export declare const batch: <R>(fn: () => R) => R;
|
|
37
|
+
/** Read signals inside `fn` without subscribing the current effect to them. */
|
|
38
|
+
export declare const untracked: <R>(fn: () => R) => R;
|
|
39
|
+
/** Called after each flush once every queued effect has run. */
|
|
40
|
+
export declare const onSettled: (fn: () => void) => (() => void);
|
|
41
|
+
export declare const flush: () => void;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
let active;
|
|
2
|
+
let owner;
|
|
3
|
+
let depth = 0;
|
|
4
|
+
let flushing = false;
|
|
5
|
+
const queue = /* @__PURE__ */ new Set();
|
|
6
|
+
const settled = /* @__PURE__ */ new Set();
|
|
7
|
+
class Signal {
|
|
8
|
+
constructor(v) {
|
|
9
|
+
/** @internal */
|
|
10
|
+
this.e = 0;
|
|
11
|
+
/** @internal */
|
|
12
|
+
this.f = /* @__PURE__ */ new Set();
|
|
13
|
+
this.a = v;
|
|
14
|
+
}
|
|
15
|
+
get value() {
|
|
16
|
+
if (active) {
|
|
17
|
+
active.b.set(this, this.e);
|
|
18
|
+
this.f.add(active);
|
|
19
|
+
}
|
|
20
|
+
return this.a;
|
|
21
|
+
}
|
|
22
|
+
set value(x) {
|
|
23
|
+
if (!Object.is(x, this.a)) {
|
|
24
|
+
this.a = x;
|
|
25
|
+
this.bump();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Read without subscribing. */
|
|
29
|
+
peek() {
|
|
30
|
+
return this.a;
|
|
31
|
+
}
|
|
32
|
+
/** Notify subscribers without replacing the value (after mutating an array or object in place). */
|
|
33
|
+
bump() {
|
|
34
|
+
this.e++;
|
|
35
|
+
for (const s of [...this.f]) s.h();
|
|
36
|
+
if (!depth) flush();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const release = (t) => {
|
|
40
|
+
for (const d of t.b.keys()) d.f.delete(t);
|
|
41
|
+
t.b.clear();
|
|
42
|
+
};
|
|
43
|
+
const stale = (t) => {
|
|
44
|
+
for (const [d, seen] of t.b) {
|
|
45
|
+
if (d instanceof Computed) d.i();
|
|
46
|
+
if (d.e !== seen) return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
50
|
+
const capture = (t, fn) => {
|
|
51
|
+
release(t);
|
|
52
|
+
const prev = active;
|
|
53
|
+
active = t;
|
|
54
|
+
try {
|
|
55
|
+
return fn();
|
|
56
|
+
} finally {
|
|
57
|
+
active = prev;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
class Computed extends Signal {
|
|
61
|
+
constructor(fn) {
|
|
62
|
+
super(void 0);
|
|
63
|
+
this.b = /* @__PURE__ */ new Map();
|
|
64
|
+
/** @internal */
|
|
65
|
+
this.g = true;
|
|
66
|
+
this.c = fn;
|
|
67
|
+
}
|
|
68
|
+
/** @internal */
|
|
69
|
+
i() {
|
|
70
|
+
if (!this.g) return;
|
|
71
|
+
this.g = false;
|
|
72
|
+
if (this.b.size && !stale(this)) return;
|
|
73
|
+
const x = capture(this, this.c);
|
|
74
|
+
if (!Object.is(x, this.a)) {
|
|
75
|
+
this.a = x;
|
|
76
|
+
this.e++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
get value() {
|
|
80
|
+
this.i();
|
|
81
|
+
return super.value;
|
|
82
|
+
}
|
|
83
|
+
set value(_) {
|
|
84
|
+
throw new Error("computed signals are read-only");
|
|
85
|
+
}
|
|
86
|
+
peek() {
|
|
87
|
+
this.i();
|
|
88
|
+
return this.a;
|
|
89
|
+
}
|
|
90
|
+
h() {
|
|
91
|
+
if (!this.g) {
|
|
92
|
+
this.g = true;
|
|
93
|
+
for (const s of this.f) s.h();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
class Effect {
|
|
98
|
+
constructor(fn, onError) {
|
|
99
|
+
this.b = /* @__PURE__ */ new Map();
|
|
100
|
+
this.j = false;
|
|
101
|
+
this.k = false;
|
|
102
|
+
this.d = /* @__PURE__ */ new Set();
|
|
103
|
+
this.c = fn;
|
|
104
|
+
this.l = onError;
|
|
105
|
+
}
|
|
106
|
+
h() {
|
|
107
|
+
if (!this.k && !this.j) {
|
|
108
|
+
this.j = true;
|
|
109
|
+
queue.add(this);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
n() {
|
|
113
|
+
this.j = false;
|
|
114
|
+
if (this.k || this.b.size && !stale(this)) return;
|
|
115
|
+
for (const c of this.d) c.m();
|
|
116
|
+
this.d.clear();
|
|
117
|
+
const prevOwner = owner;
|
|
118
|
+
owner = this;
|
|
119
|
+
depth++;
|
|
120
|
+
try {
|
|
121
|
+
capture(this, this.c);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
if (!this.l) throw e;
|
|
124
|
+
this.l(e);
|
|
125
|
+
} finally {
|
|
126
|
+
depth--;
|
|
127
|
+
owner = prevOwner;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
m() {
|
|
131
|
+
this.k = true;
|
|
132
|
+
release(this);
|
|
133
|
+
for (const c of this.d) c.m();
|
|
134
|
+
this.d.clear();
|
|
135
|
+
queue.delete(this);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const signal = (value) => new Signal(value);
|
|
139
|
+
const computed = (fn) => new Computed(fn);
|
|
140
|
+
const effect = (fn, onError) => {
|
|
141
|
+
const e = new Effect(fn, onError);
|
|
142
|
+
owner?.d.add(e);
|
|
143
|
+
e.n();
|
|
144
|
+
if (!depth) flush();
|
|
145
|
+
return () => e.m();
|
|
146
|
+
};
|
|
147
|
+
const batch = (fn) => {
|
|
148
|
+
depth++;
|
|
149
|
+
try {
|
|
150
|
+
return fn();
|
|
151
|
+
} finally {
|
|
152
|
+
if (!--depth) flush();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const untracked = (fn) => {
|
|
156
|
+
const prev = active;
|
|
157
|
+
active = void 0;
|
|
158
|
+
try {
|
|
159
|
+
return fn();
|
|
160
|
+
} finally {
|
|
161
|
+
active = prev;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
const onSettled = (fn) => {
|
|
165
|
+
settled.add(fn);
|
|
166
|
+
return () => settled.delete(fn);
|
|
167
|
+
};
|
|
168
|
+
const flush = () => {
|
|
169
|
+
if (flushing || depth) return;
|
|
170
|
+
flushing = true;
|
|
171
|
+
try {
|
|
172
|
+
let guard = 0;
|
|
173
|
+
while (queue.size) {
|
|
174
|
+
if (++guard > 1e5) throw new Error("effect loop: a signal is written by an effect that reads it");
|
|
175
|
+
const e = queue.values().next().value;
|
|
176
|
+
queue.delete(e);
|
|
177
|
+
e.n();
|
|
178
|
+
}
|
|
179
|
+
} finally {
|
|
180
|
+
flushing = false;
|
|
181
|
+
}
|
|
182
|
+
for (const fn of settled) fn();
|
|
183
|
+
};
|
|
184
|
+
export {
|
|
185
|
+
Computed,
|
|
186
|
+
Signal,
|
|
187
|
+
batch,
|
|
188
|
+
computed,
|
|
189
|
+
effect,
|
|
190
|
+
flush,
|
|
191
|
+
onSettled,
|
|
192
|
+
signal,
|
|
193
|
+
untracked
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=signals.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/signals.ts"],
|
|
4
|
+
"sourcesContent": ["// Reactive primitives: push invalidation, pull recomputation, version-checked effects.\n// No DOM dependency, so this module is unit-testable in plain Node.\n// Members prefixed with `_` are internal and get mangled by the build.\n\ninterface Tracker {\n _deps: Map<Signal<any>, number>\n _invalidate(): void\n}\n\nlet active: Tracker | undefined\nlet owner: Effect | undefined\nlet depth = 0\nlet flushing = false\nconst queue = new Set<Effect>()\nconst settled = new Set<() => void>()\n\nexport class Signal<T> {\n /** @internal */ _v: T\n /** @internal */ _ver = 0\n /** @internal */ _subs = new Set<Tracker>()\n constructor(v: T) {\n this._v = v\n }\n get value(): T {\n if (active) {\n active._deps.set(this, this._ver)\n this._subs.add(active)\n }\n return this._v\n }\n set value(x: T) {\n if (!Object.is(x, this._v)) {\n this._v = x\n this.bump()\n }\n }\n /** Read without subscribing. */\n peek(): T {\n return this._v\n }\n /** Notify subscribers without replacing the value (after mutating an array or object in place). */\n bump(): void {\n this._ver++\n for (const s of [...this._subs]) s._invalidate()\n if (!depth) flush()\n }\n}\n\nconst release = (t: Tracker): void => {\n for (const d of t._deps.keys()) d._subs.delete(t)\n t._deps.clear()\n}\n\n/** True when any dependency's version moved since the tracker last ran. Refreshes computeds on the way. */\nconst stale = (t: Tracker): boolean => {\n for (const [d, seen] of t._deps) {\n if (d instanceof Computed) d._refresh()\n if (d._ver !== seen) return true\n }\n return false\n}\n\nconst capture = <R>(t: Tracker, fn: () => R): R => {\n release(t)\n const prev = active\n active = t\n try {\n return fn()\n } finally {\n active = prev\n }\n}\n\nexport class Computed<T> extends Signal<T> implements Tracker {\n _deps = new Map<Signal<any>, number>()\n /** @internal */ _dirty = true\n /** @internal */ _fn: () => T\n constructor(fn: () => T) {\n super(undefined as T)\n this._fn = fn\n }\n /** @internal */ _refresh(): void {\n if (!this._dirty) return\n this._dirty = false\n if (this._deps.size && !stale(this)) return\n const x = capture(this, this._fn)\n if (!Object.is(x, this._v)) {\n this._v = x\n this._ver++\n }\n }\n override get value(): T {\n this._refresh()\n return super.value\n }\n override set value(_: T) {\n throw new Error('computed signals are read-only')\n }\n override peek(): T {\n this._refresh()\n return this._v\n }\n _invalidate(): void {\n if (!this._dirty) {\n this._dirty = true\n for (const s of this._subs) s._invalidate()\n }\n }\n}\n\nclass Effect implements Tracker {\n _deps = new Map<Signal<any>, number>()\n _queued = false\n _dead = false\n _kids = new Set<Effect>()\n _fn: () => void\n _onError?: (e: unknown) => void\n constructor(fn: () => void, onError?: (e: unknown) => void) {\n this._fn = fn\n this._onError = onError\n }\n _invalidate(): void {\n if (!this._dead && !this._queued) {\n this._queued = true\n queue.add(this)\n }\n }\n _exec(): void {\n this._queued = false\n if (this._dead || (this._deps.size && !stale(this))) return\n for (const c of this._kids) c._dispose()\n this._kids.clear()\n const prevOwner = owner\n owner = this\n depth++\n try {\n capture(this, this._fn)\n } catch (e) {\n if (!this._onError) throw e\n this._onError(e)\n } finally {\n depth--\n owner = prevOwner\n }\n }\n _dispose(): void {\n this._dead = true\n release(this)\n for (const c of this._kids) c._dispose()\n this._kids.clear()\n queue.delete(this)\n }\n}\n\nexport const signal = <T>(value: T): Signal<T> => new Signal(value)\nexport const computed = <T>(fn: () => T): Computed<T> => new Computed(fn)\n\n/**\n * Run `fn` now and again whenever a signal it read changes. Effects created inside another\n * effect are disposed when the parent re-runs. Returns a disposer.\n */\nexport const effect = (fn: () => void, onError?: (e: unknown) => void): (() => void) => {\n const e = new Effect(fn, onError)\n owner?._kids.add(e)\n e._exec()\n if (!depth) flush()\n return () => e._dispose()\n}\n\n/** Coalesce many writes into one round of effect runs. */\nexport const batch = <R>(fn: () => R): R => {\n depth++\n try {\n return fn()\n } finally {\n if (!--depth) flush()\n }\n}\n\n/** Read signals inside `fn` without subscribing the current effect to them. */\nexport const untracked = <R>(fn: () => R): R => {\n const prev = active\n active = undefined\n try {\n return fn()\n } finally {\n active = prev\n }\n}\n\n/** Called after each flush once every queued effect has run. */\nexport const onSettled = (fn: () => void): (() => void) => {\n settled.add(fn)\n return () => settled.delete(fn)\n}\n\nexport const flush = (): void => {\n if (flushing || depth) return\n flushing = true\n try {\n let guard = 0\n while (queue.size) {\n if (++guard > 1e5) throw new Error('effect loop: a signal is written by an effect that reads it')\n const e: Effect = queue.values().next().value!\n queue.delete(e)\n e._exec()\n }\n } finally {\n flushing = false\n }\n for (const fn of settled) fn()\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["_ver", "_subs", "_v", "_deps", "_invalidate", "_refresh", "_dirty", "_fn", "_queued", "_dead", "_kids", "_onError", "_exec", "_dispose"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Signal } from './signals.js';
|
|
2
|
+
import { type Filter } from '../utils/object.js';
|
|
3
|
+
export type Patch = Record<string, any>;
|
|
4
|
+
export interface Store {
|
|
5
|
+
/** Value at a dotted path: a leaf value, a namespace proxy, or undefined. Reads subscribe. */
|
|
6
|
+
get(path: string): any;
|
|
7
|
+
/** Replace the value at a path. Plain objects become namespaces; null/undefined removes. */
|
|
8
|
+
set(path: string, value: any): void;
|
|
9
|
+
/** JSON merge-patch (RFC 7396): objects merge, null removes, everything else replaces. */
|
|
10
|
+
merge(patch: Patch, options?: {
|
|
11
|
+
at?: string;
|
|
12
|
+
ifMissing?: boolean;
|
|
13
|
+
}): void;
|
|
14
|
+
remove(path: string): void;
|
|
15
|
+
has(path: string): boolean;
|
|
16
|
+
/** Install a computed (or any signal) as the leaf at a path. */
|
|
17
|
+
define(path: string, node: Signal<any>): void;
|
|
18
|
+
/** Leaf paths, optionally filtered. */
|
|
19
|
+
paths(filter?: Filter): string[];
|
|
20
|
+
/** Plain-object copy of the store or a namespace. */
|
|
21
|
+
snapshot(filter?: Filter, options?: {
|
|
22
|
+
at?: string;
|
|
23
|
+
computed?: boolean;
|
|
24
|
+
}): Patch;
|
|
25
|
+
/** Called after each settled batch with the nested object of changed paths (null = removed). */
|
|
26
|
+
onPatch(fn: (patch: Patch) => void): () => void;
|
|
27
|
+
/** Root namespace proxy: `$.count`, `$.user.name = 'x'`, `JSON.stringify($)`. */
|
|
28
|
+
readonly $: any;
|
|
29
|
+
/** Identifier scope for compiled expressions: resolves `$count`, `$user`, and `$`. */
|
|
30
|
+
readonly scope: object;
|
|
31
|
+
}
|
|
32
|
+
export declare const createStore: () => Store;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Computed, Signal, batch, onSettled } from "./signals.js";
|
|
2
|
+
import { expand, isPlain, toPredicate } from "../utils/object.js";
|
|
3
|
+
const parentOf = (p) => p.slice(0, Math.max(0, p.lastIndexOf(".")));
|
|
4
|
+
const nameOf = (p) => p.slice(p.lastIndexOf(".") + 1);
|
|
5
|
+
const join = (a, b) => a ? `${a}.${b}` : b;
|
|
6
|
+
const under = (p, at) => !at || p === at || p.startsWith(`${at}.`);
|
|
7
|
+
const createStore = () => {
|
|
8
|
+
const leaves = /* @__PURE__ */ new Map();
|
|
9
|
+
const kids = /* @__PURE__ */ new Map([["", /* @__PURE__ */ new Set()]]);
|
|
10
|
+
const shape = new Signal(0);
|
|
11
|
+
const pending = /* @__PURE__ */ new Map();
|
|
12
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
13
|
+
const nsCache = /* @__PURE__ */ new Map();
|
|
14
|
+
const arrCache = /* @__PURE__ */ new WeakMap();
|
|
15
|
+
const ensureNs = (p) => {
|
|
16
|
+
let set2 = kids.get(p);
|
|
17
|
+
if (!set2) {
|
|
18
|
+
if (leaves.has(p)) dropLeaf(p);
|
|
19
|
+
kids.set(p, set2 = /* @__PURE__ */ new Set());
|
|
20
|
+
ensureNs(parentOf(p)).add(nameOf(p));
|
|
21
|
+
shape.bump();
|
|
22
|
+
}
|
|
23
|
+
return set2;
|
|
24
|
+
};
|
|
25
|
+
const dropLeaf = (p) => {
|
|
26
|
+
const s = leaves.get(p);
|
|
27
|
+
if (!s) return;
|
|
28
|
+
leaves.delete(p);
|
|
29
|
+
kids.get(parentOf(p))?.delete(nameOf(p));
|
|
30
|
+
pending.set(p, null);
|
|
31
|
+
s.bump();
|
|
32
|
+
shape.bump();
|
|
33
|
+
};
|
|
34
|
+
const dropNs = (p) => {
|
|
35
|
+
const set2 = kids.get(p);
|
|
36
|
+
if (!set2) return;
|
|
37
|
+
for (const k of [...set2]) remove(join(p, k));
|
|
38
|
+
if (p) {
|
|
39
|
+
kids.delete(p);
|
|
40
|
+
kids.get(parentOf(p))?.delete(nameOf(p));
|
|
41
|
+
nsCache.delete(p);
|
|
42
|
+
}
|
|
43
|
+
shape.bump();
|
|
44
|
+
};
|
|
45
|
+
const remove = (p) => batch(() => {
|
|
46
|
+
dropLeaf(p);
|
|
47
|
+
dropNs(p);
|
|
48
|
+
});
|
|
49
|
+
const define = (p, node) => batch(() => {
|
|
50
|
+
if (kids.has(p)) dropNs(p);
|
|
51
|
+
const old = leaves.get(p);
|
|
52
|
+
leaves.set(p, node);
|
|
53
|
+
ensureNs(parentOf(p)).add(nameOf(p));
|
|
54
|
+
old?.bump();
|
|
55
|
+
shape.bump();
|
|
56
|
+
});
|
|
57
|
+
const set = (p, v) => batch(() => {
|
|
58
|
+
if (v == null) return remove(p);
|
|
59
|
+
if (isPlain(v)) {
|
|
60
|
+
const names = ensureNs(p);
|
|
61
|
+
for (const k of [...names]) if (!(k in v)) remove(join(p, k));
|
|
62
|
+
for (const k in v) set(join(p, k), v[k]);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (kids.has(p)) dropNs(p);
|
|
66
|
+
const s = leaves.get(p);
|
|
67
|
+
if (s instanceof Computed) throw new Error(`"${p}" is a computed signal and cannot be assigned`);
|
|
68
|
+
if (s) {
|
|
69
|
+
if (Object.is(s.peek(), v)) return;
|
|
70
|
+
s.value = v;
|
|
71
|
+
} else {
|
|
72
|
+
define(p, new Signal(v));
|
|
73
|
+
}
|
|
74
|
+
pending.set(p, v);
|
|
75
|
+
});
|
|
76
|
+
const merge = (patch, { at = "", ifMissing = false } = {}) => batch(() => {
|
|
77
|
+
if (!isPlain(patch)) return;
|
|
78
|
+
ensureNs(at);
|
|
79
|
+
for (const k in patch) {
|
|
80
|
+
const p = join(at, k);
|
|
81
|
+
const v = patch[k];
|
|
82
|
+
if (v === null) {
|
|
83
|
+
if (!ifMissing) remove(p);
|
|
84
|
+
} else if (isPlain(v)) {
|
|
85
|
+
merge(v, { at: p, ifMissing });
|
|
86
|
+
} else if (!(ifMissing && (leaves.has(p) || kids.has(p))) && !(leaves.get(p) instanceof Computed)) {
|
|
87
|
+
set(p, v);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const wrapArray = (raw, s, p) => {
|
|
92
|
+
let px = arrCache.get(raw);
|
|
93
|
+
if (!px) {
|
|
94
|
+
const touch = () => {
|
|
95
|
+
pending.set(p, raw);
|
|
96
|
+
s.bump();
|
|
97
|
+
};
|
|
98
|
+
px = new Proxy(raw, {
|
|
99
|
+
set: (t, k, v) => (t[k] = v, touch(), true),
|
|
100
|
+
deleteProperty: (t, k) => (delete t[k], touch(), true)
|
|
101
|
+
});
|
|
102
|
+
arrCache.set(raw, px);
|
|
103
|
+
}
|
|
104
|
+
return px;
|
|
105
|
+
};
|
|
106
|
+
const get = (p) => {
|
|
107
|
+
const s = leaves.get(p);
|
|
108
|
+
if (s) {
|
|
109
|
+
const v = s.value;
|
|
110
|
+
return Array.isArray(v) ? wrapArray(v, s, p) : v;
|
|
111
|
+
}
|
|
112
|
+
if (kids.has(p)) return ns(p);
|
|
113
|
+
shape.value;
|
|
114
|
+
return void 0;
|
|
115
|
+
};
|
|
116
|
+
const ns = (p) => {
|
|
117
|
+
let px = nsCache.get(p);
|
|
118
|
+
if (!px) {
|
|
119
|
+
const names = () => (shape.value, kids.get(p));
|
|
120
|
+
px = new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
121
|
+
get: (_, k) => typeof k !== "string" ? void 0 : k === "toJSON" ? () => snapshot(void 0, { at: p }) : get(join(p, k)),
|
|
122
|
+
set: (_, k, v) => (typeof k === "string" && set(join(p, k), v), true),
|
|
123
|
+
deleteProperty: (_, k) => (typeof k === "string" && remove(join(p, k)), true),
|
|
124
|
+
has: (_, k) => typeof k === "string" && !!names()?.has(k),
|
|
125
|
+
ownKeys: () => [...names() ?? []],
|
|
126
|
+
getOwnPropertyDescriptor: (_, k) => typeof k === "string" && names()?.has(k) ? { enumerable: true, configurable: true, writable: true, value: get(join(p, k)) } : void 0
|
|
127
|
+
});
|
|
128
|
+
nsCache.set(p, px);
|
|
129
|
+
}
|
|
130
|
+
return px;
|
|
131
|
+
};
|
|
132
|
+
const scope = new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
133
|
+
has: (_, k) => typeof k === "string" && k[0] === "$",
|
|
134
|
+
get: (_, k) => typeof k !== "string" ? void 0 : k === "$" ? ns("") : get(k.slice(1)),
|
|
135
|
+
set: (_, k, v) => {
|
|
136
|
+
if (typeof k === "string") k === "$" ? merge(v) : set(k.slice(1), v);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const paths = (filter) => {
|
|
141
|
+
shape.value;
|
|
142
|
+
const ok = toPredicate(filter);
|
|
143
|
+
return [...leaves.keys()].filter(ok);
|
|
144
|
+
};
|
|
145
|
+
const snapshot = (filter, { at = "", computed = true } = {}) => {
|
|
146
|
+
shape.value;
|
|
147
|
+
const ok = toPredicate(filter);
|
|
148
|
+
const out = {};
|
|
149
|
+
const rel = (p) => at ? p.slice(at.length + 1) : p;
|
|
150
|
+
for (const [p, s] of leaves) {
|
|
151
|
+
if (!under(p, at) || !ok(p) || !computed && s instanceof Computed) continue;
|
|
152
|
+
expand(out, rel(p), s.value);
|
|
153
|
+
}
|
|
154
|
+
for (const p of kids.keys()) {
|
|
155
|
+
if (p && p !== at && under(p, at) && ok(p) && !kids.get(p).size) expand(out, rel(p), {});
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
};
|
|
159
|
+
onSettled(() => {
|
|
160
|
+
if (!pending.size) return;
|
|
161
|
+
const patch = {};
|
|
162
|
+
for (const [p, v] of pending) expand(patch, p, v);
|
|
163
|
+
pending.clear();
|
|
164
|
+
for (const fn of listeners) fn(patch);
|
|
165
|
+
});
|
|
166
|
+
return {
|
|
167
|
+
get,
|
|
168
|
+
set,
|
|
169
|
+
merge,
|
|
170
|
+
remove,
|
|
171
|
+
has: (p) => leaves.has(p) || kids.has(p),
|
|
172
|
+
define,
|
|
173
|
+
paths,
|
|
174
|
+
snapshot,
|
|
175
|
+
onPatch: (fn) => (listeners.add(fn), () => listeners.delete(fn)),
|
|
176
|
+
get $() {
|
|
177
|
+
return ns("");
|
|
178
|
+
},
|
|
179
|
+
scope
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
export {
|
|
183
|
+
createStore
|
|
184
|
+
};
|
|
185
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/store.ts"],
|
|
4
|
+
"sourcesContent": ["// Path-keyed signal store with JSON merge-patch semantics. No DOM dependency.\nimport { Computed, Signal, batch, onSettled } from './signals.js'\nimport { expand, isPlain, toPredicate, type Filter } from '../utils/object.js'\n\nexport type Patch = Record<string, any>\n\nexport interface Store {\n /** Value at a dotted path: a leaf value, a namespace proxy, or undefined. Reads subscribe. */\n get(path: string): any\n /** Replace the value at a path. Plain objects become namespaces; null/undefined removes. */\n set(path: string, value: any): void\n /** JSON merge-patch (RFC 7396): objects merge, null removes, everything else replaces. */\n merge(patch: Patch, options?: { at?: string; ifMissing?: boolean }): void\n remove(path: string): void\n has(path: string): boolean\n /** Install a computed (or any signal) as the leaf at a path. */\n define(path: string, node: Signal<any>): void\n /** Leaf paths, optionally filtered. */\n paths(filter?: Filter): string[]\n /** Plain-object copy of the store or a namespace. */\n snapshot(filter?: Filter, options?: { at?: string; computed?: boolean }): Patch\n /** Called after each settled batch with the nested object of changed paths (null = removed). */\n onPatch(fn: (patch: Patch) => void): () => void\n /** Root namespace proxy: `$.count`, `$.user.name = 'x'`, `JSON.stringify($)`. */\n readonly $: any\n /** Identifier scope for compiled expressions: resolves `$count`, `$user`, and `$`. */\n readonly scope: object\n}\n\nconst parentOf = (p: string): string => p.slice(0, Math.max(0, p.lastIndexOf('.')))\nconst nameOf = (p: string): string => p.slice(p.lastIndexOf('.') + 1)\nconst join = (a: string, b: string): string => (a ? `${a}.${b}` : b)\nconst under = (p: string, at: string): boolean => !at || p === at || p.startsWith(`${at}.`)\n\nexport const createStore = (): Store => {\n const leaves = new Map<string, Signal<any>>()\n const kids = new Map<string, Set<string>>([['', new Set()]])\n const shape = new Signal(0) // bumped on any structural change; enumerations subscribe to it\n const pending = new Map<string, any>()\n const listeners = new Set<(p: Patch) => void>()\n const nsCache = new Map<string, any>()\n const arrCache = new WeakMap<object, any>()\n\n const ensureNs = (p: string): Set<string> => {\n let set = kids.get(p)\n if (!set) {\n if (leaves.has(p)) dropLeaf(p)\n kids.set(p, (set = new Set()))\n ensureNs(parentOf(p)).add(nameOf(p))\n shape.bump()\n }\n return set\n }\n\n const dropLeaf = (p: string): void => {\n const s = leaves.get(p)\n if (!s) return\n leaves.delete(p)\n kids.get(parentOf(p))?.delete(nameOf(p))\n pending.set(p, null)\n s.bump()\n shape.bump()\n }\n\n const dropNs = (p: string): void => {\n const set = kids.get(p)\n if (!set) return\n for (const k of [...set]) remove(join(p, k))\n if (p) {\n kids.delete(p)\n kids.get(parentOf(p))?.delete(nameOf(p))\n nsCache.delete(p)\n }\n shape.bump()\n }\n\n const remove = (p: string): void =>\n batch(() => {\n dropLeaf(p)\n dropNs(p)\n })\n\n const define = (p: string, node: Signal<any>): void =>\n batch(() => {\n if (kids.has(p)) dropNs(p)\n const old = leaves.get(p)\n leaves.set(p, node)\n ensureNs(parentOf(p)).add(nameOf(p))\n old?.bump()\n shape.bump()\n })\n\n const set = (p: string, v: any): void =>\n batch(() => {\n if (v == null) return remove(p)\n if (isPlain(v)) {\n const names = ensureNs(p)\n for (const k of [...names]) if (!(k in v)) remove(join(p, k))\n for (const k in v) set(join(p, k), v[k])\n return\n }\n if (kids.has(p)) dropNs(p)\n const s = leaves.get(p)\n if (s instanceof Computed) throw new Error(`\"${p}\" is a computed signal and cannot be assigned`)\n if (s) {\n if (Object.is(s.peek(), v)) return\n s.value = v\n } else {\n define(p, new Signal(v))\n }\n pending.set(p, v)\n })\n\n const merge = (patch: Patch, { at = '', ifMissing = false } = {}): void =>\n batch(() => {\n if (!isPlain(patch)) return\n ensureNs(at)\n for (const k in patch) {\n const p = join(at, k)\n const v = patch[k]\n if (v === null) {\n if (!ifMissing) remove(p)\n } else if (isPlain(v)) {\n merge(v, { at: p, ifMissing })\n } else if (!(ifMissing && (leaves.has(p) || kids.has(p))) && !(leaves.get(p) instanceof Computed)) {\n set(p, v) // computed leaves are skipped: patches from storage or a server cannot overwrite them\n }\n }\n })\n\n /** Arrays are returned through a proxy so in-place mutation notifies the leaf. */\n const wrapArray = (raw: any[], s: Signal<any>, p: string): any => {\n let px = arrCache.get(raw)\n if (!px) {\n const touch = () => {\n pending.set(p, raw)\n s.bump()\n }\n px = new Proxy(raw, {\n set: (t, k, v) => ((t as any)[k] = v, touch(), true),\n deleteProperty: (t, k) => (delete (t as any)[k], touch(), true),\n })\n arrCache.set(raw, px)\n }\n return px\n }\n\n const get = (p: string): any => {\n const s = leaves.get(p)\n if (s) {\n const v = s.value\n return Array.isArray(v) ? wrapArray(v, s, p) : v\n }\n if (kids.has(p)) return ns(p)\n shape.value // subscribe, so creating this path later re-runs the reader\n return undefined\n }\n\n const ns = (p: string): any => {\n let px = nsCache.get(p)\n if (!px) {\n const names = () => (shape.value, kids.get(p))\n px = new Proxy(Object.create(null), {\n get: (_, k) =>\n typeof k !== 'string' ? undefined : k === 'toJSON' ? () => snapshot(undefined, { at: p }) : get(join(p, k)),\n set: (_, k, v) => (typeof k === 'string' && set(join(p, k), v), true),\n deleteProperty: (_, k) => (typeof k === 'string' && remove(join(p, k)), true),\n has: (_, k) => typeof k === 'string' && !!names()?.has(k),\n ownKeys: () => [...(names() ?? [])],\n getOwnPropertyDescriptor: (_, k) =>\n typeof k === 'string' && names()?.has(k)\n ? { enumerable: true, configurable: true, writable: true, value: get(join(p, k)) }\n : undefined,\n })\n nsCache.set(p, px)\n }\n return px\n }\n\n const scope = new Proxy(Object.create(null), {\n has: (_, k) => typeof k === 'string' && k[0] === '$',\n get: (_, k) => (typeof k !== 'string' ? undefined : k === '$' ? ns('') : get(k.slice(1))),\n set: (_, k, v) => {\n if (typeof k === 'string') k === '$' ? merge(v) : set(k.slice(1), v)\n return true\n },\n })\n\n const paths = (filter?: Filter): string[] => {\n shape.value\n const ok = toPredicate(filter)\n return [...leaves.keys()].filter(ok)\n }\n\n const snapshot = (filter?: Filter, { at = '', computed = true } = {}): Patch => {\n shape.value\n const ok = toPredicate(filter)\n const out: Patch = {}\n const rel = (p: string) => (at ? p.slice(at.length + 1) : p)\n for (const [p, s] of leaves) {\n if (!under(p, at) || !ok(p) || (!computed && s instanceof Computed)) continue\n expand(out, rel(p), s.value)\n }\n // Empty namespaces still appear as `{}`.\n for (const p of kids.keys()) {\n if (p && p !== at && under(p, at) && ok(p) && !kids.get(p)!.size) expand(out, rel(p), {})\n }\n return out\n }\n\n onSettled(() => {\n if (!pending.size) return\n const patch: Patch = {}\n for (const [p, v] of pending) expand(patch, p, v)\n pending.clear()\n for (const fn of listeners) fn(patch)\n })\n\n return {\n get,\n set,\n merge,\n remove,\n has: (p) => leaves.has(p) || kids.has(p),\n define,\n paths,\n snapshot,\n onPatch: (fn) => (listeners.add(fn), () => listeners.delete(fn)),\n get $() {\n return ns('')\n },\n scope,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["set"]
|
|
7
|
+
}
|