@praxisjs/store 1.1.0 → 1.2.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 +19 -0
- package/dist/__tests__/decorators.test.js +48 -50
- package/dist/__tests__/decorators.test.js.map +1 -1
- package/dist/decorators.d.ts +3 -3
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +4 -12
- package/dist/decorators.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/decorators.test.ts +48 -50
- package/src/decorators.ts +4 -15
- package/src/index.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @praxisjs/store
|
|
2
2
|
|
|
3
|
+
## 1.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [378cc54]
|
|
8
|
+
- @praxisjs/core@1.7.0
|
|
9
|
+
- @praxisjs/decorators@1.1.0
|
|
10
|
+
|
|
11
|
+
## 1.2.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- 4ec660f: Rename decorators for consistency: `@Store()` → `@Storable()` (class decorator), `@UseStore(Class)` → `@Store(Class)` (field decorator), `useStore()` → `store()` (imperative function).
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [cfb0de2]
|
|
20
|
+
- @praxisjs/decorators@1.0.2
|
|
21
|
+
|
|
3
22
|
## 1.1.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
describe("
|
|
2
|
+
import { Storable, Store, store, ReactiveStore } from "../decorators";
|
|
3
|
+
describe("@Storable decorator", () => {
|
|
4
4
|
it("registers the class without throwing", () => {
|
|
5
5
|
class CounterStore extends ReactiveStore {
|
|
6
6
|
constructor() {
|
|
@@ -8,7 +8,7 @@ describe("Store decorator", () => {
|
|
|
8
8
|
this.value = 0;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
expect(() => {
|
|
11
|
+
expect(() => { Storable()(CounterStore, {}); }).not.toThrow();
|
|
12
12
|
});
|
|
13
13
|
it("returns void and the original class remains directly instantiable", () => {
|
|
14
14
|
class MyStore extends ReactiveStore {
|
|
@@ -18,7 +18,7 @@ describe("Store decorator", () => {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
-
const result =
|
|
21
|
+
const result = Storable()(MyStore, {});
|
|
22
22
|
expect(result).toBeUndefined();
|
|
23
23
|
expect(() => new MyStore()).not.toThrow();
|
|
24
24
|
expect(new MyStore().value).toBe(42);
|
|
@@ -35,7 +35,7 @@ function makeFieldCtx(name) {
|
|
|
35
35
|
run(instance) { initializers.forEach((fn) => { fn.call(instance); }); },
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
-
describe("
|
|
38
|
+
describe("@Store field decorator", () => {
|
|
39
39
|
it("injects a singleton store instance via getter", () => {
|
|
40
40
|
class AppStore extends ReactiveStore {
|
|
41
41
|
constructor() {
|
|
@@ -43,9 +43,9 @@ describe("UseStore decorator", () => {
|
|
|
43
43
|
this.name = "app";
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
Storable()(AppStore, {});
|
|
47
47
|
const { ctx, run } = makeFieldCtx("store");
|
|
48
|
-
|
|
48
|
+
Store(AppStore)(undefined, ctx);
|
|
49
49
|
const instance = {};
|
|
50
50
|
run(instance);
|
|
51
51
|
expect(instance.store).toBeInstanceOf(AppStore);
|
|
@@ -54,30 +54,28 @@ describe("UseStore decorator", () => {
|
|
|
54
54
|
it("returns the same instance on repeated access (singleton)", () => {
|
|
55
55
|
class SharedStore extends ReactiveStore {
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
Storable()(SharedStore, {});
|
|
58
58
|
const { ctx, run } = makeFieldCtx("sharedStore");
|
|
59
|
-
|
|
59
|
+
Store(SharedStore)(undefined, ctx);
|
|
60
60
|
const a = {};
|
|
61
61
|
const b = {};
|
|
62
62
|
run(a);
|
|
63
63
|
run(b);
|
|
64
64
|
expect(a.sharedStore).toBe(b.sharedStore);
|
|
65
65
|
});
|
|
66
|
-
it("@
|
|
66
|
+
it("@Store(ClassWithoutStorable) — creates a new instance (no crash, no pre-registration needed)", () => {
|
|
67
67
|
class NotRegistered {
|
|
68
68
|
constructor() {
|
|
69
69
|
this.value = 99;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
// UseStore lazily creates an instance even without @Store, but should not throw
|
|
73
72
|
const { ctx, run } = makeFieldCtx("svc");
|
|
74
|
-
|
|
73
|
+
Store(NotRegistered)(undefined, ctx);
|
|
75
74
|
const instance = {};
|
|
76
75
|
run(instance);
|
|
77
|
-
// The implementation instantiates it on first access regardless
|
|
78
76
|
expect(instance.svc).toBeInstanceOf(NotRegistered);
|
|
79
77
|
});
|
|
80
|
-
it("@
|
|
78
|
+
it("two @Store fields on the same class each get the correct store type", () => {
|
|
81
79
|
class StoreAlpha extends ReactiveStore {
|
|
82
80
|
constructor() {
|
|
83
81
|
super(...arguments);
|
|
@@ -90,12 +88,12 @@ describe("UseStore decorator", () => {
|
|
|
90
88
|
this.kind = "beta";
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
Storable()(StoreAlpha, {});
|
|
92
|
+
Storable()(StoreBeta, {});
|
|
95
93
|
const { ctx: ctxA, run: runA } = makeFieldCtx("alpha");
|
|
96
94
|
const { ctx: ctxB, run: runB } = makeFieldCtx("beta");
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
Store(StoreAlpha)(undefined, ctxA);
|
|
96
|
+
Store(StoreBeta)(undefined, ctxB);
|
|
99
97
|
const instance = {};
|
|
100
98
|
runA(instance);
|
|
101
99
|
runB(instance);
|
|
@@ -104,25 +102,39 @@ describe("UseStore decorator", () => {
|
|
|
104
102
|
expect(instance.alpha.kind).toBe("alpha");
|
|
105
103
|
expect(instance.beta.kind).toBe("beta");
|
|
106
104
|
});
|
|
107
|
-
it("
|
|
105
|
+
it("singleton is shared across multiple component instances", () => {
|
|
108
106
|
class CounterStore extends ReactiveStore {
|
|
109
107
|
constructor() {
|
|
110
108
|
super(...arguments);
|
|
111
109
|
this.count = 0;
|
|
112
110
|
}
|
|
113
111
|
}
|
|
114
|
-
|
|
112
|
+
Storable()(CounterStore, {});
|
|
115
113
|
const { ctx, run } = makeFieldCtx("counter");
|
|
116
|
-
|
|
114
|
+
Store(CounterStore)(undefined, ctx);
|
|
117
115
|
const obj1 = {};
|
|
118
116
|
const obj2 = {};
|
|
119
117
|
run(obj1);
|
|
120
118
|
run(obj2);
|
|
121
119
|
expect(obj1.counter).toBe(obj2.counter);
|
|
122
120
|
});
|
|
121
|
+
it("shares the same instance as store() (same registry)", () => {
|
|
122
|
+
class FlagsStore extends ReactiveStore {
|
|
123
|
+
constructor() {
|
|
124
|
+
super(...arguments);
|
|
125
|
+
this.enabled = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
Storable()(FlagsStore, {});
|
|
129
|
+
const { ctx, run } = makeFieldCtx("flags");
|
|
130
|
+
Store(FlagsStore)(undefined, ctx);
|
|
131
|
+
const obj = {};
|
|
132
|
+
run(obj);
|
|
133
|
+
expect(obj.flags).toBe(store(FlagsStore));
|
|
134
|
+
});
|
|
123
135
|
});
|
|
124
|
-
// ──
|
|
125
|
-
describe("
|
|
136
|
+
// ── store() ────────────────────────────────────────────────────────────────
|
|
137
|
+
describe("store()", () => {
|
|
126
138
|
it("returns a store instance without requiring a class field", () => {
|
|
127
139
|
class ProfileStore extends ReactiveStore {
|
|
128
140
|
constructor() {
|
|
@@ -130,10 +142,10 @@ describe("useStore", () => {
|
|
|
130
142
|
this.name = "alice";
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
expect(
|
|
136
|
-
expect(
|
|
145
|
+
Storable()(ProfileStore, {});
|
|
146
|
+
const instance = store(ProfileStore);
|
|
147
|
+
expect(instance).toBeInstanceOf(ProfileStore);
|
|
148
|
+
expect(instance.name).toBe("alice");
|
|
137
149
|
});
|
|
138
150
|
it("returns the same singleton instance on repeated calls", () => {
|
|
139
151
|
class TimerStore extends ReactiveStore {
|
|
@@ -142,22 +154,8 @@ describe("useStore", () => {
|
|
|
142
154
|
this.ticks = 0;
|
|
143
155
|
}
|
|
144
156
|
}
|
|
145
|
-
|
|
146
|
-
expect(
|
|
147
|
-
});
|
|
148
|
-
it("shares the same instance as @UseStore (same registry)", () => {
|
|
149
|
-
class FlagsStore extends ReactiveStore {
|
|
150
|
-
constructor() {
|
|
151
|
-
super(...arguments);
|
|
152
|
-
this.enabled = true;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
Store()(FlagsStore, {});
|
|
156
|
-
const { ctx, run } = makeFieldCtx("flags");
|
|
157
|
-
UseStore(FlagsStore)(undefined, ctx);
|
|
158
|
-
const obj = {};
|
|
159
|
-
run(obj);
|
|
160
|
-
expect(obj.flags).toBe(useStore(FlagsStore));
|
|
157
|
+
Storable()(TimerStore, {});
|
|
158
|
+
expect(store(TimerStore)).toBe(store(TimerStore));
|
|
161
159
|
});
|
|
162
160
|
it("lazily creates the instance on first call", () => {
|
|
163
161
|
class LazyStore extends ReactiveStore {
|
|
@@ -166,18 +164,18 @@ describe("useStore", () => {
|
|
|
166
164
|
this.ready = false;
|
|
167
165
|
}
|
|
168
166
|
}
|
|
169
|
-
|
|
170
|
-
const instance =
|
|
167
|
+
Storable()(LazyStore, {});
|
|
168
|
+
const instance = store(LazyStore);
|
|
171
169
|
expect(instance).toBeInstanceOf(LazyStore);
|
|
172
170
|
});
|
|
173
|
-
it("works without @
|
|
171
|
+
it("works without @Storable — creates a plain instance", () => {
|
|
174
172
|
class BareStore extends ReactiveStore {
|
|
175
173
|
constructor() {
|
|
176
174
|
super(...arguments);
|
|
177
175
|
this.value = 7;
|
|
178
176
|
}
|
|
179
177
|
}
|
|
180
|
-
const instance =
|
|
178
|
+
const instance = store(BareStore);
|
|
181
179
|
expect(instance).toBeInstanceOf(BareStore);
|
|
182
180
|
expect(instance.value).toBe(7);
|
|
183
181
|
});
|
|
@@ -188,9 +186,9 @@ describe("useStore", () => {
|
|
|
188
186
|
this.dark = false;
|
|
189
187
|
}
|
|
190
188
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
expect(
|
|
189
|
+
Storable()(ThemeStore, {});
|
|
190
|
+
store(ThemeStore).dark = true;
|
|
191
|
+
expect(store(ThemeStore).dark).toBe(true);
|
|
194
192
|
});
|
|
195
193
|
});
|
|
196
194
|
//# 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,
|
|
1
|
+
{"version":3,"file":"decorators.test.js","sourceRoot":"","sources":["../../src/__tests__/decorators.test.ts"],"names":[],"mappings":"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"}
|
package/dist/decorators.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type ReactiveHost } from "@praxisjs/decorators";
|
|
|
3
3
|
export declare class ReactiveStore implements ReactiveHost {
|
|
4
4
|
_stateDirty: boolean;
|
|
5
5
|
}
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
6
|
+
export declare function Storable(): (constructor: new (...args: unknown[]) => ReactiveStore, _context: ClassDecoratorContext) => void;
|
|
7
|
+
export declare function store<T extends ReactiveStore>(StoreClass: new () => T): T;
|
|
8
|
+
export declare function Store(StoreConstructor: new () => unknown): (_value: undefined, context: ClassFieldDecoratorContext<any>) => void;
|
|
9
9
|
//# sourceMappingURL=decorators.d.ts.map
|
package/dist/decorators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAI9B,qGAAqG;AACrG,qBAAa,aAAc,YAAW,YAAY;IAChD,WAAW,UAAS;CACrB;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAI9B,qGAAqG;AACrG,qBAAa,aAAc,YAAW,YAAY;IAChD,WAAW,UAAS;CACrB;AAED,wBAAgB,QAAQ,KAEpB,aAAa,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,aAAa,EACtD,UAAU,qBAAqB,KAC9B,IAAI,CAGR;AAED,wBAAgB,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAKzE;AAED,wBAAgB,KAAK,CAAC,gBAAgB,EAAE,UAAU,OAAO,GAYtC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,GAAG,CAAC,KAAK,IAAI,CACvF"}
|
package/dist/decorators.js
CHANGED
|
@@ -6,32 +6,24 @@ export class ReactiveStore {
|
|
|
6
6
|
this._stateDirty = false;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
-
export function
|
|
9
|
+
export function Storable() {
|
|
10
10
|
return function (constructor, _context) {
|
|
11
11
|
storeRegistry.set(constructor, null);
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
-
export function
|
|
14
|
+
export function store(StoreClass) {
|
|
15
15
|
if (!storeRegistry.has(StoreClass) || storeRegistry.get(StoreClass) === null) {
|
|
16
16
|
storeRegistry.set(StoreClass, new StoreClass());
|
|
17
17
|
}
|
|
18
18
|
return storeRegistry.get(StoreClass);
|
|
19
19
|
}
|
|
20
|
-
export function
|
|
21
|
-
const cache = new WeakMap();
|
|
20
|
+
export function Store(StoreConstructor) {
|
|
22
21
|
return createFieldDecorator({
|
|
23
22
|
bind(_instance, _name, _initialValue) {
|
|
24
23
|
return {
|
|
25
24
|
descriptor: {
|
|
26
25
|
get() {
|
|
27
|
-
|
|
28
|
-
if (!storeRegistry.has(StoreConstructor) ||
|
|
29
|
-
storeRegistry.get(StoreConstructor) === null) {
|
|
30
|
-
storeRegistry.set(StoreConstructor, new StoreConstructor());
|
|
31
|
-
}
|
|
32
|
-
cache.set(this, storeRegistry.get(StoreConstructor));
|
|
33
|
-
}
|
|
34
|
-
return cache.get(this);
|
|
26
|
+
return store(StoreConstructor);
|
|
35
27
|
},
|
|
36
28
|
},
|
|
37
29
|
};
|
package/dist/decorators.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,GAGrB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAgD,CAAC;AAE9E,qGAAqG;AACrG,MAAM,OAAO,aAAa;IAA1B;QACE,gBAAW,GAAG,KAAK,CAAC;IACtB,CAAC;CAAA;AAED,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,GAGrB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAgD,CAAC;AAE9E,qGAAqG;AACrG,MAAM,OAAO,aAAa;IAA1B;QACE,gBAAW,GAAG,KAAK,CAAC;IACtB,CAAC;CAAA;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,UACL,WAAsD,EACtD,QAA+B;QAE/B,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK,CAA0B,UAAuB;IACpE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7E,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,UAAU,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,aAAa,CAAC,GAAG,CAAC,UAAU,CAAM,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,gBAAmC;IACvD,OAAO,oBAAoB,CAAC;QAC1B,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa;YAClC,OAAO;gBACL,UAAU,EAAE;oBACV,GAAG;wBACD,OAAO,KAAK,CAAC,gBAA2C,CAAC,CAAC;oBAC5D,CAAC;iBACF;aACF,CAAC;QACJ,CAAC;QACH,8DAA8D;KAC7D,CAAqF,CAAC;AACzF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Storable, Store, store, ReactiveStore } from "./decorators";
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Storable, Store, store, ReactiveStore } from "./decorators";
|
|
2
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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisjs/store",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"typescript": "^5.9.3"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@praxisjs/core": "1.
|
|
18
|
-
"@praxisjs/decorators": "1.0
|
|
17
|
+
"@praxisjs/core": "1.7.0",
|
|
18
|
+
"@praxisjs/decorators": "1.1.0"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsc",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Storable, Store, store, ReactiveStore } from "../decorators";
|
|
4
4
|
|
|
5
|
-
describe("
|
|
5
|
+
describe("@Storable decorator", () => {
|
|
6
6
|
it("registers the class without throwing", () => {
|
|
7
7
|
class CounterStore extends ReactiveStore {
|
|
8
8
|
value = 0;
|
|
9
9
|
}
|
|
10
10
|
expect(() =>
|
|
11
|
-
{
|
|
11
|
+
{ Storable()(CounterStore, {} as ClassDecoratorContext); },
|
|
12
12
|
).not.toThrow();
|
|
13
13
|
});
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ describe("Store decorator", () => {
|
|
|
17
17
|
value = 42;
|
|
18
18
|
}
|
|
19
19
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
-
const result =
|
|
20
|
+
const result = Storable()(MyStore as any, {} as ClassDecoratorContext);
|
|
21
21
|
expect(result).toBeUndefined();
|
|
22
22
|
expect(() => new MyStore()).not.toThrow();
|
|
23
23
|
expect(new MyStore().value).toBe(42);
|
|
@@ -36,15 +36,15 @@ function makeFieldCtx(name: string) {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
describe("
|
|
39
|
+
describe("@Store field decorator", () => {
|
|
40
40
|
it("injects a singleton store instance via getter", () => {
|
|
41
41
|
class AppStore extends ReactiveStore {
|
|
42
42
|
name = "app";
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
Storable()(AppStore, {} as ClassDecoratorContext);
|
|
45
45
|
|
|
46
46
|
const { ctx, run } = makeFieldCtx("store");
|
|
47
|
-
|
|
47
|
+
Store(AppStore)(undefined, ctx);
|
|
48
48
|
|
|
49
49
|
const instance: Record<string, unknown> = {};
|
|
50
50
|
run(instance);
|
|
@@ -55,10 +55,10 @@ describe("UseStore decorator", () => {
|
|
|
55
55
|
|
|
56
56
|
it("returns the same instance on repeated access (singleton)", () => {
|
|
57
57
|
class SharedStore extends ReactiveStore {}
|
|
58
|
-
|
|
58
|
+
Storable()(SharedStore, {} as ClassDecoratorContext);
|
|
59
59
|
|
|
60
60
|
const { ctx, run } = makeFieldCtx("sharedStore");
|
|
61
|
-
|
|
61
|
+
Store(SharedStore)(undefined, ctx);
|
|
62
62
|
|
|
63
63
|
const a: Record<string, unknown> = {};
|
|
64
64
|
const b: Record<string, unknown> = {};
|
|
@@ -68,33 +68,31 @@ describe("UseStore decorator", () => {
|
|
|
68
68
|
expect(a.sharedStore).toBe(b.sharedStore);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
it("@
|
|
71
|
+
it("@Store(ClassWithoutStorable) — creates a new instance (no crash, no pre-registration needed)", () => {
|
|
72
72
|
class NotRegistered {
|
|
73
73
|
value = 99;
|
|
74
74
|
}
|
|
75
|
-
// UseStore lazily creates an instance even without @Store, but should not throw
|
|
76
75
|
const { ctx, run } = makeFieldCtx("svc");
|
|
77
|
-
|
|
76
|
+
Store(NotRegistered)(undefined, ctx);
|
|
78
77
|
const instance: Record<string, unknown> = {};
|
|
79
78
|
run(instance);
|
|
80
|
-
// The implementation instantiates it on first access regardless
|
|
81
79
|
expect(instance.svc).toBeInstanceOf(NotRegistered);
|
|
82
80
|
});
|
|
83
81
|
|
|
84
|
-
it("@
|
|
82
|
+
it("two @Store fields on the same class each get the correct store type", () => {
|
|
85
83
|
class StoreAlpha extends ReactiveStore {
|
|
86
84
|
kind = "alpha";
|
|
87
85
|
}
|
|
88
86
|
class StoreBeta extends ReactiveStore {
|
|
89
87
|
kind = "beta";
|
|
90
88
|
}
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
Storable()(StoreAlpha, {} as ClassDecoratorContext);
|
|
90
|
+
Storable()(StoreBeta, {} as ClassDecoratorContext);
|
|
93
91
|
|
|
94
92
|
const { ctx: ctxA, run: runA } = makeFieldCtx("alpha");
|
|
95
93
|
const { ctx: ctxB, run: runB } = makeFieldCtx("beta");
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
Store(StoreAlpha)(undefined, ctxA);
|
|
95
|
+
Store(StoreBeta)(undefined, ctxB);
|
|
98
96
|
|
|
99
97
|
const instance: Record<string, unknown> = {};
|
|
100
98
|
runA(instance);
|
|
@@ -106,14 +104,14 @@ describe("UseStore decorator", () => {
|
|
|
106
104
|
expect((instance.beta as StoreBeta).kind).toBe("beta");
|
|
107
105
|
});
|
|
108
106
|
|
|
109
|
-
it("
|
|
107
|
+
it("singleton is shared across multiple component instances", () => {
|
|
110
108
|
class CounterStore extends ReactiveStore {
|
|
111
109
|
count = 0;
|
|
112
110
|
}
|
|
113
|
-
|
|
111
|
+
Storable()(CounterStore, {} as ClassDecoratorContext);
|
|
114
112
|
|
|
115
113
|
const { ctx, run } = makeFieldCtx("counter");
|
|
116
|
-
|
|
114
|
+
Store(CounterStore)(undefined, ctx);
|
|
117
115
|
|
|
118
116
|
const obj1: Record<string, unknown> = {};
|
|
119
117
|
const obj2: Record<string, unknown> = {};
|
|
@@ -122,60 +120,60 @@ describe("UseStore decorator", () => {
|
|
|
122
120
|
|
|
123
121
|
expect(obj1.counter).toBe(obj2.counter);
|
|
124
122
|
});
|
|
123
|
+
|
|
124
|
+
it("shares the same instance as store() (same registry)", () => {
|
|
125
|
+
class FlagsStore extends ReactiveStore {
|
|
126
|
+
enabled = true;
|
|
127
|
+
}
|
|
128
|
+
Storable()(FlagsStore, {} as ClassDecoratorContext);
|
|
129
|
+
|
|
130
|
+
const { ctx, run } = makeFieldCtx("flags");
|
|
131
|
+
Store(FlagsStore)(undefined, ctx);
|
|
132
|
+
const obj: Record<string, unknown> = {};
|
|
133
|
+
run(obj);
|
|
134
|
+
|
|
135
|
+
expect(obj.flags).toBe(store(FlagsStore));
|
|
136
|
+
});
|
|
125
137
|
});
|
|
126
138
|
|
|
127
|
-
// ──
|
|
139
|
+
// ── store() ────────────────────────────────────────────────────────────────
|
|
128
140
|
|
|
129
|
-
describe("
|
|
141
|
+
describe("store()", () => {
|
|
130
142
|
it("returns a store instance without requiring a class field", () => {
|
|
131
143
|
class ProfileStore extends ReactiveStore {
|
|
132
144
|
name = "alice";
|
|
133
145
|
}
|
|
134
|
-
|
|
146
|
+
Storable()(ProfileStore, {} as ClassDecoratorContext);
|
|
135
147
|
|
|
136
|
-
const
|
|
137
|
-
expect(
|
|
138
|
-
expect(
|
|
148
|
+
const instance = store(ProfileStore);
|
|
149
|
+
expect(instance).toBeInstanceOf(ProfileStore);
|
|
150
|
+
expect(instance.name).toBe("alice");
|
|
139
151
|
});
|
|
140
152
|
|
|
141
153
|
it("returns the same singleton instance on repeated calls", () => {
|
|
142
154
|
class TimerStore extends ReactiveStore {
|
|
143
155
|
ticks = 0;
|
|
144
156
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
expect(useStore(TimerStore)).toBe(useStore(TimerStore));
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("shares the same instance as @UseStore (same registry)", () => {
|
|
151
|
-
class FlagsStore extends ReactiveStore {
|
|
152
|
-
enabled = true;
|
|
153
|
-
}
|
|
154
|
-
Store()(FlagsStore, {} as ClassDecoratorContext);
|
|
155
|
-
|
|
156
|
-
const { ctx, run } = makeFieldCtx("flags");
|
|
157
|
-
UseStore(FlagsStore)(undefined, ctx);
|
|
158
|
-
const obj: Record<string, unknown> = {};
|
|
159
|
-
run(obj);
|
|
157
|
+
Storable()(TimerStore, {} as ClassDecoratorContext);
|
|
160
158
|
|
|
161
|
-
expect(
|
|
159
|
+
expect(store(TimerStore)).toBe(store(TimerStore));
|
|
162
160
|
});
|
|
163
161
|
|
|
164
162
|
it("lazily creates the instance on first call", () => {
|
|
165
163
|
class LazyStore extends ReactiveStore {
|
|
166
164
|
ready = false;
|
|
167
165
|
}
|
|
168
|
-
|
|
166
|
+
Storable()(LazyStore, {} as ClassDecoratorContext);
|
|
169
167
|
|
|
170
|
-
const instance =
|
|
168
|
+
const instance = store(LazyStore);
|
|
171
169
|
expect(instance).toBeInstanceOf(LazyStore);
|
|
172
170
|
});
|
|
173
171
|
|
|
174
|
-
it("works without @
|
|
172
|
+
it("works without @Storable — creates a plain instance", () => {
|
|
175
173
|
class BareStore extends ReactiveStore {
|
|
176
174
|
value = 7;
|
|
177
175
|
}
|
|
178
|
-
const instance =
|
|
176
|
+
const instance = store(BareStore);
|
|
179
177
|
expect(instance).toBeInstanceOf(BareStore);
|
|
180
178
|
expect(instance.value).toBe(7);
|
|
181
179
|
});
|
|
@@ -184,9 +182,9 @@ describe("useStore", () => {
|
|
|
184
182
|
class ThemeStore extends ReactiveStore {
|
|
185
183
|
dark = false;
|
|
186
184
|
}
|
|
187
|
-
|
|
185
|
+
Storable()(ThemeStore, {} as ClassDecoratorContext);
|
|
188
186
|
|
|
189
|
-
|
|
190
|
-
expect(
|
|
187
|
+
store(ThemeStore).dark = true;
|
|
188
|
+
expect(store(ThemeStore).dark).toBe(true);
|
|
191
189
|
});
|
|
192
190
|
});
|
package/src/decorators.ts
CHANGED
|
@@ -11,7 +11,7 @@ export class ReactiveStore implements ReactiveHost {
|
|
|
11
11
|
_stateDirty = false;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function
|
|
14
|
+
export function Storable() {
|
|
15
15
|
return function (
|
|
16
16
|
constructor: new (...args: unknown[]) => ReactiveStore,
|
|
17
17
|
_context: ClassDecoratorContext,
|
|
@@ -20,31 +20,20 @@ export function Store() {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export function
|
|
23
|
+
export function store<T extends ReactiveStore>(StoreClass: new () => T): T {
|
|
24
24
|
if (!storeRegistry.has(StoreClass) || storeRegistry.get(StoreClass) === null) {
|
|
25
25
|
storeRegistry.set(StoreClass, new StoreClass());
|
|
26
26
|
}
|
|
27
27
|
return storeRegistry.get(StoreClass) as T;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export function
|
|
31
|
-
const cache = new WeakMap<object, unknown>();
|
|
32
|
-
|
|
30
|
+
export function Store(StoreConstructor: new () => unknown) {
|
|
33
31
|
return createFieldDecorator({
|
|
34
32
|
bind(_instance, _name, _initialValue): FieldBinding {
|
|
35
33
|
return {
|
|
36
34
|
descriptor: {
|
|
37
35
|
get(this: object): unknown {
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
!storeRegistry.has(StoreConstructor) ||
|
|
41
|
-
storeRegistry.get(StoreConstructor) === null
|
|
42
|
-
) {
|
|
43
|
-
storeRegistry.set(StoreConstructor, new StoreConstructor());
|
|
44
|
-
}
|
|
45
|
-
cache.set(this, storeRegistry.get(StoreConstructor));
|
|
46
|
-
}
|
|
47
|
-
return cache.get(this);
|
|
36
|
+
return store(StoreConstructor as new () => ReactiveStore);
|
|
48
37
|
},
|
|
49
38
|
},
|
|
50
39
|
};
|
package/src/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Storable, Store, store, ReactiveStore } from "./decorators";
|