@ng-org/alien-deepsignals 0.1.2-alpha.5 → 0.1.2-alpha.7

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.
Files changed (62) hide show
  1. package/README.md +55 -374
  2. package/dist/core.d.ts +66 -60
  3. package/dist/core.d.ts.map +1 -1
  4. package/dist/core.js +70 -82
  5. package/dist/deepSignal.d.ts +19 -5
  6. package/dist/deepSignal.d.ts.map +1 -1
  7. package/dist/deepSignal.js +214 -141
  8. package/dist/effect.d.ts.map +1 -1
  9. package/dist/effect.js +8 -1
  10. package/dist/hooks/react/useDeepSignal.d.ts +1 -1
  11. package/dist/hooks/react/useDeepSignal.d.ts.map +1 -1
  12. package/dist/hooks/react/useDeepSignal.js +5 -2
  13. package/dist/hooks/svelte/index.d.ts +0 -1
  14. package/dist/hooks/svelte/index.d.ts.map +1 -1
  15. package/dist/hooks/svelte/useDeepSignal.svelte.d.ts +3 -15
  16. package/dist/hooks/svelte/useDeepSignal.svelte.d.ts.map +1 -1
  17. package/dist/hooks/svelte/useDeepSignal.svelte.js +29 -63
  18. package/dist/hooks/svelte4/index.d.ts +4 -0
  19. package/dist/hooks/svelte4/index.d.ts.map +1 -0
  20. package/dist/hooks/svelte4/index.js +8 -0
  21. package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts +27 -0
  22. package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts.map +1 -0
  23. package/dist/hooks/svelte4/useDeepSignal.svelte.js +91 -0
  24. package/dist/hooks/vue/useDeepSignal.d.ts +2 -2
  25. package/dist/hooks/vue/useDeepSignal.d.ts.map +1 -1
  26. package/dist/hooks/vue/useDeepSignal.js +22 -74
  27. package/dist/index.d.ts +1 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +8 -2
  30. package/dist/test/frontend/astro-app/src/components/ReactPanel.d.ts.map +1 -1
  31. package/dist/test/frontend/astro-app/src/components/{ReactPanel.js → ReactPanel.jsx} +56 -45
  32. package/dist/test/frontend/playwright/crossFrameworkHooks.spec.js +13 -3
  33. package/dist/test/frontend/utils/mockData.d.ts.map +1 -1
  34. package/dist/test/frontend/utils/mockData.js +13 -4
  35. package/dist/test/lib/index.test.js +16 -3
  36. package/dist/test/lib/misc.test.js +104 -1
  37. package/dist/test/lib/watch.test.js +2 -11
  38. package/dist/types.d.ts +94 -19
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/types.js +9 -0
  41. package/dist/watch.d.ts +37 -0
  42. package/dist/watch.d.ts.map +1 -1
  43. package/dist/watch.js +35 -0
  44. package/package.json +8 -5
  45. package/dist/test/frontend/astro-app/src/components/PerfSuiteClient.d.ts +0 -4
  46. package/dist/test/frontend/astro-app/src/components/PerfSuiteClient.d.ts.map +0 -1
  47. package/dist/test/frontend/astro-app/src/components/PerfSuiteClient.js +0 -225
  48. package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfDeep.d.ts +0 -4
  49. package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfDeep.d.ts.map +0 -1
  50. package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfDeep.js +0 -150
  51. package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfNative.d.ts +0 -4
  52. package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfNative.d.ts.map +0 -1
  53. package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfNative.js +0 -184
  54. package/dist/test/frontend/playwright/perfSuite.spec.d.ts +0 -2
  55. package/dist/test/frontend/playwright/perfSuite.spec.d.ts.map +0 -1
  56. package/dist/test/frontend/playwright/perfSuite.spec.js +0 -128
  57. package/dist/test/frontend/utils/perfScenarios.d.ts +0 -15
  58. package/dist/test/frontend/utils/perfScenarios.d.ts.map +0 -1
  59. package/dist/test/frontend/utils/perfScenarios.js +0 -287
  60. package/dist/test/lib/core.test.d.ts +0 -2
  61. package/dist/test/lib/core.test.d.ts.map +0 -1
  62. package/dist/test/lib/core.test.js +0 -53
package/dist/effect.js CHANGED
@@ -1,5 +1,12 @@
1
1
  "use strict";
2
2
  // Copyright (c) 2025 Laurin Weger, Par le Peuple, NextGraph.org developers
3
+ // All rights reserved.
4
+ // Licensed under the Apache License, Version 2.0
5
+ // <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
6
+ // or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
7
+ // at your option. All files in the project carrying such
8
+ // notice may not be copied, modified, or distributed except
9
+ // according to those terms.
3
10
  // SPDX-License-Identifier: Apache-2.0 OR MIT
4
11
  Object.defineProperty(exports, "__esModule", { value: true });
5
12
  exports.effect = effect;
@@ -10,7 +17,7 @@ function effect(run) {
10
17
  const registerCleanup = (fn) => {
11
18
  cleanup = fn;
12
19
  };
13
- const stop = (0, core_1._rawEffect)(() => {
20
+ const stop = (0, core_1.alienEffect)(() => {
14
21
  if (cleanup) {
15
22
  try {
16
23
  cleanup();
@@ -6,7 +6,7 @@ import { DeepSignalOptions } from "../..";
6
6
  * is rerendered as well.
7
7
  *
8
8
  * @param object The object that should become reactive
9
- * @param deepSignalOptions When the object is not a deepSignal already, options passed to `deepSignal`.
9
+ * @param options When the object is not a deepSignal already, options passed to {@link deepSignal}.
10
10
  * @returns The deepSignal object of the object param. On every change, the returned object will change (a new no-op proxy is created) around the deepSignal object.
11
11
  */
12
12
  declare const useSignal: <T extends object>(object: T, deepSignalOptions?: DeepSignalOptions) => import("../..").DeepSignal<T>;
@@ -1 +1 @@
1
- {"version":3,"file":"useDeepSignal.d.ts","sourceRoot":"","sources":["../../../src/hooks/react/useDeepSignal.ts"],"names":[],"mappings":"AAYA,OAAO,EAAc,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAEtD;;;;;;;;;GASG;AACH,QAAA,MAAM,SAAS,GAAI,CAAC,SAAS,MAAM,EAC/B,QAAQ,CAAC,EACT,oBAAoB,iBAAiB,kCAqCxC,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"useDeepSignal.d.ts","sourceRoot":"","sources":["../../../src/hooks/react/useDeepSignal.ts"],"names":[],"mappings":"AAYA,OAAO,EAAc,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAEtD;;;;;;;;;GASG;AACH,QAAA,MAAM,SAAS,GAAI,CAAC,SAAS,MAAM,EAC/B,QAAQ,CAAC,EACT,oBAAoB,iBAAiB,kCAyCxC,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -19,12 +19,15 @@ const __1 = require("../..");
19
19
  * is rerendered as well.
20
20
  *
21
21
  * @param object The object that should become reactive
22
- * @param deepSignalOptions When the object is not a deepSignal already, options passed to `deepSignal`.
22
+ * @param options When the object is not a deepSignal already, options passed to {@link deepSignal}.
23
23
  * @returns The deepSignal object of the object param. On every change, the returned object will change (a new no-op proxy is created) around the deepSignal object.
24
24
  */
25
25
  const useSignal = (object, deepSignalOptions) => {
26
26
  // Create the actual deepSignal object from the raw object (if the object is a deepSignal object already, it returns itself).
27
- const signal = (0, react_1.useMemo)(() => (0, __1.deepSignal)(object, deepSignalOptions), [object, deepSignalOptions]);
27
+ const signal = (0, react_1.useMemo)(() => (0, __1.deepSignal)(object, {
28
+ replaceProxiesInBranchOnChange: true, // Set so that react can detect change in object hierarchy by equality comparison.
29
+ ...deepSignalOptions,
30
+ }), [object, deepSignalOptions]);
28
31
  // Create a shallow proxy of the original object which can be disposed and a new one
29
32
  // recreated on rerenders so that react knows it changed on comparisons.
30
33
  const proxyRef = (0, react_1.useRef)(new Proxy(signal, {}));
@@ -1,4 +1,3 @@
1
1
  import useDeepSignal from "./useDeepSignal.svelte.js";
2
2
  export { useDeepSignal };
3
- export type { UseDeepSignalResult } from "./useDeepSignal.svelte.js";
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -1,16 +1,4 @@
1
- import { type Readable } from "svelte/store";
2
- import { DeepSignalOptions, RevertDeepSignal } from "../../index";
3
- /** Base result contract for a deepSignal-backed Svelte integration. */
4
- export interface UseDeepSignalResult<T> extends Readable<T> {
5
- /** Derive a nested selection; re-runs when the underlying tree version increments. */
6
- select<U>(selector: (tree: T) => U): Readable<U>;
7
- /** Stop receiving further updates (invoked automatically on component destroy). */
8
- dispose(): void;
9
- /** Replace root shape contents (mutative merge) – enables Svelte writable store binding semantics. */
10
- set(next: Partial<T> | T): void;
11
- /** Functional update helper using current tree snapshot. */
12
- update(updater: (current: T) => T | void): void;
13
- }
1
+ import { DeepSignalOptions, DeepSignal } from "../../index";
14
2
  /**
15
3
  * Create a rune from a deepSignal object (creates one if it is just a regular object).
16
4
  *
@@ -19,9 +7,9 @@ export interface UseDeepSignalResult<T> extends Readable<T> {
19
7
  * is rerendered as well.
20
8
  *
21
9
  * @param object The object that should become reactive
22
- * @param deepSignalObjects When the object is not a deepSignal already, options passed to `deepSignal`.
10
+ * @param options Options passed to {@link deepSignal}.
23
11
  * @returns A rune for using the deepSignal object in svelte.
24
12
  */
25
- export declare function useDeepSignal<T extends object>(object: T | Promise<T>, options?: DeepSignalOptions): UseDeepSignalResult<RevertDeepSignal<T>>;
13
+ export declare function useDeepSignal<T extends object>(object: T, options?: DeepSignalOptions): T extends DeepSignal<any> ? T : DeepSignal<T>;
26
14
  export default useDeepSignal;
27
15
  //# sourceMappingURL=useDeepSignal.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDeepSignal.svelte.d.ts","sourceRoot":"","sources":["../../../src/hooks/svelte/useDeepSignal.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAIH,iBAAiB,EAEjB,gBAAgB,EAEnB,MAAM,aAAa,CAAC;AAErB,uEAAuE;AACvE,MAAM,WAAW,mBAAmB,CAAC,CAAC,CAAE,SAAQ,QAAQ,CAAC,CAAC,CAAC;IACvD,sFAAsF;IACtF,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACjD,mFAAmF;IACnF,OAAO,IAAI,IAAI,CAAC;IAChB,sGAAsG;IACtG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAChC,4DAA4D;IAC5D,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;CACnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC1C,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC5B,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAkE1C;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"useDeepSignal.svelte.d.ts","sourceRoot":"","sources":["../../../src/hooks/svelte/useDeepSignal.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,iBAAiB,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AAExE;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC1C,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,iBAAiB,GAab,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAC9D;AAyBD,eAAe,aAAa,CAAC"}
@@ -10,8 +10,7 @@
10
10
  // SPDX-License-Identifier: Apache-2.0 OR MIT
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.useDeepSignal = useDeepSignal;
13
- const store_1 = require("svelte/store");
14
- const svelte_1 = require("svelte");
13
+ const reactivity_1 = require("svelte/reactivity");
15
14
  const index_1 = require("../../index");
16
15
  /**
17
16
  * Create a rune from a deepSignal object (creates one if it is just a regular object).
@@ -21,70 +20,37 @@ const index_1 = require("../../index");
21
20
  * is rerendered as well.
22
21
  *
23
22
  * @param object The object that should become reactive
24
- * @param deepSignalObjects When the object is not a deepSignal already, options passed to `deepSignal`.
23
+ * @param options Options passed to {@link deepSignal}.
25
24
  * @returns A rune for using the deepSignal object in svelte.
26
25
  */
27
26
  function useDeepSignal(object, options) {
28
- const version = (0, store_1.writable)(-1);
29
- let deepProxy;
30
- let unsubscribe;
31
- let isDestroyed = false;
32
- const init = (obj) => {
33
- if (isDestroyed)
34
- return;
35
- deepProxy = (0, index_1.deepSignal)(obj, options);
36
- const rootId = (0, index_1.getDeepSignalRootId)(deepProxy);
37
- const initialVersion = (0, index_1.getDeepSignalVersion)(deepProxy) ?? 0;
38
- unsubscribe = (0, index_1.subscribeDeepMutations)(deepProxy, (batch) => {
39
- if (!rootId)
40
- return;
41
- if (batch.patches.length) {
42
- version.set(batch.version);
43
- }
44
- });
45
- version.set(initialVersion);
46
- };
47
- if (object instanceof Promise) {
48
- object.then(init);
49
- }
50
- else {
51
- init(object);
52
- }
53
- const dispose = () => {
54
- isDestroyed = true;
55
- if (unsubscribe)
56
- unsubscribe();
57
- };
58
- (0, svelte_1.onDestroy)(dispose);
59
- const deep = (0, store_1.derived)(version, () => deepProxy);
60
- const select = (selector) => (0, store_1.derived)(deep, (t) => (t ? selector(t) : undefined));
61
- // Expose Svelte store contract by delegating subscribe to deep store.
62
- const applyReplacement = (next) => {
63
- if (!deepProxy || !next || typeof next !== "object")
64
- return;
65
- // Remove keys absent in next
66
- for (const k of Object.keys(deepProxy)) {
67
- if (!(k in next))
68
- delete deepProxy[k];
69
- }
70
- // Assign / overwrite provided keys
71
- Object.assign(deepProxy, next);
27
+ const ret = (0, index_1.deepSignal)(object, {
28
+ ...options,
29
+ subscriberFactories: (options?.subscriberFactories ?? new Set()).union(new Set([subscriberFactory])),
30
+ });
31
+ // onDestroy(() => {
32
+ // // TODO: Tell signal that subscriber can be removed?
33
+ // });
34
+ return ret;
35
+ }
36
+ /**
37
+ * Calls Svelte's `createSubscriber` and wraps it for compatibility with
38
+ * deepSignal's external subscriber format.
39
+ * @returns
40
+ */
41
+ const subscriberFactory = () => {
42
+ let setter;
43
+ let onSet = () => {
44
+ setter?.();
72
45
  };
73
- const store = {
74
- select,
75
- dispose,
76
- subscribe: deep.subscribe,
77
- set(next) {
78
- applyReplacement(next);
79
- },
80
- update(updater) {
81
- if (!deepProxy)
82
- return;
83
- const result = updater(deepProxy);
84
- if (result && typeof result === "object")
85
- applyReplacement(result);
86
- },
46
+ const onGet = (0, reactivity_1.createSubscriber)((update) => {
47
+ setter = () => {
48
+ update();
49
+ };
50
+ });
51
+ return {
52
+ onGet,
53
+ onSet,
87
54
  };
88
- return store;
89
- }
55
+ };
90
56
  exports.default = useDeepSignal;
@@ -0,0 +1,4 @@
1
+ import useDeepSignal from "./useDeepSignal.svelte.js";
2
+ export { useDeepSignal };
3
+ export type { UseDeepSignalResult } from "./useDeepSignal.svelte.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/svelte4/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useDeepSignal = void 0;
7
+ const useDeepSignal_svelte_js_1 = __importDefault(require("./useDeepSignal.svelte.js"));
8
+ exports.useDeepSignal = useDeepSignal_svelte_js_1.default;
@@ -0,0 +1,27 @@
1
+ import { type Readable } from "svelte/store";
2
+ import { DeepSignalOptions, UnwrapDeepSignal } from "../../index";
3
+ /** Base result contract for a deepSignal-backed Svelte integration. */
4
+ export interface UseDeepSignalResult<T> extends Readable<T> {
5
+ /** Derive a nested selection; re-runs when the underlying tree version increments. */
6
+ select<U>(selector: (tree: T) => U): Readable<U>;
7
+ /** Stop receiving further updates (invoked automatically on component destroy). */
8
+ dispose(): void;
9
+ /** Replace root shape contents (mutative merge) – enables Svelte writable store binding semantics. */
10
+ set(next: Partial<T> | T): void;
11
+ /** Functional update helper using current tree snapshot. */
12
+ update(updater: (current: T) => T | void): void;
13
+ }
14
+ /**
15
+ * Create a store from a deepSignal object (creates one if it is just a regular object).
16
+ *
17
+ * Modifications to the returned deepSignal object cause an immediate rerender.
18
+ * If modifications of the object are made from somewhere else, the component
19
+ * is rerendered as well.
20
+ *
21
+ * @param object The object that should become reactive
22
+ * @param options Options passed to {@link deepSignal}.
23
+ * @returns A store for using the deepSignal object in svelte.
24
+ */
25
+ export declare function useDeepSignal<T extends object>(object: T | Promise<T>, options?: DeepSignalOptions): UseDeepSignalResult<UnwrapDeepSignal<T>>;
26
+ export default useDeepSignal;
27
+ //# sourceMappingURL=useDeepSignal.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeepSignal.svelte.d.ts","sourceRoot":"","sources":["../../../src/hooks/svelte4/useDeepSignal.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAGH,iBAAiB,EAEjB,gBAAgB,EACnB,MAAM,aAAa,CAAC;AAGrB,uEAAuE;AACvE,MAAM,WAAW,mBAAmB,CAAC,CAAC,CAAE,SAAQ,QAAQ,CAAC,CAAC,CAAC;IACvD,sFAAsF;IACtF,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACjD,mFAAmF;IACnF,OAAO,IAAI,IAAI,CAAC;IAChB,sGAAsG;IACtG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAChC,4DAA4D;IAC5D,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;CACnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC1C,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC5B,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAkE1C;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ // Copyright (c) 2025 Laurin Weger, Par le Peuple, NextGraph.org developers
3
+ // All rights reserved.
4
+ // Licensed under the Apache License, Version 2.0
5
+ // <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
6
+ // or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
7
+ // at your option. All files in the project carrying such
8
+ // notice may not be copied, modified, or distributed except
9
+ // according to those terms.
10
+ // SPDX-License-Identifier: Apache-2.0 OR MIT
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.useDeepSignal = useDeepSignal;
13
+ const store_1 = require("svelte/store");
14
+ const svelte_1 = require("svelte");
15
+ const index_1 = require("../../index");
16
+ const deepSignal_1 = require("../../deepSignal");
17
+ /**
18
+ * Create a store from a deepSignal object (creates one if it is just a regular object).
19
+ *
20
+ * Modifications to the returned deepSignal object cause an immediate rerender.
21
+ * If modifications of the object are made from somewhere else, the component
22
+ * is rerendered as well.
23
+ *
24
+ * @param object The object that should become reactive
25
+ * @param options Options passed to {@link deepSignal}.
26
+ * @returns A store for using the deepSignal object in svelte.
27
+ */
28
+ function useDeepSignal(object, options) {
29
+ const version = (0, store_1.writable)(-1);
30
+ let deepProxy;
31
+ let unsubscribe;
32
+ let isDestroyed = false;
33
+ const init = (obj) => {
34
+ if (isDestroyed)
35
+ return;
36
+ deepProxy = (0, index_1.deepSignal)(obj, options);
37
+ const rootId = (0, deepSignal_1.getDeepSignalRootId)(deepProxy);
38
+ const initialVersion = (0, deepSignal_1.getDeepSignalVersion)(deepProxy) ?? 0;
39
+ unsubscribe = (0, index_1.subscribeDeepMutations)(deepProxy, (batch) => {
40
+ if (!rootId)
41
+ return;
42
+ if (batch.patches.length) {
43
+ version.set(batch.version);
44
+ }
45
+ });
46
+ version.set(initialVersion);
47
+ };
48
+ if (object instanceof Promise) {
49
+ object.then(init);
50
+ }
51
+ else {
52
+ init(object);
53
+ }
54
+ const dispose = () => {
55
+ isDestroyed = true;
56
+ if (unsubscribe)
57
+ unsubscribe();
58
+ };
59
+ (0, svelte_1.onDestroy)(dispose);
60
+ const deep = (0, store_1.derived)(version, () => deepProxy);
61
+ const select = (selector) => (0, store_1.derived)(deep, (t) => (t ? selector(t) : undefined));
62
+ // Expose Svelte store contract by delegating subscribe to deep store.
63
+ const applyReplacement = (next) => {
64
+ if (!deepProxy || !next || typeof next !== "object")
65
+ return;
66
+ // Remove keys absent in next
67
+ for (const k of Object.keys(deepProxy)) {
68
+ if (!(k in next))
69
+ delete deepProxy[k];
70
+ }
71
+ // Assign / overwrite provided keys
72
+ Object.assign(deepProxy, next);
73
+ };
74
+ const store = {
75
+ select,
76
+ dispose,
77
+ subscribe: deep.subscribe,
78
+ set(next) {
79
+ applyReplacement(next);
80
+ },
81
+ update(updater) {
82
+ if (!deepProxy)
83
+ return;
84
+ const result = updater(deepProxy);
85
+ if (result && typeof result === "object")
86
+ applyReplacement(result);
87
+ },
88
+ };
89
+ return store;
90
+ }
91
+ exports.default = useDeepSignal;
@@ -1,13 +1,13 @@
1
1
  import { type MaybeRefOrGetter } from "vue";
2
2
  import { DeepSignal, DeepSignalOptions } from "../../";
3
3
  /**
4
- * Create or use an existing deepSignal object in your component.
4
+ * Create or use an existing (child) deepSignal object in your component.
5
5
  * Modifications to the returned deepSignal object cause an immediate rerender.
6
6
  * If modifications of the object are made from somewhere else, the component
7
7
  * is rerendered as well.
8
8
  *
9
9
  * @param object The object that should become reactive (can be a ref or getter)
10
- * @param options When the object is not a deepSignal already, options passed to `deepSignal`.
10
+ * @param options Options passed to {@link deepSignal}.
11
11
  * @returns The deepSignal object of the object param.
12
12
  *
13
13
  */
@@ -1 +1 @@
1
- {"version":3,"file":"useDeepSignal.d.ts","sourceRoot":"","sources":["../../../src/hooks/vue/useDeepSignal.ts"],"names":[],"mappings":"AAUA,OAAO,EAGH,KAAK,gBAAgB,EAGxB,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,UAAU,EAAc,iBAAiB,EAAS,MAAM,QAAQ,CAAC;AAE1E;;;;;;;;;;GAUG;AAEH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC1C,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC3B,OAAO,CAAC,EAAE,iBAAiB,GAC5B,UAAU,CAAC,CAAC,CAAC,CAkFf;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"useDeepSignal.d.ts","sourceRoot":"","sources":["../../../src/hooks/vue/useDeepSignal.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,KAAK,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAc,iBAAiB,EAAS,MAAM,QAAQ,CAAC;AAE1E;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC1C,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC3B,OAAO,CAAC,EAAE,iBAAiB,GAC5B,UAAU,CAAC,CAAC,CAAC,CAaf;AAkBD,eAAe,aAAa,CAAC"}
@@ -13,89 +13,37 @@ exports.useDeepSignal = useDeepSignal;
13
13
  const vue_1 = require("vue");
14
14
  const __1 = require("../../");
15
15
  /**
16
- * Create or use an existing deepSignal object in your component.
16
+ * Create or use an existing (child) deepSignal object in your component.
17
17
  * Modifications to the returned deepSignal object cause an immediate rerender.
18
18
  * If modifications of the object are made from somewhere else, the component
19
19
  * is rerendered as well.
20
20
  *
21
21
  * @param object The object that should become reactive (can be a ref or getter)
22
- * @param options When the object is not a deepSignal already, options passed to `deepSignal`.
22
+ * @param options Options passed to {@link deepSignal}.
23
23
  * @returns The deepSignal object of the object param.
24
24
  *
25
25
  */
26
- // Note partly written with the help of Gemini 3.
27
26
  function useDeepSignal(object, options) {
28
- const version = (0, vue_1.ref)(0);
29
- // Holds the current reactive signal object.
30
- let currentSignal;
31
- let stopHandle;
32
- // Watch the input object for changes.
33
- const stopWatchingSource = (0, vue_1.watch)(() => (0, vue_1.toValue)(object), (newObj) => {
34
- if (stopHandle) {
35
- stopHandle.stopListening();
36
- stopHandle = undefined;
37
- }
38
- if (newObj) {
39
- currentSignal = (0, __1.deepSignal)(newObj, options);
40
- stopHandle = (0, __1.watch)(currentSignal, ({ patches }) => {
41
- if (patches.length > 0)
42
- version.value++;
43
- });
44
- }
45
- // Trigger Vue update.
46
- version.value++;
47
- }, { immediate: true });
48
- // Determines the initial target for the Proxy (array vs object).
49
- const initialVal = (0, vue_1.toValue)(object);
50
- const proxyTarget = (Array.isArray(initialVal) ? [] : {});
51
- // Proxy that creates Vue dependency on version for any access.
52
- const proxy = new Proxy(proxyTarget, {
53
- get(target, key) {
54
- if (key === "__raw")
55
- return currentSignal;
56
- // Track version to create reactive dependency.
57
- version.value;
58
- // Delegate to current signal.
59
- const actualTarget = currentSignal || target;
60
- const value = Reflect.get(actualTarget, key);
61
- // Bind methods to maintain correct `this` context.
62
- return typeof value === "function"
63
- ? value.bind(actualTarget)
64
- : value;
65
- },
66
- set(target, key, value) {
67
- // Delegate to current signal.
68
- const actualTarget = currentSignal || target;
69
- return Reflect.set(actualTarget, key, value);
70
- },
71
- has(target, key) {
72
- version.value;
73
- const actualTarget = currentSignal || target;
74
- return Reflect.has(actualTarget, key);
75
- },
76
- ownKeys(target) {
77
- version.value;
78
- const actualTarget = currentSignal || target;
79
- return Reflect.ownKeys(actualTarget);
80
- },
81
- getOwnPropertyDescriptor(target, key) {
82
- version.value;
83
- const actualTarget = currentSignal || target;
84
- const desc = Reflect.getOwnPropertyDescriptor(actualTarget, key);
85
- return desc ? { ...desc, configurable: true } : undefined;
86
- },
27
+ const deepProxy = (0, __1.deepSignal)((0, vue_1.toValue)(object), {
28
+ ...options,
29
+ subscriberFactories: (options?.subscriberFactories ?? new Set()).union(new Set([subscriberFactory])),
87
30
  });
88
- (0, vue_1.onBeforeUnmount)(() => {
89
- stopWatchingSource();
90
- if (stopHandle) {
91
- try {
92
- stopHandle.stopListening();
93
- }
94
- catch {
95
- // ignore
96
- }
97
- }
98
- });
99
- return proxy;
31
+ // onBeforeUnmount(() => {
32
+ // // TODO: Tell signal that subscriber can be removed?
33
+ // });
34
+ return deepProxy;
100
35
  }
36
+ /** Calls Vue's customRef for notifications of value changes. */
37
+ const subscriberFactory = () => {
38
+ let onGet;
39
+ let onSet;
40
+ // We don't use the actually returned value of the get/set.
41
+ // We only need it to notify Vue, since Dep is not exposed directly.
42
+ (0, vue_1.customRef)((track, trigger) => {
43
+ onGet = track;
44
+ onSet = trigger;
45
+ return { get() { }, set() { } };
46
+ });
47
+ return { onGet: onGet, onSet: onSet };
48
+ };
101
49
  exports.default = useDeepSignal;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- export * from "./deepSignal";
1
+ export { addWithId, deepSignal, getRaw, isDeepSignal, shallow, subscribeDeepMutations, } from "./deepSignal";
2
2
  export * from "./core";
3
3
  export * from "./watch";
4
- export * from "./effect";
5
4
  export * from "./types";
6
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,SAAS,EACT,UAAU,EACV,MAAM,EACN,YAAY,EACZ,OAAO,EACP,sBAAsB,GACzB,MAAM,cAAc,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -14,8 +14,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./deepSignal"), exports);
17
+ exports.subscribeDeepMutations = exports.shallow = exports.isDeepSignal = exports.getRaw = exports.deepSignal = exports.addWithId = void 0;
18
+ var deepSignal_1 = require("./deepSignal");
19
+ Object.defineProperty(exports, "addWithId", { enumerable: true, get: function () { return deepSignal_1.addWithId; } });
20
+ Object.defineProperty(exports, "deepSignal", { enumerable: true, get: function () { return deepSignal_1.deepSignal; } });
21
+ Object.defineProperty(exports, "getRaw", { enumerable: true, get: function () { return deepSignal_1.getRaw; } });
22
+ Object.defineProperty(exports, "isDeepSignal", { enumerable: true, get: function () { return deepSignal_1.isDeepSignal; } });
23
+ Object.defineProperty(exports, "shallow", { enumerable: true, get: function () { return deepSignal_1.shallow; } });
24
+ Object.defineProperty(exports, "subscribeDeepMutations", { enumerable: true, get: function () { return deepSignal_1.subscribeDeepMutations; } });
18
25
  __exportStar(require("./core"), exports);
19
26
  __exportStar(require("./watch"), exports);
20
- __exportStar(require("./effect"), exports);
21
27
  __exportStar(require("./types"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"ReactPanel.d.ts","sourceRoot":"","sources":["../../../../../../src/test/frontend/astro-app/src/components/ReactPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAMjD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAqSvB,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ReactPanel.d.ts","sourceRoot":"","sources":["../../../../../../src/test/frontend/astro-app/src/components/ReactPanel.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAM1D,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EA6LvB,CAAC;AAwGF,eAAe,UAAU,CAAC"}