bunja 2.0.0-alpha.5 → 2.0.0-alpha.6
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/bunja.ts +79 -17
- package/deno.json +5 -3
- package/dist/{bunja-DsftUL38.js → bunja-BB7ru8D0.js} +55 -19
- package/dist/{bunja-Bj2Zho1e.d.ts → bunja-CqyhNWOx.d.ts} +13 -2
- package/dist/{bunja-WQqJyoyx.d.cts → bunja-P0kiwZQC.d.cts} +13 -2
- package/dist/{bunja-i3L_5FKm.cjs → bunja-bhXTtuLY.cjs} +66 -18
- package/dist/bunja.cjs +4 -2
- package/dist/bunja.d.cts +2 -2
- package/dist/bunja.d.ts +2 -2
- package/dist/bunja.js +2 -2
- package/dist/chunk-CUT6urMc.cjs +30 -0
- package/dist/react.cjs +14 -35
- package/dist/react.d.cts +7 -5
- package/dist/react.d.ts +7 -5
- package/dist/react.js +12 -11
- package/dist/solid.cjs +57 -0
- package/dist/solid.d.cts +14 -0
- package/dist/solid.d.ts +14 -0
- package/dist/solid.js +51 -0
- package/package.json +21 -4
- package/react.ts +18 -20
- package/solid.ts +101 -0
- package/test.ts +65 -20
- package/tsconfig.json +0 -1
- package/tsdown.config.ts +1 -1
- package/.vscode/settings.json +0 -5
- package/README.md +0 -239
- package/codemod/bunja-v1-to-v2.js +0 -118
- package/compat/bunja-v1.ts +0 -48
- package/deno.lock +0 -671
- package/presentations/2024-11-28-en.pdf +0 -0
- package/presentations/2024-11-28.pdf +0 -0
- package/presentations/README.md +0 -9
package/bunja.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface BunjaFn {
|
|
2
2
|
<T>(init: () => T): Bunja<T>;
|
|
3
3
|
use: BunjaUseFn;
|
|
4
|
+
fork: BunjaForkFn;
|
|
4
5
|
effect: BunjaEffectFn;
|
|
5
6
|
}
|
|
6
7
|
export const bunja: BunjaFn = bunjaFn;
|
|
@@ -8,9 +9,14 @@ function bunjaFn<T>(init: () => T): Bunja<T> {
|
|
|
8
9
|
return new Bunja(init);
|
|
9
10
|
}
|
|
10
11
|
bunjaFn.use = invalidUse as BunjaUseFn;
|
|
12
|
+
bunjaFn.fork = invalidFork as BunjaForkFn;
|
|
11
13
|
bunjaFn.effect = invalidEffect as BunjaEffectFn;
|
|
12
14
|
|
|
13
15
|
export type BunjaUseFn = <T>(dep: Dep<T>) => T;
|
|
16
|
+
export type BunjaForkFn = <T>(
|
|
17
|
+
bunja: Bunja<T>,
|
|
18
|
+
scopeValuePairs: ScopeValuePair<any>[],
|
|
19
|
+
) => T;
|
|
14
20
|
export type BunjaEffectFn = (callback: BunjaEffectCallback) => void;
|
|
15
21
|
export type BunjaEffectCallback = () => (() => void) | void;
|
|
16
22
|
|
|
@@ -18,8 +24,14 @@ export function createScope<T>(hash?: HashFn<T>): Scope<T> {
|
|
|
18
24
|
return new Scope(hash);
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
export
|
|
22
|
-
|
|
27
|
+
export interface CreateBunjaStoreConfig {
|
|
28
|
+
wrapInstance?: WrapInstanceFn;
|
|
29
|
+
}
|
|
30
|
+
export function createBunjaStore(config?: CreateBunjaStoreConfig): BunjaStore {
|
|
31
|
+
const { wrapInstance = defaultWrapInstanceFn } = config ?? {};
|
|
32
|
+
const store = new BunjaStore();
|
|
33
|
+
store.wrapInstance = wrapInstance;
|
|
34
|
+
return store;
|
|
23
35
|
}
|
|
24
36
|
|
|
25
37
|
export type Dep<T> = Bunja<T> | Scope<T>;
|
|
@@ -29,6 +41,11 @@ function invalidUse() {
|
|
|
29
41
|
"`bunja.use` can only be used inside a bunja init function.",
|
|
30
42
|
);
|
|
31
43
|
}
|
|
44
|
+
function invalidFork() {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"`bunja.fork` can only be used inside a bunja init function.",
|
|
47
|
+
);
|
|
48
|
+
}
|
|
32
49
|
function invalidEffect() {
|
|
33
50
|
throw new Error(
|
|
34
51
|
"`bunja.effect` can only be used inside a bunja init function.",
|
|
@@ -48,10 +65,14 @@ interface BunjaBakingContext {
|
|
|
48
65
|
currentBunja: Bunja<unknown>;
|
|
49
66
|
}
|
|
50
67
|
|
|
68
|
+
export type WrapInstanceFn = <T>(fn: (dispose: () => void) => T) => T;
|
|
69
|
+
const defaultWrapInstanceFn: WrapInstanceFn = (fn) => fn(noop);
|
|
70
|
+
|
|
51
71
|
export class BunjaStore {
|
|
52
72
|
#bunjas: Record<string, BunjaInstance> = {};
|
|
53
73
|
#scopes: Map<Scope<unknown>, Map<unknown, ScopeInstance>> = new Map();
|
|
54
74
|
#bakingContext: BunjaBakingContext | undefined;
|
|
75
|
+
wrapInstance: WrapInstanceFn = defaultWrapInstanceFn;
|
|
55
76
|
dispose(): void {
|
|
56
77
|
for (const instance of Object.values(this.#bunjas)) instance.dispose();
|
|
57
78
|
for (const instanceMap of Object.values(this.#scopes)) {
|
|
@@ -73,11 +94,9 @@ export class BunjaStore {
|
|
|
73
94
|
bunjaInstance.add();
|
|
74
95
|
scopeInstanceMap.forEach((instance) => instance.add());
|
|
75
96
|
const unmount = () => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
scopeInstanceMap.forEach((instance) => instance.sub());
|
|
80
|
-
});
|
|
97
|
+
bunjaInstanceMap.forEach((instance) => instance.sub());
|
|
98
|
+
bunjaInstance.sub();
|
|
99
|
+
scopeInstanceMap.forEach((instance) => instance.sub());
|
|
81
100
|
};
|
|
82
101
|
return unmount;
|
|
83
102
|
},
|
|
@@ -150,12 +169,13 @@ export class BunjaStore {
|
|
|
150
169
|
if (dep instanceof Scope) return useScope(dep) as T;
|
|
151
170
|
throw new Error("`bunja.use` can only be used with Bunja or Scope.");
|
|
152
171
|
};
|
|
172
|
+
const originalBakingContext = this.#bakingContext;
|
|
153
173
|
try {
|
|
154
174
|
this.#bakingContext = { currentBunja: bunja };
|
|
155
175
|
const bunjaInstance = this.#getBunjaInstance(bunja, scopeInstanceMap);
|
|
156
176
|
return { bunjaInstance, bunjaInstanceMap, scopeInstanceMap };
|
|
157
177
|
} finally {
|
|
158
|
-
this.#bakingContext =
|
|
178
|
+
this.#bakingContext = originalBakingContext;
|
|
159
179
|
}
|
|
160
180
|
}
|
|
161
181
|
#getBunjaInstance<T>(
|
|
@@ -163,26 +183,38 @@ export class BunjaStore {
|
|
|
163
183
|
scopeInstanceMap: ScopeInstanceMap,
|
|
164
184
|
): BunjaInstance {
|
|
165
185
|
const originalEffect = bunjaFn.effect;
|
|
186
|
+
const originalFork = bunjaFn.fork;
|
|
166
187
|
const prevBunja = this.#bakingContext?.currentBunja;
|
|
167
188
|
try {
|
|
168
189
|
const effects: BunjaEffectCallback[] = [];
|
|
169
190
|
bunjaFn.effect = (callback: BunjaEffectCallback) => {
|
|
170
191
|
effects.push(callback);
|
|
171
192
|
};
|
|
193
|
+
bunjaFn.fork = (b, scopeValuePairs) => {
|
|
194
|
+
const readScope = createReadScopeFn(scopeValuePairs, bunjaFn.use);
|
|
195
|
+
const { value, mount } = this.get(b, readScope);
|
|
196
|
+
bunjaFn.effect(mount);
|
|
197
|
+
return value;
|
|
198
|
+
};
|
|
172
199
|
if (this.#bakingContext) this.#bakingContext.currentBunja = bunja;
|
|
173
200
|
if (bunja.baked) {
|
|
174
201
|
const id = bunja.calcInstanceId(scopeInstanceMap);
|
|
175
202
|
if (id in this.#bunjas) return this.#bunjas[id];
|
|
176
|
-
|
|
177
|
-
|
|
203
|
+
return this.wrapInstance((dispose) => {
|
|
204
|
+
const value = bunja.init();
|
|
205
|
+
return this.#createBunjaInstance(id, value, effects, dispose);
|
|
206
|
+
});
|
|
178
207
|
} else {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
208
|
+
return this.wrapInstance((dispose) => {
|
|
209
|
+
const value = bunja.init();
|
|
210
|
+
bunja.bake();
|
|
211
|
+
const id = bunja.calcInstanceId(scopeInstanceMap);
|
|
212
|
+
return this.#createBunjaInstance(id, value, effects, dispose);
|
|
213
|
+
});
|
|
183
214
|
}
|
|
184
215
|
} finally {
|
|
185
216
|
bunjaFn.effect = originalEffect;
|
|
217
|
+
bunjaFn.fork = originalFork;
|
|
186
218
|
if (this.#bakingContext) this.#bakingContext.currentBunja = prevBunja!;
|
|
187
219
|
}
|
|
188
220
|
}
|
|
@@ -200,6 +232,7 @@ export class BunjaStore {
|
|
|
200
232
|
id: string,
|
|
201
233
|
value: unknown,
|
|
202
234
|
effects: BunjaEffectCallback[],
|
|
235
|
+
dispose: () => void,
|
|
203
236
|
): BunjaInstance {
|
|
204
237
|
const effect = () => {
|
|
205
238
|
const cleanups = effects
|
|
@@ -207,14 +240,28 @@ export class BunjaStore {
|
|
|
207
240
|
.filter(Boolean) as (() => void)[];
|
|
208
241
|
return () => cleanups.forEach((cleanup) => cleanup());
|
|
209
242
|
};
|
|
210
|
-
const
|
|
211
|
-
|
|
243
|
+
const bunjaInstance = new BunjaInstance(id, value, effect, () => {
|
|
244
|
+
dispose();
|
|
245
|
+
delete this.#bunjas[id];
|
|
246
|
+
});
|
|
212
247
|
this.#bunjas[id] = bunjaInstance;
|
|
213
248
|
return bunjaInstance;
|
|
214
249
|
}
|
|
215
250
|
}
|
|
216
251
|
|
|
217
252
|
export type ReadScope = <T>(scope: Scope<T>) => T;
|
|
253
|
+
export function createReadScopeFn(
|
|
254
|
+
scopeValuePairs: ScopeValuePair<any>[],
|
|
255
|
+
readScope: ReadScope,
|
|
256
|
+
): ReadScope {
|
|
257
|
+
const map = new Map(scopeValuePairs);
|
|
258
|
+
return <T>(scope: Scope<T>) => {
|
|
259
|
+
if (map.has(scope as Scope<unknown>)) {
|
|
260
|
+
return map.get(scope as Scope<unknown>) as T;
|
|
261
|
+
}
|
|
262
|
+
return readScope(scope);
|
|
263
|
+
};
|
|
264
|
+
}
|
|
218
265
|
|
|
219
266
|
export interface BunjaStoreGetResult<T> {
|
|
220
267
|
value: T;
|
|
@@ -222,6 +269,16 @@ export interface BunjaStoreGetResult<T> {
|
|
|
222
269
|
deps: unknown[];
|
|
223
270
|
}
|
|
224
271
|
|
|
272
|
+
export function delayUnmount(
|
|
273
|
+
mount: () => () => void,
|
|
274
|
+
ms: number = 0,
|
|
275
|
+
): () => () => void {
|
|
276
|
+
return () => {
|
|
277
|
+
const unmount = mount();
|
|
278
|
+
return () => setTimeout(unmount, ms);
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
225
282
|
export class Bunja<T> {
|
|
226
283
|
private static counter: number = 0;
|
|
227
284
|
readonly id: string = String(Bunja.counter++);
|
|
@@ -299,6 +356,9 @@ export class Scope<T> {
|
|
|
299
356
|
private static identity<T>(x: T): T {
|
|
300
357
|
return x;
|
|
301
358
|
}
|
|
359
|
+
bind(value: T): ScopeValuePair<T> {
|
|
360
|
+
return [this, value];
|
|
361
|
+
}
|
|
302
362
|
toString(): string {
|
|
303
363
|
const { id, debugLabel } = this;
|
|
304
364
|
return `[Scope:${id}${debugLabel && ` - ${debugLabel}`}]`;
|
|
@@ -306,8 +366,8 @@ export class Scope<T> {
|
|
|
306
366
|
}
|
|
307
367
|
|
|
308
368
|
export type HashFn<T> = (value: T) => unknown;
|
|
369
|
+
export type ScopeValuePair<T> = [Scope<T>, T];
|
|
309
370
|
|
|
310
|
-
const noop = () => {};
|
|
311
371
|
abstract class RefCounter {
|
|
312
372
|
#count: number = 0;
|
|
313
373
|
abstract dispose(): void;
|
|
@@ -369,3 +429,5 @@ function toposort<T extends Toposortable>(nodes: T[]): T[] {
|
|
|
369
429
|
for (const node of nodes) visit(node);
|
|
370
430
|
return result;
|
|
371
431
|
}
|
|
432
|
+
|
|
433
|
+
const noop = () => {};
|
package/deno.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@disjukr/bunja",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.6",
|
|
4
4
|
"license": "Zlib",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./bunja.ts",
|
|
7
|
-
"./react": "./react.ts"
|
|
8
|
-
|
|
7
|
+
"./react": "./react.ts",
|
|
8
|
+
"./solid": "./solid.ts"
|
|
9
|
+
},
|
|
10
|
+
"exclude": ["dist"]
|
|
9
11
|
}
|
|
@@ -4,23 +4,32 @@ function bunjaFn(init) {
|
|
|
4
4
|
return new Bunja(init);
|
|
5
5
|
}
|
|
6
6
|
bunjaFn.use = invalidUse;
|
|
7
|
+
bunjaFn.fork = invalidFork;
|
|
7
8
|
bunjaFn.effect = invalidEffect;
|
|
8
9
|
function createScope(hash) {
|
|
9
10
|
return new Scope(hash);
|
|
10
11
|
}
|
|
11
|
-
function createBunjaStore() {
|
|
12
|
-
|
|
12
|
+
function createBunjaStore(config) {
|
|
13
|
+
const { wrapInstance = defaultWrapInstanceFn } = config ?? {};
|
|
14
|
+
const store = new BunjaStore();
|
|
15
|
+
store.wrapInstance = wrapInstance;
|
|
16
|
+
return store;
|
|
13
17
|
}
|
|
14
18
|
function invalidUse() {
|
|
15
19
|
throw new Error("`bunja.use` can only be used inside a bunja init function.");
|
|
16
20
|
}
|
|
21
|
+
function invalidFork() {
|
|
22
|
+
throw new Error("`bunja.fork` can only be used inside a bunja init function.");
|
|
23
|
+
}
|
|
17
24
|
function invalidEffect() {
|
|
18
25
|
throw new Error("`bunja.effect` can only be used inside a bunja init function.");
|
|
19
26
|
}
|
|
27
|
+
const defaultWrapInstanceFn = (fn) => fn(noop);
|
|
20
28
|
var BunjaStore = class {
|
|
21
29
|
#bunjas = {};
|
|
22
30
|
#scopes = /* @__PURE__ */ new Map();
|
|
23
31
|
#bakingContext;
|
|
32
|
+
wrapInstance = defaultWrapInstanceFn;
|
|
24
33
|
dispose() {
|
|
25
34
|
for (const instance of Object.values(this.#bunjas)) instance.dispose();
|
|
26
35
|
for (const instanceMap of Object.values(this.#scopes)) for (const instance of instanceMap.values()) instance.dispose();
|
|
@@ -38,11 +47,9 @@ var BunjaStore = class {
|
|
|
38
47
|
bunjaInstance.add();
|
|
39
48
|
scopeInstanceMap.forEach((instance) => instance.add());
|
|
40
49
|
const unmount = () => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
scopeInstanceMap.forEach((instance) => instance.sub());
|
|
45
|
-
});
|
|
50
|
+
bunjaInstanceMap.forEach((instance) => instance.sub());
|
|
51
|
+
bunjaInstance.sub();
|
|
52
|
+
scopeInstanceMap.forEach((instance) => instance.sub());
|
|
46
53
|
};
|
|
47
54
|
return unmount;
|
|
48
55
|
},
|
|
@@ -91,6 +98,7 @@ var BunjaStore = class {
|
|
|
91
98
|
if (dep instanceof Scope) return useScope(dep);
|
|
92
99
|
throw new Error("`bunja.use` can only be used with Bunja or Scope.");
|
|
93
100
|
};
|
|
101
|
+
const originalBakingContext = this.#bakingContext;
|
|
94
102
|
try {
|
|
95
103
|
this.#bakingContext = { currentBunja: bunja$1 };
|
|
96
104
|
const bunjaInstance = this.#getBunjaInstance(bunja$1, scopeInstanceMap);
|
|
@@ -100,31 +108,41 @@ var BunjaStore = class {
|
|
|
100
108
|
scopeInstanceMap
|
|
101
109
|
};
|
|
102
110
|
} finally {
|
|
103
|
-
this.#bakingContext =
|
|
111
|
+
this.#bakingContext = originalBakingContext;
|
|
104
112
|
}
|
|
105
113
|
}
|
|
106
114
|
#getBunjaInstance(bunja$1, scopeInstanceMap) {
|
|
107
115
|
const originalEffect = bunjaFn.effect;
|
|
116
|
+
const originalFork = bunjaFn.fork;
|
|
108
117
|
const prevBunja = this.#bakingContext?.currentBunja;
|
|
109
118
|
try {
|
|
110
119
|
const effects = [];
|
|
111
120
|
bunjaFn.effect = (callback) => {
|
|
112
121
|
effects.push(callback);
|
|
113
122
|
};
|
|
123
|
+
bunjaFn.fork = (b, scopeValuePairs) => {
|
|
124
|
+
const readScope = createReadScopeFn(scopeValuePairs, bunjaFn.use);
|
|
125
|
+
const { value, mount } = this.get(b, readScope);
|
|
126
|
+
bunjaFn.effect(mount);
|
|
127
|
+
return value;
|
|
128
|
+
};
|
|
114
129
|
if (this.#bakingContext) this.#bakingContext.currentBunja = bunja$1;
|
|
115
130
|
if (bunja$1.baked) {
|
|
116
131
|
const id = bunja$1.calcInstanceId(scopeInstanceMap);
|
|
117
132
|
if (id in this.#bunjas) return this.#bunjas[id];
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
133
|
+
return this.wrapInstance((dispose) => {
|
|
134
|
+
const value = bunja$1.init();
|
|
135
|
+
return this.#createBunjaInstance(id, value, effects, dispose);
|
|
136
|
+
});
|
|
137
|
+
} else return this.wrapInstance((dispose) => {
|
|
138
|
+
const value = bunja$1.init();
|
|
122
139
|
bunja$1.bake();
|
|
123
140
|
const id = bunja$1.calcInstanceId(scopeInstanceMap);
|
|
124
|
-
return this.#createBunjaInstance(id,
|
|
125
|
-
}
|
|
141
|
+
return this.#createBunjaInstance(id, value, effects, dispose);
|
|
142
|
+
});
|
|
126
143
|
} finally {
|
|
127
144
|
bunjaFn.effect = originalEffect;
|
|
145
|
+
bunjaFn.fork = originalFork;
|
|
128
146
|
if (this.#bakingContext) this.#bakingContext.currentBunja = prevBunja;
|
|
129
147
|
}
|
|
130
148
|
}
|
|
@@ -133,17 +151,32 @@ var BunjaStore = class {
|
|
|
133
151
|
const instanceMap = this.#scopes.get(scope) ?? this.#scopes.set(scope, /* @__PURE__ */ new Map()).get(scope);
|
|
134
152
|
return instanceMap.get(key) ?? instanceMap.set(key, new ScopeInstance(value, () => instanceMap.delete(key))).get(key);
|
|
135
153
|
}
|
|
136
|
-
#createBunjaInstance(id, value, effects) {
|
|
154
|
+
#createBunjaInstance(id, value, effects, dispose) {
|
|
137
155
|
const effect = () => {
|
|
138
156
|
const cleanups = effects.map((effect$1) => effect$1()).filter(Boolean);
|
|
139
157
|
return () => cleanups.forEach((cleanup) => cleanup());
|
|
140
158
|
};
|
|
141
|
-
const
|
|
142
|
-
|
|
159
|
+
const bunjaInstance = new BunjaInstance(id, value, effect, () => {
|
|
160
|
+
dispose();
|
|
161
|
+
delete this.#bunjas[id];
|
|
162
|
+
});
|
|
143
163
|
this.#bunjas[id] = bunjaInstance;
|
|
144
164
|
return bunjaInstance;
|
|
145
165
|
}
|
|
146
166
|
};
|
|
167
|
+
function createReadScopeFn(scopeValuePairs, readScope) {
|
|
168
|
+
const map = new Map(scopeValuePairs);
|
|
169
|
+
return (scope) => {
|
|
170
|
+
if (map.has(scope)) return map.get(scope);
|
|
171
|
+
return readScope(scope);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function delayUnmount(mount, ms = 0) {
|
|
175
|
+
return () => {
|
|
176
|
+
const unmount = mount();
|
|
177
|
+
return () => setTimeout(unmount, ms);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
147
180
|
var Bunja = class Bunja {
|
|
148
181
|
static counter = 0;
|
|
149
182
|
id = String(Bunja.counter++);
|
|
@@ -211,12 +244,14 @@ var Scope = class Scope {
|
|
|
211
244
|
static identity(x) {
|
|
212
245
|
return x;
|
|
213
246
|
}
|
|
247
|
+
bind(value) {
|
|
248
|
+
return [this, value];
|
|
249
|
+
}
|
|
214
250
|
toString() {
|
|
215
251
|
const { id, debugLabel } = this;
|
|
216
252
|
return `[Scope:${id}${debugLabel && ` - ${debugLabel}`}]`;
|
|
217
253
|
}
|
|
218
254
|
};
|
|
219
|
-
const noop = () => {};
|
|
220
255
|
var RefCounter = class {
|
|
221
256
|
#count = 0;
|
|
222
257
|
add() {
|
|
@@ -269,6 +304,7 @@ function toposort(nodes) {
|
|
|
269
304
|
for (const node of nodes) visit(node);
|
|
270
305
|
return result;
|
|
271
306
|
}
|
|
307
|
+
const noop = () => {};
|
|
272
308
|
|
|
273
309
|
//#endregion
|
|
274
|
-
export { Bunja, BunjaStore, Scope, bunja, createBunjaStore, createScope };
|
|
310
|
+
export { Bunja, BunjaStore, Scope, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
|
|
@@ -2,26 +2,35 @@
|
|
|
2
2
|
interface BunjaFn {
|
|
3
3
|
<T>(init: () => T): Bunja<T>;
|
|
4
4
|
use: BunjaUseFn;
|
|
5
|
+
fork: BunjaForkFn;
|
|
5
6
|
effect: BunjaEffectFn;
|
|
6
7
|
}
|
|
7
8
|
declare const bunja: BunjaFn;
|
|
8
9
|
type BunjaUseFn = <T>(dep: Dep<T>) => T;
|
|
10
|
+
type BunjaForkFn = <T>(bunja: Bunja<T>, scopeValuePairs: ScopeValuePair<any>[]) => T;
|
|
9
11
|
type BunjaEffectFn = (callback: BunjaEffectCallback) => void;
|
|
10
12
|
type BunjaEffectCallback = () => (() => void) | void;
|
|
11
13
|
declare function createScope<T>(hash?: HashFn<T>): Scope<T>;
|
|
12
|
-
|
|
14
|
+
interface CreateBunjaStoreConfig {
|
|
15
|
+
wrapInstance?: WrapInstanceFn;
|
|
16
|
+
}
|
|
17
|
+
declare function createBunjaStore(config?: CreateBunjaStoreConfig): BunjaStore;
|
|
13
18
|
type Dep<T> = Bunja<T> | Scope<T>;
|
|
19
|
+
type WrapInstanceFn = <T>(fn: (dispose: () => void) => T) => T;
|
|
14
20
|
declare class BunjaStore {
|
|
15
21
|
#private;
|
|
22
|
+
wrapInstance: WrapInstanceFn;
|
|
16
23
|
dispose(): void;
|
|
17
24
|
get<T>(bunja: Bunja<T>, readScope: ReadScope): BunjaStoreGetResult<T>;
|
|
18
25
|
}
|
|
19
26
|
type ReadScope = <T>(scope: Scope<T>) => T;
|
|
27
|
+
declare function createReadScopeFn(scopeValuePairs: ScopeValuePair<any>[], readScope: ReadScope): ReadScope;
|
|
20
28
|
interface BunjaStoreGetResult<T> {
|
|
21
29
|
value: T;
|
|
22
30
|
mount: () => () => void;
|
|
23
31
|
deps: unknown[];
|
|
24
32
|
}
|
|
33
|
+
declare function delayUnmount(mount: () => () => void, ms?: number): () => () => void;
|
|
25
34
|
declare class Bunja<T> {
|
|
26
35
|
#private;
|
|
27
36
|
init: () => T;
|
|
@@ -46,9 +55,11 @@ declare class Scope<T> {
|
|
|
46
55
|
debugLabel: string;
|
|
47
56
|
constructor(hash?: HashFn<T>);
|
|
48
57
|
private static identity;
|
|
58
|
+
bind(value: T): ScopeValuePair<T>;
|
|
49
59
|
toString(): string;
|
|
50
60
|
}
|
|
51
61
|
type HashFn<T> = (value: T) => unknown;
|
|
62
|
+
type ScopeValuePair<T> = [Scope<T>, T];
|
|
52
63
|
declare abstract class RefCounter {
|
|
53
64
|
#private;
|
|
54
65
|
abstract dispose(): void;
|
|
@@ -63,4 +74,4 @@ declare class ScopeInstance extends RefCounter {
|
|
|
63
74
|
constructor(value: unknown, dispose: () => void);
|
|
64
75
|
}
|
|
65
76
|
//#endregion
|
|
66
|
-
export { Bunja, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaStore, BunjaStoreGetResult, BunjaUseFn, Dep, HashFn, ReadScope, Scope, bunja, createBunjaStore, createScope };
|
|
77
|
+
export { Bunja, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaForkFn, BunjaStore, BunjaStoreGetResult, BunjaUseFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
|
|
@@ -2,26 +2,35 @@
|
|
|
2
2
|
interface BunjaFn {
|
|
3
3
|
<T>(init: () => T): Bunja<T>;
|
|
4
4
|
use: BunjaUseFn;
|
|
5
|
+
fork: BunjaForkFn;
|
|
5
6
|
effect: BunjaEffectFn;
|
|
6
7
|
}
|
|
7
8
|
declare const bunja: BunjaFn;
|
|
8
9
|
type BunjaUseFn = <T>(dep: Dep<T>) => T;
|
|
10
|
+
type BunjaForkFn = <T>(bunja: Bunja<T>, scopeValuePairs: ScopeValuePair<any>[]) => T;
|
|
9
11
|
type BunjaEffectFn = (callback: BunjaEffectCallback) => void;
|
|
10
12
|
type BunjaEffectCallback = () => (() => void) | void;
|
|
11
13
|
declare function createScope<T>(hash?: HashFn<T>): Scope<T>;
|
|
12
|
-
|
|
14
|
+
interface CreateBunjaStoreConfig {
|
|
15
|
+
wrapInstance?: WrapInstanceFn;
|
|
16
|
+
}
|
|
17
|
+
declare function createBunjaStore(config?: CreateBunjaStoreConfig): BunjaStore;
|
|
13
18
|
type Dep<T> = Bunja<T> | Scope<T>;
|
|
19
|
+
type WrapInstanceFn = <T>(fn: (dispose: () => void) => T) => T;
|
|
14
20
|
declare class BunjaStore {
|
|
15
21
|
#private;
|
|
22
|
+
wrapInstance: WrapInstanceFn;
|
|
16
23
|
dispose(): void;
|
|
17
24
|
get<T>(bunja: Bunja<T>, readScope: ReadScope): BunjaStoreGetResult<T>;
|
|
18
25
|
}
|
|
19
26
|
type ReadScope = <T>(scope: Scope<T>) => T;
|
|
27
|
+
declare function createReadScopeFn(scopeValuePairs: ScopeValuePair<any>[], readScope: ReadScope): ReadScope;
|
|
20
28
|
interface BunjaStoreGetResult<T> {
|
|
21
29
|
value: T;
|
|
22
30
|
mount: () => () => void;
|
|
23
31
|
deps: unknown[];
|
|
24
32
|
}
|
|
33
|
+
declare function delayUnmount(mount: () => () => void, ms?: number): () => () => void;
|
|
25
34
|
declare class Bunja<T> {
|
|
26
35
|
#private;
|
|
27
36
|
init: () => T;
|
|
@@ -46,9 +55,11 @@ declare class Scope<T> {
|
|
|
46
55
|
debugLabel: string;
|
|
47
56
|
constructor(hash?: HashFn<T>);
|
|
48
57
|
private static identity;
|
|
58
|
+
bind(value: T): ScopeValuePair<T>;
|
|
49
59
|
toString(): string;
|
|
50
60
|
}
|
|
51
61
|
type HashFn<T> = (value: T) => unknown;
|
|
62
|
+
type ScopeValuePair<T> = [Scope<T>, T];
|
|
52
63
|
declare abstract class RefCounter {
|
|
53
64
|
#private;
|
|
54
65
|
abstract dispose(): void;
|
|
@@ -63,4 +74,4 @@ declare class ScopeInstance extends RefCounter {
|
|
|
63
74
|
constructor(value: unknown, dispose: () => void);
|
|
64
75
|
}
|
|
65
76
|
//#endregion
|
|
66
|
-
export { Bunja, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaStore, BunjaStoreGetResult, BunjaUseFn, Dep, HashFn, ReadScope, Scope, bunja, createBunjaStore, createScope };
|
|
77
|
+
export { Bunja, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaForkFn, BunjaStore, BunjaStoreGetResult, BunjaUseFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
|