@praxisjs/store 0.2.3 → 1.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # @praxisjs/store
2
2
 
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 029ef04: `$patch` now skips `undefined` values, preventing partial updates from overwriting existing state with `undefined`.
8
+ - Updated dependencies [029ef04]
9
+ - Updated dependencies [029ef04]
10
+ - Updated dependencies [029ef04]
11
+ - Updated dependencies [029ef04]
12
+ - Updated dependencies [029ef04]
13
+ - @praxisjs/core@1.1.0
14
+ - @praxisjs/decorators@0.6.0
15
+
16
+ ## 1.0.0
17
+
18
+ ### Major Changes
19
+
20
+ - 3372878: Migrate all packages from functional APIs to a decorator-first design.
21
+
22
+ **`@praxisjs/core`**
23
+
24
+ - Added `Composable` abstract base class for building class-based composables
25
+ - Removed `resource`, `createResource`, `Resource`, `ResourceStatus`, `ResourceOptions` from public exports — use `@Resource` from `@praxisjs/decorators` instead
26
+
27
+ **`@praxisjs/motion`**
28
+
29
+ - Replaced `useMotion`, `tween`, `spring`, `createTransition`, `Animate`, `easings`, `resolveEasing` with `@Tween` and `@Spring` decorators
30
+
31
+ **`@praxisjs/di`**
32
+
33
+ - Replaced `useService` and `createScope` with a `@Scope` decorator
34
+ - Renamed exported type `Scope` to `ScopeType` to free the name for the new decorator
35
+
36
+ **`@praxisjs/fsm`**
37
+
38
+ - Removed `createMachine` — use the `@StateMachine` and `@Transition` decorators directly
39
+
40
+ **`@praxisjs/router`**
41
+
42
+ - Removed `createRouter`, `lazy`, `useRouter`, `useParams`, `useQuery`, `useLocation`
43
+ - Added `@RouterConfig`, `@Lazy`, `@InjectRouter`, `@Params`, `@Query`, `@Location` decorators
44
+
45
+ **`@praxisjs/store`**
46
+
47
+ - Removed `createStore` — use the `@Store` and `@UseStore` decorators directly
48
+
49
+ **`@praxisjs/composables`**
50
+
51
+ - Replaced all `use*` composable functions with class-based composables extending `Composable`:
52
+ `WindowSize`, `ScrollPosition`, `ElementSize`, `Intersection`, `Focus`, `MediaQuery`, `ColorScheme`, `Mouse`, `KeyCombo`, `Idle`, `Clipboard`, `Geolocation`, `TimeAgo`, `Pagination`
53
+
54
+ **`@praxisjs/concurrent`**
55
+
56
+ - Removed `task`, `queue`, `pool` and their instance types — use `@Task`, `@Queue`, `@Pool` decorators instead
57
+
58
+ ### Patch Changes
59
+
60
+ - Updated dependencies [3372878]
61
+ - Updated dependencies [feaa478]
62
+ - @praxisjs/core@1.0.0
63
+ - @praxisjs/decorators@0.5.0
64
+
3
65
  ## 0.2.3
4
66
 
5
67
  ### Patch Changes
@@ -110,6 +110,12 @@ describe("createStore", () => {
110
110
  expect(snapshots).toContain(1);
111
111
  expect(snapshots).not.toContain(2);
112
112
  });
113
+ it("getting via a symbol key returns undefined", () => {
114
+ const store = makeCounter();
115
+ const sym = Symbol("test");
116
+ const val = Reflect.get(store, sym);
117
+ expect(val).toBeUndefined();
118
+ });
113
119
  it("$state() snapshot includes getter values", () => {
114
120
  const store = createStore({
115
121
  a: 2,
@@ -123,5 +129,58 @@ describe("createStore", () => {
123
129
  expect(state).toHaveProperty("a", 2);
124
130
  expect(state).toHaveProperty("b", 3);
125
131
  });
132
+ it("$patch({ count: undefined }) — skips that key (count unchanged)", () => {
133
+ const store = makeCounter();
134
+ store.$patch({ count: undefined });
135
+ expect(store.count).toBe(0);
136
+ });
137
+ it("$patch({ count: null }) — sets count to null (valid update)", () => {
138
+ const store = makeCounter();
139
+ store.$patch({ count: null });
140
+ expect(store.count).toBeNull();
141
+ });
142
+ it("getter reads two signals — getter result updates when either signal changes", () => {
143
+ // Use a non-enumerable getter so it is NOT captured by Object.entries
144
+ // and instead goes through the live desc.get.call(store) path.
145
+ const definition = { a: 10, b: 20 };
146
+ Object.defineProperty(definition, "total", {
147
+ enumerable: false,
148
+ configurable: true,
149
+ get() {
150
+ return this.a +
151
+ this.b;
152
+ },
153
+ });
154
+ const store = createStore(definition)();
155
+ const s = store;
156
+ expect(s.total).toBe(30);
157
+ Reflect.set(store, "a", 5);
158
+ expect(s.total).toBe(25);
159
+ Reflect.set(store, "b", 5);
160
+ expect(s.total).toBe(10);
161
+ });
162
+ it("$subscribe listener called with the correct new value", () => {
163
+ const store = makeCounter();
164
+ const received = [];
165
+ store.$subscribe((s) => received.push(s.count));
166
+ store.count = 7;
167
+ expect(received).toContain(7);
168
+ });
169
+ it("$reset restores all signals to initial values after multiple mutations", () => {
170
+ const store = makeCounter();
171
+ store.count = 10;
172
+ store.step = 5;
173
+ store.$reset();
174
+ expect(store.count).toBe(0);
175
+ expect(store.step).toBe(1);
176
+ });
177
+ it("two store factory calls with same definition — produce independent stores", () => {
178
+ const definition = { count: 0 };
179
+ const storeA = createStore({ ...definition })();
180
+ const storeB = createStore({ ...definition })();
181
+ storeA.count = 42;
182
+ expect(storeA.count).toBe(42);
183
+ expect(storeB.count).toBe(0); // independent — storeB unaffected
184
+ });
126
185
  });
127
186
  //# sourceMappingURL=create-store.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-store.test.js","sourceRoot":"","sources":["../../src/__tests__/create-store.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-store.test.js","sourceRoot":"","sources":["../../src/__tests__/create-store.test.ts"],"names":[],"mappings":"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"}
@@ -3,26 +3,48 @@ import { Store, UseStore } from "../decorators";
3
3
  describe("Store decorator", () => {
4
4
  it("registers the class without throwing", () => {
5
5
  class CounterStore {
6
- value = 0;
6
+ constructor() {
7
+ this.value = 0;
8
+ }
7
9
  }
8
10
  expect(() => { Store()(CounterStore, {}); }).not.toThrow();
9
11
  });
12
+ it("StoreBehavior.create() is invoked when an enhanced instance is constructed", () => {
13
+ class MyStore {
14
+ constructor() {
15
+ this.value = 42;
16
+ }
17
+ }
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const Enhanced = Store()(MyStore, {});
20
+ // Creating an instance calls StoreBehavior.create() internally (returns {})
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ expect(() => new Enhanced()).not.toThrow();
23
+ });
10
24
  });
25
+ function makeFieldCtx(name) {
26
+ const initializers = [];
27
+ return {
28
+ ctx: {
29
+ name,
30
+ kind: "field",
31
+ addInitializer(fn) { initializers.push(fn); },
32
+ },
33
+ run(instance) { initializers.forEach((fn) => { fn.call(instance); }); },
34
+ };
35
+ }
11
36
  describe("UseStore decorator", () => {
12
37
  it("injects a singleton store instance via getter", () => {
13
38
  class AppStore {
14
- name = "app";
39
+ constructor() {
40
+ this.name = "app";
41
+ }
15
42
  }
16
43
  Store()(AppStore, {});
17
- const initializers = [];
18
- const ctx = {
19
- name: "store",
20
- kind: "field",
21
- addInitializer(fn) { initializers.push(fn); },
22
- };
44
+ const { ctx, run } = makeFieldCtx("store");
23
45
  UseStore(AppStore)(undefined, ctx);
24
46
  const instance = {};
25
- initializers.forEach((fn) => { fn.call(instance); });
47
+ run(instance);
26
48
  expect(instance.store).toBeInstanceOf(AppStore);
27
49
  expect(instance.store.name).toBe("app");
28
50
  });
@@ -30,18 +52,67 @@ describe("UseStore decorator", () => {
30
52
  class SharedStore {
31
53
  }
32
54
  Store()(SharedStore, {});
33
- const initializers = [];
34
- const ctx = {
35
- name: "sharedStore",
36
- kind: "field",
37
- addInitializer(fn) { initializers.push(fn); },
38
- };
55
+ const { ctx, run } = makeFieldCtx("sharedStore");
39
56
  UseStore(SharedStore)(undefined, ctx);
40
57
  const a = {};
41
58
  const b = {};
42
- initializers.forEach((fn) => { fn.call(a); });
43
- initializers.forEach((fn) => { fn.call(b); });
59
+ run(a);
60
+ run(b);
44
61
  expect(a.sharedStore).toBe(b.sharedStore);
45
62
  });
63
+ it("@UseStore(ClassWithoutStoreDecorator) — creates a new instance (no crash, no pre-registration needed)", () => {
64
+ class NotRegistered {
65
+ constructor() {
66
+ this.value = 99;
67
+ }
68
+ }
69
+ // UseStore lazily creates an instance even without @Store, but should not throw
70
+ const { ctx, run } = makeFieldCtx("svc");
71
+ UseStore(NotRegistered)(undefined, ctx);
72
+ const instance = {};
73
+ run(instance);
74
+ // The implementation instantiates it on first access regardless
75
+ expect(instance.svc).toBeInstanceOf(NotRegistered);
76
+ });
77
+ it("@UseStore on two fields of same class — each field gets the correct store type independently", () => {
78
+ class StoreAlpha {
79
+ constructor() {
80
+ this.kind = "alpha";
81
+ }
82
+ }
83
+ class StoreBeta {
84
+ constructor() {
85
+ this.kind = "beta";
86
+ }
87
+ }
88
+ Store()(StoreAlpha, {});
89
+ Store()(StoreBeta, {});
90
+ const { ctx: ctxA, run: runA } = makeFieldCtx("alpha");
91
+ const { ctx: ctxB, run: runB } = makeFieldCtx("beta");
92
+ UseStore(StoreAlpha)(undefined, ctxA);
93
+ UseStore(StoreBeta)(undefined, ctxB);
94
+ const instance = {};
95
+ runA(instance);
96
+ runB(instance);
97
+ expect(instance.alpha).toBeInstanceOf(StoreAlpha);
98
+ expect(instance.beta).toBeInstanceOf(StoreBeta);
99
+ expect(instance.alpha.kind).toBe("alpha");
100
+ expect(instance.beta.kind).toBe("beta");
101
+ });
102
+ it("store singleton is shared across multiple class instances", () => {
103
+ class CounterStore {
104
+ constructor() {
105
+ this.count = 0;
106
+ }
107
+ }
108
+ Store()(CounterStore, {});
109
+ const { ctx, run } = makeFieldCtx("counter");
110
+ UseStore(CounterStore)(undefined, ctx);
111
+ const obj1 = {};
112
+ const obj2 = {};
113
+ run(obj1);
114
+ run(obj2);
115
+ expect(obj1.counter).toBe(obj2.counter);
116
+ });
46
117
  });
47
118
  //# sourceMappingURL=decorators.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.test.js","sourceRoot":"","sources":["../../src/__tests__/decorators.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEhD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,YAAY;YAChB,KAAK,GAAG,CAAC,CAAC;SACX;QACD,MAAM,CAAC,GAAG,EAAE,GACR,KAAK,EAAE,CAAC,YAAY,EAAE,EAA2B,CAAC,CAAC,CAAC,CAAC,CACxD,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,QAAQ;YACZ,IAAI,GAAG,KAAK,CAAC;SACd;QACD,KAAK,EAAE,CAAC,QAAQ,EAAE,EAA2B,CAAC,CAAC;QAE/C,MAAM,YAAY,GAAmC,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG;YACV,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAgB;YACtB,cAAc,CAAC,EAA2B,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SACzC,CAAC;QAEhC,QAAQ,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAA4B,EAAE,CAAC;QAC7C,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAErD,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAE,QAAQ,CAAC,KAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,WAAW;SAAG;QACpB,KAAK,EAAE,CAAC,WAAW,EAAE,EAA2B,CAAC,CAAC;QAElD,MAAM,YAAY,GAAmC,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG;YACV,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,OAAgB;YACtB,cAAc,CAAC,EAA2B,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SACzC,CAAC;QAEhC,QAAQ,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAEtC,MAAM,CAAC,GAA4B,EAAE,CAAC;QACtC,MAAM,CAAC,GAA4B,EAAE,CAAC;QACtC,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9C,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"decorators.test.js","sourceRoot":"","sources":["../../src/__tests__/decorators.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-store.d.ts","sourceRoot":"","sources":["../src/create-store.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,UAAU,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,WAgE5B"}
1
+ {"version":3,"file":"create-store.d.ts","sourceRoot":"","sources":["../src/create-store.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,UAAU,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,WAiE5B"}
@@ -60,6 +60,8 @@ export function createStore(definition) {
60
60
  }
61
61
  function patch(partial) {
62
62
  for (const [k, v] of Object.entries(partial)) {
63
+ if (v === undefined)
64
+ continue;
63
65
  if (k in signals)
64
66
  signals[k].set(v);
65
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"create-store.js","sourceRoot":"","sources":["../src/create-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-store.js","sourceRoot":"","sources":["../src/create-store.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- export declare function Store(): (value: new (...args: unknown[]) => unknown, _context: ClassDecoratorContext) => void;
2
- export declare function UseStore(StoreConstructor: new () => unknown): (_value: undefined, context: ClassFieldDecoratorContext) => void;
1
+ export declare function Store(): (value: new (...args: unknown[]) => unknown, context: ClassDecoratorContext) => new (...args: unknown[]) => unknown;
2
+ export declare function UseStore(StoreConstructor: new () => unknown): (_value: undefined, context: ClassFieldDecoratorContext<any>) => void;
3
3
  //# sourceMappingURL=decorators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAEA,wBAAgB,KAAK,KACF,OAAO,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,UAAU,qBAAqB,KAAG,IAAI,CAGpG;AAED,wBAAgB,QAAQ,CAAC,gBAAgB,EAAE,UAAU,OAAO,IACzC,QAAQ,SAAS,EAAE,SAAS,0BAA0B,KAAG,IAAI,CAsB/E"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAwBA,wBAAgB,KAAK,IAIY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,qBAAqB,KAAK,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CACnJ;AAED,wBAAgB,QAAQ,CAAC,gBAAgB,EAAE,UAAU,OAAO,GAwBzC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,GAAG,CAAC,KAAK,IAAI,CACvF"}
@@ -1,28 +1,41 @@
1
+ import { createClassDecorator, ClassBehavior, createFieldDecorator, } from "@praxisjs/decorators";
1
2
  const storeRegistry = new Map();
3
+ class StoreBehavior extends ClassBehavior {
4
+ create(_instance) {
5
+ return {};
6
+ }
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ initialize(Enhanced) {
9
+ storeRegistry.set(Enhanced, null);
10
+ }
11
+ }
12
+ const storeBehavior = new StoreBehavior();
2
13
  export function Store() {
3
- return function (value, _context) {
4
- storeRegistry.set(value, null);
5
- };
14
+ const decorator = createClassDecorator(storeBehavior);
15
+ // Store decorators work on any class, not just RootComponent
16
+ return decorator;
6
17
  }
7
18
  export function UseStore(StoreConstructor) {
8
- return function (_value, context) {
9
- const cache = new WeakMap();
10
- context.addInitializer(function () {
11
- Object.defineProperty(this, context.name, {
12
- get() {
13
- if (!cache.has(this)) {
14
- if (!storeRegistry.has(StoreConstructor) ||
15
- storeRegistry.get(StoreConstructor) === null) {
16
- storeRegistry.set(StoreConstructor, new StoreConstructor());
19
+ const cache = new WeakMap();
20
+ return createFieldDecorator({
21
+ bind(_instance, _name, _initialValue) {
22
+ return {
23
+ descriptor: {
24
+ get() {
25
+ if (!cache.has(this)) {
26
+ if (!storeRegistry.has(StoreConstructor) ||
27
+ storeRegistry.get(StoreConstructor) === null) {
28
+ storeRegistry.set(StoreConstructor, new StoreConstructor());
29
+ }
30
+ cache.set(this, storeRegistry.get(StoreConstructor));
17
31
  }
18
- cache.set(this, storeRegistry.get(StoreConstructor));
19
- }
20
- return cache.get(this);
32
+ return cache.get(this);
33
+ },
21
34
  },
22
- enumerable: true,
23
- configurable: true,
24
- });
25
- });
26
- };
35
+ };
36
+ },
37
+ // Store decorators work on any class, not just StatefulComponent
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ });
27
40
  }
28
41
  //# sourceMappingURL=decorators.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,IAAI,GAAG,EAAgD,CAAC;AAE9E,MAAM,UAAU,KAAK;IACnB,OAAO,UAAU,KAA0C,EAAE,QAA+B;QAC1F,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,gBAAmC;IAC1D,OAAO,UAAU,MAAiB,EAAE,OAAmC;QACrE,MAAM,KAAK,GAAG,IAAI,OAAO,EAAmB,CAAC;QAE7C,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;gBACxC,GAAG;oBACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;wBACrB,IACE,CAAC,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC;4BACpC,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,IAAI,EAC5C,CAAC;4BACD,aAAa,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,gBAAgB,EAAE,CAAC,CAAC;wBAC9D,CAAC;wBACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;oBACvD,CAAC;oBACD,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;gBACD,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,aAAa,EAEb,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAgD,CAAC;AAE9E,MAAM,aAAc,SAAQ,aAAa;IACvC,MAAM,CAAC,SAAwB;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,8DAA8D;IAC9D,UAAU,CAAC,QAAyC;QAClD,aAAa,CAAC,GAAG,CAAC,QAA+C,EAAE,IAAI,CAAC,CAAC;IAC3E,CAAC;CACF;AAED,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;AAE1C,MAAM,UAAU,KAAK;IACnB,MAAM,SAAS,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;IACtD,6DAA6D;IAE7D,OAAO,SAA2I,CAAC;AACrJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,gBAAmC;IAC1D,MAAM,KAAK,GAAG,IAAI,OAAO,EAAmB,CAAC;IAE7C,OAAO,oBAAoB,CAAC;QAC1B,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa;YAClC,OAAO;gBACL,UAAU,EAAE;oBACV,GAAG;wBACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;4BACrB,IACE,CAAC,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC;gCACpC,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,IAAI,EAC5C,CAAC;gCACD,aAAa,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,gBAAgB,EAAE,CAAC,CAAC;4BAC9D,CAAC;4BACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;wBACvD,CAAC;wBACD,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACzB,CAAC;iBACF;aACF,CAAC;QACJ,CAAC;QACH,iEAAiE;QACjE,8DAA8D;KAC7D,CAAqF,CAAC;AACzF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- export { createStore } from "./create-store";
2
1
  export { Store, UseStore } from "./decorators";
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,2 @@
1
- export { createStore } from "./create-store";
2
1
  export { Store, UseStore } from "./decorators";
3
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisjs/store",
3
- "version": "0.2.3",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -14,7 +14,8 @@
14
14
  "typescript": "^5.9.3"
15
15
  },
16
16
  "dependencies": {
17
- "@praxisjs/core": "0.4.2"
17
+ "@praxisjs/core": "1.1.0",
18
+ "@praxisjs/decorators": "0.6.0"
18
19
  },
19
20
  "scripts": {
20
21
  "build": "tsc",
@@ -145,6 +145,13 @@ describe("createStore", () => {
145
145
  expect(snapshots).not.toContain(2);
146
146
  });
147
147
 
148
+ it("getting via a symbol key returns undefined", () => {
149
+ const store = makeCounter();
150
+ const sym = Symbol("test");
151
+ const val = Reflect.get(store as object, sym);
152
+ expect(val).toBeUndefined();
153
+ });
154
+
148
155
  it("$state() snapshot includes getter values", () => {
149
156
  const store = createStore({
150
157
  a: 2,
@@ -159,4 +166,67 @@ describe("createStore", () => {
159
166
  expect(state).toHaveProperty("a", 2);
160
167
  expect(state).toHaveProperty("b", 3);
161
168
  });
169
+
170
+ it("$patch({ count: undefined }) — skips that key (count unchanged)", () => {
171
+ const store = makeCounter();
172
+ (store as unknown as { $patch: (p: Record<string, unknown>) => void }).$patch({ count: undefined });
173
+ expect(store.count).toBe(0);
174
+ });
175
+
176
+ it("$patch({ count: null }) — sets count to null (valid update)", () => {
177
+ const store = makeCounter();
178
+ (store as unknown as { $patch: (p: Record<string, unknown>) => void }).$patch({ count: null });
179
+ expect(store.count).toBeNull();
180
+ });
181
+
182
+ it("getter reads two signals — getter result updates when either signal changes", () => {
183
+ // Use a non-enumerable getter so it is NOT captured by Object.entries
184
+ // and instead goes through the live desc.get.call(store) path.
185
+ const definition: Record<string, unknown> = { a: 10, b: 20 };
186
+ Object.defineProperty(definition, "total", {
187
+ enumerable: false,
188
+ configurable: true,
189
+ get() {
190
+ return (this as unknown as { a: number; b: number }).a +
191
+ (this as unknown as { a: number; b: number }).b;
192
+ },
193
+ });
194
+
195
+ const store = createStore(definition as { a: number; b: number })();
196
+ type S = { a: number; b: number; total: number };
197
+ const s = store as unknown as S;
198
+
199
+ expect(s.total).toBe(30);
200
+ Reflect.set(store as object, "a", 5);
201
+ expect(s.total).toBe(25);
202
+ Reflect.set(store as object, "b", 5);
203
+ expect(s.total).toBe(10);
204
+ });
205
+
206
+ it("$subscribe listener called with the correct new value", () => {
207
+ const store = makeCounter();
208
+ const received: number[] = [];
209
+ type StoreType = { $subscribe: (fn: (s: Record<string, unknown>) => void) => () => void };
210
+ (store as unknown as StoreType).$subscribe((s) => received.push(s.count as number));
211
+ (store as unknown as { count: number }).count = 7;
212
+ expect(received).toContain(7);
213
+ });
214
+
215
+ it("$reset restores all signals to initial values after multiple mutations", () => {
216
+ const store = makeCounter();
217
+ (store as unknown as { count: number }).count = 10;
218
+ (store as unknown as { step: number }).step = 5;
219
+ (store as unknown as { $reset: () => void }).$reset();
220
+ expect(store.count).toBe(0);
221
+ expect(store.step).toBe(1);
222
+ });
223
+
224
+ it("two store factory calls with same definition — produce independent stores", () => {
225
+ const definition = { count: 0 };
226
+ const storeA = createStore({ ...definition })();
227
+ const storeB = createStore({ ...definition })();
228
+ (storeA as unknown as { count: number }).count = 42;
229
+ expect(storeA.count).toBe(42);
230
+ expect(storeB.count).toBe(0); // independent — storeB unaffected
231
+ });
162
232
  });
@@ -11,8 +11,31 @@ describe("Store decorator", () => {
11
11
  { Store()(CounterStore, {} as ClassDecoratorContext); },
12
12
  ).not.toThrow();
13
13
  });
14
+
15
+ it("StoreBehavior.create() is invoked when an enhanced instance is constructed", () => {
16
+ class MyStore {
17
+ value = 42;
18
+ }
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ const Enhanced = Store()(MyStore as any, {} as ClassDecoratorContext);
21
+ // Creating an instance calls StoreBehavior.create() internally (returns {})
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ expect(() => new (Enhanced as any)()).not.toThrow();
24
+ });
14
25
  });
15
26
 
27
+ function makeFieldCtx(name: string) {
28
+ const initializers: Array<(this: unknown) => void> = [];
29
+ return {
30
+ ctx: {
31
+ name,
32
+ kind: "field" as const,
33
+ addInitializer(fn: (this: unknown) => void) { initializers.push(fn); },
34
+ } as ClassFieldDecoratorContext,
35
+ run(instance: unknown) { initializers.forEach((fn) => { fn.call(instance); }); },
36
+ };
37
+ }
38
+
16
39
  describe("UseStore decorator", () => {
17
40
  it("injects a singleton store instance via getter", () => {
18
41
  class AppStore {
@@ -20,17 +43,11 @@ describe("UseStore decorator", () => {
20
43
  }
21
44
  Store()(AppStore, {} as ClassDecoratorContext);
22
45
 
23
- const initializers: Array<(this: unknown) => void> = [];
24
- const ctx = {
25
- name: "store",
26
- kind: "field" as const,
27
- addInitializer(fn: (this: unknown) => void) { initializers.push(fn); },
28
- } as ClassFieldDecoratorContext;
29
-
46
+ const { ctx, run } = makeFieldCtx("store");
30
47
  UseStore(AppStore)(undefined, ctx);
31
48
 
32
49
  const instance: Record<string, unknown> = {};
33
- initializers.forEach((fn) => { fn.call(instance); });
50
+ run(instance);
34
51
 
35
52
  expect(instance.store).toBeInstanceOf(AppStore);
36
53
  expect((instance.store as AppStore).name).toBe("app");
@@ -40,20 +57,69 @@ describe("UseStore decorator", () => {
40
57
  class SharedStore {}
41
58
  Store()(SharedStore, {} as ClassDecoratorContext);
42
59
 
43
- const initializers: Array<(this: unknown) => void> = [];
44
- const ctx = {
45
- name: "sharedStore",
46
- kind: "field" as const,
47
- addInitializer(fn: (this: unknown) => void) { initializers.push(fn); },
48
- } as ClassFieldDecoratorContext;
49
-
60
+ const { ctx, run } = makeFieldCtx("sharedStore");
50
61
  UseStore(SharedStore)(undefined, ctx);
51
62
 
52
63
  const a: Record<string, unknown> = {};
53
64
  const b: Record<string, unknown> = {};
54
- initializers.forEach((fn) => { fn.call(a); });
55
- initializers.forEach((fn) => { fn.call(b); });
65
+ run(a);
66
+ run(b);
56
67
 
57
68
  expect(a.sharedStore).toBe(b.sharedStore);
58
69
  });
70
+
71
+ it("@UseStore(ClassWithoutStoreDecorator) — creates a new instance (no crash, no pre-registration needed)", () => {
72
+ class NotRegistered {
73
+ value = 99;
74
+ }
75
+ // UseStore lazily creates an instance even without @Store, but should not throw
76
+ const { ctx, run } = makeFieldCtx("svc");
77
+ UseStore(NotRegistered)(undefined, ctx);
78
+ const instance: Record<string, unknown> = {};
79
+ run(instance);
80
+ // The implementation instantiates it on first access regardless
81
+ expect(instance.svc).toBeInstanceOf(NotRegistered);
82
+ });
83
+
84
+ it("@UseStore on two fields of same class — each field gets the correct store type independently", () => {
85
+ class StoreAlpha {
86
+ kind = "alpha";
87
+ }
88
+ class StoreBeta {
89
+ kind = "beta";
90
+ }
91
+ Store()(StoreAlpha, {} as ClassDecoratorContext);
92
+ Store()(StoreBeta, {} as ClassDecoratorContext);
93
+
94
+ const { ctx: ctxA, run: runA } = makeFieldCtx("alpha");
95
+ const { ctx: ctxB, run: runB } = makeFieldCtx("beta");
96
+ UseStore(StoreAlpha)(undefined, ctxA);
97
+ UseStore(StoreBeta)(undefined, ctxB);
98
+
99
+ const instance: Record<string, unknown> = {};
100
+ runA(instance);
101
+ runB(instance);
102
+
103
+ expect(instance.alpha).toBeInstanceOf(StoreAlpha);
104
+ expect(instance.beta).toBeInstanceOf(StoreBeta);
105
+ expect((instance.alpha as StoreAlpha).kind).toBe("alpha");
106
+ expect((instance.beta as StoreBeta).kind).toBe("beta");
107
+ });
108
+
109
+ it("store singleton is shared across multiple class instances", () => {
110
+ class CounterStore {
111
+ count = 0;
112
+ }
113
+ Store()(CounterStore, {} as ClassDecoratorContext);
114
+
115
+ const { ctx, run } = makeFieldCtx("counter");
116
+ UseStore(CounterStore)(undefined, ctx);
117
+
118
+ const obj1: Record<string, unknown> = {};
119
+ const obj2: Record<string, unknown> = {};
120
+ run(obj1);
121
+ run(obj2);
122
+
123
+ expect(obj1.counter).toBe(obj2.counter);
124
+ });
59
125
  });
@@ -60,6 +60,7 @@ export function createStore<T extends Record<string, unknown>>(
60
60
 
61
61
  function patch(partial: Partial<Record<string, unknown>>): void {
62
62
  for (const [k, v] of Object.entries(partial)) {
63
+ if (v === undefined) continue;
63
64
  if (k in signals) signals[k].set(v);
64
65
  }
65
66
  }
package/src/decorators.ts CHANGED
@@ -1,32 +1,57 @@
1
+ import type { RootComponent } from "@praxisjs/core/internal";
2
+ import {
3
+ createClassDecorator,
4
+ ClassBehavior,
5
+ type ClassEnhancement,
6
+ createFieldDecorator,
7
+ type FieldBinding,
8
+ } from "@praxisjs/decorators";
9
+
1
10
  const storeRegistry = new Map<new (...args: unknown[]) => unknown, unknown>();
2
11
 
12
+ class StoreBehavior extends ClassBehavior {
13
+ create(_instance: RootComponent): ClassEnhancement {
14
+ return {};
15
+ }
16
+
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ initialize(Enhanced: new (...args: any[]) => unknown): void {
19
+ storeRegistry.set(Enhanced as new (...args: unknown[]) => unknown, null);
20
+ }
21
+ }
22
+
23
+ const storeBehavior = new StoreBehavior();
24
+
3
25
  export function Store() {
4
- return function (value: new (...args: unknown[]) => unknown, _context: ClassDecoratorContext): void {
5
- storeRegistry.set(value, null);
6
- };
26
+ const decorator = createClassDecorator(storeBehavior);
27
+ // Store decorators work on any class, not just RootComponent
28
+
29
+ return decorator as unknown as (value: new (...args: unknown[]) => unknown, context: ClassDecoratorContext) => new (...args: unknown[]) => unknown;
7
30
  }
8
31
 
9
32
  export function UseStore(StoreConstructor: new () => unknown) {
10
- return function (_value: undefined, context: ClassFieldDecoratorContext): void {
11
- const cache = new WeakMap<object, unknown>();
33
+ const cache = new WeakMap<object, unknown>();
12
34
 
13
- context.addInitializer(function (this: unknown) {
14
- Object.defineProperty(this, context.name, {
15
- get(this: object): unknown {
16
- if (!cache.has(this)) {
17
- if (
18
- !storeRegistry.has(StoreConstructor) ||
19
- storeRegistry.get(StoreConstructor) === null
20
- ) {
21
- storeRegistry.set(StoreConstructor, new StoreConstructor());
35
+ return createFieldDecorator({
36
+ bind(_instance, _name, _initialValue): FieldBinding {
37
+ return {
38
+ descriptor: {
39
+ get(this: object): unknown {
40
+ if (!cache.has(this)) {
41
+ if (
42
+ !storeRegistry.has(StoreConstructor) ||
43
+ storeRegistry.get(StoreConstructor) === null
44
+ ) {
45
+ storeRegistry.set(StoreConstructor, new StoreConstructor());
46
+ }
47
+ cache.set(this, storeRegistry.get(StoreConstructor));
22
48
  }
23
- cache.set(this, storeRegistry.get(StoreConstructor));
24
- }
25
- return cache.get(this);
49
+ return cache.get(this);
50
+ },
26
51
  },
27
- enumerable: true,
28
- configurable: true,
29
- });
30
- });
31
- };
52
+ };
53
+ },
54
+ // Store decorators work on any class, not just StatefulComponent
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ }) as unknown as (_value: undefined, context: ClassFieldDecoratorContext<any>) => void;
32
57
  }
package/src/index.ts CHANGED
@@ -1,2 +1 @@
1
- export { createStore } from "./create-store";
2
1
  export { Store, UseStore } from "./decorators";