@logixjs/react 0.1.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 +64 -0
- package/dist/Hooks.cjs +2194 -0
- package/dist/Hooks.d.cts +77 -0
- package/dist/Hooks.d.ts +77 -0
- package/dist/Hooks.js +27 -0
- package/dist/ModuleRef-wZSQ3Wwo.d.cts +73 -0
- package/dist/ModuleRef-wZSQ3Wwo.d.ts +73 -0
- package/dist/ModuleScope.cjs +2695 -0
- package/dist/ModuleScope.d.cts +62 -0
- package/dist/ModuleScope.d.ts +62 -0
- package/dist/ModuleScope.js +9 -0
- package/dist/Platform.cjs +60 -0
- package/dist/Platform.d.cts +6 -0
- package/dist/Platform.d.ts +6 -0
- package/dist/Platform.js +6 -0
- package/dist/ReactPlatform.cjs +2813 -0
- package/dist/ReactPlatform.d.cts +40 -0
- package/dist/ReactPlatform.d.ts +40 -0
- package/dist/ReactPlatform.js +11 -0
- package/dist/RuntimeProvider.cjs +1618 -0
- package/dist/RuntimeProvider.d.cts +66 -0
- package/dist/RuntimeProvider.d.ts +66 -0
- package/dist/RuntimeProvider.js +8 -0
- package/dist/chunk-2WFULYPJ.js +856 -0
- package/dist/chunk-4G7H66OY.js +54 -0
- package/dist/chunk-G5MRIFKK.js +95 -0
- package/dist/chunk-JXAJTWSZ.js +773 -0
- package/dist/chunk-PYWHL7TA.js +351 -0
- package/dist/chunk-UFFCJGSZ.js +981 -0
- package/dist/chunk-VFWWMK67.js +0 -0
- package/dist/chunk-ZANGOPUQ.js +34 -0
- package/dist/global.d.cjs +1 -0
- package/dist/global.d.d.cts +9 -0
- package/dist/global.d.d.ts +9 -0
- package/dist/global.d.js +0 -0
- package/dist/index.cjs +3118 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +44 -0
- package/dist/useDispatch-BnzYVkRE.d.ts +81 -0
- package/dist/useDispatch-CnO5-66H.d.cts +81 -0
- package/package.json +58 -0
|
@@ -0,0 +1,981 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RuntimeContext,
|
|
3
|
+
createRuntimeAdapter,
|
|
4
|
+
getModuleCache,
|
|
5
|
+
isDevEnv,
|
|
6
|
+
stableHash,
|
|
7
|
+
useLayerBinding
|
|
8
|
+
} from "./chunk-2WFULYPJ.js";
|
|
9
|
+
|
|
10
|
+
// src/internal/hooks/useRuntime.ts
|
|
11
|
+
import { useContext, useEffect, useMemo, useRef } from "react";
|
|
12
|
+
import { Layer } from "effect";
|
|
13
|
+
|
|
14
|
+
// src/internal/provider/errors.ts
|
|
15
|
+
var RuntimeProviderNotFoundError = class extends Error {
|
|
16
|
+
constructor(hookName) {
|
|
17
|
+
super(
|
|
18
|
+
`[${hookName}] RuntimeProvider not found.
|
|
19
|
+
|
|
20
|
+
Fix:
|
|
21
|
+
- Wrap your app (or the calling component subtree) with <RuntimeProvider runtime={runtime}>.
|
|
22
|
+
- If using nested providers, ensure an ancestor RuntimeProvider provides \`runtime\`.
|
|
23
|
+
- If you intended to call this hook outside React, use @logixjs/core directly.
|
|
24
|
+
`
|
|
25
|
+
);
|
|
26
|
+
this.name = "RuntimeProviderNotFoundError";
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/internal/hooks/useRuntime.ts
|
|
31
|
+
function useRuntime(options) {
|
|
32
|
+
const context = useContext(RuntimeContext);
|
|
33
|
+
if (!context) {
|
|
34
|
+
throw new RuntimeProviderNotFoundError("useRuntime");
|
|
35
|
+
}
|
|
36
|
+
const mergedLayerCacheRef = useRef(null);
|
|
37
|
+
const mergedLayer = useMemo(() => {
|
|
38
|
+
if (!options) {
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
const { layer, layers } = options;
|
|
42
|
+
const hasLayersArray = Array.isArray(layers) && layers.length > 0;
|
|
43
|
+
if (!layer && !hasLayersArray) {
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
if (hasLayersArray) {
|
|
47
|
+
const all = layer ? [layer, ...layers] : layers;
|
|
48
|
+
const cached = mergedLayerCacheRef.current;
|
|
49
|
+
const shallowEqual = cached && cached.layers.length === all.length && cached.layers.every((item, idx) => item === all[idx]);
|
|
50
|
+
if (shallowEqual) {
|
|
51
|
+
return cached.merged;
|
|
52
|
+
}
|
|
53
|
+
const merged = Layer.mergeAll(...all);
|
|
54
|
+
mergedLayerCacheRef.current = { layers: all, merged };
|
|
55
|
+
return merged;
|
|
56
|
+
}
|
|
57
|
+
return layer;
|
|
58
|
+
}, [options?.layer, options?.layers]);
|
|
59
|
+
const lastLayersRef = useRef(null);
|
|
60
|
+
const shallowEqualLayers = (a, b) => !!a && !!b && a.length === b.length && a.every((item, idx) => item === b[idx]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (!isDevEnv()) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (options?.layers && lastLayersRef.current && lastLayersRef.current !== options.layers && !shallowEqualLayers(lastLayersRef.current, options.layers)) {
|
|
66
|
+
console.warn(
|
|
67
|
+
"[RuntimeProvider] useRuntime received a new layers reference. Memoize the layers array with useMemo to avoid rebuilding Layers on every render (performance jitter)."
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
lastLayersRef.current = options?.layers ?? null;
|
|
71
|
+
}, [options?.layers]);
|
|
72
|
+
const { binding } = useLayerBinding(context.runtime, mergedLayer, !!mergedLayer);
|
|
73
|
+
return useMemo(() => {
|
|
74
|
+
if (!binding) {
|
|
75
|
+
return context.runtime;
|
|
76
|
+
}
|
|
77
|
+
return createRuntimeAdapter(
|
|
78
|
+
context.runtime,
|
|
79
|
+
[binding.context],
|
|
80
|
+
[binding.scope],
|
|
81
|
+
[binding.loggers],
|
|
82
|
+
[binding.logLevel],
|
|
83
|
+
[binding.debugSinks]
|
|
84
|
+
);
|
|
85
|
+
}, [context.runtime, binding]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/internal/hooks/shallow.ts
|
|
89
|
+
var hasObjectShape = (value) => typeof value === "object" && value !== null;
|
|
90
|
+
var hasIterator = (value) => hasObjectShape(value) && typeof value[Symbol.iterator] === "function";
|
|
91
|
+
var shallow = (previous, next) => {
|
|
92
|
+
if (Object.is(previous, next)) return true;
|
|
93
|
+
if (!hasObjectShape(previous) || !hasObjectShape(next)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (Array.isArray(previous) && Array.isArray(next)) {
|
|
97
|
+
if (previous.length !== next.length) return false;
|
|
98
|
+
for (let i = 0; i < previous.length; i++) {
|
|
99
|
+
if (!Object.is(previous[i], next[i])) return false;
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
if (previous instanceof Map && next instanceof Map) {
|
|
104
|
+
if (previous.size !== next.size) return false;
|
|
105
|
+
for (const [key, value] of previous) {
|
|
106
|
+
if (!next.has(key)) return false;
|
|
107
|
+
if (!Object.is(value, next.get(key))) return false;
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (previous instanceof Set && next instanceof Set) {
|
|
112
|
+
if (previous.size !== next.size) return false;
|
|
113
|
+
for (const value of previous) {
|
|
114
|
+
if (!next.has(value)) return false;
|
|
115
|
+
}
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
if (hasIterator(previous) && hasIterator(next)) {
|
|
119
|
+
const a = previous[Symbol.iterator]();
|
|
120
|
+
const b = next[Symbol.iterator]();
|
|
121
|
+
while (true) {
|
|
122
|
+
const ra = a.next();
|
|
123
|
+
const rb = b.next();
|
|
124
|
+
if (ra.done || rb.done) return ra.done === rb.done;
|
|
125
|
+
if (!Object.is(ra.value, rb.value)) return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const prevKeys = Object.keys(previous);
|
|
129
|
+
const nextKeys = Object.keys(next);
|
|
130
|
+
if (prevKeys.length !== nextKeys.length) return false;
|
|
131
|
+
for (const key of prevKeys) {
|
|
132
|
+
if (!Object.prototype.hasOwnProperty.call(next, key)) return false;
|
|
133
|
+
if (!Object.is(previous[key], next[key])) return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// src/internal/hooks/useSelector.ts
|
|
139
|
+
import { useContext as useContext3, useEffect as useEffect3, useMemo as useMemo3 } from "react";
|
|
140
|
+
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/shim/with-selector";
|
|
141
|
+
import * as Logix2 from "@logixjs/core";
|
|
142
|
+
|
|
143
|
+
// src/internal/hooks/useModuleRuntime.ts
|
|
144
|
+
import { useEffect as useEffect2, useMemo as useMemo2, useContext as useContext2 } from "react";
|
|
145
|
+
import * as Logix from "@logixjs/core";
|
|
146
|
+
import { Scope } from "effect";
|
|
147
|
+
|
|
148
|
+
// src/internal/store/ModuleRef.ts
|
|
149
|
+
var isModuleRef = (value) => typeof value === "object" && value !== null && "runtime" in value && "actions" in value && "dispatch" in value;
|
|
150
|
+
var makeModuleActions = (dispatch) => {
|
|
151
|
+
const cache = /* @__PURE__ */ new Map();
|
|
152
|
+
const api = new Proxy(
|
|
153
|
+
{},
|
|
154
|
+
{
|
|
155
|
+
get: (_target, prop) => {
|
|
156
|
+
if (cache.has(prop)) {
|
|
157
|
+
return cache.get(prop);
|
|
158
|
+
}
|
|
159
|
+
if (prop === "dispatch") {
|
|
160
|
+
cache.set(prop, dispatch);
|
|
161
|
+
return dispatch;
|
|
162
|
+
}
|
|
163
|
+
if (prop === "then" || typeof prop !== "string") {
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
const fn = (...args) => {
|
|
167
|
+
const payload = args[0];
|
|
168
|
+
dispatch({ _tag: prop, payload });
|
|
169
|
+
};
|
|
170
|
+
cache.set(prop, fn);
|
|
171
|
+
return fn;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
return api;
|
|
176
|
+
};
|
|
177
|
+
function makeModuleDispatchers(dispatch, tokens) {
|
|
178
|
+
const cache = /* @__PURE__ */ new Map();
|
|
179
|
+
if (tokens) {
|
|
180
|
+
const out = {};
|
|
181
|
+
for (const [key, token] of Object.entries(tokens)) {
|
|
182
|
+
const fn = Object.assign(
|
|
183
|
+
((...args) => {
|
|
184
|
+
const action = token(...args);
|
|
185
|
+
dispatch(action);
|
|
186
|
+
return action;
|
|
187
|
+
}),
|
|
188
|
+
token
|
|
189
|
+
);
|
|
190
|
+
out[key] = fn;
|
|
191
|
+
}
|
|
192
|
+
return out;
|
|
193
|
+
}
|
|
194
|
+
const api = new Proxy(
|
|
195
|
+
{},
|
|
196
|
+
{
|
|
197
|
+
get: (_target, prop) => {
|
|
198
|
+
if (cache.has(prop)) {
|
|
199
|
+
return cache.get(prop);
|
|
200
|
+
}
|
|
201
|
+
if (prop === "then" || prop === "dispatch" || typeof prop !== "string") {
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
const fn = (...args) => {
|
|
205
|
+
const payload = args[0];
|
|
206
|
+
const action = { _tag: prop, payload };
|
|
207
|
+
dispatch(action);
|
|
208
|
+
return action;
|
|
209
|
+
};
|
|
210
|
+
cache.set(prop, fn);
|
|
211
|
+
return fn;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
return api;
|
|
216
|
+
}
|
|
217
|
+
var HANDLE_EXTEND = /* @__PURE__ */ Symbol.for("logix.module.handle.extend");
|
|
218
|
+
var isObjectLike = (value) => typeof value === "object" && value !== null || typeof value === "function";
|
|
219
|
+
var applyHandleExtend = (tag, runtime, base) => {
|
|
220
|
+
if (!isObjectLike(tag)) {
|
|
221
|
+
return base;
|
|
222
|
+
}
|
|
223
|
+
const extend = tag[HANDLE_EXTEND];
|
|
224
|
+
if (typeof extend !== "function") {
|
|
225
|
+
return base;
|
|
226
|
+
}
|
|
227
|
+
const next = extend(
|
|
228
|
+
runtime,
|
|
229
|
+
base
|
|
230
|
+
);
|
|
231
|
+
if (!next || typeof next !== "object") {
|
|
232
|
+
return base;
|
|
233
|
+
}
|
|
234
|
+
return { ...base, ...next };
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// src/internal/hooks/useModuleRuntime.ts
|
|
238
|
+
var isModuleRuntime = (value) => typeof value === "object" && value !== null && "dispatch" in value && "getState" in value;
|
|
239
|
+
function useModuleRuntime(handle) {
|
|
240
|
+
const runtime = useRuntime();
|
|
241
|
+
const runtimeContext = useContext2(RuntimeContext);
|
|
242
|
+
if (!runtimeContext) {
|
|
243
|
+
throw new RuntimeProviderNotFoundError("useModuleRuntime");
|
|
244
|
+
}
|
|
245
|
+
const cache = useMemo2(
|
|
246
|
+
() => getModuleCache(runtimeContext.runtime, runtimeContext.reactConfigSnapshot, runtimeContext.configVersion),
|
|
247
|
+
[runtimeContext.runtime, runtimeContext.reactConfigSnapshot, runtimeContext.configVersion]
|
|
248
|
+
);
|
|
249
|
+
const isTagHandle = !isModuleRef(handle) && !isModuleRuntime(handle);
|
|
250
|
+
const resolved = useMemo2(() => {
|
|
251
|
+
if (isModuleRef(handle)) {
|
|
252
|
+
return handle.runtime;
|
|
253
|
+
}
|
|
254
|
+
if (isModuleRuntime(handle)) {
|
|
255
|
+
return handle;
|
|
256
|
+
}
|
|
257
|
+
const tag = handle;
|
|
258
|
+
const tokenId = tag.id ?? "ModuleTag";
|
|
259
|
+
const preloadKey = runtimeContext.policy.preload?.keysByTagId.get(tokenId);
|
|
260
|
+
const key = preloadKey ?? `tag:${tokenId}`;
|
|
261
|
+
const mode = runtimeContext.policy.moduleTagMode;
|
|
262
|
+
const factory = (scope) => tag.pipe(Scope.extend(scope));
|
|
263
|
+
return mode === "suspend" ? cache.read(key, factory, void 0, tokenId, {
|
|
264
|
+
entrypoint: "react.useModuleRuntime",
|
|
265
|
+
policyMode: runtimeContext.policy.mode,
|
|
266
|
+
yield: runtimeContext.policy.yield
|
|
267
|
+
}) : cache.readSync(key, factory, void 0, tokenId, {
|
|
268
|
+
entrypoint: "react.useModuleRuntime",
|
|
269
|
+
policyMode: runtimeContext.policy.mode,
|
|
270
|
+
warnSyncBlockingThresholdMs: 5
|
|
271
|
+
});
|
|
272
|
+
}, [cache, runtimeContext.policy, handle]);
|
|
273
|
+
useEffect2(() => {
|
|
274
|
+
if (!isTagHandle) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (!isDevEnv() && !Logix.Debug.isDevtoolsEnabled()) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const tokenId = handle?.id ?? "ModuleTag";
|
|
281
|
+
const effect = Logix.Debug.record({
|
|
282
|
+
type: "trace:react.moduleTag.resolve",
|
|
283
|
+
moduleId: resolved.moduleId,
|
|
284
|
+
instanceId: resolved.instanceId,
|
|
285
|
+
data: {
|
|
286
|
+
mode: runtimeContext.policy.moduleTagMode,
|
|
287
|
+
tokenId,
|
|
288
|
+
yieldStrategy: runtimeContext.policy.yield.strategy
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
runtime.runFork(effect);
|
|
292
|
+
}, [runtime, runtimeContext.policy, resolved, handle, isTagHandle]);
|
|
293
|
+
return resolved;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/internal/store/ModuleRuntimeExternalStore.ts
|
|
297
|
+
import { Effect as Effect2, Fiber, Stream } from "effect";
|
|
298
|
+
var storesByRuntime = /* @__PURE__ */ new WeakMap();
|
|
299
|
+
var getStoreMapForRuntime = (runtime) => {
|
|
300
|
+
const cached = storesByRuntime.get(runtime);
|
|
301
|
+
if (cached) return cached;
|
|
302
|
+
const next = /* @__PURE__ */ new WeakMap();
|
|
303
|
+
storesByRuntime.set(runtime, next);
|
|
304
|
+
return next;
|
|
305
|
+
};
|
|
306
|
+
var getModuleRuntimeExternalStore = (runtime, moduleRuntime, options) => {
|
|
307
|
+
const byModule = getStoreMapForRuntime(runtime);
|
|
308
|
+
const cached = byModule.get(moduleRuntime);
|
|
309
|
+
if (cached) {
|
|
310
|
+
return cached;
|
|
311
|
+
}
|
|
312
|
+
let currentState;
|
|
313
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
314
|
+
const lowPriorityDelayMs = options?.lowPriorityDelayMs ?? 16;
|
|
315
|
+
const lowPriorityMaxDelayMs = options?.lowPriorityMaxDelayMs ?? 50;
|
|
316
|
+
let notifyScheduled = false;
|
|
317
|
+
let notifyScheduledLow = false;
|
|
318
|
+
let lowTimeoutId;
|
|
319
|
+
let lowMaxTimeoutId;
|
|
320
|
+
let lowRafId;
|
|
321
|
+
const cancelLow = () => {
|
|
322
|
+
if (!notifyScheduledLow) return;
|
|
323
|
+
notifyScheduledLow = false;
|
|
324
|
+
if (lowTimeoutId != null) {
|
|
325
|
+
clearTimeout(lowTimeoutId);
|
|
326
|
+
lowTimeoutId = void 0;
|
|
327
|
+
}
|
|
328
|
+
if (lowMaxTimeoutId != null) {
|
|
329
|
+
clearTimeout(lowMaxTimeoutId);
|
|
330
|
+
lowMaxTimeoutId = void 0;
|
|
331
|
+
}
|
|
332
|
+
const cancel = globalThis.cancelAnimationFrame;
|
|
333
|
+
if (cancel && typeof lowRafId === "number") {
|
|
334
|
+
cancel(lowRafId);
|
|
335
|
+
lowRafId = void 0;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
const flushNotify = () => {
|
|
339
|
+
notifyScheduled = false;
|
|
340
|
+
cancelLow();
|
|
341
|
+
for (const listener of listeners) {
|
|
342
|
+
listener();
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
const scheduleNotify = (priority) => {
|
|
346
|
+
if (priority === "low") {
|
|
347
|
+
if (notifyScheduled) return;
|
|
348
|
+
if (notifyScheduledLow) return;
|
|
349
|
+
notifyScheduledLow = true;
|
|
350
|
+
const flush = () => {
|
|
351
|
+
if (!notifyScheduledLow) return;
|
|
352
|
+
flushNotify();
|
|
353
|
+
};
|
|
354
|
+
const raf = globalThis.requestAnimationFrame;
|
|
355
|
+
if (raf) {
|
|
356
|
+
lowRafId = raf(flush);
|
|
357
|
+
} else {
|
|
358
|
+
lowTimeoutId = setTimeout(flush, lowPriorityDelayMs);
|
|
359
|
+
}
|
|
360
|
+
lowMaxTimeoutId = setTimeout(flush, lowPriorityMaxDelayMs);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
cancelLow();
|
|
364
|
+
if (notifyScheduled) return;
|
|
365
|
+
notifyScheduled = true;
|
|
366
|
+
queueMicrotask(flushNotify);
|
|
367
|
+
};
|
|
368
|
+
let fiber;
|
|
369
|
+
const ensureSubscription = () => {
|
|
370
|
+
if (fiber) return;
|
|
371
|
+
fiber = runtime.runFork(
|
|
372
|
+
Stream.runForEach(
|
|
373
|
+
moduleRuntime.changesWithMeta((state) => state),
|
|
374
|
+
({ value: state, meta }) => Effect2.sync(() => {
|
|
375
|
+
currentState = state;
|
|
376
|
+
scheduleNotify(meta.priority);
|
|
377
|
+
})
|
|
378
|
+
)
|
|
379
|
+
);
|
|
380
|
+
};
|
|
381
|
+
const refreshSnapshotIfStale = () => {
|
|
382
|
+
if (currentState === void 0) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
try {
|
|
386
|
+
const latest = runtime.runSync(moduleRuntime.getState);
|
|
387
|
+
if (currentState === void 0 || !Object.is(currentState, latest)) {
|
|
388
|
+
currentState = latest;
|
|
389
|
+
scheduleNotify("normal");
|
|
390
|
+
}
|
|
391
|
+
} catch {
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
const getSnapshot = () => {
|
|
395
|
+
if (currentState !== void 0) return currentState;
|
|
396
|
+
currentState = runtime.runSync(moduleRuntime.getState);
|
|
397
|
+
return currentState;
|
|
398
|
+
};
|
|
399
|
+
const subscribe = (listener) => {
|
|
400
|
+
listeners.add(listener);
|
|
401
|
+
ensureSubscription();
|
|
402
|
+
refreshSnapshotIfStale();
|
|
403
|
+
return () => {
|
|
404
|
+
listeners.delete(listener);
|
|
405
|
+
if (listeners.size > 0) return;
|
|
406
|
+
const running = fiber;
|
|
407
|
+
if (!running) return;
|
|
408
|
+
fiber = void 0;
|
|
409
|
+
cancelLow();
|
|
410
|
+
runtime.runFork(Fiber.interrupt(running));
|
|
411
|
+
};
|
|
412
|
+
};
|
|
413
|
+
const store = { getSnapshot, subscribe };
|
|
414
|
+
byModule.set(moduleRuntime, store);
|
|
415
|
+
return store;
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
// src/internal/store/ModuleRuntimeSelectorExternalStore.ts
|
|
419
|
+
import { Effect as Effect3, Fiber as Fiber2, Stream as Stream2 } from "effect";
|
|
420
|
+
var storesByRuntime2 = /* @__PURE__ */ new WeakMap();
|
|
421
|
+
var getStoreMapForRuntime2 = (runtime) => {
|
|
422
|
+
const cached = storesByRuntime2.get(runtime);
|
|
423
|
+
if (cached) return cached;
|
|
424
|
+
const next = /* @__PURE__ */ new WeakMap();
|
|
425
|
+
storesByRuntime2.set(runtime, next);
|
|
426
|
+
return next;
|
|
427
|
+
};
|
|
428
|
+
var getOrCreateSelectorMapForModule = (byModule, moduleRuntime) => {
|
|
429
|
+
const cached = byModule.get(moduleRuntime);
|
|
430
|
+
if (cached) return cached;
|
|
431
|
+
const next = /* @__PURE__ */ new Map();
|
|
432
|
+
byModule.set(moduleRuntime, next);
|
|
433
|
+
return next;
|
|
434
|
+
};
|
|
435
|
+
var equalsValue = (readQuery, a, b) => {
|
|
436
|
+
if (readQuery.equalsKind === "custom" && typeof readQuery.equals === "function") {
|
|
437
|
+
return readQuery.equals(a, b);
|
|
438
|
+
}
|
|
439
|
+
if (readQuery.equalsKind === "shallowStruct") {
|
|
440
|
+
return shallow(a, b);
|
|
441
|
+
}
|
|
442
|
+
return Object.is(a, b);
|
|
443
|
+
};
|
|
444
|
+
var getModuleRuntimeSelectorExternalStore = (runtime, moduleRuntime, selectorReadQuery, options) => {
|
|
445
|
+
const byModule = getStoreMapForRuntime2(runtime);
|
|
446
|
+
const bySelector = getOrCreateSelectorMapForModule(byModule, moduleRuntime);
|
|
447
|
+
const cached = bySelector.get(selectorReadQuery.selectorId);
|
|
448
|
+
if (cached) {
|
|
449
|
+
return cached;
|
|
450
|
+
}
|
|
451
|
+
let currentValue;
|
|
452
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
453
|
+
const lowPriorityDelayMs = options?.lowPriorityDelayMs ?? 16;
|
|
454
|
+
const lowPriorityMaxDelayMs = options?.lowPriorityMaxDelayMs ?? 50;
|
|
455
|
+
let notifyScheduled = false;
|
|
456
|
+
let notifyScheduledLow = false;
|
|
457
|
+
let lowTimeoutId;
|
|
458
|
+
let lowMaxTimeoutId;
|
|
459
|
+
let lowRafId;
|
|
460
|
+
const cancelLow = () => {
|
|
461
|
+
if (!notifyScheduledLow) return;
|
|
462
|
+
notifyScheduledLow = false;
|
|
463
|
+
if (lowTimeoutId != null) {
|
|
464
|
+
clearTimeout(lowTimeoutId);
|
|
465
|
+
lowTimeoutId = void 0;
|
|
466
|
+
}
|
|
467
|
+
if (lowMaxTimeoutId != null) {
|
|
468
|
+
clearTimeout(lowMaxTimeoutId);
|
|
469
|
+
lowMaxTimeoutId = void 0;
|
|
470
|
+
}
|
|
471
|
+
const cancel = globalThis.cancelAnimationFrame;
|
|
472
|
+
if (cancel && typeof lowRafId === "number") {
|
|
473
|
+
cancel(lowRafId);
|
|
474
|
+
lowRafId = void 0;
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
const flushNotify = () => {
|
|
478
|
+
notifyScheduled = false;
|
|
479
|
+
cancelLow();
|
|
480
|
+
for (const listener of listeners) {
|
|
481
|
+
listener();
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
const scheduleNotify = (priority) => {
|
|
485
|
+
if (priority === "low") {
|
|
486
|
+
if (notifyScheduled) return;
|
|
487
|
+
if (notifyScheduledLow) return;
|
|
488
|
+
notifyScheduledLow = true;
|
|
489
|
+
const flush = () => {
|
|
490
|
+
if (!notifyScheduledLow) return;
|
|
491
|
+
flushNotify();
|
|
492
|
+
};
|
|
493
|
+
const raf = globalThis.requestAnimationFrame;
|
|
494
|
+
if (raf) {
|
|
495
|
+
lowRafId = raf(flush);
|
|
496
|
+
} else {
|
|
497
|
+
lowTimeoutId = setTimeout(flush, lowPriorityDelayMs);
|
|
498
|
+
}
|
|
499
|
+
lowMaxTimeoutId = setTimeout(flush, lowPriorityMaxDelayMs);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
cancelLow();
|
|
503
|
+
if (notifyScheduled) return;
|
|
504
|
+
notifyScheduled = true;
|
|
505
|
+
queueMicrotask(flushNotify);
|
|
506
|
+
};
|
|
507
|
+
let fiber;
|
|
508
|
+
const ensureSubscription = () => {
|
|
509
|
+
if (fiber) return;
|
|
510
|
+
fiber = runtime.runFork(
|
|
511
|
+
Stream2.runForEach(
|
|
512
|
+
moduleRuntime.changesReadQueryWithMeta(selectorReadQuery),
|
|
513
|
+
({ value, meta }) => Effect3.sync(() => {
|
|
514
|
+
currentValue = value;
|
|
515
|
+
scheduleNotify(meta.priority);
|
|
516
|
+
})
|
|
517
|
+
)
|
|
518
|
+
);
|
|
519
|
+
};
|
|
520
|
+
const refreshSnapshotIfStale = () => {
|
|
521
|
+
if (currentValue === void 0) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
try {
|
|
525
|
+
const state = runtime.runSync(moduleRuntime.getState);
|
|
526
|
+
const next = selectorReadQuery.select(state);
|
|
527
|
+
if (currentValue === void 0 || !equalsValue(selectorReadQuery, currentValue, next)) {
|
|
528
|
+
currentValue = next;
|
|
529
|
+
scheduleNotify("normal");
|
|
530
|
+
}
|
|
531
|
+
} catch {
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
const getSnapshot = () => {
|
|
535
|
+
if (currentValue !== void 0) return currentValue;
|
|
536
|
+
const state = runtime.runSync(moduleRuntime.getState);
|
|
537
|
+
currentValue = selectorReadQuery.select(state);
|
|
538
|
+
return currentValue;
|
|
539
|
+
};
|
|
540
|
+
const subscribe = (listener) => {
|
|
541
|
+
listeners.add(listener);
|
|
542
|
+
ensureSubscription();
|
|
543
|
+
refreshSnapshotIfStale();
|
|
544
|
+
return () => {
|
|
545
|
+
listeners.delete(listener);
|
|
546
|
+
if (listeners.size > 0) return;
|
|
547
|
+
const running = fiber;
|
|
548
|
+
if (!running) return;
|
|
549
|
+
fiber = void 0;
|
|
550
|
+
cancelLow();
|
|
551
|
+
runtime.runFork(Fiber2.interrupt(running));
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
const store = { getSnapshot, subscribe };
|
|
555
|
+
bySelector.set(selectorReadQuery.selectorId, store);
|
|
556
|
+
return store;
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
// src/internal/hooks/useSelector.ts
|
|
560
|
+
function useSelector(handle, selector, equalityFn) {
|
|
561
|
+
const runtimeContext = useContext3(RuntimeContext);
|
|
562
|
+
if (!runtimeContext) {
|
|
563
|
+
throw new RuntimeProviderNotFoundError("useSelector");
|
|
564
|
+
}
|
|
565
|
+
const runtime = runtimeContext.runtime;
|
|
566
|
+
const moduleRuntime = useModuleRuntime(handle);
|
|
567
|
+
const actualSelector = selector ?? ((state) => state);
|
|
568
|
+
const selectorReadQuery = useMemo3(
|
|
569
|
+
() => typeof selector === "function" ? Logix2.ReadQuery.compile(selector) : void 0,
|
|
570
|
+
[selector]
|
|
571
|
+
);
|
|
572
|
+
const actualEqualityFn = useMemo3(() => {
|
|
573
|
+
if (typeof equalityFn === "function") return equalityFn;
|
|
574
|
+
if (typeof selector !== "function") return Object.is;
|
|
575
|
+
return selectorReadQuery?.equalsKind === "shallowStruct" ? shallow : Object.is;
|
|
576
|
+
}, [equalityFn, selector, selectorReadQuery?.equalsKind]);
|
|
577
|
+
const useStaticLane = typeof selector === "function" && selectorReadQuery?.lane === "static";
|
|
578
|
+
const store = useMemo3(
|
|
579
|
+
() => useStaticLane && selectorReadQuery ? getModuleRuntimeSelectorExternalStore(
|
|
580
|
+
runtime,
|
|
581
|
+
moduleRuntime,
|
|
582
|
+
selectorReadQuery,
|
|
583
|
+
{
|
|
584
|
+
lowPriorityDelayMs: runtimeContext.reactConfigSnapshot.lowPriorityDelayMs,
|
|
585
|
+
lowPriorityMaxDelayMs: runtimeContext.reactConfigSnapshot.lowPriorityMaxDelayMs
|
|
586
|
+
}
|
|
587
|
+
) : getModuleRuntimeExternalStore(
|
|
588
|
+
runtime,
|
|
589
|
+
moduleRuntime,
|
|
590
|
+
{
|
|
591
|
+
lowPriorityDelayMs: runtimeContext.reactConfigSnapshot.lowPriorityDelayMs,
|
|
592
|
+
lowPriorityMaxDelayMs: runtimeContext.reactConfigSnapshot.lowPriorityMaxDelayMs
|
|
593
|
+
}
|
|
594
|
+
),
|
|
595
|
+
[
|
|
596
|
+
moduleRuntime,
|
|
597
|
+
runtime,
|
|
598
|
+
runtimeContext.reactConfigSnapshot.lowPriorityDelayMs,
|
|
599
|
+
runtimeContext.reactConfigSnapshot.lowPriorityMaxDelayMs,
|
|
600
|
+
selectorReadQuery,
|
|
601
|
+
useStaticLane
|
|
602
|
+
]
|
|
603
|
+
);
|
|
604
|
+
const selected = useSyncExternalStoreWithSelector(
|
|
605
|
+
store.subscribe,
|
|
606
|
+
store.getSnapshot,
|
|
607
|
+
store.getSnapshot,
|
|
608
|
+
useStaticLane ? (snapshot) => snapshot : (snapshot) => actualSelector(snapshot),
|
|
609
|
+
actualEqualityFn
|
|
610
|
+
);
|
|
611
|
+
useEffect3(() => {
|
|
612
|
+
if (!isDevEnv() && !Logix2.Debug.isDevtoolsEnabled()) {
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const instanceId = moduleRuntime.instanceId;
|
|
616
|
+
let fieldPaths;
|
|
617
|
+
let selectorKey;
|
|
618
|
+
if (typeof selector === "function") {
|
|
619
|
+
const meta = selector;
|
|
620
|
+
const rawFieldPaths = meta.fieldPaths;
|
|
621
|
+
if (Array.isArray(rawFieldPaths)) {
|
|
622
|
+
const paths = rawFieldPaths.filter((p) => typeof p === "string");
|
|
623
|
+
fieldPaths = paths.length > 0 ? paths.slice() : void 0;
|
|
624
|
+
}
|
|
625
|
+
const rawDebugKey = meta.debugKey;
|
|
626
|
+
selectorKey = typeof rawDebugKey === "string" && rawDebugKey.length > 0 ? rawDebugKey : typeof selector.name === "string" && selector.name.length > 0 ? selector.name : void 0;
|
|
627
|
+
}
|
|
628
|
+
const effect = Logix2.Debug.record({
|
|
629
|
+
type: "trace:react-selector",
|
|
630
|
+
moduleId: moduleRuntime.moduleId,
|
|
631
|
+
instanceId,
|
|
632
|
+
data: {
|
|
633
|
+
componentLabel: "useSelector",
|
|
634
|
+
selectorKey,
|
|
635
|
+
fieldPaths,
|
|
636
|
+
selectorId: selectorReadQuery?.selectorId,
|
|
637
|
+
lane: selectorReadQuery?.lane,
|
|
638
|
+
producer: selectorReadQuery?.producer,
|
|
639
|
+
fallbackReason: selectorReadQuery?.fallbackReason,
|
|
640
|
+
readsDigest: selectorReadQuery?.readsDigest,
|
|
641
|
+
equalsKind: selectorReadQuery?.equalsKind,
|
|
642
|
+
strictModePhase: "commit"
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
runtime.runFork(effect);
|
|
646
|
+
}, [runtime, moduleRuntime, selector, selected, selectorReadQuery]);
|
|
647
|
+
return selected;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// src/internal/hooks/useModule.ts
|
|
651
|
+
import React2 from "react";
|
|
652
|
+
import * as Logix4 from "@logixjs/core";
|
|
653
|
+
import { Context, Effect as Effect4, Layer as Layer2 } from "effect";
|
|
654
|
+
|
|
655
|
+
// src/internal/store/resolveImportedModuleRef.ts
|
|
656
|
+
import * as Logix3 from "@logixjs/core";
|
|
657
|
+
var getOrCreateWeakMap = (map, key, make) => {
|
|
658
|
+
const cached = map.get(key);
|
|
659
|
+
if (cached) return cached;
|
|
660
|
+
const next = make();
|
|
661
|
+
map.set(key, next);
|
|
662
|
+
return next;
|
|
663
|
+
};
|
|
664
|
+
var cacheByRuntime = /* @__PURE__ */ new WeakMap();
|
|
665
|
+
var resolveImportedModuleRef = (runtime, parentRuntime, module) => {
|
|
666
|
+
const byParent = getOrCreateWeakMap(
|
|
667
|
+
cacheByRuntime,
|
|
668
|
+
runtime,
|
|
669
|
+
() => /* @__PURE__ */ new WeakMap()
|
|
670
|
+
);
|
|
671
|
+
const byModule = getOrCreateWeakMap(
|
|
672
|
+
byParent,
|
|
673
|
+
parentRuntime,
|
|
674
|
+
() => /* @__PURE__ */ new WeakMap()
|
|
675
|
+
);
|
|
676
|
+
const cached = byModule.get(module);
|
|
677
|
+
if (cached) {
|
|
678
|
+
return cached;
|
|
679
|
+
}
|
|
680
|
+
const importsScope = Logix3.InternalContracts.getImportsScope(parentRuntime);
|
|
681
|
+
const childRuntime = importsScope.get(module);
|
|
682
|
+
if (childRuntime) {
|
|
683
|
+
const dispatch = Object.assign(
|
|
684
|
+
(action) => {
|
|
685
|
+
runtime.runFork(childRuntime.dispatch(action));
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
batch: (actions2) => {
|
|
689
|
+
runtime.runFork(
|
|
690
|
+
childRuntime.dispatchBatch(
|
|
691
|
+
actions2
|
|
692
|
+
)
|
|
693
|
+
);
|
|
694
|
+
},
|
|
695
|
+
lowPriority: (action) => {
|
|
696
|
+
runtime.runFork(
|
|
697
|
+
childRuntime.dispatchLowPriority(action)
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
);
|
|
702
|
+
const actions = makeModuleActions(dispatch);
|
|
703
|
+
const dispatchers = makeModuleDispatchers(dispatch, module.actions);
|
|
704
|
+
const ref = {
|
|
705
|
+
def: module,
|
|
706
|
+
runtime: childRuntime,
|
|
707
|
+
dispatch,
|
|
708
|
+
actions,
|
|
709
|
+
dispatchers,
|
|
710
|
+
imports: {
|
|
711
|
+
get: (m) => resolveImportedModuleRef(runtime, childRuntime, m)
|
|
712
|
+
},
|
|
713
|
+
getState: childRuntime.getState,
|
|
714
|
+
setState: childRuntime.setState,
|
|
715
|
+
actions$: childRuntime.actions$,
|
|
716
|
+
changes: childRuntime.changes,
|
|
717
|
+
ref: childRuntime.ref
|
|
718
|
+
};
|
|
719
|
+
byModule.set(module, ref);
|
|
720
|
+
return ref;
|
|
721
|
+
}
|
|
722
|
+
const parentId = parentRuntime.moduleId;
|
|
723
|
+
const tokenId = String(module.id);
|
|
724
|
+
const parentInstanceId = parentRuntime.instanceId;
|
|
725
|
+
const fix = isDevEnv() ? [
|
|
726
|
+
"- Ensure the child is imported in the same scope.",
|
|
727
|
+
` Example: ${parentId}.implement({ imports: [${tokenId}.impl], ... })`,
|
|
728
|
+
"- Ensure parentRuntime is an instance scope (not a ModuleTag singleton).",
|
|
729
|
+
" Example: useModule(ParentImpl, { key }) / useModule(ParentImpl) / useLocalModule(ParentModule, ...)",
|
|
730
|
+
"- If you intentionally want a singleton (not an imported child), use useModule(Child.tag) (ModuleTag) in the current React runtime environment.",
|
|
731
|
+
"- If you intentionally want the root provider singleton (ignore RuntimeProvider.layer overrides), use runtime.runSync(Root.resolve(Child.tag))."
|
|
732
|
+
] : [];
|
|
733
|
+
const err = new Error(
|
|
734
|
+
isDevEnv() ? [
|
|
735
|
+
"[MissingImportedModuleError] Cannot resolve imported module from parent imports scope.",
|
|
736
|
+
"",
|
|
737
|
+
`tokenId: ${tokenId}`,
|
|
738
|
+
"entrypoint: react.useImportedModule/imports.get",
|
|
739
|
+
"mode: strict",
|
|
740
|
+
`startScope: moduleId=${parentId}, instanceId=${parentInstanceId}`,
|
|
741
|
+
"",
|
|
742
|
+
"fix:",
|
|
743
|
+
...fix
|
|
744
|
+
].join("\n") : "[MissingImportedModuleError] imported module runtime not found"
|
|
745
|
+
);
|
|
746
|
+
err.tokenId = tokenId;
|
|
747
|
+
err.entrypoint = "react.useImportedModule/imports.get";
|
|
748
|
+
err.mode = "strict";
|
|
749
|
+
err.startScope = {
|
|
750
|
+
moduleId: parentId,
|
|
751
|
+
instanceId: parentInstanceId
|
|
752
|
+
};
|
|
753
|
+
err.fix = fix;
|
|
754
|
+
err.name = "MissingImportedModuleError";
|
|
755
|
+
throw err;
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
// src/internal/hooks/useStableId.ts
|
|
759
|
+
import React from "react";
|
|
760
|
+
var useStableId = () => {
|
|
761
|
+
return React.useId();
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
// src/internal/hooks/useModule.ts
|
|
765
|
+
var isModuleImpl = (handle) => Boolean(handle) && typeof handle === "object" && handle._tag === "ModuleImpl";
|
|
766
|
+
var isModule = (handle) => Logix4.Module.hasImpl(handle);
|
|
767
|
+
var isModuleDef = (handle) => Logix4.Module.is(handle) && handle._kind === "ModuleDef";
|
|
768
|
+
function useModule(handle, selectorOrOptions, equalityFn) {
|
|
769
|
+
const runtimeBase = useRuntime();
|
|
770
|
+
const runtimeContext = React2.useContext(RuntimeContext);
|
|
771
|
+
if (!runtimeContext) {
|
|
772
|
+
throw new RuntimeProviderNotFoundError("useModule");
|
|
773
|
+
}
|
|
774
|
+
const normalizedHandle = isModule(handle) ? handle.impl : isModuleDef(handle) ? handle.tag : handle;
|
|
775
|
+
let selector;
|
|
776
|
+
let options;
|
|
777
|
+
if (isModuleImpl(normalizedHandle)) {
|
|
778
|
+
if (typeof selectorOrOptions === "function") {
|
|
779
|
+
selector = selectorOrOptions;
|
|
780
|
+
} else if (selectorOrOptions && typeof selectorOrOptions === "object") {
|
|
781
|
+
options = selectorOrOptions;
|
|
782
|
+
}
|
|
783
|
+
} else {
|
|
784
|
+
if (typeof selectorOrOptions === "function" || selectorOrOptions === void 0) {
|
|
785
|
+
selector = selectorOrOptions;
|
|
786
|
+
} else if (selectorOrOptions && typeof selectorOrOptions === "object") {
|
|
787
|
+
throw new Error("useModule(handle, options) \u4EC5\u652F\u6301 ModuleImpl \u53E5\u67C4");
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
let runtime;
|
|
791
|
+
if (isModuleImpl(normalizedHandle)) {
|
|
792
|
+
const cache = React2.useMemo(
|
|
793
|
+
() => getModuleCache(runtimeBase, runtimeContext.reactConfigSnapshot, runtimeContext.configVersion),
|
|
794
|
+
[runtimeBase, runtimeContext.reactConfigSnapshot, runtimeContext.configVersion]
|
|
795
|
+
);
|
|
796
|
+
const deps = options?.deps ?? [];
|
|
797
|
+
const depsHash = stableHash(deps);
|
|
798
|
+
const explicitSuspend = options?.suspend === true;
|
|
799
|
+
const suspend = explicitSuspend || options?.suspend !== false && runtimeContext.policy.moduleImplMode === "suspend";
|
|
800
|
+
const gcTime = options?.gcTime ?? runtimeContext.reactConfigSnapshot.gcTime;
|
|
801
|
+
let initTimeoutMs = suspend ? options?.initTimeoutMs : void 0;
|
|
802
|
+
if (suspend && initTimeoutMs === void 0) {
|
|
803
|
+
initTimeoutMs = runtimeContext.reactConfigSnapshot.initTimeoutMs;
|
|
804
|
+
}
|
|
805
|
+
if (explicitSuspend && (!options || !options.key)) {
|
|
806
|
+
if (isDevEnv()) {
|
|
807
|
+
throw new Error(
|
|
808
|
+
"[useModule] suspend:true \u6A21\u5F0F\u5FC5\u987B\u663E\u5F0F\u63D0\u4F9B options.key\uFF1B\u8BF7\u5728 Suspense \u8FB9\u754C\u5916\u751F\u6210\u7A33\u5B9A ID\uFF08\u4F8B\u5982 useId() \u6216\u4E1A\u52A1 id\uFF09\uFF0C\u5E76\u5728 useModule(Impl, { suspend: true, key }) \u4E2D\u4F20\u5165\u8BE5\u503C\u3002"
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
const componentId = useStableId();
|
|
813
|
+
const moduleId = normalizedHandle.module.id ?? "ModuleImpl";
|
|
814
|
+
const preloadKey = runtimeContext.policy.preload?.keysByModuleId.get(moduleId);
|
|
815
|
+
const baseKey = preloadKey ?? options?.key ?? (suspend ? `impl:${moduleId}` : `impl:${moduleId}:${componentId}`);
|
|
816
|
+
const key = depsHash ? `${baseKey}:${depsHash}` : baseKey;
|
|
817
|
+
const ownerId = moduleId;
|
|
818
|
+
const baseFactory = React2.useMemo(
|
|
819
|
+
() => (scope) => Layer2.buildWithScope(normalizedHandle.layer, scope).pipe(
|
|
820
|
+
Effect4.map(
|
|
821
|
+
(context) => Context.get(context, normalizedHandle.module)
|
|
822
|
+
)
|
|
823
|
+
),
|
|
824
|
+
[normalizedHandle]
|
|
825
|
+
);
|
|
826
|
+
const factory = React2.useMemo(() => {
|
|
827
|
+
if (!suspend || initTimeoutMs === void 0) {
|
|
828
|
+
return baseFactory;
|
|
829
|
+
}
|
|
830
|
+
return (scope) => baseFactory(scope).pipe(
|
|
831
|
+
Effect4.timeoutFail({
|
|
832
|
+
duration: initTimeoutMs,
|
|
833
|
+
onTimeout: () => new Error(`[useModule] Module "${ownerId}" initialization timed out after ${initTimeoutMs}ms`)
|
|
834
|
+
})
|
|
835
|
+
);
|
|
836
|
+
}, [baseFactory, suspend, initTimeoutMs, ownerId]);
|
|
837
|
+
const moduleRuntime = suspend ? cache.read(key, factory, gcTime, ownerId, {
|
|
838
|
+
entrypoint: "react.useModule",
|
|
839
|
+
policyMode: runtimeContext.policy.mode,
|
|
840
|
+
yield: runtimeContext.policy.yield
|
|
841
|
+
}) : cache.readSync(key, factory, gcTime, ownerId, {
|
|
842
|
+
entrypoint: "react.useModule",
|
|
843
|
+
policyMode: runtimeContext.policy.mode,
|
|
844
|
+
warnSyncBlockingThresholdMs: 5
|
|
845
|
+
});
|
|
846
|
+
React2.useEffect(() => cache.retain(key), [cache, key]);
|
|
847
|
+
runtime = moduleRuntime;
|
|
848
|
+
} else {
|
|
849
|
+
runtime = useModuleRuntime(normalizedHandle);
|
|
850
|
+
}
|
|
851
|
+
React2.useEffect(() => {
|
|
852
|
+
if (!isModuleImpl(normalizedHandle)) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
const opt = options;
|
|
856
|
+
const label = opt && "label" in opt && opt.label || opt && opt.key;
|
|
857
|
+
if (!label) {
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
const effect = Logix4.Debug.record({
|
|
861
|
+
type: "trace:instanceLabel",
|
|
862
|
+
moduleId: normalizedHandle.module.id,
|
|
863
|
+
instanceId: runtime.instanceId,
|
|
864
|
+
data: { label }
|
|
865
|
+
});
|
|
866
|
+
runtimeBase.runFork(effect);
|
|
867
|
+
}, [runtimeBase, runtime, normalizedHandle, options]);
|
|
868
|
+
React2.useEffect(() => {
|
|
869
|
+
if (!isDevEnv() && !Logix4.Debug.isDevtoolsEnabled()) {
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
if (!runtime.instanceId) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
const effect = Logix4.Debug.record({
|
|
876
|
+
type: "trace:react-render",
|
|
877
|
+
moduleId: runtime.moduleId,
|
|
878
|
+
instanceId: runtime.instanceId,
|
|
879
|
+
data: {
|
|
880
|
+
componentLabel: "useModule",
|
|
881
|
+
strictModePhase: "commit"
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
runtimeBase.runFork(effect);
|
|
885
|
+
}, [runtimeBase, runtime]);
|
|
886
|
+
if (selector) {
|
|
887
|
+
if (isModuleImpl(normalizedHandle)) {
|
|
888
|
+
return useSelector(runtime, selector, equalityFn);
|
|
889
|
+
}
|
|
890
|
+
return useSelector(normalizedHandle, selector, equalityFn);
|
|
891
|
+
}
|
|
892
|
+
const def = React2.useMemo(() => {
|
|
893
|
+
if (isModule(handle) || isModuleDef(handle)) {
|
|
894
|
+
return handle;
|
|
895
|
+
}
|
|
896
|
+
if (isModuleRef(handle)) {
|
|
897
|
+
return handle.def;
|
|
898
|
+
}
|
|
899
|
+
if (isModuleImpl(handle)) {
|
|
900
|
+
return handle.module;
|
|
901
|
+
}
|
|
902
|
+
if (handle && (typeof handle === "object" || typeof handle === "function") && handle._kind === "ModuleTag") {
|
|
903
|
+
return handle;
|
|
904
|
+
}
|
|
905
|
+
if (isModuleImpl(normalizedHandle)) {
|
|
906
|
+
return normalizedHandle.module;
|
|
907
|
+
}
|
|
908
|
+
if (isModuleRef(normalizedHandle)) {
|
|
909
|
+
return normalizedHandle.def;
|
|
910
|
+
}
|
|
911
|
+
if (normalizedHandle && (typeof normalizedHandle === "object" || typeof normalizedHandle === "function") && normalizedHandle._kind === "ModuleTag") {
|
|
912
|
+
return normalizedHandle;
|
|
913
|
+
}
|
|
914
|
+
return void 0;
|
|
915
|
+
}, [handle, normalizedHandle]);
|
|
916
|
+
const tokens = React2.useMemo(() => {
|
|
917
|
+
if (!def || typeof def !== "object" && typeof def !== "function") {
|
|
918
|
+
return void 0;
|
|
919
|
+
}
|
|
920
|
+
const candidate = def;
|
|
921
|
+
if (!candidate.actions || typeof candidate.actions !== "object") {
|
|
922
|
+
return void 0;
|
|
923
|
+
}
|
|
924
|
+
return candidate.actions;
|
|
925
|
+
}, [def]);
|
|
926
|
+
const dispatch = React2.useMemo(() => {
|
|
927
|
+
const base = (action) => {
|
|
928
|
+
runtimeBase.runFork(runtime.dispatch(action));
|
|
929
|
+
};
|
|
930
|
+
return Object.assign(base, {
|
|
931
|
+
batch: (actions2) => {
|
|
932
|
+
runtimeBase.runFork(runtime.dispatchBatch(actions2));
|
|
933
|
+
},
|
|
934
|
+
lowPriority: (action) => {
|
|
935
|
+
runtimeBase.runFork(runtime.dispatchLowPriority(action));
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
}, [runtimeBase, runtime]);
|
|
939
|
+
const extendTag = React2.useMemo(() => {
|
|
940
|
+
if (isModuleImpl(normalizedHandle)) {
|
|
941
|
+
return normalizedHandle.module;
|
|
942
|
+
}
|
|
943
|
+
return normalizedHandle;
|
|
944
|
+
}, [normalizedHandle]);
|
|
945
|
+
const actions = React2.useMemo(() => makeModuleActions(dispatch), [dispatch]);
|
|
946
|
+
const dispatchers = React2.useMemo(
|
|
947
|
+
() => tokens ? makeModuleDispatchers(dispatch, tokens) : makeModuleDispatchers(dispatch),
|
|
948
|
+
[dispatch, tokens]
|
|
949
|
+
);
|
|
950
|
+
return React2.useMemo(() => {
|
|
951
|
+
const base = {
|
|
952
|
+
def,
|
|
953
|
+
runtime,
|
|
954
|
+
dispatch,
|
|
955
|
+
actions,
|
|
956
|
+
dispatchers,
|
|
957
|
+
imports: {
|
|
958
|
+
get: (module) => resolveImportedModuleRef(runtimeBase, runtime, module)
|
|
959
|
+
},
|
|
960
|
+
getState: runtime.getState,
|
|
961
|
+
setState: runtime.setState,
|
|
962
|
+
actions$: runtime.actions$,
|
|
963
|
+
changes: runtime.changes,
|
|
964
|
+
ref: runtime.ref
|
|
965
|
+
};
|
|
966
|
+
return applyHandleExtend(extendTag, runtime, base);
|
|
967
|
+
}, [runtimeBase, runtime, dispatch, actions, dispatchers, extendTag, def]);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
export {
|
|
971
|
+
RuntimeProviderNotFoundError,
|
|
972
|
+
useRuntime,
|
|
973
|
+
makeModuleActions,
|
|
974
|
+
makeModuleDispatchers,
|
|
975
|
+
useModuleRuntime,
|
|
976
|
+
shallow,
|
|
977
|
+
useSelector,
|
|
978
|
+
resolveImportedModuleRef,
|
|
979
|
+
useStableId,
|
|
980
|
+
useModule
|
|
981
|
+
};
|