@virentia/effector 0.1.1 → 0.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/README.md +40 -33
- package/dist/index.cjs +283 -485
- package/dist/index.d.cts +29 -181
- package/dist/index.d.mts +29 -181
- package/dist/index.mjs +284 -472
- package/package.json +8 -5
package/dist/index.cjs
CHANGED
|
@@ -23,515 +23,313 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
let _virentia_core = require("@virentia/core");
|
|
25
25
|
_virentia_core = __toESM(_virentia_core, 1);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
function isEvent(value) {
|
|
51
|
-
return isUnit(value) && value[unitKind] === "event";
|
|
52
|
-
}
|
|
53
|
-
function isStore(value) {
|
|
54
|
-
return isUnit(value) && value[unitKind] === "store";
|
|
55
|
-
}
|
|
56
|
-
function isEffect(value) {
|
|
57
|
-
return isUnit(value) && value[unitKind] === "effect";
|
|
58
|
-
}
|
|
59
|
-
function isTargetable(value) {
|
|
60
|
-
return isEvent(value) || isEffect(value) || isStore(value) && typeof value.setState === "function";
|
|
61
|
-
}
|
|
62
|
-
function isScope(value) {
|
|
63
|
-
return Boolean(value && typeof value === "object" && "__core" in value && !(unitKind in value));
|
|
64
|
-
}
|
|
65
|
-
function isScopeError(error) {
|
|
66
|
-
return error instanceof Error && error.message === "Scope is required";
|
|
67
|
-
}
|
|
68
|
-
//#endregion
|
|
69
|
-
//#region lib/shared.ts
|
|
70
|
-
const defaultScope = _virentia_core.scope();
|
|
71
|
-
const compatScopes = /* @__PURE__ */ new WeakMap();
|
|
72
|
-
const storesBySid = /* @__PURE__ */ new Map();
|
|
73
|
-
const nativeStoreKeys = new Set([
|
|
74
|
-
"node",
|
|
75
|
-
"writable",
|
|
76
|
-
"subscribe",
|
|
77
|
-
"map",
|
|
78
|
-
"filter",
|
|
79
|
-
"filterMap"
|
|
80
|
-
]);
|
|
81
|
-
function createCompatScope(scope) {
|
|
82
|
-
const existing = compatScopes.get(scope);
|
|
83
|
-
if (existing) return existing;
|
|
84
|
-
const compatScope = {
|
|
85
|
-
__core: scope,
|
|
86
|
-
__changedSids: /* @__PURE__ */ new Set(),
|
|
87
|
-
getState(store) {
|
|
88
|
-
return store.getState(this);
|
|
89
|
-
}
|
|
26
|
+
let effector = require("effector");
|
|
27
|
+
//#region lib/index.ts
|
|
28
|
+
function createEffectorCompatibility(_options = {}) {
|
|
29
|
+
const runtimes = /* @__PURE__ */ new Set();
|
|
30
|
+
const effectorByVirentia = /* @__PURE__ */ new WeakMap();
|
|
31
|
+
const virentiaByEffector = /* @__PURE__ */ new WeakMap();
|
|
32
|
+
const installers = /* @__PURE__ */ new Set();
|
|
33
|
+
return {
|
|
34
|
+
associate,
|
|
35
|
+
ensureAssociation(config = {}) {
|
|
36
|
+
return ensureAssociation(config);
|
|
37
|
+
},
|
|
38
|
+
link(from, to, map) {
|
|
39
|
+
const definition = {
|
|
40
|
+
from,
|
|
41
|
+
to,
|
|
42
|
+
map
|
|
43
|
+
};
|
|
44
|
+
const installer = (runtime) => installLink(runtime, definition);
|
|
45
|
+
return registerInstaller(installer);
|
|
46
|
+
},
|
|
47
|
+
asEffector: ((unit) => createEffectorAdapter(unit)),
|
|
48
|
+
asVirentia: ((unit) => createVirentiaAdapter(unit))
|
|
90
49
|
};
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (!isScopeError(error)) throw error;
|
|
100
|
-
return _virentia_core.scoped(defaultScope, fn);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
function callWithFallback(unit) {
|
|
104
|
-
return ((...args) => {
|
|
105
|
-
try {
|
|
106
|
-
return unit(...args).catch((error) => {
|
|
107
|
-
if (!isScopeError(error)) throw error;
|
|
108
|
-
return _virentia_core.scoped(defaultScope, () => unit(...args));
|
|
109
|
-
});
|
|
110
|
-
} catch (error) {
|
|
111
|
-
if (!isScopeError(error)) throw error;
|
|
112
|
-
return _virentia_core.scoped(defaultScope, () => unit(...args));
|
|
50
|
+
function associate(config) {
|
|
51
|
+
if (!config.virentia) throw new Error("Effector compatibility association requires a Virentia scope");
|
|
52
|
+
if (!config.effector) throw new Error("Effector compatibility association requires an Effector scope");
|
|
53
|
+
assertScopesAvailable(config);
|
|
54
|
+
const existing = findRuntime(config);
|
|
55
|
+
if (existing) {
|
|
56
|
+
existing.assertSamePair(config);
|
|
57
|
+
return existing;
|
|
113
58
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (!filter) return true;
|
|
128
|
-
if (isStore(filter)) return filter.getState();
|
|
129
|
-
return filter(source, clock);
|
|
130
|
-
}
|
|
131
|
-
function launchTarget(target, payload) {
|
|
132
|
-
for (const unit of toArray(target)) if (isStore(unit)) unit.setState(payload);
|
|
133
|
-
else unit(payload);
|
|
134
|
-
}
|
|
135
|
-
function computeCombined(shape, fn) {
|
|
136
|
-
const value = readSource(shape);
|
|
137
|
-
return fn ? fn(value) : value;
|
|
138
|
-
}
|
|
139
|
-
function registerStore(store) {
|
|
140
|
-
if (store.sid) storesBySid.set(store.sid, store);
|
|
141
|
-
}
|
|
142
|
-
function markScopeChanged(scope, sid) {
|
|
143
|
-
if (sid) createCompatScope(scope ?? defaultScope).__changedSids.add(sid);
|
|
144
|
-
}
|
|
145
|
-
function applyStoreValues(scope, values) {
|
|
146
|
-
if (Array.isArray(values)) {
|
|
147
|
-
for (const [store, value] of values) store.setState(value, scope);
|
|
148
|
-
return;
|
|
59
|
+
const runtime = new EffectorRuntimeImpl({
|
|
60
|
+
...config,
|
|
61
|
+
release: () => {
|
|
62
|
+
runtimes.delete(runtime);
|
|
63
|
+
effectorByVirentia.delete(config.virentia);
|
|
64
|
+
virentiaByEffector.delete(config.effector);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
runtimes.add(runtime);
|
|
68
|
+
effectorByVirentia.set(config.virentia, config.effector);
|
|
69
|
+
virentiaByEffector.set(config.effector, config.virentia);
|
|
70
|
+
for (const installer of installers) runtime.addInstaller(installer);
|
|
71
|
+
return runtime;
|
|
149
72
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
73
|
+
function assertScopesAvailable(config) {
|
|
74
|
+
const existingEffector = effectorByVirentia.get(config.virentia);
|
|
75
|
+
if (existingEffector && existingEffector !== config.effector) throw new Error("Virentia scope is already associated with another Effector scope");
|
|
76
|
+
const existingVirentia = virentiaByEffector.get(config.effector);
|
|
77
|
+
if (existingVirentia && existingVirentia !== config.virentia) throw new Error("Effector scope is already associated with another Virentia scope");
|
|
153
78
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (input && (typeof input === "object" || typeof input === "function") && "shortName" in input) return String(input.shortName ?? "unit");
|
|
159
|
-
if (input && (typeof input === "object" || typeof input === "function") && "name" in input) return String(input.name ?? "unit");
|
|
160
|
-
return "unit";
|
|
161
|
-
}
|
|
162
|
-
function toArray(value) {
|
|
163
|
-
return Array.isArray(value) ? value : [value];
|
|
164
|
-
}
|
|
165
|
-
function applyStoreValue(scope, storeOrSid, value) {
|
|
166
|
-
if (typeof storeOrSid === "string") {
|
|
167
|
-
storesBySid.get(storeOrSid)?.setState(value, scope);
|
|
168
|
-
return;
|
|
79
|
+
function ensureAssociation(config = {}) {
|
|
80
|
+
const runtime = findRuntime(config);
|
|
81
|
+
if (!runtime) throw createMissingRuntimeError(config);
|
|
82
|
+
return runtime;
|
|
169
83
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const box = _virentia_core.store({ value: defaultState });
|
|
176
|
-
const updates = createEvent({ name: `${config?.name ?? "store"} updates` });
|
|
177
|
-
const store = createStoreFromBox(box, updates, defaultState, config?.name, config?.sid);
|
|
178
|
-
registerStore(store);
|
|
179
|
-
box.subscribe((next, scope) => {
|
|
180
|
-
markScopeChanged(scope, store.sid);
|
|
181
|
-
_virentia_core.run({
|
|
182
|
-
unit: updates.__core.node,
|
|
183
|
-
payload: next.value,
|
|
184
|
-
scope
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
return store;
|
|
188
|
-
}
|
|
189
|
-
function createStoreFromBox(box, updates, defaultState, name = "store", sid) {
|
|
190
|
-
const result = {
|
|
191
|
-
[unitKind]: "store",
|
|
192
|
-
__box: box,
|
|
193
|
-
__core: updates,
|
|
194
|
-
node: updates.__core.node,
|
|
195
|
-
shortName: name,
|
|
196
|
-
sid,
|
|
197
|
-
defaultState,
|
|
198
|
-
updates,
|
|
199
|
-
getType: () => name,
|
|
200
|
-
getState(scope) {
|
|
201
|
-
return readBox(box, scope);
|
|
202
|
-
},
|
|
203
|
-
setState(value, scope) {
|
|
204
|
-
writeBox(box, value, scope);
|
|
205
|
-
},
|
|
206
|
-
watch(fn) {
|
|
207
|
-
fn(readBox(box));
|
|
208
|
-
return box.subscribe((next) => {
|
|
209
|
-
fn(next.value);
|
|
210
|
-
});
|
|
211
|
-
},
|
|
212
|
-
map(fn) {
|
|
213
|
-
const mapped = createStore(fn(result.getState()));
|
|
214
|
-
_virentia_core.scoped(defaultScope, () => {
|
|
215
|
-
_virentia_core.reaction(() => {
|
|
216
|
-
mapped.setState(fn(result.getState()));
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
return mapped;
|
|
220
|
-
},
|
|
221
|
-
on(trigger, reducer) {
|
|
222
|
-
_virentia_core.reaction({
|
|
223
|
-
on: trigger,
|
|
224
|
-
run: (payload) => {
|
|
225
|
-
result.setState(reducer(result.getState(), payload));
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
return result;
|
|
229
|
-
},
|
|
230
|
-
reset(trigger) {
|
|
231
|
-
for (const unit of toArray(trigger)) _virentia_core.reaction({
|
|
232
|
-
on: unit,
|
|
233
|
-
run: () => {
|
|
234
|
-
result.setState(defaultState);
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
return result;
|
|
84
|
+
function findRuntime(config = {}) {
|
|
85
|
+
if (config.virentia) {
|
|
86
|
+
const effectorScope = effectorByVirentia.get(config.virentia);
|
|
87
|
+
const runtime = effectorScope ? findRuntimeByPair(config.virentia, effectorScope) : null;
|
|
88
|
+
if (runtime) return runtime;
|
|
238
89
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
90
|
+
if (config.effector) {
|
|
91
|
+
const virentiaScope = virentiaByEffector.get(config.effector);
|
|
92
|
+
const runtime = virentiaScope ? findRuntimeByPair(virentiaScope, config.effector) : null;
|
|
93
|
+
if (runtime) return runtime;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function findRuntimeByPair(virentiaScope, effectorScope) {
|
|
98
|
+
for (const runtime of runtimes) if (runtime.virentia === virentiaScope && runtime.effector === effectorScope) return runtime;
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
function registerInstaller(installer) {
|
|
102
|
+
installers.add(installer);
|
|
103
|
+
for (const runtime of runtimes) runtime.addInstaller(installer);
|
|
104
|
+
return () => {
|
|
105
|
+
installers.delete(installer);
|
|
106
|
+
for (const runtime of runtimes) runtime.removeInstaller(installer);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function createEffectorAdapter(unit) {
|
|
110
|
+
if (isEffectorUnit(unit)) return unit;
|
|
111
|
+
if (isVirentiaEffect(unit)) {
|
|
112
|
+
const scopeQueue = [];
|
|
113
|
+
const adapter = (0, effector.createEffect)((payload) => {
|
|
114
|
+
return resolveRuntimeFromEffectorScope(scopeQueue.shift()).call(unit, payload);
|
|
259
115
|
});
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const mapped = createStore(fn(result.getState()));
|
|
263
|
-
_virentia_core.scoped(defaultScope, () => {
|
|
264
|
-
_virentia_core.reaction(() => {
|
|
265
|
-
mapped.setState(fn(result.getState()));
|
|
266
|
-
});
|
|
116
|
+
createEffectorScopeNode(adapter, (_payload, scope) => {
|
|
117
|
+
scopeQueue.push(scope);
|
|
267
118
|
});
|
|
268
|
-
return
|
|
269
|
-
},
|
|
270
|
-
on() {
|
|
271
|
-
throw new Error("Store is read-only");
|
|
272
|
-
},
|
|
273
|
-
reset() {
|
|
274
|
-
throw new Error("Store is read-only");
|
|
119
|
+
return adapter;
|
|
275
120
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
payload:
|
|
281
|
-
scope
|
|
121
|
+
const adapter = (0, effector.createEvent)();
|
|
122
|
+
createEffectorScopeNode(adapter, (payload, scope) => {
|
|
123
|
+
const runtime = resolveRuntimeFromEffectorScope(scope);
|
|
124
|
+
if (runtime.shouldSkipEffector(adapter)) return;
|
|
125
|
+
runtime.emitVirentia(unit, payload, { suppressReaction: true });
|
|
282
126
|
});
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
function
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
function readNativeStore(store, scope) {
|
|
295
|
-
return inScope(scope, () => {
|
|
296
|
-
const keys = Reflect.ownKeys(store).filter((key) => !nativeStoreKeys.has(key));
|
|
297
|
-
if (keys.length === 1 && keys[0] === "value") return Reflect.get(store, "value");
|
|
298
|
-
return Object.fromEntries(keys.map((key) => [key, Reflect.get(store, key)]));
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
//#endregion
|
|
302
|
-
//#region lib/operators.ts
|
|
303
|
-
function sample(config) {
|
|
304
|
-
const target = config.target ?? createEvent();
|
|
305
|
-
const clocks = toArray(config.clock ?? sourceToClock(config.source));
|
|
306
|
-
for (const clock of clocks) _virentia_core.reaction({
|
|
307
|
-
on: clock,
|
|
308
|
-
run: (clockPayload) => {
|
|
309
|
-
const sourceValue = config.source === void 0 ? void 0 : readSource(config.source);
|
|
310
|
-
if (!passesFilter(config.filter, sourceValue, clockPayload)) return;
|
|
311
|
-
launchTarget(target, config.fn ? config.source === void 0 ? config.fn(clockPayload, clockPayload) : config.fn(sourceValue, clockPayload) : config.source === void 0 ? clockPayload : sourceValue);
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
return Array.isArray(target) ? target[0] : target;
|
|
315
|
-
}
|
|
316
|
-
function combine(...args) {
|
|
317
|
-
const fn = typeof args[args.length - 1] === "function" ? args.pop() : void 0;
|
|
318
|
-
const shape = args.length === 1 ? args[0] : args;
|
|
319
|
-
const result = createStore(computeCombined(shape, fn));
|
|
320
|
-
_virentia_core.scoped(defaultScope, () => {
|
|
321
|
-
_virentia_core.reaction(() => {
|
|
322
|
-
result.setState(computeCombined(shape, fn));
|
|
127
|
+
registerInstaller((runtime) => installLink(runtime, {
|
|
128
|
+
from: unit,
|
|
129
|
+
to: adapter
|
|
130
|
+
}));
|
|
131
|
+
return adapter;
|
|
132
|
+
}
|
|
133
|
+
function createVirentiaAdapter(unit) {
|
|
134
|
+
if (isVirentiaUnit(unit)) return unit;
|
|
135
|
+
if (effector.is.effect(unit)) return _virentia_core.effect((payload) => {
|
|
136
|
+
return resolveRuntimeFromVirentiaScope().call(unit, payload);
|
|
323
137
|
});
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const event = createEvent(String(key));
|
|
348
|
-
store.on(event, reducers[key]);
|
|
349
|
-
result[key] = event;
|
|
138
|
+
const adapter = _virentia_core.event();
|
|
139
|
+
createEffectorScopeNode(unit, (payload, scope) => {
|
|
140
|
+
const runtime = resolveRuntimeFromEffectorScope(scope);
|
|
141
|
+
if (runtime.shouldSkipEffector(unit)) return;
|
|
142
|
+
runtime.emitVirentia(adapter, payload, { suppressReaction: true });
|
|
143
|
+
});
|
|
144
|
+
registerInstaller((runtime) => installLink(runtime, {
|
|
145
|
+
from: adapter,
|
|
146
|
+
to: unit
|
|
147
|
+
}));
|
|
148
|
+
return adapter;
|
|
149
|
+
}
|
|
150
|
+
function resolveRuntimeFromEffectorScope(scope) {
|
|
151
|
+
if (!scope) throw createMissingRuntimeError({});
|
|
152
|
+
const runtime = ensureAssociation({ effector: scope });
|
|
153
|
+
const activeVirentiaScope = _virentia_core.getCurrentScope();
|
|
154
|
+
if (activeVirentiaScope && activeVirentiaScope !== runtime.virentia) throw new Error("Effector scope is associated with another Virentia scope");
|
|
155
|
+
return runtime;
|
|
156
|
+
}
|
|
157
|
+
function resolveRuntimeFromVirentiaScope() {
|
|
158
|
+
const activeVirentiaScope = _virentia_core.getCurrentScope();
|
|
159
|
+
if (!activeVirentiaScope) throw createMissingRuntimeError({});
|
|
160
|
+
return ensureAssociation({ virentia: activeVirentiaScope });
|
|
350
161
|
}
|
|
351
|
-
return result;
|
|
352
|
-
}
|
|
353
|
-
function restore(unit, defaultState) {
|
|
354
|
-
const store = createStore(defaultState);
|
|
355
|
-
const source = isEffect(unit) ? unit.doneData : unit;
|
|
356
|
-
store.on(source, (_, payload) => payload);
|
|
357
|
-
return store;
|
|
358
|
-
}
|
|
359
|
-
//#endregion
|
|
360
|
-
//#region lib/watch.ts
|
|
361
|
-
function watchUnit(unit, fn) {
|
|
362
|
-
const subscription = _virentia_core.reaction({
|
|
363
|
-
on: unit,
|
|
364
|
-
run: fn
|
|
365
|
-
});
|
|
366
|
-
return () => subscription.stop();
|
|
367
|
-
}
|
|
368
|
-
//#endregion
|
|
369
|
-
//#region lib/event.ts
|
|
370
|
-
function createEvent(nameOrConfig) {
|
|
371
|
-
const name = typeof nameOrConfig === "string" ? nameOrConfig : nameOrConfig?.name ?? "unit";
|
|
372
|
-
return wrapEvent(_virentia_core.event(), name);
|
|
373
|
-
}
|
|
374
|
-
function wrapEvent(event, name = "event") {
|
|
375
|
-
const result = callWithFallback(typeof event === "function" ? event : ((...payload) => _virentia_core.allSettled(event, { payload: payload[0] })));
|
|
376
|
-
Object.assign(result, {
|
|
377
|
-
[unitKind]: "event",
|
|
378
|
-
__core: event,
|
|
379
|
-
node: event.node,
|
|
380
|
-
shortName: name,
|
|
381
|
-
getType: () => name,
|
|
382
|
-
watch(fn) {
|
|
383
|
-
return watchUnit(result, fn);
|
|
384
|
-
},
|
|
385
|
-
map(fn) {
|
|
386
|
-
return wrapEvent(event.map(fn));
|
|
387
|
-
},
|
|
388
|
-
filter(config) {
|
|
389
|
-
const fn = typeof config === "function" ? config : config.fn;
|
|
390
|
-
return wrapEvent(event.filter(fn));
|
|
391
|
-
},
|
|
392
|
-
filterMap(fn) {
|
|
393
|
-
return wrapEvent(event.filterMap(fn));
|
|
394
|
-
},
|
|
395
|
-
prepend(fn) {
|
|
396
|
-
const prepended = createEvent();
|
|
397
|
-
sample({
|
|
398
|
-
clock: prepended,
|
|
399
|
-
fn,
|
|
400
|
-
target: result
|
|
401
|
-
});
|
|
402
|
-
return prepended;
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
return result;
|
|
406
162
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
163
|
+
var EffectorRuntimeImpl = class {
|
|
164
|
+
virentia;
|
|
165
|
+
effector;
|
|
166
|
+
disposed = false;
|
|
167
|
+
cleanups = /* @__PURE__ */ new Set();
|
|
168
|
+
cleanupByInstaller = /* @__PURE__ */ new Map();
|
|
169
|
+
releaseAssociation;
|
|
170
|
+
suppressedEffector = /* @__PURE__ */ new Map();
|
|
171
|
+
suppressedVirentia = /* @__PURE__ */ new Map();
|
|
172
|
+
constructor(config) {
|
|
173
|
+
this.virentia = config.virentia;
|
|
174
|
+
this.effector = config.effector;
|
|
175
|
+
this.releaseAssociation = config.release;
|
|
176
|
+
}
|
|
177
|
+
async call(unit, payload) {
|
|
178
|
+
this.assertAlive();
|
|
179
|
+
if (isEffectorUnit(unit)) return (0, effector.allSettled)(unit, {
|
|
180
|
+
params: payload,
|
|
181
|
+
scope: this.effector
|
|
182
|
+
});
|
|
183
|
+
if (isVirentiaEffect(unit)) return _virentia_core.scoped(this.virentia, () => unit(payload));
|
|
184
|
+
await _virentia_core.allSettled(unit, {
|
|
185
|
+
payload,
|
|
186
|
+
scope: this.virentia
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
trackCleanup(unsubscribe) {
|
|
190
|
+
this.cleanups.add(unsubscribe);
|
|
191
|
+
return () => {
|
|
192
|
+
this.cleanups.delete(unsubscribe);
|
|
193
|
+
unsubscribe();
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
dispose() {
|
|
197
|
+
if (this.disposed) return;
|
|
198
|
+
this.disposed = true;
|
|
199
|
+
for (const cleanup of [...this.cleanups]) cleanup();
|
|
200
|
+
this.cleanups.clear();
|
|
201
|
+
this.cleanupByInstaller.clear();
|
|
202
|
+
this.releaseAssociation();
|
|
203
|
+
}
|
|
204
|
+
addInstaller(installer) {
|
|
205
|
+
if (this.disposed || this.cleanupByInstaller.has(installer)) return;
|
|
206
|
+
const cleanup = installer(this);
|
|
207
|
+
this.cleanupByInstaller.set(installer, cleanup);
|
|
208
|
+
this.cleanups.add(cleanup);
|
|
209
|
+
}
|
|
210
|
+
removeInstaller(installer) {
|
|
211
|
+
const cleanup = this.cleanupByInstaller.get(installer);
|
|
212
|
+
if (!cleanup) return;
|
|
213
|
+
this.cleanupByInstaller.delete(installer);
|
|
214
|
+
this.cleanups.delete(cleanup);
|
|
215
|
+
cleanup();
|
|
216
|
+
}
|
|
217
|
+
assertSamePair(config) {
|
|
218
|
+
if (config.virentia !== this.virentia || config.effector !== this.effector) throw new Error("Effector compatibility association is already bound to another scope pair");
|
|
219
|
+
}
|
|
220
|
+
launchEffector(unit, payload, options = {}) {
|
|
221
|
+
this.assertAlive();
|
|
222
|
+
if (options.suppressWatch) this.incrementSuppression(this.suppressedEffector, unit);
|
|
223
|
+
try {
|
|
224
|
+
(0, effector.launch)({
|
|
225
|
+
target: unit,
|
|
226
|
+
params: payload,
|
|
227
|
+
scope: this.effector
|
|
439
228
|
});
|
|
440
|
-
|
|
229
|
+
} finally {
|
|
230
|
+
if (options.suppressWatch) this.decrementSuppression(this.suppressedEffector, unit);
|
|
441
231
|
}
|
|
232
|
+
}
|
|
233
|
+
emitVirentia(unit, payload, options = {}) {
|
|
234
|
+
this.assertAlive();
|
|
235
|
+
if (options.suppressReaction) this.incrementSuppression(this.suppressedVirentia, unit);
|
|
236
|
+
const settled = _virentia_core.allSettled(unit, {
|
|
237
|
+
payload,
|
|
238
|
+
scope: this.virentia
|
|
239
|
+
});
|
|
240
|
+
if (options.suppressReaction) settled.finally(() => {
|
|
241
|
+
this.decrementSuppression(this.suppressedVirentia, unit);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
shouldSkipEffector(unit) {
|
|
245
|
+
return (this.suppressedEffector.get(unit) ?? 0) > 0;
|
|
246
|
+
}
|
|
247
|
+
shouldSkipVirentia(unit) {
|
|
248
|
+
return (this.suppressedVirentia.get(unit) ?? 0) > 0;
|
|
249
|
+
}
|
|
250
|
+
assertAlive() {
|
|
251
|
+
if (this.disposed) throw new Error("Effector compatibility association is disposed");
|
|
252
|
+
}
|
|
253
|
+
incrementSuppression(map, unit) {
|
|
254
|
+
map.set(unit, (map.get(unit) ?? 0) + 1);
|
|
255
|
+
}
|
|
256
|
+
decrementSuppression(map, unit) {
|
|
257
|
+
const next = (map.get(unit) ?? 0) - 1;
|
|
258
|
+
if (next <= 0) map.delete(unit);
|
|
259
|
+
else map.set(unit, next);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
function createEffectorScopeNode(unit, fn) {
|
|
263
|
+
const node = (0, effector.createNode)({
|
|
264
|
+
parent: [unit],
|
|
265
|
+
node: [...effector.is.store(unit) ? [effector.step.mov({
|
|
266
|
+
store: unit.stateRef,
|
|
267
|
+
to: "stack"
|
|
268
|
+
})] : [], effector.step.run({ fn(payload, _local, stack) {
|
|
269
|
+
fn(payload, stack.scope);
|
|
270
|
+
} })],
|
|
271
|
+
family: { owners: [unit] }
|
|
442
272
|
});
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
return result;
|
|
446
|
-
});
|
|
447
|
-
use.getCurrent = () => {
|
|
448
|
-
if (!handler) throw new Error("Effect handler is not defined");
|
|
449
|
-
return handler;
|
|
273
|
+
return () => {
|
|
274
|
+
(0, effector.clearNode)(node);
|
|
450
275
|
};
|
|
451
|
-
result.use = use;
|
|
452
|
-
return result;
|
|
453
276
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const
|
|
462
|
-
if (
|
|
463
|
-
|
|
464
|
-
return
|
|
277
|
+
function installLink(runtime, definition) {
|
|
278
|
+
const map = definition.map ?? identity;
|
|
279
|
+
if (isEffectorUnit(definition.from)) return toUnsubscribe((0, effector.createWatch)({
|
|
280
|
+
unit: definition.from,
|
|
281
|
+
scope: runtime.effector,
|
|
282
|
+
fn(payload) {
|
|
283
|
+
if (runtime.shouldSkipEffector(definition.from)) return;
|
|
284
|
+
const nextPayload = map(payload);
|
|
285
|
+
if (isEffectorUnit(definition.to)) {
|
|
286
|
+
runtime.launchEffector(definition.to, nextPayload);
|
|
287
|
+
return;
|
|
465
288
|
}
|
|
466
|
-
|
|
289
|
+
runtime.emitVirentia(definition.to, nextPayload, { suppressReaction: true });
|
|
467
290
|
}
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
291
|
+
}));
|
|
292
|
+
if (isVirentiaUnit(definition.from)) {
|
|
293
|
+
const watcher = _virentia_core.reaction({
|
|
294
|
+
on: definition.from,
|
|
295
|
+
scope: runtime.virentia,
|
|
296
|
+
run(payload) {
|
|
297
|
+
if (runtime.shouldSkipVirentia(definition.from)) return;
|
|
298
|
+
const nextPayload = map(payload);
|
|
299
|
+
if (isEffectorUnit(definition.to)) {
|
|
300
|
+
runtime.launchEffector(definition.to, nextPayload, { suppressWatch: true });
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
runtime.emitVirentia(definition.to, nextPayload);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
return () => {
|
|
307
|
+
watcher.stop();
|
|
308
|
+
};
|
|
481
309
|
}
|
|
482
|
-
|
|
310
|
+
throw new Error("Effector compatibility link expects Effector or Virentia units");
|
|
483
311
|
}
|
|
484
|
-
function
|
|
485
|
-
|
|
312
|
+
function createMissingRuntimeError(config) {
|
|
313
|
+
if (config.effector) return /* @__PURE__ */ new Error("Effector compatibility association is missing for provided Effector scope");
|
|
314
|
+
if (config.virentia) return /* @__PURE__ */ new Error("Effector compatibility association is missing for provided Virentia scope");
|
|
315
|
+
return /* @__PURE__ */ new Error("Effector compatibility association is missing. Call associate({ virentia, effector }) before using adapters.");
|
|
486
316
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
function fork(config) {
|
|
490
|
-
const nextScope = createCompatScope(_virentia_core.scope());
|
|
491
|
-
if (config?.values) hydrate(nextScope, { values: config.values });
|
|
492
|
-
return nextScope;
|
|
317
|
+
function isEffectorUnit(value) {
|
|
318
|
+
return effector.is.unit(value);
|
|
493
319
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
status: "done",
|
|
505
|
-
value: await _virentia_core.scoped(scope.__core, () => unit(options.params))
|
|
506
|
-
};
|
|
507
|
-
} catch (value) {
|
|
508
|
-
return {
|
|
509
|
-
status: "fail",
|
|
510
|
-
value
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
await _virentia_core.allSettled(unit.__core, {
|
|
514
|
-
scope: scope.__core,
|
|
515
|
-
payload: options.params
|
|
516
|
-
});
|
|
320
|
+
function isVirentiaUnit(value) {
|
|
321
|
+
return Boolean(value && (typeof value === "object" || typeof value === "function") && "node" in value && !isEffectorUnit(value));
|
|
322
|
+
}
|
|
323
|
+
function isVirentiaEffect(value) {
|
|
324
|
+
return Boolean(isVirentiaUnit(value) && "doneData" in value && "$pending" in value);
|
|
325
|
+
}
|
|
326
|
+
function toUnsubscribe(subscription) {
|
|
327
|
+
return () => {
|
|
328
|
+
subscription.unsubscribe();
|
|
329
|
+
};
|
|
517
330
|
}
|
|
518
|
-
function
|
|
519
|
-
|
|
520
|
-
return (...payload) => _virentia_core.scoped(scope.__core, () => unit(...payload));
|
|
331
|
+
function identity(value) {
|
|
332
|
+
return value;
|
|
521
333
|
}
|
|
522
334
|
//#endregion
|
|
523
|
-
exports.
|
|
524
|
-
exports.attach = attach;
|
|
525
|
-
exports.combine = combine;
|
|
526
|
-
exports.createApi = createApi;
|
|
527
|
-
exports.createEffect = createEffect;
|
|
528
|
-
exports.createEvent = createEvent;
|
|
529
|
-
exports.createStore = createStore;
|
|
530
|
-
exports.fork = fork;
|
|
531
|
-
exports.hydrate = hydrate;
|
|
532
|
-
exports.is = is;
|
|
533
|
-
exports.restore = restore;
|
|
534
|
-
exports.sample = sample;
|
|
535
|
-
exports.scopeBind = scopeBind;
|
|
536
|
-
exports.serialize = serialize;
|
|
537
|
-
exports.split = split;
|
|
335
|
+
exports.createEffectorCompatibility = createEffectorCompatibility;
|