sigmx 0.1.0 → 0.1.1
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/README.md +52 -41
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +2 -2
- package/dist/kernel/compile.js.map +2 -2
- package/dist/kernel/contracts.d.ts +1 -8
- package/dist/kernel/index.d.ts +10 -11
- package/dist/kernel/index.js +10 -7
- package/dist/kernel/index.js.map +3 -3
- package/dist/kernel/precompile.d.ts +0 -2
- package/dist/kernel/precompile.js +11 -4
- package/dist/kernel/precompile.js.map +2 -2
- package/dist/kernel/precompiled.js.map +2 -2
- package/dist/kernel/reactive.d.ts +6 -10
- package/dist/kernel/reactive.js +4 -8
- package/dist/kernel/reactive.js.map +2 -2
- package/dist/kernel/runtime.js +19 -7
- package/dist/kernel/runtime.js.map +2 -2
- package/dist/kernel/scan.d.ts +1 -10
- package/dist/kernel/scan.js +24 -7
- package/dist/kernel/scan.js.map +2 -2
- package/dist/kernel/state.d.ts +1 -5
- package/dist/kernel/state.js +49 -22
- package/dist/kernel/state.js.map +2 -2
- package/dist/kernel/strict-csp.js.map +1 -1
- package/dist/lib/casing.js.map +2 -2
- package/dist/lib/objects.d.ts +0 -1
- package/dist/lib/objects.js +4 -1
- package/dist/lib/objects.js.map +2 -2
- package/dist/lib/schedule.d.ts +0 -2
- package/dist/lib/schedule.js.map +2 -2
- package/dist/lib/sse.d.ts +0 -1
- package/dist/lib/sse.js +3 -2
- package/dist/lib/sse.js.map +2 -2
- package/dist/plugins/directives/attribute-sync.js.map +1 -1
- package/dist/plugins/directives/boost.js +2 -1
- package/dist/plugins/directives/boost.js.map +2 -2
- package/dist/plugins/directives/busy-flag.js.map +1 -1
- package/dist/plugins/directives/class-toggle.js.map +1 -1
- package/dist/plugins/directives/cloak.js.map +1 -1
- package/dist/plugins/directives/collapse.js.map +1 -1
- package/dist/plugins/directives/declare.js.map +1 -1
- package/dist/plugins/directives/derive.js +4 -1
- package/dist/plugins/directives/derive.js.map +2 -2
- package/dist/plugins/directives/element-ref.js.map +1 -1
- package/dist/plugins/directives/event-listener.js +4 -1
- package/dist/plugins/directives/event-listener.js.map +2 -2
- package/dist/plugins/directives/frame-loop.js.map +1 -1
- package/dist/plugins/directives/html.js.map +1 -1
- package/dist/plugins/directives/inline-style.js +1 -1
- package/dist/plugins/directives/inline-style.js.map +2 -2
- package/dist/plugins/directives/mask.js.map +1 -1
- package/dist/plugins/directives/media-query.js +2 -1
- package/dist/plugins/directives/media-query.js.map +2 -2
- package/dist/plugins/directives/on-mount.js +4 -1
- package/dist/plugins/directives/on-mount.js.map +2 -2
- package/dist/plugins/directives/patch-listener.js.map +1 -1
- package/dist/plugins/directives/remove-me.js.map +1 -1
- package/dist/plugins/directives/scroll-to.js.map +1 -1
- package/dist/plugins/directives/size-watch.js.map +1 -1
- package/dist/plugins/directives/state-dump.js.map +1 -1
- package/dist/plugins/directives/storage-sync.js.map +1 -1
- package/dist/plugins/directives/teleport.js.map +1 -1
- package/dist/plugins/directives/text-content.js.map +1 -1
- package/dist/plugins/directives/timer.js.map +1 -1
- package/dist/plugins/directives/transition-name.js.map +1 -1
- package/dist/plugins/directives/transition.js.map +1 -1
- package/dist/plugins/directives/trap.js +8 -2
- package/dist/plugins/directives/trap.js.map +2 -2
- package/dist/plugins/directives/tween.js.map +2 -2
- package/dist/plugins/directives/two-way-bind.js +37 -7
- package/dist/plugins/directives/two-way-bind.js.map +2 -2
- package/dist/plugins/directives/url-params.js +2 -1
- package/dist/plugins/directives/url-params.js.map +2 -2
- package/dist/plugins/directives/url-replace.js.map +1 -1
- package/dist/plugins/directives/validity.js.map +1 -1
- package/dist/plugins/directives/viewport.js +4 -1
- package/dist/plugins/directives/viewport.js.map +2 -2
- package/dist/plugins/directives/visibility.js.map +1 -1
- package/dist/plugins/directives/watch.d.ts +0 -1
- package/dist/plugins/directives/watch.js.map +2 -2
- package/dist/plugins/functions/bulk-set.js +5 -3
- package/dist/plugins/functions/bulk-set.js.map +2 -2
- package/dist/plugins/functions/bulk-toggle.js +5 -3
- package/dist/plugins/functions/bulk-toggle.js.map +2 -2
- package/dist/plugins/functions/confirm.js.map +1 -1
- package/dist/plugins/functions/copy-text.js.map +1 -1
- package/dist/plugins/functions/dispatch.js.map +2 -2
- package/dist/plugins/functions/locale-format.js.map +1 -1
- package/dist/plugins/functions/range-map.js.map +1 -1
- package/dist/plugins/functions/request.js +19 -5
- package/dist/plugins/functions/request.js.map +2 -2
- package/dist/plugins/functions/untracked-read.js.map +1 -1
- package/dist/plugins/functions/websocket.js +5 -1
- package/dist/plugins/functions/websocket.js.map +2 -2
- package/dist/plugins/index.d.ts +36 -36
- package/dist/plugins/index.js +33 -33
- package/dist/plugins/index.js.map +2 -2
- package/dist/plugins/server-events/apply-elements.js +4 -1
- package/dist/plugins/server-events/apply-elements.js.map +2 -2
- package/dist/plugins/server-events/apply-state.js.map +1 -1
- package/dist/plugins/server-events/morph.d.ts +0 -2
- package/dist/plugins/server-events/morph.js +31 -8
- package/dist/plugins/server-events/morph.js.map +2 -2
- package/dist/presets/all.d.ts +0 -1
- package/dist/presets/all.js +23 -23
- package/dist/presets/all.js.map +2 -2
- package/dist/presets/essentials.d.ts +0 -1
- package/dist/presets/essentials.js +27 -9
- package/dist/presets/essentials.js.map +2 -2
- package/dist/presets/minimal.d.ts +0 -1
- package/dist/presets/minimal.js +2 -2
- package/dist/presets/minimal.js.map +2 -2
- package/dist/server.d.ts +102 -0
- package/dist/server.js +190 -0
- package/dist/server.js.map +7 -0
- package/dist/sigmx.standalone.js +1 -1
- package/dist/standalone.js.map +2 -2
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +31 -8
- package/dist/vite.js.map +2 -2
- package/package.json +19 -2
- package/dist/auto.d.ts +0 -1
- package/dist/auto.js +0 -7
- package/dist/auto.js.map +0 -7
- package/dist/core/csp.d.ts +0 -7
- package/dist/core/csp.js +0 -20
- package/dist/core/csp.js.map +0 -7
- package/dist/core/engine.d.ts +0 -10
- package/dist/core/engine.js +0 -200
- package/dist/core/engine.js.map +0 -7
- package/dist/core/expr.d.ts +0 -12
- package/dist/core/expr.js +0 -94
- package/dist/core/expr.js.map +0 -7
- package/dist/core/index.d.ts +0 -16
- package/dist/core/index.js +0 -46
- package/dist/core/index.js.map +0 -7
- package/dist/core/signals.d.ts +0 -42
- package/dist/core/signals.js +0 -195
- package/dist/core/signals.js.map +0 -7
- package/dist/core/store.d.ts +0 -32
- package/dist/core/store.js +0 -185
- package/dist/core/store.js.map +0 -7
- package/dist/core/types.d.ts +0 -101
- package/dist/core/types.js +0 -1
- package/dist/core/types.js.map +0 -7
- package/dist/plugins/actions/clipboard.d.ts +0 -2
- package/dist/plugins/actions/clipboard.js +0 -11
- package/dist/plugins/actions/clipboard.js.map +0 -7
- package/dist/plugins/actions/fit.d.ts +0 -2
- package/dist/plugins/actions/fit.js +0 -14
- package/dist/plugins/actions/fit.js.map +0 -7
- package/dist/plugins/actions/intl.d.ts +0 -2
- package/dist/plugins/actions/intl.js +0 -21
- package/dist/plugins/actions/intl.js.map +0 -7
- package/dist/plugins/actions/peek.d.ts +0 -2
- package/dist/plugins/actions/peek.js +0 -6
- package/dist/plugins/actions/peek.js.map +0 -7
- package/dist/plugins/actions/setAll.d.ts +0 -2
- package/dist/plugins/actions/setAll.js +0 -11
- package/dist/plugins/actions/setAll.js.map +0 -7
- package/dist/plugins/actions/toggleAll.d.ts +0 -2
- package/dist/plugins/actions/toggleAll.js +0 -11
- package/dist/plugins/actions/toggleAll.js.map +0 -7
- package/dist/plugins/attributes/attr.d.ts +0 -2
- package/dist/plugins/attributes/attr.js +0 -20
- package/dist/plugins/attributes/attr.js.map +0 -7
- package/dist/plugins/attributes/bind.d.ts +0 -6
- package/dist/plugins/attributes/bind.js +0 -81
- package/dist/plugins/attributes/bind.js.map +0 -7
- package/dist/plugins/attributes/class.d.ts +0 -2
- package/dist/plugins/attributes/class.js +0 -22
- package/dist/plugins/attributes/class.js.map +0 -7
- package/dist/plugins/attributes/computed.d.ts +0 -2
- package/dist/plugins/attributes/computed.js +0 -20
- package/dist/plugins/attributes/computed.js.map +0 -7
- package/dist/plugins/attributes/customValidity.d.ts +0 -2
- package/dist/plugins/attributes/customValidity.js +0 -14
- package/dist/plugins/attributes/customValidity.js.map +0 -7
- package/dist/plugins/attributes/effect.d.ts +0 -2
- package/dist/plugins/attributes/effect.js +0 -12
- package/dist/plugins/attributes/effect.js.map +0 -7
- package/dist/plugins/attributes/indicator.d.ts +0 -2
- package/dist/plugins/attributes/indicator.js +0 -20
- package/dist/plugins/attributes/indicator.js.map +0 -7
- package/dist/plugins/attributes/init.d.ts +0 -2
- package/dist/plugins/attributes/init.js +0 -14
- package/dist/plugins/attributes/init.js.map +0 -7
- package/dist/plugins/attributes/jsonSignals.d.ts +0 -2
- package/dist/plugins/attributes/jsonSignals.js +0 -15
- package/dist/plugins/attributes/jsonSignals.js.map +0 -7
- package/dist/plugins/attributes/matchMedia.d.ts +0 -2
- package/dist/plugins/attributes/matchMedia.js +0 -19
- package/dist/plugins/attributes/matchMedia.js.map +0 -7
- package/dist/plugins/attributes/on.d.ts +0 -5
- package/dist/plugins/attributes/on.js +0 -28
- package/dist/plugins/attributes/on.js.map +0 -7
- package/dist/plugins/attributes/onIntersect.d.ts +0 -2
- package/dist/plugins/attributes/onIntersect.js +0 -28
- package/dist/plugins/attributes/onIntersect.js.map +0 -7
- package/dist/plugins/attributes/onInterval.d.ts +0 -2
- package/dist/plugins/attributes/onInterval.js +0 -18
- package/dist/plugins/attributes/onInterval.js.map +0 -7
- package/dist/plugins/attributes/onRaf.d.ts +0 -1
- package/dist/plugins/attributes/onRaf.js +0 -19
- package/dist/plugins/attributes/onRaf.js.map +0 -7
- package/dist/plugins/attributes/onResize.d.ts +0 -1
- package/dist/plugins/attributes/onResize.js +0 -17
- package/dist/plugins/attributes/onResize.js.map +0 -7
- package/dist/plugins/attributes/onSignalPatch.d.ts +0 -5
- package/dist/plugins/attributes/onSignalPatch.js +0 -35
- package/dist/plugins/attributes/onSignalPatch.js.map +0 -7
- package/dist/plugins/attributes/persist.d.ts +0 -6
- package/dist/plugins/attributes/persist.js +0 -16
- package/dist/plugins/attributes/persist.js.map +0 -7
- package/dist/plugins/attributes/queryString.d.ts +0 -5
- package/dist/plugins/attributes/queryString.js +0 -54
- package/dist/plugins/attributes/queryString.js.map +0 -7
- package/dist/plugins/attributes/ref.d.ts +0 -2
- package/dist/plugins/attributes/ref.js +0 -13
- package/dist/plugins/attributes/ref.js.map +0 -7
- package/dist/plugins/attributes/replaceUrl.d.ts +0 -1
- package/dist/plugins/attributes/replaceUrl.js +0 -11
- package/dist/plugins/attributes/replaceUrl.js.map +0 -7
- package/dist/plugins/attributes/scrollIntoView.d.ts +0 -2
- package/dist/plugins/attributes/scrollIntoView.js +0 -19
- package/dist/plugins/attributes/scrollIntoView.js.map +0 -7
- package/dist/plugins/attributes/show.d.ts +0 -2
- package/dist/plugins/attributes/show.js +0 -19
- package/dist/plugins/attributes/show.js.map +0 -7
- package/dist/plugins/attributes/signals.d.ts +0 -2
- package/dist/plugins/attributes/signals.js +0 -13
- package/dist/plugins/attributes/signals.js.map +0 -7
- package/dist/plugins/attributes/style.d.ts +0 -2
- package/dist/plugins/attributes/style.js +0 -25
- package/dist/plugins/attributes/style.js.map +0 -7
- package/dist/plugins/attributes/text.d.ts +0 -1
- package/dist/plugins/attributes/text.js +0 -13
- package/dist/plugins/attributes/text.js.map +0 -7
- package/dist/plugins/attributes/viewTransition.d.ts +0 -1
- package/dist/plugins/attributes/viewTransition.js +0 -11
- package/dist/plugins/attributes/viewTransition.js.map +0 -7
- package/dist/sigmx.auto.js +0 -5
- package/dist/utils/object.d.ts +0 -9
- package/dist/utils/object.js +0 -26
- package/dist/utils/object.js.map +0 -7
- package/dist/utils/text.d.ts +0 -7
- package/dist/utils/text.js +0 -15
- package/dist/utils/text.js.map +0 -7
- package/dist/utils/timing.d.ts +0 -14
- package/dist/utils/timing.js +0 -58
- package/dist/utils/timing.js.map +0 -7
package/dist/kernel/reactive.js
CHANGED
|
@@ -5,11 +5,8 @@ let flushing = false;
|
|
|
5
5
|
const queue = /* @__PURE__ */ new Set();
|
|
6
6
|
const settled = /* @__PURE__ */ new Set();
|
|
7
7
|
class Signal {
|
|
8
|
-
/** @internal */
|
|
9
8
|
a;
|
|
10
|
-
/** @internal */
|
|
11
9
|
e = 0;
|
|
12
|
-
/** @internal */
|
|
13
10
|
f = /* @__PURE__ */ new Set();
|
|
14
11
|
constructor(v) {
|
|
15
12
|
this.a = v;
|
|
@@ -27,7 +24,6 @@ class Signal {
|
|
|
27
24
|
this.bump();
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
|
-
/** Read without subscribing. */
|
|
31
27
|
peek() {
|
|
32
28
|
return this.a;
|
|
33
29
|
}
|
|
@@ -61,15 +57,12 @@ const capture = (t, fn) => {
|
|
|
61
57
|
};
|
|
62
58
|
class Computed extends Signal {
|
|
63
59
|
b = /* @__PURE__ */ new Map();
|
|
64
|
-
/** @internal */
|
|
65
60
|
g = true;
|
|
66
|
-
/** @internal */
|
|
67
61
|
c;
|
|
68
62
|
constructor(fn) {
|
|
69
63
|
super(void 0);
|
|
70
64
|
this.c = fn;
|
|
71
65
|
}
|
|
72
|
-
/** @internal */
|
|
73
66
|
i() {
|
|
74
67
|
if (!this.g) return;
|
|
75
68
|
this.g = false;
|
|
@@ -177,7 +170,10 @@ const flush = () => {
|
|
|
177
170
|
try {
|
|
178
171
|
let guard = 0;
|
|
179
172
|
while (queue.size) {
|
|
180
|
-
if (++guard > 1e5)
|
|
173
|
+
if (++guard > 1e5) {
|
|
174
|
+
queue.clear();
|
|
175
|
+
throw new Error("effect loop");
|
|
176
|
+
}
|
|
181
177
|
const e = queue.values().next().value;
|
|
182
178
|
queue.delete(e);
|
|
183
179
|
e.n();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/reactive.ts"],
|
|
4
|
-
"sourcesContent": ["//
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["// 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 _v: T;\n _ver = 0;\n _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 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 _dirty = true;\n _fn: () => T;\n constructor(fn: () => T) {\n super(undefined as T);\n this._fn = fn;\n }\n _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\nexport const batch = <R>(fn: () => R): R => {\n depth++;\n try {\n return fn();\n } finally {\n if (!--depth) flush();\n }\n};\n\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\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) {\n queue.clear(); // leave nothing behind, or every later flush would trip the same guard\n throw new Error('effect loop');\n }\n const e = queue.values().next().value as Effect;\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
6
|
"names": ["_v", "_ver", "_subs", "_deps", "_invalidate", "_refresh", "_dirty", "_fn", "_queued", "_dead", "_kids", "_onError", "_exec", "_dispose"]
|
|
7
7
|
}
|
package/dist/kernel/runtime.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { recase } from "../lib/casing.js";
|
|
1
2
|
import { functionCompiler } from "./compile.js";
|
|
2
3
|
import { effect } from "./reactive.js";
|
|
3
4
|
import { createStore } from "./state.js";
|
|
4
|
-
|
|
5
|
-
const isEl = (n) => n instanceof HTMLElement || n instanceof SVGElement || n instanceof MathMLElement;
|
|
5
|
+
const isEl = (n) => n.nodeType === 1;
|
|
6
6
|
const tree = (n) => isEl(n) ? [n, ...n.querySelectorAll("*")] : n instanceof ShadowRoot ? [...n.querySelectorAll("*")] : [];
|
|
7
7
|
const parsed = /* @__PURE__ */ new Map();
|
|
8
8
|
const parseAttr = (raw) => {
|
|
@@ -72,9 +72,18 @@ const createRuntime = (options) => {
|
|
|
72
72
|
m?.get(attr)?.();
|
|
73
73
|
m?.delete(attr);
|
|
74
74
|
};
|
|
75
|
-
const actionsFor = (el, evt, error, cleanup) => {
|
|
75
|
+
const actionsFor = (el, evt, error, cleanup, report) => {
|
|
76
76
|
const ctx = { el, evt, store, runtime, error, cleanup };
|
|
77
|
-
return new Proxy(
|
|
77
|
+
return new Proxy(
|
|
78
|
+
{},
|
|
79
|
+
{
|
|
80
|
+
get: (_, name) => (...args) => {
|
|
81
|
+
const r = runtime.call(name, ctx, args);
|
|
82
|
+
if (r instanceof Promise) r.catch(report);
|
|
83
|
+
return r;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
);
|
|
78
87
|
};
|
|
79
88
|
const mount = (el, attr, raw, value, only) => {
|
|
80
89
|
const { plugin: name, key, mods } = parseAttr(raw);
|
|
@@ -96,7 +105,7 @@ const createRuntime = (options) => {
|
|
|
96
105
|
cased: (style = "camel") => recase(key ?? "", mods.get("case")?.[0] || style),
|
|
97
106
|
evaluate: (evt, ...args) => {
|
|
98
107
|
fn ??= expressions(value, ["el", "evt", ...plugin.args ?? []], plugin.returns ?? true);
|
|
99
|
-
return fn(store, actionsFor(el, evt, error, ctx.cleanup), el, evt, ...args);
|
|
108
|
+
return fn(store, actionsFor(el, evt, error, ctx.cleanup, report), el, evt, ...args);
|
|
100
109
|
},
|
|
101
110
|
effect: (f) => disposers.push(effect(f, report)),
|
|
102
111
|
listen: (target, type, f, opts) => {
|
|
@@ -116,7 +125,10 @@ const createRuntime = (options) => {
|
|
|
116
125
|
runtime
|
|
117
126
|
};
|
|
118
127
|
let m = mounted.get(el);
|
|
119
|
-
if (!m)
|
|
128
|
+
if (!m) {
|
|
129
|
+
m = /* @__PURE__ */ new Map();
|
|
130
|
+
mounted.set(el, m);
|
|
131
|
+
}
|
|
120
132
|
m.set(attr, () => {
|
|
121
133
|
for (const d of disposers.splice(0)) d();
|
|
122
134
|
});
|
|
@@ -136,7 +148,7 @@ const createRuntime = (options) => {
|
|
|
136
148
|
if (ignored(el)) continue;
|
|
137
149
|
for (const { name, value } of [...el.attributes]) {
|
|
138
150
|
const raw = strip(name);
|
|
139
|
-
if (raw) mount(el, name, raw, value, only);
|
|
151
|
+
if (raw && !mounted.get(el)?.has(name)) mount(el, name, raw, value, only);
|
|
140
152
|
}
|
|
141
153
|
}
|
|
142
154
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/runtime.ts"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": "AAAA,SAAS,wBAAwB;
|
|
4
|
+
"sourcesContent": ["import { type CaseStyle, recase } from '../lib/casing.js';\nimport { functionCompiler } from './compile.js';\nimport type {\n ActionCtx,\n AttributePlugin,\n Ctx,\n El,\n Evaluator,\n Mods,\n Plugin,\n Runtime,\n RuntimeOptions,\n Sigmx,\n} from './contracts.js';\nimport { effect } from './reactive.js';\nimport { createStore } from './state.js';\n\nconst isEl = (n: Node): n is El => n.nodeType === 1;\n/** An element (or shadow root) followed by every element under it; nothing for text and comment nodes. */\nconst tree = (n: Node): El[] =>\n isEl(n) ? [n, ...n.querySelectorAll<El>('*')] : n instanceof ShadowRoot ? [...n.querySelectorAll<El>('*')] : [];\n\ntype Parsed = { plugin: string; key: string | undefined; mods: Mods };\nconst parsed = new Map<string, Parsed>();\n\n/** 'on:click__debounce.300ms__prevent' \u2192 { plugin: 'on', key: 'click', mods: {debounce: ['300ms'], prevent: []} } */\nexport const parseAttr = (raw: string): Parsed => {\n let p = parsed.get(raw);\n if (!p) {\n const [head, ...modParts] = raw.split('__');\n const i = head.indexOf(':');\n const mods: Mods = new Map();\n for (const m of modParts) {\n const [name, ...args] = m.split('.');\n mods.set(name, args);\n }\n p = { plugin: i < 0 ? head : head.slice(0, i), key: i < 0 ? undefined : head.slice(i + 1), mods };\n parsed.set(raw, p);\n }\n return p;\n};\n\nconst fail = (message: string, info: Record<string, unknown>): Error => Object.assign(new Error(message), { info });\n\n/** Low-level constructor: you supply the expression pipeline. `createSigmx` wraps it with the runtime compiler. */\nexport const createRuntime = (options: RuntimeOptions): Sigmx => {\n const prefixes = ([] as string[]).concat(options.prefix ?? 'data-');\n const eventPrefixes = ([] as string[]).concat(options.eventPrefix ?? 'sigmx-');\n const store = options.store ?? createStore();\n const compiler = options.compile ?? functionCompiler;\n const { expressions } = options;\n const onError = options.onError ?? ((e, info) => console.error(e, info));\n const attributes: Record<string, AttributePlugin> = Object.create(null);\n const actions: Runtime['actions'] = Object.create(null);\n const handlers: Runtime['handlers'] = Object.create(null);\n\n const runtime: Runtime = {\n prefixes,\n attr: (name) => prefixes[0] + name,\n store,\n compiler,\n emit: (type, detail) => document.dispatchEvent(new CustomEvent(`sigmx-${type}`, { detail })),\n call: (name, ctx, args) => {\n const a = actions[name];\n if (!a) throw ctx.error(`unknown action @${name}`);\n return a.call(ctx, ...args);\n },\n eventPrefixes,\n handle: (event, data) => {\n const p = eventPrefixes.find((p) => event.startsWith(p));\n const h = handlers[p ? event.slice(p.length) : event];\n h?.handle(runtime, data);\n return !!h;\n },\n attributes,\n actions,\n handlers,\n };\n\n // element \u2192 attribute name \u2192 dispose\n const mounted = new Map<El, Map<string, () => void>>();\n const roots = new Set<El | ShadowRoot>();\n const ignoreSelf = prefixes.map((p) => `[${p}ignore__self]`).join();\n const ignoreAny = prefixes.map((p) => `[${p}ignore]`).join();\n const ignored = (el: El) => el.matches(ignoreSelf) || !!el.closest(ignoreAny);\n\n const strip = (attr: string): string | undefined => {\n for (const p of prefixes) if (attr.startsWith(p)) return attr.slice(p.length);\n };\n\n const unmount = (els: Iterable<El>): void => {\n for (const el of els) {\n const m = mounted.get(el);\n if (m && mounted.delete(el)) for (const d of m.values()) d();\n }\n };\n\n const unmountAttr = (el: El, attr: string): void => {\n const m = mounted.get(el);\n m?.get(attr)?.();\n m?.delete(attr);\n };\n\n const actionsFor = (\n el: El,\n evt: Event | undefined,\n error: Ctx['error'],\n cleanup: (fn: () => void) => void,\n report: (e: unknown) => void,\n ) => {\n const ctx: ActionCtx = { el, evt, store, runtime, error, cleanup };\n return new Proxy(\n {},\n {\n get:\n (_, name: string) =>\n (...args: any[]) => {\n const r = runtime.call(name, ctx, args);\n // Async actions (requests) reject long after the expression returned; route that to onError.\n if (r instanceof Promise) r.catch(report);\n return r;\n },\n },\n );\n };\n\n const mount = (el: El, attr: string, raw: string, value: string, only?: Set<string>): void => {\n const { plugin: name, key, mods } = parseAttr(raw);\n const plugin = attributes[name];\n if (!plugin || (only && !only.has(name))) return;\n unmountAttr(el, attr);\n\n const disposers: (() => void)[] = [];\n const info = { plugin: name, el, attr };\n const error: Ctx['error'] = (message, extra) => fail(`${prefixes[0]}${name}: ${message}`, { ...info, ...extra });\n const report = (e: unknown) => onError(e, info);\n let fn: Evaluator | undefined;\n const ctx: Ctx = {\n el,\n plugin: name,\n attr,\n key,\n value,\n mods,\n cased: (style = 'camel') => recase(key ?? '', (mods.get('case')?.[0] as CaseStyle) || style),\n evaluate: (evt, ...args) => {\n fn ??= expressions(value, ['el', 'evt', ...(plugin.args ?? [])], plugin.returns ?? true);\n return fn(store, actionsFor(el, evt, error, ctx.cleanup, report), el, evt, ...args);\n },\n effect: (f) => disposers.push(effect(f, report)),\n listen: (target, type, f, opts) => {\n const h = (e: Event) => {\n try {\n f(e);\n } catch (err) {\n report(err);\n }\n };\n target.addEventListener(type, h, opts);\n disposers.push(() => target.removeEventListener(type, h, opts));\n },\n cleanup: (f) => disposers.push(f),\n error,\n store,\n runtime,\n };\n\n let m = mounted.get(el);\n if (!m) {\n m = new Map();\n mounted.set(el, m);\n }\n m.set(attr, () => {\n for (const d of disposers.splice(0)) d();\n });\n\n try {\n if (plugin.key === 'required' && !key) throw error('needs a key');\n if (plugin.key === 'forbidden' && key) throw error('takes no key');\n if (plugin.value === 'required' && !value) throw error('needs a value');\n if (plugin.value === 'forbidden' && value) throw error('takes no value');\n const r = plugin.mount(ctx);\n if (typeof r === 'function') disposers.push(r);\n } catch (e) {\n report(e);\n }\n };\n\n const mountEls = (els: Iterable<El>, only?: Set<string>): void => {\n for (const el of els) {\n if (ignored(el)) continue;\n for (const { name, value } of [...el.attributes]) {\n const raw = strip(name);\n // Observers can report a subtree more than once (nested insertions); a mounted attribute stays as it is.\n if (raw && !mounted.get(el)?.has(name)) mount(el, name, raw, value, only);\n }\n }\n };\n\n const observer = new MutationObserver((records) => {\n for (const { type, target, attributeName, addedNodes, removedNodes } of records) {\n if (type === 'childList') {\n for (const n of removedNodes) unmount(tree(n));\n for (const n of addedNodes) mountEls(tree(n));\n } else if (attributeName && isEl(target) && !ignored(target)) {\n const raw = strip(attributeName);\n if (!raw) continue;\n const value = target.getAttribute(attributeName);\n if (value === null) unmountAttr(target, attributeName);\n else mount(target, attributeName, raw, value);\n }\n }\n });\n\n let ready = false;\n const apply = (root: El | ShadowRoot = document.documentElement, observe = true, only?: Set<string>) => {\n mountEls(tree(root), only);\n if (observe && !roots.has(root)) {\n observer.observe(root, { subtree: true, childList: true, attributes: true });\n roots.add(root);\n }\n if (!ready && roots.has(document.documentElement)) {\n ready = true;\n runtime.emit('ready');\n }\n };\n\n const use = (...plugins: Plugin[]): void => {\n const added = new Set<string>();\n for (const p of plugins) {\n if (p.type === 'attribute') {\n attributes[p.name] = p;\n added.add(p.name);\n } else if (p.type === 'action') actions[p.name] = p;\n else handlers[p.name] = p;\n }\n if (added.size) for (const r of roots) apply(r, false, added);\n };\n\n const stopPatches = store.onPatch((patch) => runtime.emit('signal-patch', patch));\n use(...(options.plugins ?? []));\n\n const sigmx: Sigmx = {\n runtime,\n store,\n get $() {\n return store.$;\n },\n apply: (root, observe) => apply(root, observe),\n use,\n destroy: () => {\n observer.disconnect();\n stopPatches();\n unmount([...mounted.keys()]);\n roots.clear();\n },\n };\n\n if (options.autoStart ?? true) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => sigmx.apply(), { once: true });\n } else {\n sigmx.apply();\n }\n }\n return sigmx;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["p"]
|
|
7
7
|
}
|
package/dist/kernel/scan.d.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import type { Plugin } from './contracts.js';
|
|
2
2
|
export type PluginMeta = {
|
|
3
|
-
/** Export name, e.g. `httpGet`; what the generated module imports. */
|
|
4
3
|
export: string;
|
|
5
|
-
/** Registered name, e.g. `get`; what markup refers to. */
|
|
6
4
|
name: string;
|
|
7
5
|
type: Plugin['type'];
|
|
8
|
-
/** Module to import from; built-ins come from `sigmx/plugins`. */
|
|
9
6
|
from: string;
|
|
10
7
|
returns?: boolean;
|
|
11
8
|
args?: string[];
|
|
12
9
|
};
|
|
13
|
-
/** Plugins that only make sense together. */
|
|
14
10
|
export declare const implied: Record<string, string[]>;
|
|
15
|
-
/** Metadata for every built-in plugin. */
|
|
16
11
|
export declare const builtinPlugins: () => PluginMeta[];
|
|
17
12
|
/**
|
|
18
13
|
* Read a custom plugin's metadata from its source without executing it: finds
|
|
@@ -22,21 +17,17 @@ export declare const customPluginMeta: (exportName: string, source: string, from
|
|
|
22
17
|
/** True if `source` refers to the plugin: `data-<name>` for directives, `@name(` for functions, the name as a string for handlers. */
|
|
23
18
|
export declare const mentions: (source: string, p: PluginMeta, prefixes: string[]) => boolean;
|
|
24
19
|
export type Selection = {
|
|
25
|
-
/** Selected plugins in a stable order. */
|
|
26
20
|
plugins: PluginMeta[];
|
|
27
|
-
/** Why each one is in: 'used', 'always', or the plugin that implied it. */
|
|
28
21
|
reasons: Record<string, string>;
|
|
29
|
-
/** Known plugins that were left out. */
|
|
30
22
|
unused: string[];
|
|
31
23
|
};
|
|
32
24
|
/**
|
|
33
25
|
* Decide which plugins to ship. `sources` are file contents; `custom` are extra plugins (from
|
|
34
26
|
* `customPluginMeta`); `always` are export names that ship regardless.
|
|
35
27
|
*/
|
|
36
|
-
export declare const selectPlugins: (sources: string[], { prefixes, always, custom }?: {
|
|
28
|
+
export declare const selectPlugins: (sources: string[], { prefixes, always, custom, }?: {
|
|
37
29
|
prefixes?: string[];
|
|
38
30
|
always?: string[];
|
|
39
31
|
custom?: PluginMeta[];
|
|
40
32
|
}) => Selection;
|
|
41
|
-
/** JavaScript source for a module exporting `plugins` (and the selection report). */
|
|
42
33
|
export declare const generatePluginsModule: (sel: Selection) => string;
|
package/dist/kernel/scan.js
CHANGED
|
@@ -6,10 +6,20 @@ const implied = {
|
|
|
6
6
|
};
|
|
7
7
|
const builtinPlugins = () => Object.entries(builtins).filter(([, v]) => v && typeof v === "object" && "type" in v).map(([key, v]) => {
|
|
8
8
|
const p = v;
|
|
9
|
-
return {
|
|
9
|
+
return {
|
|
10
|
+
export: key,
|
|
11
|
+
name: p.name,
|
|
12
|
+
type: p.type,
|
|
13
|
+
from: "sigmx/plugins",
|
|
14
|
+
returns: p.returns,
|
|
15
|
+
args: p.args
|
|
16
|
+
};
|
|
10
17
|
});
|
|
11
18
|
const customPluginMeta = (exportName, source, from) => {
|
|
12
|
-
const re = new RegExp(
|
|
19
|
+
const re = new RegExp(
|
|
20
|
+
`export\\s+const\\s+${exportName}\\s*(?::[^=]+)?=\\s*(attribute|action|handler)\\s*\\(\\s*\\{([\\s\\S]*?)\\}\\s*\\)`,
|
|
21
|
+
"m"
|
|
22
|
+
);
|
|
13
23
|
const m = re.exec(source);
|
|
14
24
|
if (!m) return;
|
|
15
25
|
const body = m[2];
|
|
@@ -26,14 +36,19 @@ const customPluginMeta = (exportName, source, from) => {
|
|
|
26
36
|
args: args?.split(",").map((s) => s.trim().replace(/^['"`]|['"`]$/g, "")).filter(Boolean)
|
|
27
37
|
};
|
|
28
38
|
};
|
|
29
|
-
const
|
|
39
|
+
const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
30
40
|
const mentions = (source, p, prefixes) => {
|
|
31
|
-
const n =
|
|
32
|
-
if (p.type === "attribute")
|
|
41
|
+
const n = esc(p.name);
|
|
42
|
+
if (p.type === "attribute")
|
|
43
|
+
return prefixes.some((pre) => new RegExp(`(^|[\\s"'\`<])${esc(pre)}${n}(?=[\\s=:_>"'\`/]|$)`, "m").test(source));
|
|
33
44
|
if (p.type === "action") return new RegExp(`@${n}\\s*\\(`).test(source);
|
|
34
45
|
return new RegExp(`['"\`](?:[\\w-]+-)?${n}['"\`]`).test(source);
|
|
35
46
|
};
|
|
36
|
-
const selectPlugins = (sources, {
|
|
47
|
+
const selectPlugins = (sources, {
|
|
48
|
+
prefixes = ["data-"],
|
|
49
|
+
always = [],
|
|
50
|
+
custom = []
|
|
51
|
+
} = {}) => {
|
|
37
52
|
const known = [...builtinPlugins(), ...custom];
|
|
38
53
|
const byExport = new Map(known.map((p) => [p.export, p]));
|
|
39
54
|
const reasons = {};
|
|
@@ -44,7 +59,9 @@ const selectPlugins = (sources, { prefixes = ["data-"], always = [], custom = []
|
|
|
44
59
|
};
|
|
45
60
|
for (const exp of always) add(exp, "always");
|
|
46
61
|
const text = sources.join("\n");
|
|
47
|
-
for (const p of known)
|
|
62
|
+
for (const p of known)
|
|
63
|
+
if (!reasons[p.export] && (p.type !== "handler" || custom.includes(p)) && mentions(text, p, prefixes))
|
|
64
|
+
add(p.export, "used");
|
|
48
65
|
const plugins = known.filter((p) => reasons[p.export]);
|
|
49
66
|
return { plugins, reasons, unused: known.filter((p) => !reasons[p.export]).map((p) => p.export) };
|
|
50
67
|
};
|
package/dist/kernel/scan.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/scan.ts"],
|
|
4
|
-
"sourcesContent": ["//
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["// Node only; never bundled for the browser.\nimport * as builtins from '../plugins/index.js';\nimport type { Plugin } from './contracts.js';\n\nexport type PluginMeta = {\n export: string;\n name: string;\n type: Plugin['type'];\n from: string;\n returns?: boolean;\n args?: string[];\n};\n\nconst NETWORK = ['httpGet', 'httpPost', 'httpPut', 'httpPatch', 'httpDelete', 'websocket', 'boost'];\n\nexport const implied: Record<string, string[]> = {\n ...Object.fromEntries(NETWORK.map((n) => [n, ['applyElements', 'applyState']])),\n boost: ['httpGet', 'httpPost', 'applyElements', 'applyState'],\n};\n\nexport const builtinPlugins = (): PluginMeta[] =>\n Object.entries(builtins)\n .filter(([, v]) => v && typeof v === 'object' && 'type' in (v as object))\n .map(([key, v]) => {\n const p = v as Plugin;\n return {\n export: key,\n name: p.name,\n type: p.type,\n from: 'sigmx/plugins',\n returns: (p as any).returns,\n args: (p as any).args,\n };\n });\n\n/**\n * Read a custom plugin's metadata from its source without executing it: finds\n * `attribute({ name: 'x', ... })`, `action({...})` or `handler({...})` near `export const <exportName>`.\n */\nexport const customPluginMeta = (exportName: string, source: string, from: string): PluginMeta | undefined => {\n const re = new RegExp(\n `export\\\\s+const\\\\s+${exportName}\\\\s*(?::[^=]+)?=\\\\s*(attribute|action|handler)\\\\s*\\\\(\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*\\\\)`,\n 'm',\n );\n const m = re.exec(source);\n if (!m) return;\n const body = m[2];\n const name = /\\bname\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(body)?.[1];\n if (!name) return;\n const returns = /\\breturns\\s*:\\s*(true|false)/.exec(body)?.[1];\n const args = /\\bargs\\s*:\\s*\\[([^\\]]*)\\]/.exec(body)?.[1];\n return {\n export: exportName,\n name,\n type: m[1] as Plugin['type'],\n from,\n returns: returns === undefined ? undefined : returns === 'true',\n args: args\n ?.split(',')\n .map((s) => s.trim().replace(/^['\"`]|['\"`]$/g, ''))\n .filter(Boolean),\n };\n};\n\nconst esc = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** True if `source` refers to the plugin: `data-<name>` for directives, `@name(` for functions, the name as a string for handlers. */\nexport const mentions = (source: string, p: PluginMeta, prefixes: string[]): boolean => {\n const n = esc(p.name);\n if (p.type === 'attribute')\n return prefixes.some((pre) => new RegExp(`(^|[\\\\s\"'\\`<])${esc(pre)}${n}(?=[\\\\s=:_>\"'\\`/]|$)`, 'm').test(source));\n if (p.type === 'action') return new RegExp(`@${n}\\\\s*\\\\(`).test(source);\n return new RegExp(`['\"\\`](?:[\\\\w-]+-)?${n}['\"\\`]`).test(source);\n};\n\nexport type Selection = {\n plugins: PluginMeta[];\n reasons: Record<string, string>;\n unused: string[];\n};\n\n/**\n * Decide which plugins to ship. `sources` are file contents; `custom` are extra plugins (from\n * `customPluginMeta`); `always` are export names that ship regardless.\n */\nexport const selectPlugins = (\n sources: string[],\n {\n prefixes = ['data-'],\n always = [],\n custom = [],\n }: { prefixes?: string[]; always?: string[]; custom?: PluginMeta[] } = {},\n): Selection => {\n const known = [...builtinPlugins(), ...custom];\n const byExport = new Map(known.map((p) => [p.export, p]));\n const reasons: Record<string, string> = {};\n const add = (exp: string, why: string) => {\n if (!byExport.has(exp) || reasons[exp]) return;\n reasons[exp] = why;\n for (const dep of implied[exp] ?? []) add(dep, exp);\n };\n for (const exp of always) add(exp, 'always');\n const text = sources.join('\\n');\n for (const p of known)\n if (!reasons[p.export] && (p.type !== 'handler' || custom.includes(p)) && mentions(text, p, prefixes))\n add(p.export, 'used');\n const plugins = known.filter((p) => reasons[p.export]);\n return { plugins, reasons, unused: known.filter((p) => !reasons[p.export]).map((p) => p.export) };\n};\n\nexport const generatePluginsModule = (sel: Selection): string => {\n const groups = new Map<string, string[]>();\n for (const p of sel.plugins) groups.set(p.from, [...(groups.get(p.from) ?? []), p.export]);\n const imports = [...groups]\n .map(([from, names]) => `import { ${names.join(', ')} } from ${JSON.stringify(from)}`)\n .join('\\n');\n return `${imports}\\nexport const plugins = [${sel.plugins.map((p) => p.export).join(', ')}]\\nexport const report = ${JSON.stringify({ reasons: sel.reasons, unused: sel.unused }, null, 2)}\\n`;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/kernel/state.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Signal } from './reactive.js';
|
|
2
1
|
import { type Filter } from '../lib/objects.js';
|
|
2
|
+
import { Signal } from './reactive.js';
|
|
3
3
|
export type Patch = Record<string, any>;
|
|
4
4
|
export interface Store {
|
|
5
5
|
/** Value at a dotted path: a leaf value, a namespace proxy, or undefined. Reads subscribe. */
|
|
@@ -13,18 +13,14 @@ export interface Store {
|
|
|
13
13
|
}): void;
|
|
14
14
|
remove(path: string): void;
|
|
15
15
|
has(path: string): boolean;
|
|
16
|
-
/** Install a computed (or any signal) as the leaf at a path. */
|
|
17
16
|
define(path: string, node: Signal<any>): void;
|
|
18
|
-
/** Leaf paths, optionally filtered. */
|
|
19
17
|
paths(filter?: Filter): string[];
|
|
20
|
-
/** Plain-object copy of the store or a namespace. */
|
|
21
18
|
snapshot(filter?: Filter, options?: {
|
|
22
19
|
at?: string;
|
|
23
20
|
computed?: boolean;
|
|
24
21
|
}): Patch;
|
|
25
22
|
/** Called after each settled batch with the nested object of changed paths (null = removed). */
|
|
26
23
|
onPatch(fn: (patch: Patch) => void): () => void;
|
|
27
|
-
/** Root namespace proxy: `$.count`, `$.user.name = 'x'`, `JSON.stringify($)`. */
|
|
28
24
|
readonly $: any;
|
|
29
25
|
/** Identifier scope for compiled expressions: resolves `$count`, `$user`, and `$`. */
|
|
30
26
|
readonly scope: object;
|
package/dist/kernel/state.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Computed, Signal, batch, onSettled } from "./reactive.js";
|
|
2
1
|
import { expand, isPlain, toPredicate } from "../lib/objects.js";
|
|
2
|
+
import { batch, Computed, onSettled, Signal } from "./reactive.js";
|
|
3
3
|
const parentOf = (p) => p.slice(0, Math.max(0, p.lastIndexOf(".")));
|
|
4
4
|
const nameOf = (p) => p.slice(p.lastIndexOf(".") + 1);
|
|
5
5
|
const join = (a, b) => a ? `${a}.${b}` : b;
|
|
@@ -17,7 +17,8 @@ const createStore = () => {
|
|
|
17
17
|
let set2 = kids.get(p);
|
|
18
18
|
if (!set2) {
|
|
19
19
|
if (leaves.has(p)) dropLeaf(p);
|
|
20
|
-
|
|
20
|
+
set2 = /* @__PURE__ */ new Set();
|
|
21
|
+
kids.set(p, set2);
|
|
21
22
|
ensureNs(parentOf(p)).add(nameOf(p));
|
|
22
23
|
shape.bump();
|
|
23
24
|
}
|
|
@@ -97,8 +98,16 @@ const createStore = () => {
|
|
|
97
98
|
s.bump();
|
|
98
99
|
};
|
|
99
100
|
px = new Proxy(raw, {
|
|
100
|
-
set: (t, k, v) =>
|
|
101
|
-
|
|
101
|
+
set: (t, k, v) => {
|
|
102
|
+
t[k] = v;
|
|
103
|
+
touch();
|
|
104
|
+
return true;
|
|
105
|
+
},
|
|
106
|
+
deleteProperty: (t, k) => {
|
|
107
|
+
delete t[k];
|
|
108
|
+
touch();
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
102
111
|
});
|
|
103
112
|
arrCache.set(raw, px);
|
|
104
113
|
}
|
|
@@ -117,27 +126,42 @@ const createStore = () => {
|
|
|
117
126
|
const ns = (p) => {
|
|
118
127
|
let px = nsCache.get(p);
|
|
119
128
|
if (!px) {
|
|
120
|
-
const names = () =>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
const names = () => {
|
|
130
|
+
shape.value;
|
|
131
|
+
return kids.get(p);
|
|
132
|
+
};
|
|
133
|
+
px = new Proxy(
|
|
134
|
+
{},
|
|
135
|
+
{
|
|
136
|
+
get: (_, k) => !str(k) ? void 0 : k === "toJSON" ? () => snapshot(void 0, { at: p }) : get(join(p, k)),
|
|
137
|
+
set: (_, k, v) => {
|
|
138
|
+
if (str(k)) set(join(p, k), v);
|
|
139
|
+
return true;
|
|
140
|
+
},
|
|
141
|
+
deleteProperty: (_, k) => {
|
|
142
|
+
if (str(k)) remove(join(p, k));
|
|
143
|
+
return true;
|
|
144
|
+
},
|
|
145
|
+
has: (_, k) => str(k) && !!names()?.has(k),
|
|
146
|
+
ownKeys: () => [...names() ?? []],
|
|
147
|
+
getOwnPropertyDescriptor: (_, k) => str(k) && names()?.has(k) ? { enumerable: true, configurable: true, writable: true, value: get(join(p, k)) } : void 0
|
|
148
|
+
}
|
|
149
|
+
);
|
|
129
150
|
nsCache.set(p, px);
|
|
130
151
|
}
|
|
131
152
|
return px;
|
|
132
153
|
};
|
|
133
|
-
const scope = new Proxy(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
154
|
+
const scope = new Proxy(
|
|
155
|
+
{},
|
|
156
|
+
{
|
|
157
|
+
has: (_, k) => str(k) && k[0] === "$",
|
|
158
|
+
get: (_, k) => !str(k) ? void 0 : k === "$" ? ns("") : get(k.slice(1)),
|
|
159
|
+
set: (_, k, v) => {
|
|
160
|
+
if (str(k)) k === "$" ? merge(v) : set(k.slice(1), v);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
139
163
|
}
|
|
140
|
-
|
|
164
|
+
);
|
|
141
165
|
const paths = (filter) => {
|
|
142
166
|
shape.value;
|
|
143
167
|
const ok = toPredicate(filter);
|
|
@@ -153,7 +177,7 @@ const createStore = () => {
|
|
|
153
177
|
expand(out, rel(p), s.value);
|
|
154
178
|
}
|
|
155
179
|
for (const p of kids.keys()) {
|
|
156
|
-
if (p && p !== at && under(p, at) && ok(p) && !kids.get(p)
|
|
180
|
+
if (p && p !== at && under(p, at) && ok(p) && !kids.get(p)?.size) expand(out, rel(p), {});
|
|
157
181
|
}
|
|
158
182
|
return out;
|
|
159
183
|
};
|
|
@@ -173,7 +197,10 @@ const createStore = () => {
|
|
|
173
197
|
define,
|
|
174
198
|
paths,
|
|
175
199
|
snapshot,
|
|
176
|
-
onPatch: (fn) =>
|
|
200
|
+
onPatch: (fn) => {
|
|
201
|
+
listeners.add(fn);
|
|
202
|
+
return () => listeners.delete(fn);
|
|
203
|
+
},
|
|
177
204
|
get $() {
|
|
178
205
|
return ns("");
|
|
179
206
|
},
|