@virentia/effector 0.2.1 → 0.3.0
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 +113 -25
- package/dist/index.cjs +255 -274
- package/dist/index.d.cts +23 -19
- package/dist/index.d.mts +23 -19
- package/dist/index.mjs +253 -275
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -24,241 +24,186 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
let _virentia_core = require("@virentia/core");
|
|
25
25
|
_virentia_core = __toESM(_virentia_core, 1);
|
|
26
26
|
let effector = require("effector");
|
|
27
|
-
//#region lib/
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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;
|
|
58
|
-
}
|
|
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;
|
|
72
|
-
}
|
|
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");
|
|
27
|
+
//#region lib/errors.ts
|
|
28
|
+
function createMissingAssociationError(config) {
|
|
29
|
+
if (config.effector) return /* @__PURE__ */ new Error("Effector association is missing for provided Effector scope");
|
|
30
|
+
if (config.virentia) return /* @__PURE__ */ new Error("Effector association is missing for provided Virentia scope");
|
|
31
|
+
return /* @__PURE__ */ new Error("Effector association is missing. Call associate({ virentia, effector }) before using fooled units.");
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region lib/associations.ts
|
|
35
|
+
const effectorAssociations = {
|
|
36
|
+
byVirentia: /* @__PURE__ */ new WeakMap(),
|
|
37
|
+
byEffector: /* @__PURE__ */ new WeakMap()
|
|
38
|
+
};
|
|
39
|
+
function associate(config) {
|
|
40
|
+
if (!config.virentia) throw new Error("Effector association requires a Virentia scope");
|
|
41
|
+
if (!config.effector) throw new Error("Effector association requires an Effector scope");
|
|
42
|
+
const existingByVirentia = effectorAssociations.byVirentia.get(config.virentia);
|
|
43
|
+
const existingByEffector = effectorAssociations.byEffector.get(config.effector);
|
|
44
|
+
if (existingByVirentia && existingByVirentia.effector !== config.effector) throw new Error("Virentia scope is already associated with another Effector scope");
|
|
45
|
+
if (existingByEffector && existingByEffector.virentia !== config.virentia) throw new Error("Effector scope is already associated with another Virentia scope");
|
|
46
|
+
const existing = existingByVirentia ?? existingByEffector;
|
|
47
|
+
if (existing) {
|
|
48
|
+
effectorAssociations.byVirentia.set(config.virentia, existing);
|
|
49
|
+
effectorAssociations.byEffector.set(config.effector, existing);
|
|
50
|
+
return existing;
|
|
78
51
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
52
|
+
const association = {
|
|
53
|
+
virentia: config.virentia,
|
|
54
|
+
effector: config.effector
|
|
55
|
+
};
|
|
56
|
+
effectorAssociations.byVirentia.set(config.virentia, association);
|
|
57
|
+
effectorAssociations.byEffector.set(config.effector, association);
|
|
58
|
+
return association;
|
|
59
|
+
}
|
|
60
|
+
function ensureAssociation(config = {}) {
|
|
61
|
+
const association = findAssociation(config);
|
|
62
|
+
if (!association) throw createMissingAssociationError(config);
|
|
63
|
+
return association;
|
|
64
|
+
}
|
|
65
|
+
function findAssociation(config = {}) {
|
|
66
|
+
let association;
|
|
67
|
+
if (config.virentia) {
|
|
68
|
+
association = effectorAssociations.byVirentia.get(config.virentia);
|
|
69
|
+
if (association && config.effector && association.effector !== config.effector) return null;
|
|
70
|
+
if (association) return association;
|
|
83
71
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (runtime) return runtime;
|
|
89
|
-
}
|
|
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;
|
|
72
|
+
if (config.effector) {
|
|
73
|
+
association = effectorAssociations.byEffector.get(config.effector);
|
|
74
|
+
if (association && config.virentia && association.virentia !== config.virentia) return null;
|
|
75
|
+
if (association) return association;
|
|
96
76
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region lib/association-state.ts
|
|
81
|
+
const associationState = /* @__PURE__ */ new WeakMap();
|
|
82
|
+
function shouldSkipEffector(association, unit) {
|
|
83
|
+
return (getAssociationState(association).suppressedEffector.get(unit) ?? 0) > 0;
|
|
84
|
+
}
|
|
85
|
+
function shouldSkipVirentia(association, unit) {
|
|
86
|
+
return (getAssociationState(association).suppressedVirentia.get(unit) ?? 0) > 0;
|
|
87
|
+
}
|
|
88
|
+
function suppressEffector(association, unit, fn) {
|
|
89
|
+
const state = getAssociationState(association);
|
|
90
|
+
incrementSuppression(state.suppressedEffector, unit);
|
|
91
|
+
try {
|
|
92
|
+
return fn();
|
|
93
|
+
} finally {
|
|
94
|
+
decrementSuppression(state.suppressedEffector, unit);
|
|
100
95
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
}
|
|
97
|
+
function suppressVirentia(association, unit) {
|
|
98
|
+
const state = getAssociationState(association);
|
|
99
|
+
incrementSuppression(state.suppressedVirentia, unit);
|
|
100
|
+
return () => {
|
|
101
|
+
decrementSuppression(state.suppressedVirentia, unit);
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function getAssociationState(association) {
|
|
105
|
+
let state = associationState.get(association);
|
|
106
|
+
if (!state) {
|
|
107
|
+
state = {
|
|
108
|
+
suppressedEffector: /* @__PURE__ */ new Map(),
|
|
109
|
+
suppressedVirentia: /* @__PURE__ */ new Map()
|
|
107
110
|
};
|
|
111
|
+
associationState.set(association, state);
|
|
108
112
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
return state;
|
|
114
|
+
}
|
|
115
|
+
function incrementSuppression(map, unit) {
|
|
116
|
+
map.set(unit, (map.get(unit) ?? 0) + 1);
|
|
117
|
+
}
|
|
118
|
+
function decrementSuppression(map, unit) {
|
|
119
|
+
const next = (map.get(unit) ?? 0) - 1;
|
|
120
|
+
if (next <= 0) map.delete(unit);
|
|
121
|
+
else map.set(unit, next);
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region lib/guards.ts
|
|
125
|
+
function isEffectorUnit(value) {
|
|
126
|
+
return effector.is.unit(value);
|
|
127
|
+
}
|
|
128
|
+
function isVirentiaUnit(value) {
|
|
129
|
+
return Boolean(value && (typeof value === "object" || typeof value === "function") && "node" in value && !isEffectorUnit(value));
|
|
130
|
+
}
|
|
131
|
+
function isVirentiaEffect(value) {
|
|
132
|
+
return Boolean(isVirentiaUnit(value) && "doneData" in value && "pending" in value);
|
|
133
|
+
}
|
|
134
|
+
function isObjectLike(value) {
|
|
135
|
+
return (typeof value === "object" || typeof value === "function") && value !== null;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region lib/runtime.ts
|
|
139
|
+
function installVirentiaToEffectorLink(from, to) {
|
|
140
|
+
installVirentiaToTargetLink(from, to, identity, true);
|
|
141
|
+
}
|
|
142
|
+
function installVirentiaToTargetLink(from, to, map, suppressEffectorWatch) {
|
|
143
|
+
const watcher = _virentia_core.reaction({
|
|
144
|
+
on: from,
|
|
145
|
+
run(payload) {
|
|
146
|
+
const association = resolveAssociationFromVirentiaScope();
|
|
147
|
+
if (shouldSkipVirentia(association, from)) return;
|
|
148
|
+
runBridgeTarget(association, to, map(payload), { suppressWatch: suppressEffectorWatch });
|
|
120
149
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
runtime.emitVirentia(unit, payload, { suppressReaction: true });
|
|
126
|
-
});
|
|
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);
|
|
137
|
-
});
|
|
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 });
|
|
161
|
-
}
|
|
150
|
+
});
|
|
151
|
+
return () => {
|
|
152
|
+
watcher.stop();
|
|
153
|
+
};
|
|
162
154
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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;
|
|
155
|
+
function runBridgeTarget(association, to, payload, options = {}) {
|
|
156
|
+
if (isEffectorUnit(to)) {
|
|
157
|
+
launchEffector(association, to, payload, { suppressWatch: options.suppressWatch });
|
|
158
|
+
return;
|
|
176
159
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
160
|
+
emitVirentia(association, to, payload, { suppressReaction: options.suppressReaction });
|
|
161
|
+
}
|
|
162
|
+
async function callAssociation(association, unit, payload) {
|
|
163
|
+
if (isEffectorUnit(unit)) return (0, effector.allSettled)(unit, {
|
|
164
|
+
params: payload,
|
|
165
|
+
scope: association.effector
|
|
166
|
+
});
|
|
167
|
+
if (isVirentiaEffect(unit)) return _virentia_core.scoped(association.virentia, () => unit(payload));
|
|
168
|
+
await _virentia_core.allSettled(unit, {
|
|
169
|
+
payload,
|
|
170
|
+
scope: association.virentia
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function launchEffector(association, unit, payload, options = {}) {
|
|
174
|
+
const launchUnit = () => {
|
|
175
|
+
(0, effector.launch)({
|
|
176
|
+
target: unit,
|
|
180
177
|
params: payload,
|
|
181
|
-
scope:
|
|
178
|
+
scope: association.effector
|
|
182
179
|
});
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
|
228
|
-
});
|
|
229
|
-
} finally {
|
|
230
|
-
if (options.suppressWatch) this.decrementSuppression(this.suppressedEffector, unit);
|
|
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);
|
|
180
|
+
};
|
|
181
|
+
if (options.suppressWatch) {
|
|
182
|
+
suppressEffector(association, unit, launchUnit);
|
|
183
|
+
return;
|
|
260
184
|
}
|
|
261
|
-
|
|
185
|
+
launchUnit();
|
|
186
|
+
}
|
|
187
|
+
function emitVirentia(association, unit, payload, options = {}) {
|
|
188
|
+
const release = options.suppressReaction ? suppressVirentia(association, unit) : null;
|
|
189
|
+
const settled = _virentia_core.allSettled(unit, {
|
|
190
|
+
payload,
|
|
191
|
+
scope: association.virentia
|
|
192
|
+
});
|
|
193
|
+
if (release) settled.finally(release);
|
|
194
|
+
}
|
|
195
|
+
function resolveAssociationFromEffectorScope(scope) {
|
|
196
|
+
if (!scope) throw createMissingAssociationError({});
|
|
197
|
+
const association = ensureAssociation({ effector: scope });
|
|
198
|
+
const activeVirentiaScope = _virentia_core.getCurrentScope();
|
|
199
|
+
if (activeVirentiaScope && activeVirentiaScope !== association.virentia) throw new Error("Effector scope is associated with another Virentia scope");
|
|
200
|
+
return association;
|
|
201
|
+
}
|
|
202
|
+
function resolveAssociationFromVirentiaScope() {
|
|
203
|
+
const activeVirentiaScope = _virentia_core.getCurrentScope();
|
|
204
|
+
if (!activeVirentiaScope) throw createMissingAssociationError({});
|
|
205
|
+
return ensureAssociation({ virentia: activeVirentiaScope });
|
|
206
|
+
}
|
|
262
207
|
function createEffectorScopeNode(unit, fn) {
|
|
263
208
|
const node = (0, effector.createNode)({
|
|
264
209
|
parent: [unit],
|
|
@@ -274,62 +219,98 @@ function createEffectorScopeNode(unit, fn) {
|
|
|
274
219
|
(0, effector.clearNode)(node);
|
|
275
220
|
};
|
|
276
221
|
}
|
|
277
|
-
function
|
|
278
|
-
|
|
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;
|
|
288
|
-
}
|
|
289
|
-
runtime.emitVirentia(definition.to, nextPayload, { suppressReaction: true });
|
|
290
|
-
}
|
|
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
|
-
};
|
|
309
|
-
}
|
|
310
|
-
throw new Error("Effector compatibility link expects Effector or Virentia units");
|
|
222
|
+
function identity(value) {
|
|
223
|
+
return value;
|
|
311
224
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region lib/fool.ts
|
|
227
|
+
const fooledUnit = Symbol("virentia.effector.fooledUnit");
|
|
228
|
+
const fooledUnits = /* @__PURE__ */ new WeakMap();
|
|
229
|
+
function fool(unit) {
|
|
230
|
+
if (!isObjectLike(unit)) throw new Error("fool() expects an Effector or Virentia unit");
|
|
231
|
+
if (unit[fooledUnit]) return unit;
|
|
232
|
+
const cached = fooledUnits.get(unit);
|
|
233
|
+
if (cached) return cached;
|
|
234
|
+
const fooled = isEffectorUnit(unit) ? createFooledEffectorUnit(unit) : isVirentiaUnit(unit) ? createFooledVirentiaUnit(unit) : null;
|
|
235
|
+
if (!fooled) throw new Error("fool() expects an Effector or Virentia unit");
|
|
236
|
+
markFooledUnit(fooled);
|
|
237
|
+
fooledUnits.set(unit, fooled);
|
|
238
|
+
return fooled;
|
|
316
239
|
}
|
|
317
|
-
function
|
|
318
|
-
|
|
240
|
+
function createFooledVirentiaUnit(unit) {
|
|
241
|
+
const effectorUnit = createEffectorAdapter(unit);
|
|
242
|
+
const base = typeof unit === "function" ? createCallableBridge((...args) => unit(...args)) : {};
|
|
243
|
+
copyUnitProperties(base, effectorUnit);
|
|
244
|
+
copyUnitProperties(base, unit);
|
|
245
|
+
return base;
|
|
319
246
|
}
|
|
320
|
-
function
|
|
321
|
-
|
|
247
|
+
function createFooledEffectorUnit(unit) {
|
|
248
|
+
const virentiaUnit = createVirentiaAdapter(unit);
|
|
249
|
+
const base = typeof unit === "function" || typeof virentiaUnit === "function" ? createCallableBridge((...args) => {
|
|
250
|
+
if (_virentia_core.getCurrentScope() && typeof virentiaUnit === "function") return virentiaUnit(...args);
|
|
251
|
+
if (typeof unit === "function") return unit(...args);
|
|
252
|
+
throw new Error("Effector store cannot be called");
|
|
253
|
+
}) : {};
|
|
254
|
+
copyUnitProperties(base, virentiaUnit);
|
|
255
|
+
copyUnitProperties(base, unit);
|
|
256
|
+
return base;
|
|
322
257
|
}
|
|
323
|
-
function
|
|
324
|
-
return
|
|
258
|
+
function createCallableBridge(call) {
|
|
259
|
+
return (...args) => call(...args);
|
|
325
260
|
}
|
|
326
|
-
function
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
261
|
+
function createEffectorAdapter(unit) {
|
|
262
|
+
if (isEffectorUnit(unit)) return unit;
|
|
263
|
+
if (isVirentiaEffect(unit)) {
|
|
264
|
+
const scopeQueue = [];
|
|
265
|
+
const adapter = (0, effector.createEffect)((payload) => {
|
|
266
|
+
return callAssociation(resolveAssociationFromEffectorScope(scopeQueue.shift()), unit, payload);
|
|
267
|
+
});
|
|
268
|
+
createEffectorScopeNode(adapter, (_payload, scope) => {
|
|
269
|
+
scopeQueue.push(scope);
|
|
270
|
+
});
|
|
271
|
+
return adapter;
|
|
272
|
+
}
|
|
273
|
+
const adapter = (0, effector.createEvent)();
|
|
274
|
+
createEffectorScopeNode(adapter, (payload, scope) => {
|
|
275
|
+
const association = resolveAssociationFromEffectorScope(scope);
|
|
276
|
+
if (shouldSkipEffector(association, adapter)) return;
|
|
277
|
+
emitVirentia(association, unit, payload, { suppressReaction: true });
|
|
278
|
+
});
|
|
279
|
+
installVirentiaToEffectorLink(unit, adapter);
|
|
280
|
+
return adapter;
|
|
330
281
|
}
|
|
331
|
-
function
|
|
332
|
-
return
|
|
282
|
+
function createVirentiaAdapter(unit) {
|
|
283
|
+
if (isVirentiaUnit(unit)) return unit;
|
|
284
|
+
if (effector.is.effect(unit)) return _virentia_core.effect((payload) => {
|
|
285
|
+
return callAssociation(resolveAssociationFromVirentiaScope(), unit, payload);
|
|
286
|
+
});
|
|
287
|
+
const adapter = _virentia_core.event();
|
|
288
|
+
createEffectorScopeNode(unit, (payload, scope) => {
|
|
289
|
+
const association = resolveAssociationFromEffectorScope(scope);
|
|
290
|
+
if (shouldSkipEffector(association, unit)) return;
|
|
291
|
+
emitVirentia(association, adapter, payload, { suppressReaction: true });
|
|
292
|
+
});
|
|
293
|
+
installVirentiaToEffectorLink(adapter, unit);
|
|
294
|
+
return adapter;
|
|
295
|
+
}
|
|
296
|
+
function copyUnitProperties(target, source) {
|
|
297
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
298
|
+
if (key === "length" || key === "name" || key === "prototype") continue;
|
|
299
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
300
|
+
if (!descriptor) continue;
|
|
301
|
+
const existing = Object.getOwnPropertyDescriptor(target, key);
|
|
302
|
+
if (existing && !existing.configurable) continue;
|
|
303
|
+
Object.defineProperty(target, key, descriptor);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function markFooledUnit(unit) {
|
|
307
|
+
Object.defineProperty(unit, fooledUnit, {
|
|
308
|
+
enumerable: false,
|
|
309
|
+
value: true
|
|
310
|
+
});
|
|
333
311
|
}
|
|
334
312
|
//#endregion
|
|
335
|
-
exports.
|
|
313
|
+
exports.associate = associate;
|
|
314
|
+
exports.effectorAssociations = effectorAssociations;
|
|
315
|
+
exports.ensureAssociation = ensureAssociation;
|
|
316
|
+
exports.fool = fool;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import * as virentia from "@virentia/core";
|
|
2
2
|
import { Effect, EventCallable, Scope, Unit, UnitTargetable } from "effector";
|
|
3
3
|
|
|
4
|
-
//#region lib/
|
|
5
|
-
interface EffectorCompatibilityOptions {
|
|
6
|
-
name?: string;
|
|
7
|
-
}
|
|
4
|
+
//#region lib/types.d.ts
|
|
8
5
|
interface EffectorAssociationConfig {
|
|
9
6
|
virentia: virentia.Scope;
|
|
10
7
|
effector: Scope;
|
|
@@ -13,24 +10,31 @@ interface EffectorAssociationLookup {
|
|
|
13
10
|
virentia?: virentia.Scope;
|
|
14
11
|
effector?: Scope;
|
|
15
12
|
}
|
|
16
|
-
type EffectorPayloadMap<From, To> = (payload: From) => To;
|
|
17
|
-
type EffectorCompatibilityUnsubscribe = () => void;
|
|
18
13
|
interface EffectorAssociation {
|
|
19
|
-
|
|
14
|
+
readonly virentia: virentia.Scope;
|
|
15
|
+
readonly effector: Scope;
|
|
20
16
|
}
|
|
21
|
-
interface
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
link<From, To = From>(from: Unit<From> | VirentiaUnit<From>, to: UnitTargetable<To> | VirentiaTarget<To>, map?: EffectorPayloadMap<From, To>): EffectorCompatibilityUnsubscribe;
|
|
25
|
-
asEffector<T>(unit: virentia.Effect<T, any, any>): Effect<T, any, unknown>;
|
|
26
|
-
asEffector<T>(unit: VirentiaUnit<T>): EventCallable<T>;
|
|
27
|
-
asEffector<T>(unit: Unit<T>): Unit<T>;
|
|
28
|
-
asVirentia<T>(unit: VirentiaUnit<T>): VirentiaUnit<T>;
|
|
29
|
-
asVirentia<T>(unit: Effect<T, any, any>): virentia.Effect<T, any, unknown>;
|
|
30
|
-
asVirentia<T>(unit: Unit<T>): virentia.EventCallable<T>;
|
|
17
|
+
interface EffectorAssociations {
|
|
18
|
+
readonly byVirentia: WeakMap<virentia.Scope, EffectorAssociation>;
|
|
19
|
+
readonly byEffector: WeakMap<Scope, EffectorAssociation>;
|
|
31
20
|
}
|
|
32
21
|
type VirentiaUnit<T = unknown> = virentia.Event<T> | virentia.EventCallable<T> | virentia.Effect<T, any, any> | virentia.Store<T> | virentia.StoreWritable<T>;
|
|
33
22
|
type VirentiaTarget<T = unknown> = virentia.EventCallable<T> | virentia.Effect<T, any, any> | virentia.StoreWritable<T>;
|
|
34
|
-
declare function createEffectorCompatibility(_options?: EffectorCompatibilityOptions): EffectorCompatibility;
|
|
35
23
|
//#endregion
|
|
36
|
-
|
|
24
|
+
//#region lib/associations.d.ts
|
|
25
|
+
declare const effectorAssociations: EffectorAssociations;
|
|
26
|
+
declare function associate(config: EffectorAssociationConfig): EffectorAssociation;
|
|
27
|
+
declare function ensureAssociation(config?: EffectorAssociationLookup): EffectorAssociation;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region lib/fool.d.ts
|
|
30
|
+
declare function fool<Params, Done, Fail>(unit: virentia.Effect<Params, Done, Fail>): virentia.Effect<Params, Done, Fail> & Effect<Params, Done, Fail>;
|
|
31
|
+
declare function fool<T>(unit: virentia.EventCallable<T>): virentia.EventCallable<T> & EventCallable<T>;
|
|
32
|
+
declare function fool<T>(unit: virentia.Event<T>): virentia.Event<T> & EventCallable<T>;
|
|
33
|
+
declare function fool<T>(unit: virentia.StoreWritable<T>): virentia.StoreWritable<T> & EventCallable<T>;
|
|
34
|
+
declare function fool<T>(unit: virentia.Store<T>): virentia.Store<T> & EventCallable<T>;
|
|
35
|
+
declare function fool<Params, Done, Fail>(unit: Effect<Params, Done, Fail>): Effect<Params, Done, Fail> & virentia.Effect<Params, Done, Fail>;
|
|
36
|
+
declare function fool<T>(unit: EventCallable<T>): EventCallable<T> & virentia.EventCallable<T>;
|
|
37
|
+
declare function fool<T>(unit: UnitTargetable<T>): UnitTargetable<T> & virentia.EventCallable<T>;
|
|
38
|
+
declare function fool<T>(unit: Unit<T>): Unit<T> & virentia.EventCallable<T>;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { EffectorAssociation, EffectorAssociationConfig, EffectorAssociationLookup, EffectorAssociations, VirentiaTarget, VirentiaUnit, associate, effectorAssociations, ensureAssociation, fool };
|