@logixjs/core 0.0.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/dist/Action-BkRHy2vg.d.cts +10 -0
- package/dist/Action-mqVvtEHt.d.ts +10 -0
- package/dist/Action.cjs +57 -0
- package/dist/Action.cjs.map +1 -0
- package/dist/Action.d.cts +2 -0
- package/dist/Action.d.ts +2 -0
- package/dist/Action.js +9 -0
- package/dist/Action.js.map +1 -0
- package/dist/Actions-AsQ07yTP.d.cts +22 -0
- package/dist/Actions-AsQ07yTP.d.ts +22 -0
- package/dist/Actions.cjs +19 -0
- package/dist/Actions.cjs.map +1 -0
- package/dist/Actions.d.cts +2 -0
- package/dist/Actions.d.ts +2 -0
- package/dist/Actions.js +2 -0
- package/dist/Actions.js.map +1 -0
- package/dist/Bound-BN1DQ_lM.d.ts +23 -0
- package/dist/Bound-BPIfH9SS.d.cts +23 -0
- package/dist/Bound.cjs +1532 -0
- package/dist/Bound.cjs.map +1 -0
- package/dist/Bound.d.cts +7 -0
- package/dist/Bound.d.ts +7 -0
- package/dist/Bound.js +25 -0
- package/dist/Bound.js.map +1 -0
- package/dist/Debug-B5q5Bkzx.d.ts +320 -0
- package/dist/Debug-Bq8Sqjcr.d.cts +320 -0
- package/dist/Debug.cjs +1821 -0
- package/dist/Debug.cjs.map +1 -0
- package/dist/Debug.d.cts +13 -0
- package/dist/Debug.d.ts +13 -0
- package/dist/Debug.js +76 -0
- package/dist/Debug.js.map +1 -0
- package/dist/EffectOp.cjs +169 -0
- package/dist/EffectOp.cjs.map +1 -0
- package/dist/EffectOp.d.cts +118 -0
- package/dist/EffectOp.d.ts +118 -0
- package/dist/EffectOp.js +28 -0
- package/dist/EffectOp.js.map +1 -0
- package/dist/Env-DuJ6JrU2.d.cts +10 -0
- package/dist/Env-DuJ6JrU2.d.ts +10 -0
- package/dist/Env.cjs +60 -0
- package/dist/Env.cjs.map +1 -0
- package/dist/Env.d.cts +1 -0
- package/dist/Env.d.ts +1 -0
- package/dist/Env.js +11 -0
- package/dist/Env.js.map +1 -0
- package/dist/Flow-1fZT8MpX.d.cts +152 -0
- package/dist/Flow-BhpjE22E.d.ts +152 -0
- package/dist/Flow.cjs +504 -0
- package/dist/Flow.cjs.map +1 -0
- package/dist/Flow.d.cts +8 -0
- package/dist/Flow.d.ts +8 -0
- package/dist/Flow.js +15 -0
- package/dist/Flow.js.map +1 -0
- package/dist/Handle-D8D1zPb_.d.cts +30 -0
- package/dist/Handle-D_cLW1Z3.d.ts +30 -0
- package/dist/Handle.cjs +42 -0
- package/dist/Handle.cjs.map +1 -0
- package/dist/Handle.d.cts +7 -0
- package/dist/Handle.d.ts +7 -0
- package/dist/Handle.js +10 -0
- package/dist/Handle.js.map +1 -0
- package/dist/Kernel-8kC-jOda.d.cts +171 -0
- package/dist/Kernel-CnGE1Fyk.d.ts +171 -0
- package/dist/Kernel.cjs +284 -0
- package/dist/Kernel.cjs.map +1 -0
- package/dist/Kernel.d.cts +14 -0
- package/dist/Kernel.d.ts +14 -0
- package/dist/Kernel.js +36 -0
- package/dist/Kernel.js.map +1 -0
- package/dist/Link-Db7975nU.d.ts +45 -0
- package/dist/Link-fX8x1eCK.d.cts +45 -0
- package/dist/Link.cjs +542 -0
- package/dist/Link.cjs.map +1 -0
- package/dist/Link.d.cts +7 -0
- package/dist/Link.d.ts +7 -0
- package/dist/Link.js +35 -0
- package/dist/Link.js.map +1 -0
- package/dist/Logic-BRjEMr-W.d.ts +38 -0
- package/dist/Logic-DRh4sDZj.d.cts +38 -0
- package/dist/Logic.cjs +37 -0
- package/dist/Logic.cjs.map +1 -0
- package/dist/Logic.d.cts +7 -0
- package/dist/Logic.d.ts +7 -0
- package/dist/Logic.js +10 -0
- package/dist/Logic.js.map +1 -0
- package/dist/MatchBuilder-0QOc-nlU.d.ts +14 -0
- package/dist/MatchBuilder-CJk5oCkR.d.cts +14 -0
- package/dist/MatchBuilder.cjs +85 -0
- package/dist/MatchBuilder.cjs.map +1 -0
- package/dist/MatchBuilder.d.cts +8 -0
- package/dist/MatchBuilder.d.ts +8 -0
- package/dist/MatchBuilder.js +11 -0
- package/dist/MatchBuilder.js.map +1 -0
- package/dist/Middleware.cjs +411 -0
- package/dist/Middleware.cjs.map +1 -0
- package/dist/Middleware.d.cts +88 -0
- package/dist/Middleware.d.ts +88 -0
- package/dist/Middleware.js +27 -0
- package/dist/Middleware.js.map +1 -0
- package/dist/Module-B_0xRDMR.d.cts +203 -0
- package/dist/Module-DnzluX2J.d.ts +203 -0
- package/dist/Module.cjs +13512 -0
- package/dist/Module.cjs.map +1 -0
- package/dist/Module.d.cts +8 -0
- package/dist/Module.d.ts +8 -0
- package/dist/Module.js +53 -0
- package/dist/Module.js.map +1 -0
- package/dist/ModuleTag-C8FHY_sY.d.ts +93 -0
- package/dist/ModuleTag-EGbgBMpZ.d.cts +93 -0
- package/dist/ModuleTag.cjs +12231 -0
- package/dist/ModuleTag.cjs.map +1 -0
- package/dist/ModuleTag.d.cts +8 -0
- package/dist/ModuleTag.d.ts +8 -0
- package/dist/ModuleTag.js +39 -0
- package/dist/ModuleTag.js.map +1 -0
- package/dist/Observability-COqEvp2C.d.cts +713 -0
- package/dist/Observability-cY4kLn0S.d.ts +713 -0
- package/dist/Observability.cjs +5865 -0
- package/dist/Observability.cjs.map +1 -0
- package/dist/Observability.d.cts +9 -0
- package/dist/Observability.d.ts +9 -0
- package/dist/Observability.js +41 -0
- package/dist/Observability.js.map +1 -0
- package/dist/Platform-C49Pv956.d.cts +21 -0
- package/dist/Platform-C49Pv956.d.ts +21 -0
- package/dist/Platform-CHX8o-U4.d.ts +51 -0
- package/dist/Platform-CVlv0xLQ.d.cts +51 -0
- package/dist/Platform.cjs +58 -0
- package/dist/Platform.cjs.map +1 -0
- package/dist/Platform.d.cts +4 -0
- package/dist/Platform.d.ts +4 -0
- package/dist/Platform.js +15 -0
- package/dist/Platform.js.map +1 -0
- package/dist/Process-CM9xbMdP.d.ts +92 -0
- package/dist/Process-mL8fHDSB.d.cts +92 -0
- package/dist/Process.cjs +575 -0
- package/dist/Process.cjs.map +1 -0
- package/dist/Process.d.cts +8 -0
- package/dist/Process.d.ts +8 -0
- package/dist/Process.js +42 -0
- package/dist/Process.js.map +1 -0
- package/dist/ReadQuery-BlMwhe-F.d.ts +30 -0
- package/dist/ReadQuery-CL5XlXts.d.cts +30 -0
- package/dist/ReadQuery-SinbStGF.d.cts +38 -0
- package/dist/ReadQuery-SinbStGF.d.ts +38 -0
- package/dist/ReadQuery.cjs +377 -0
- package/dist/ReadQuery.cjs.map +1 -0
- package/dist/ReadQuery.d.cts +2 -0
- package/dist/ReadQuery.d.ts +2 -0
- package/dist/ReadQuery.js +14 -0
- package/dist/ReadQuery.js.map +1 -0
- package/dist/Reflection-CQnKwPXj.d.ts +182 -0
- package/dist/Reflection-Kabo1mlU.d.cts +182 -0
- package/dist/Reflection.cjs +2954 -0
- package/dist/Reflection.cjs.map +1 -0
- package/dist/Reflection.d.cts +17 -0
- package/dist/Reflection.d.ts +17 -0
- package/dist/Reflection.js +40 -0
- package/dist/Reflection.js.map +1 -0
- package/dist/Resource-Dy1xD_DG.d.cts +75 -0
- package/dist/Resource-Dy1xD_DG.d.ts +75 -0
- package/dist/Resource.cjs +166 -0
- package/dist/Resource.cjs.map +1 -0
- package/dist/Resource.d.cts +3 -0
- package/dist/Resource.d.ts +3 -0
- package/dist/Resource.js +21 -0
- package/dist/Resource.js.map +1 -0
- package/dist/Root-7ADUMk4t.d.cts +29 -0
- package/dist/Root-7ADUMk4t.d.ts +29 -0
- package/dist/Root.cjs +125 -0
- package/dist/Root.cjs.map +1 -0
- package/dist/Root.d.cts +4 -0
- package/dist/Root.d.ts +4 -0
- package/dist/Root.js +12 -0
- package/dist/Root.js.map +1 -0
- package/dist/Runtime-B-aL-f29.d.cts +274 -0
- package/dist/Runtime-CtyzZG4i.d.ts +274 -0
- package/dist/Runtime.cjs +5740 -0
- package/dist/Runtime.cjs.map +1 -0
- package/dist/Runtime.d.cts +19 -0
- package/dist/Runtime.d.ts +19 -0
- package/dist/Runtime.js +62 -0
- package/dist/Runtime.js.map +1 -0
- package/dist/ScopeRegistry-D1owDNSm.d.cts +61 -0
- package/dist/ScopeRegistry-D1owDNSm.d.ts +61 -0
- package/dist/ScopeRegistry.cjs +152 -0
- package/dist/ScopeRegistry.cjs.map +1 -0
- package/dist/ScopeRegistry.d.cts +2 -0
- package/dist/ScopeRegistry.d.ts +2 -0
- package/dist/ScopeRegistry.js +16 -0
- package/dist/ScopeRegistry.js.map +1 -0
- package/dist/State-CU50R26M.d.cts +19 -0
- package/dist/State-CU50R26M.d.ts +19 -0
- package/dist/State.cjs +19 -0
- package/dist/State.cjs.map +1 -0
- package/dist/State.d.cts +2 -0
- package/dist/State.d.ts +2 -0
- package/dist/State.js +2 -0
- package/dist/State.js.map +1 -0
- package/dist/StateTrait-BGsZghTz.d.ts +122 -0
- package/dist/StateTrait-OWhbj12c.d.cts +122 -0
- package/dist/StateTrait.cjs +2737 -0
- package/dist/StateTrait.cjs.map +1 -0
- package/dist/StateTrait.d.cts +9 -0
- package/dist/StateTrait.d.ts +9 -0
- package/dist/StateTrait.js +39 -0
- package/dist/StateTrait.js.map +1 -0
- package/dist/TraitLifecycle-CwV5WPFX.d.cts +88 -0
- package/dist/TraitLifecycle-LdIWmKlg.d.ts +88 -0
- package/dist/TraitLifecycle.cjs +581 -0
- package/dist/TraitLifecycle.cjs.map +1 -0
- package/dist/TraitLifecycle.d.cts +8 -0
- package/dist/TraitLifecycle.d.ts +8 -0
- package/dist/TraitLifecycle.js +24 -0
- package/dist/TraitLifecycle.js.map +1 -0
- package/dist/action-DiMDD_0v.d.cts +35 -0
- package/dist/action-DiMDD_0v.d.ts +35 -0
- package/dist/chunk-24VULZ7A.js +76 -0
- package/dist/chunk-24VULZ7A.js.map +1 -0
- package/dist/chunk-3IYZ5IGG.js +17 -0
- package/dist/chunk-3IYZ5IGG.js.map +1 -0
- package/dist/chunk-3QMIVH35.js +43 -0
- package/dist/chunk-3QMIVH35.js.map +1 -0
- package/dist/chunk-3RMKLXHX.js +83 -0
- package/dist/chunk-3RMKLXHX.js.map +1 -0
- package/dist/chunk-3TMODYZV.js +111 -0
- package/dist/chunk-3TMODYZV.js.map +1 -0
- package/dist/chunk-3VG5TWQR.js +27 -0
- package/dist/chunk-3VG5TWQR.js.map +1 -0
- package/dist/chunk-4CQAV7YB.js +37 -0
- package/dist/chunk-4CQAV7YB.js.map +1 -0
- package/dist/chunk-4SO6JMZL.js +7 -0
- package/dist/chunk-4SO6JMZL.js.map +1 -0
- package/dist/chunk-66ALHVEX.js +40 -0
- package/dist/chunk-66ALHVEX.js.map +1 -0
- package/dist/chunk-76WT3HOR.js +397 -0
- package/dist/chunk-76WT3HOR.js.map +1 -0
- package/dist/chunk-ANLBCBDC.js +285 -0
- package/dist/chunk-ANLBCBDC.js.map +1 -0
- package/dist/chunk-AUIR5O6W.js +75 -0
- package/dist/chunk-AUIR5O6W.js.map +1 -0
- package/dist/chunk-BABLDP24.js +445 -0
- package/dist/chunk-BABLDP24.js.map +1 -0
- package/dist/chunk-BE3HW4FY.js +1099 -0
- package/dist/chunk-BE3HW4FY.js.map +1 -0
- package/dist/chunk-BZ2SHDN2.js +54 -0
- package/dist/chunk-BZ2SHDN2.js.map +1 -0
- package/dist/chunk-CW6T36TN.js +393 -0
- package/dist/chunk-CW6T36TN.js.map +1 -0
- package/dist/chunk-DFNM3WX2.js +632 -0
- package/dist/chunk-DFNM3WX2.js.map +1 -0
- package/dist/chunk-DMBALCE2.js +1034 -0
- package/dist/chunk-DMBALCE2.js.map +1 -0
- package/dist/chunk-EGK3KN7B.js +406 -0
- package/dist/chunk-EGK3KN7B.js.map +1 -0
- package/dist/chunk-EY4NZKDR.js +19 -0
- package/dist/chunk-EY4NZKDR.js.map +1 -0
- package/dist/chunk-G5ZBFPNU.js +23 -0
- package/dist/chunk-G5ZBFPNU.js.map +1 -0
- package/dist/chunk-GMPEOUP2.js +31 -0
- package/dist/chunk-GMPEOUP2.js.map +1 -0
- package/dist/chunk-IHVBV5C2.js +279 -0
- package/dist/chunk-IHVBV5C2.js.map +1 -0
- package/dist/chunk-IPF7E66P.js +23 -0
- package/dist/chunk-IPF7E66P.js.map +1 -0
- package/dist/chunk-JCXGZRMU.js +204 -0
- package/dist/chunk-JCXGZRMU.js.map +1 -0
- package/dist/chunk-JGIWG6SR.js +6359 -0
- package/dist/chunk-JGIWG6SR.js.map +1 -0
- package/dist/chunk-JWOYLO27.js +241 -0
- package/dist/chunk-JWOYLO27.js.map +1 -0
- package/dist/chunk-KIXAU3GM.js +137 -0
- package/dist/chunk-KIXAU3GM.js.map +1 -0
- package/dist/chunk-KL5ACTCT.js +8 -0
- package/dist/chunk-KL5ACTCT.js.map +1 -0
- package/dist/chunk-KP7MUZNX.js +83 -0
- package/dist/chunk-KP7MUZNX.js.map +1 -0
- package/dist/chunk-LEU6UA5J.js +1 -0
- package/dist/chunk-LEU6UA5J.js.map +1 -0
- package/dist/chunk-M2RGJPXX.js +35 -0
- package/dist/chunk-M2RGJPXX.js.map +1 -0
- package/dist/chunk-M3BFQ7HK.js +13 -0
- package/dist/chunk-M3BFQ7HK.js.map +1 -0
- package/dist/chunk-M3WTHJHJ.js +1051 -0
- package/dist/chunk-M3WTHJHJ.js.map +1 -0
- package/dist/chunk-M7IYCTJV.js +79 -0
- package/dist/chunk-M7IYCTJV.js.map +1 -0
- package/dist/chunk-NBD3KUOZ.js +838 -0
- package/dist/chunk-NBD3KUOZ.js.map +1 -0
- package/dist/chunk-NQZ2OSGR.js +151 -0
- package/dist/chunk-NQZ2OSGR.js.map +1 -0
- package/dist/chunk-NZJKFF45.js +106 -0
- package/dist/chunk-NZJKFF45.js.map +1 -0
- package/dist/chunk-OFADUJWJ.js +175 -0
- package/dist/chunk-OFADUJWJ.js.map +1 -0
- package/dist/chunk-OGWBVHB3.js +461 -0
- package/dist/chunk-OGWBVHB3.js.map +1 -0
- package/dist/chunk-PAYXCY6A.js +1696 -0
- package/dist/chunk-PAYXCY6A.js.map +1 -0
- package/dist/chunk-PYOE4VSI.js +1924 -0
- package/dist/chunk-PYOE4VSI.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-QCHIQWAJ.js +21 -0
- package/dist/chunk-QCHIQWAJ.js.map +1 -0
- package/dist/chunk-QMM6O4CD.js +71 -0
- package/dist/chunk-QMM6O4CD.js.map +1 -0
- package/dist/chunk-RNFE3ML2.js +22 -0
- package/dist/chunk-RNFE3ML2.js.map +1 -0
- package/dist/chunk-TAAPQVZN.js +23 -0
- package/dist/chunk-TAAPQVZN.js.map +1 -0
- package/dist/chunk-THATMZXD.js +21 -0
- package/dist/chunk-THATMZXD.js.map +1 -0
- package/dist/chunk-TKZ7MEIA.js +27 -0
- package/dist/chunk-TKZ7MEIA.js.map +1 -0
- package/dist/chunk-TQOBJYDP.js +7 -0
- package/dist/chunk-TQOBJYDP.js.map +1 -0
- package/dist/chunk-VZB726PE.js +93 -0
- package/dist/chunk-VZB726PE.js.map +1 -0
- package/dist/chunk-W3TEWHLO.js +568 -0
- package/dist/chunk-W3TEWHLO.js.map +1 -0
- package/dist/chunk-YS3AZQ2G.js +52 -0
- package/dist/chunk-YS3AZQ2G.js.map +1 -0
- package/dist/chunk-ZDTRWK5F.js +40 -0
- package/dist/chunk-ZDTRWK5F.js.map +1 -0
- package/dist/chunk-ZFLHVFUC.js +192 -0
- package/dist/chunk-ZFLHVFUC.js.map +1 -0
- package/dist/chunk-ZFY7U2FR.js +133 -0
- package/dist/chunk-ZFY7U2FR.js.map +1 -0
- package/dist/chunk-ZGDVUPTM.js +270 -0
- package/dist/chunk-ZGDVUPTM.js.map +1 -0
- package/dist/index.cjs +19700 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +195 -0
- package/dist/index.d.ts +195 -0
- package/dist/index.js +286 -0
- package/dist/index.js.map +1 -0
- package/dist/ir-BMP7yxJJ.d.cts +39 -0
- package/dist/ir-DUOz6H-5.d.ts +39 -0
- package/dist/module-B8CBqIZ_.d.cts +1191 -0
- package/dist/module-k7m3txak.d.ts +1191 -0
- package/dist/protocol-g_1897M2.d.cts +127 -0
- package/dist/protocol-g_1897M2.d.ts +127 -0
- package/package.json +162 -0
|
@@ -0,0 +1,1924 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ReplayLog,
|
|
3
|
+
getAtPath,
|
|
4
|
+
parseListItemFieldPath,
|
|
5
|
+
setAtPathMutating,
|
|
6
|
+
toListItemValuePath
|
|
7
|
+
} from "./chunk-BABLDP24.js";
|
|
8
|
+
import {
|
|
9
|
+
Snapshot,
|
|
10
|
+
internal,
|
|
11
|
+
keyHash
|
|
12
|
+
} from "./chunk-NZJKFF45.js";
|
|
13
|
+
import {
|
|
14
|
+
forceSourceRefresh,
|
|
15
|
+
inSyncTransactionFiber
|
|
16
|
+
} from "./chunk-ZFLHVFUC.js";
|
|
17
|
+
import {
|
|
18
|
+
compareFieldPath,
|
|
19
|
+
getFieldPathId,
|
|
20
|
+
makeFieldPathIdRegistry,
|
|
21
|
+
normalizeFieldPath
|
|
22
|
+
} from "./chunk-IHVBV5C2.js";
|
|
23
|
+
import {
|
|
24
|
+
getBoundInternals
|
|
25
|
+
} from "./chunk-3RMKLXHX.js";
|
|
26
|
+
import {
|
|
27
|
+
ReplayModeConfigTag,
|
|
28
|
+
isDevEnv
|
|
29
|
+
} from "./chunk-3QMIVH35.js";
|
|
30
|
+
import {
|
|
31
|
+
record
|
|
32
|
+
} from "./chunk-DMBALCE2.js";
|
|
33
|
+
import {
|
|
34
|
+
fnv1a32,
|
|
35
|
+
stableStringify
|
|
36
|
+
} from "./chunk-GMPEOUP2.js";
|
|
37
|
+
import {
|
|
38
|
+
RunSessionTag,
|
|
39
|
+
make,
|
|
40
|
+
run
|
|
41
|
+
} from "./chunk-OFADUJWJ.js";
|
|
42
|
+
import {
|
|
43
|
+
EffectOpMiddlewareTag
|
|
44
|
+
} from "./chunk-JWOYLO27.js";
|
|
45
|
+
|
|
46
|
+
// src/internal/state-trait/build.ts
|
|
47
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
48
|
+
|
|
49
|
+
// src/internal/state-trait/meta.ts
|
|
50
|
+
var uniqSortedStrings = (input) => {
|
|
51
|
+
const set = /* @__PURE__ */ new Set();
|
|
52
|
+
for (const item of input) {
|
|
53
|
+
const v = item.trim();
|
|
54
|
+
if (!v) continue;
|
|
55
|
+
set.add(v);
|
|
56
|
+
}
|
|
57
|
+
return Array.from(set).sort((a, b) => a.localeCompare(b));
|
|
58
|
+
};
|
|
59
|
+
var isPlainRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
60
|
+
var sanitizeJsonValue = (input, depth) => {
|
|
61
|
+
if (input === null) return null;
|
|
62
|
+
if (typeof input === "string") return input;
|
|
63
|
+
if (typeof input === "boolean") return input;
|
|
64
|
+
if (typeof input === "number") {
|
|
65
|
+
return Number.isFinite(input) ? input : void 0;
|
|
66
|
+
}
|
|
67
|
+
if (depth >= 6) return void 0;
|
|
68
|
+
if (Array.isArray(input)) {
|
|
69
|
+
const out = [];
|
|
70
|
+
for (const item of input) {
|
|
71
|
+
const v = sanitizeJsonValue(item, depth + 1);
|
|
72
|
+
if (v !== void 0) out.push(v);
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
if (isPlainRecord(input)) {
|
|
77
|
+
const keys = Object.keys(input).sort();
|
|
78
|
+
const out = {};
|
|
79
|
+
for (const key of keys) {
|
|
80
|
+
const v = sanitizeJsonValue(input[key], depth + 1);
|
|
81
|
+
if (v !== void 0) out[key] = v;
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
return void 0;
|
|
86
|
+
};
|
|
87
|
+
var sanitize = (input) => {
|
|
88
|
+
if (input === null || input === void 0) return void 0;
|
|
89
|
+
if (typeof input !== "object" || Array.isArray(input)) return void 0;
|
|
90
|
+
const record2 = input;
|
|
91
|
+
const out = {};
|
|
92
|
+
const pickString = (key) => {
|
|
93
|
+
const value = record2[key];
|
|
94
|
+
if (typeof value !== "string") return;
|
|
95
|
+
const trimmed = value.trim();
|
|
96
|
+
if (!trimmed) return;
|
|
97
|
+
out[key] = trimmed;
|
|
98
|
+
};
|
|
99
|
+
pickString("label");
|
|
100
|
+
pickString("description");
|
|
101
|
+
pickString("group");
|
|
102
|
+
pickString("docsUrl");
|
|
103
|
+
pickString("cacheGroup");
|
|
104
|
+
const canonical = record2.canonical;
|
|
105
|
+
if (typeof canonical === "boolean") {
|
|
106
|
+
out.canonical = canonical;
|
|
107
|
+
}
|
|
108
|
+
const tagsRaw = record2.tags;
|
|
109
|
+
if (typeof tagsRaw === "string") {
|
|
110
|
+
const tags = uniqSortedStrings([tagsRaw]);
|
|
111
|
+
if (tags.length > 0) out.tags = tags;
|
|
112
|
+
} else if (Array.isArray(tagsRaw)) {
|
|
113
|
+
const tags = uniqSortedStrings(tagsRaw.filter((x) => typeof x === "string"));
|
|
114
|
+
if (tags.length > 0) out.tags = tags;
|
|
115
|
+
}
|
|
116
|
+
const annotations = {};
|
|
117
|
+
const annotationKeys = Object.keys(record2).filter((k) => k.startsWith("x-")).sort((a, b) => a.localeCompare(b));
|
|
118
|
+
for (const key of annotationKeys) {
|
|
119
|
+
const v = sanitizeJsonValue(record2[key], 0);
|
|
120
|
+
if (v !== void 0) annotations[key] = v;
|
|
121
|
+
}
|
|
122
|
+
const annotationsRaw = record2.annotations;
|
|
123
|
+
if (isPlainRecord(annotationsRaw)) {
|
|
124
|
+
const keys = Object.keys(annotationsRaw).filter((k) => k.startsWith("x-")).sort((a, b) => a.localeCompare(b));
|
|
125
|
+
for (const key of keys) {
|
|
126
|
+
const v = sanitizeJsonValue(annotationsRaw[key], 0);
|
|
127
|
+
if (v !== void 0) annotations[key] = v;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (Object.keys(annotations).length > 0) out.annotations = annotations;
|
|
131
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
132
|
+
};
|
|
133
|
+
var stableStringify2 = (meta) => {
|
|
134
|
+
const out = {};
|
|
135
|
+
const keys = Object.keys(meta).sort();
|
|
136
|
+
for (const k of keys) {
|
|
137
|
+
out[k] = meta[k];
|
|
138
|
+
}
|
|
139
|
+
return JSON.stringify(out);
|
|
140
|
+
};
|
|
141
|
+
var equals = (a, b) => {
|
|
142
|
+
if (a === b) return true;
|
|
143
|
+
if (!a || !b) return false;
|
|
144
|
+
return stableStringify2(a) === stableStringify2(b);
|
|
145
|
+
};
|
|
146
|
+
var mergeCanonical = (current, incoming) => {
|
|
147
|
+
const existing = current.meta;
|
|
148
|
+
if (!existing) {
|
|
149
|
+
return {
|
|
150
|
+
meta: incoming.meta,
|
|
151
|
+
origin: incoming.origin,
|
|
152
|
+
conflicts: current.conflicts
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (equals(existing, incoming.meta)) {
|
|
156
|
+
return current;
|
|
157
|
+
}
|
|
158
|
+
const conflicts = [...current.conflicts ?? []];
|
|
159
|
+
const push = (conflict) => {
|
|
160
|
+
const exists = conflicts.some((c) => c.origin === conflict.origin && equals(c.meta, conflict.meta));
|
|
161
|
+
if (!exists) conflicts.push(conflict);
|
|
162
|
+
};
|
|
163
|
+
const existingCanonical = existing.canonical === true;
|
|
164
|
+
const incomingCanonical = incoming.meta.canonical === true;
|
|
165
|
+
if (!existingCanonical && incomingCanonical) {
|
|
166
|
+
push({
|
|
167
|
+
origin: current.origin ?? "unknown",
|
|
168
|
+
meta: existing
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
meta: incoming.meta,
|
|
172
|
+
origin: incoming.origin,
|
|
173
|
+
conflicts
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
push({
|
|
177
|
+
origin: incoming.origin,
|
|
178
|
+
meta: incoming.meta
|
|
179
|
+
});
|
|
180
|
+
return {
|
|
181
|
+
meta: existing,
|
|
182
|
+
origin: current.origin ?? incoming.origin,
|
|
183
|
+
conflicts
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/internal/state-trait/model.ts
|
|
188
|
+
var normalizeSpec = (spec) => {
|
|
189
|
+
const entries = [];
|
|
190
|
+
const isNode = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitNode";
|
|
191
|
+
const isList = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitList";
|
|
192
|
+
const joinPath = (prefix, suffix) => {
|
|
193
|
+
if (!prefix) return suffix;
|
|
194
|
+
if (!suffix) return prefix;
|
|
195
|
+
return `${prefix}.${suffix}`;
|
|
196
|
+
};
|
|
197
|
+
const prefixDeps = (deps, prefix) => {
|
|
198
|
+
if (!deps || deps.length === 0) return [];
|
|
199
|
+
return deps.map((d) => prefix ? joinPath(prefix, d) : d);
|
|
200
|
+
};
|
|
201
|
+
const normalizeEntry = (entry, fieldPath, depPrefix) => {
|
|
202
|
+
if (entry.kind === "computed") {
|
|
203
|
+
const meta = entry.meta;
|
|
204
|
+
const rawDeps = meta.deps;
|
|
205
|
+
const deps = rawDeps !== void 0 ? prefixDeps(rawDeps, depPrefix) : void 0;
|
|
206
|
+
return {
|
|
207
|
+
...entry,
|
|
208
|
+
fieldPath,
|
|
209
|
+
meta: { ...meta, deps }
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (entry.kind === "source") {
|
|
213
|
+
const meta = entry.meta;
|
|
214
|
+
const rawDeps = meta.deps;
|
|
215
|
+
const deps = rawDeps !== void 0 ? prefixDeps(rawDeps, depPrefix) : void 0;
|
|
216
|
+
return {
|
|
217
|
+
...entry,
|
|
218
|
+
fieldPath,
|
|
219
|
+
meta: { ...meta, deps, _fieldPath: fieldPath }
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (entry.kind === "link") {
|
|
223
|
+
const meta = entry.meta;
|
|
224
|
+
const from = prefixDeps([meta.from], depPrefix)[0] ?? meta.from;
|
|
225
|
+
return {
|
|
226
|
+
...entry,
|
|
227
|
+
fieldPath,
|
|
228
|
+
meta: { ...meta, from }
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
...entry,
|
|
233
|
+
fieldPath
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
const expandNode = (scopeId, joinPrefix, node, options) => {
|
|
237
|
+
const addEntry = (relativeTarget, raw) => {
|
|
238
|
+
const rel = raw.fieldPath ?? relativeTarget;
|
|
239
|
+
const fieldPath = joinPrefix ? joinPath(joinPrefix, String(rel)) : String(rel);
|
|
240
|
+
entries.push(normalizeEntry(raw, fieldPath, joinPrefix));
|
|
241
|
+
};
|
|
242
|
+
const expandMaybeRecord = (value) => {
|
|
243
|
+
if (!value) return;
|
|
244
|
+
if (typeof value.kind === "string") {
|
|
245
|
+
addEntry("", value);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const record2 = value;
|
|
249
|
+
for (const key in record2) {
|
|
250
|
+
if (!Object.prototype.hasOwnProperty.call(record2, key)) continue;
|
|
251
|
+
const entry = record2[key];
|
|
252
|
+
if (!entry) continue;
|
|
253
|
+
addEntry(key, entry);
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
expandMaybeRecord(node.computed);
|
|
257
|
+
expandMaybeRecord(node.source);
|
|
258
|
+
expandMaybeRecord(node.link);
|
|
259
|
+
if (node.check) {
|
|
260
|
+
const rules = {};
|
|
261
|
+
const checkDepsPrefix = options?.checkDepsPrefix ?? (joinPrefix.endsWith("[]") ? joinPrefix : "");
|
|
262
|
+
const prefixCheckDeps = (deps) => {
|
|
263
|
+
if (!deps || deps.length === 0) return [];
|
|
264
|
+
return deps.map((d) => d === "" ? scopeId : checkDepsPrefix ? joinPath(checkDepsPrefix, d) : d);
|
|
265
|
+
};
|
|
266
|
+
for (const name of Object.keys(node.check)) {
|
|
267
|
+
const rule = node.check[name];
|
|
268
|
+
if (typeof rule === "function") {
|
|
269
|
+
rules[name] = rule;
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (rule && typeof rule === "object") {
|
|
273
|
+
const meta = sanitize(rule.meta);
|
|
274
|
+
rules[name] = {
|
|
275
|
+
...rule,
|
|
276
|
+
deps: prefixCheckDeps(rule.deps),
|
|
277
|
+
meta
|
|
278
|
+
};
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
entries.push({
|
|
283
|
+
fieldPath: scopeId,
|
|
284
|
+
kind: "check",
|
|
285
|
+
meta: {
|
|
286
|
+
rules,
|
|
287
|
+
writeback: { kind: "errors" }
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
for (const key in spec) {
|
|
293
|
+
if (!Object.prototype.hasOwnProperty.call(spec, key)) continue;
|
|
294
|
+
const raw = spec[key];
|
|
295
|
+
if (!raw) continue;
|
|
296
|
+
if (isList(raw)) {
|
|
297
|
+
const listPath = key;
|
|
298
|
+
if (raw.item) {
|
|
299
|
+
expandNode(`${listPath}[]`, `${listPath}[]`, raw.item);
|
|
300
|
+
}
|
|
301
|
+
if (raw.list) {
|
|
302
|
+
expandNode(listPath, listPath, raw.list, {
|
|
303
|
+
checkDepsPrefix: `${listPath}[]`
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
if (isNode(raw)) {
|
|
309
|
+
if (key === "$root") {
|
|
310
|
+
expandNode("$root", "", raw);
|
|
311
|
+
} else {
|
|
312
|
+
expandNode(key, key, raw);
|
|
313
|
+
}
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const entry = raw;
|
|
317
|
+
const fieldPath = entry.fieldPath ?? key;
|
|
318
|
+
entries.push(normalizeEntry(entry, String(fieldPath), ""));
|
|
319
|
+
}
|
|
320
|
+
return entries;
|
|
321
|
+
};
|
|
322
|
+
var collectNodeMeta = (spec) => {
|
|
323
|
+
const out = /* @__PURE__ */ new Map();
|
|
324
|
+
const isNode = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitNode";
|
|
325
|
+
const isList = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitList";
|
|
326
|
+
const add = (scopeId, node) => {
|
|
327
|
+
const meta = sanitize(node.meta);
|
|
328
|
+
if (meta) out.set(scopeId, meta);
|
|
329
|
+
};
|
|
330
|
+
for (const key in spec) {
|
|
331
|
+
if (!Object.prototype.hasOwnProperty.call(spec, key)) continue;
|
|
332
|
+
const raw = spec[key];
|
|
333
|
+
if (!raw) continue;
|
|
334
|
+
if (isList(raw)) {
|
|
335
|
+
const listPath = key;
|
|
336
|
+
if (raw.item) add(`${listPath}[]`, raw.item);
|
|
337
|
+
if (raw.list) add(listPath, raw.list);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
if (isNode(raw)) {
|
|
341
|
+
if (key === "$root") add("$root", raw);
|
|
342
|
+
else add(key, raw);
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return out;
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// src/internal/state-trait/build.ts
|
|
350
|
+
var nowPerf = () => typeof globalThis.performance !== "undefined" && typeof globalThis.performance.now === "function" ? globalThis.performance.now() : Date.now();
|
|
351
|
+
var getConvergeWriterDeps = (entry) => {
|
|
352
|
+
if (entry.kind === "computed") {
|
|
353
|
+
return entry.meta?.deps ?? [];
|
|
354
|
+
}
|
|
355
|
+
return [entry.meta.from];
|
|
356
|
+
};
|
|
357
|
+
var computeConvergeTopoOrder = (writers) => {
|
|
358
|
+
const writerByPath = /* @__PURE__ */ new Map();
|
|
359
|
+
for (const entry of writers) {
|
|
360
|
+
const existing = writerByPath.get(entry.fieldPath);
|
|
361
|
+
if (existing) {
|
|
362
|
+
return {
|
|
363
|
+
order: [],
|
|
364
|
+
configError: {
|
|
365
|
+
code: "MULTIPLE_WRITERS",
|
|
366
|
+
message: `[StateTrait.converge] Multiple writers for field "${entry.fieldPath}" (${existing.kind} + ${entry.kind}).`,
|
|
367
|
+
fields: [entry.fieldPath]
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
writerByPath.set(entry.fieldPath, entry);
|
|
372
|
+
}
|
|
373
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
374
|
+
for (const entry of writers) {
|
|
375
|
+
nodes.add(entry.fieldPath);
|
|
376
|
+
}
|
|
377
|
+
const indegree = /* @__PURE__ */ new Map();
|
|
378
|
+
const forward = /* @__PURE__ */ new Map();
|
|
379
|
+
for (const node of nodes) {
|
|
380
|
+
indegree.set(node, 0);
|
|
381
|
+
forward.set(node, []);
|
|
382
|
+
}
|
|
383
|
+
for (const entry of writers) {
|
|
384
|
+
const to = entry.fieldPath;
|
|
385
|
+
const deps = getConvergeWriterDeps(entry);
|
|
386
|
+
for (const dep of deps) {
|
|
387
|
+
if (!nodes.has(dep)) continue;
|
|
388
|
+
forward.get(dep).push(to);
|
|
389
|
+
indegree.set(to, (indegree.get(to) ?? 0) + 1);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const queue = [];
|
|
393
|
+
for (const [node, deg] of indegree.entries()) {
|
|
394
|
+
if (deg === 0) queue.push(node);
|
|
395
|
+
}
|
|
396
|
+
const order = [];
|
|
397
|
+
while (queue.length) {
|
|
398
|
+
const n = queue.shift();
|
|
399
|
+
order.push(n);
|
|
400
|
+
const outs = forward.get(n);
|
|
401
|
+
for (const to of outs) {
|
|
402
|
+
const next = (indegree.get(to) ?? 0) - 1;
|
|
403
|
+
indegree.set(to, next);
|
|
404
|
+
if (next === 0) queue.push(to);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (order.length !== nodes.size) {
|
|
408
|
+
const remaining = Array.from(nodes).filter((n) => !order.includes(n));
|
|
409
|
+
return {
|
|
410
|
+
order: [],
|
|
411
|
+
configError: {
|
|
412
|
+
code: "CYCLE_DETECTED",
|
|
413
|
+
message: `[StateTrait.converge] Cycle detected in computed/link graph: ${remaining.join(", ")}`,
|
|
414
|
+
fields: remaining
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
return { order };
|
|
419
|
+
};
|
|
420
|
+
var collectSchemaFieldPaths = (schema) => {
|
|
421
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
422
|
+
const add = (path) => {
|
|
423
|
+
const normalized = normalizeFieldPath(path);
|
|
424
|
+
if (!normalized) return;
|
|
425
|
+
byKey.set(JSON.stringify(normalized), normalized);
|
|
426
|
+
};
|
|
427
|
+
const visit = (ast, prefix, seen) => {
|
|
428
|
+
let current = ast;
|
|
429
|
+
while (true) {
|
|
430
|
+
if (SchemaAST.isSuspend(current)) {
|
|
431
|
+
if (seen.has(current)) return;
|
|
432
|
+
seen.add(current);
|
|
433
|
+
current = current.f();
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
if (SchemaAST.isRefinement(current)) {
|
|
437
|
+
current = current.from;
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
if (SchemaAST.isTransformation(current)) {
|
|
443
|
+
visit(current.to, prefix, seen);
|
|
444
|
+
visit(current.from, prefix, seen);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
if (SchemaAST.isUnion(current)) {
|
|
448
|
+
for (const t of current.types) {
|
|
449
|
+
visit(t, prefix, seen);
|
|
450
|
+
}
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (SchemaAST.isTupleType(current)) {
|
|
454
|
+
for (const e of current.elements) {
|
|
455
|
+
visit(e.type, prefix, seen);
|
|
456
|
+
}
|
|
457
|
+
for (const r of current.rest) {
|
|
458
|
+
visit(r.type, prefix, seen);
|
|
459
|
+
}
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
if (SchemaAST.isTypeLiteral(current)) {
|
|
463
|
+
for (const ps of current.propertySignatures) {
|
|
464
|
+
const seg = String(ps.name);
|
|
465
|
+
if (!seg) continue;
|
|
466
|
+
const next = [...prefix, seg];
|
|
467
|
+
add(next);
|
|
468
|
+
visit(ps.type, next, seen);
|
|
469
|
+
}
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
visit(schema.ast, [], /* @__PURE__ */ new Set());
|
|
474
|
+
return Array.from(byKey.values()).sort(compareFieldPath);
|
|
475
|
+
};
|
|
476
|
+
var buildConvergeIr = (stateSchema, entries) => {
|
|
477
|
+
const startedAt = nowPerf();
|
|
478
|
+
const generation = 0;
|
|
479
|
+
const writers = entries.filter((e) => e.kind === "computed" || e.kind === "link");
|
|
480
|
+
const writersKey = writers.map((entry) => `${entry.kind}:${entry.fieldPath}`).sort().join("|");
|
|
481
|
+
const depsKey = writers.map((entry) => {
|
|
482
|
+
const deps = getConvergeWriterDeps(entry).slice().sort().join(",");
|
|
483
|
+
const scheduling = entry.meta?.scheduling === "deferred" ? "d" : "i";
|
|
484
|
+
return `${entry.kind}:${entry.fieldPath}@${scheduling}=>${deps}`;
|
|
485
|
+
}).sort().join("|");
|
|
486
|
+
const writerByPath = /* @__PURE__ */ new Map();
|
|
487
|
+
for (const entry of writers) {
|
|
488
|
+
writerByPath.set(entry.fieldPath, entry);
|
|
489
|
+
}
|
|
490
|
+
const topo = writers.length > 0 ? computeConvergeTopoOrder(writers) : { order: [] };
|
|
491
|
+
const stepsById = topo.configError ? [] : topo.order.map((path) => writerByPath.get(path));
|
|
492
|
+
const fieldPathTable = /* @__PURE__ */ new Map();
|
|
493
|
+
const addPath = (path) => {
|
|
494
|
+
for (let i = 1; i <= path.length; i++) {
|
|
495
|
+
const prefix = path.slice(0, i);
|
|
496
|
+
const key = JSON.stringify(prefix);
|
|
497
|
+
if (!fieldPathTable.has(key)) fieldPathTable.set(key, prefix);
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
for (const schemaPath of collectSchemaFieldPaths(stateSchema)) {
|
|
501
|
+
addPath(schemaPath);
|
|
502
|
+
}
|
|
503
|
+
for (const entry of writers) {
|
|
504
|
+
const out = normalizeFieldPath(entry.fieldPath);
|
|
505
|
+
if (out) addPath(out);
|
|
506
|
+
for (const dep of getConvergeWriterDeps(entry)) {
|
|
507
|
+
const depPath = normalizeFieldPath(dep);
|
|
508
|
+
if (depPath) addPath(depPath);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
const fieldPaths = Array.from(fieldPathTable.values()).sort(compareFieldPath);
|
|
512
|
+
const fieldPathIdRegistry = makeFieldPathIdRegistry(fieldPaths);
|
|
513
|
+
const fieldPathsKey = fnv1a32(stableStringify(fieldPaths));
|
|
514
|
+
const stepOutFieldPathIdByStepId = [];
|
|
515
|
+
const stepDepsFieldPathIdsByStepId = [];
|
|
516
|
+
const stepSchedulingByStepId = [];
|
|
517
|
+
for (const entry of stepsById) {
|
|
518
|
+
const out = normalizeFieldPath(entry.fieldPath);
|
|
519
|
+
const outId = out != null ? getFieldPathId(fieldPathIdRegistry, out) : void 0;
|
|
520
|
+
if (outId == null) {
|
|
521
|
+
throw new Error(`[StateTrait.build] Failed to map converge output fieldPath "${entry.fieldPath}" to FieldPathId.`);
|
|
522
|
+
}
|
|
523
|
+
const depIds = [];
|
|
524
|
+
for (const dep of getConvergeWriterDeps(entry)) {
|
|
525
|
+
const depPath = normalizeFieldPath(dep);
|
|
526
|
+
if (!depPath) continue;
|
|
527
|
+
const depId = getFieldPathId(fieldPathIdRegistry, depPath);
|
|
528
|
+
if (depId != null) depIds.push(depId);
|
|
529
|
+
}
|
|
530
|
+
stepOutFieldPathIdByStepId.push(outId);
|
|
531
|
+
stepDepsFieldPathIdsByStepId.push(depIds);
|
|
532
|
+
stepSchedulingByStepId.push(entry.meta?.scheduling === "deferred" ? "deferred" : "immediate");
|
|
533
|
+
}
|
|
534
|
+
const topoOrder = stepsById.map((_, i) => i);
|
|
535
|
+
const buildDurationMs = Math.max(0, nowPerf() - startedAt);
|
|
536
|
+
return {
|
|
537
|
+
generation,
|
|
538
|
+
writersKey,
|
|
539
|
+
depsKey,
|
|
540
|
+
fieldPathsKey,
|
|
541
|
+
fieldPaths,
|
|
542
|
+
fieldPathIdRegistry,
|
|
543
|
+
...topo.configError ? { configError: topo.configError } : null,
|
|
544
|
+
stepsById,
|
|
545
|
+
stepOutFieldPathIdByStepId,
|
|
546
|
+
stepDepsFieldPathIdsByStepId,
|
|
547
|
+
stepSchedulingByStepId,
|
|
548
|
+
topoOrder,
|
|
549
|
+
buildDurationMs
|
|
550
|
+
};
|
|
551
|
+
};
|
|
552
|
+
var toFieldTrait = (entry) => {
|
|
553
|
+
const deps = [];
|
|
554
|
+
if (entry.kind === "computed") {
|
|
555
|
+
const meta = entry.meta;
|
|
556
|
+
const list = meta.deps;
|
|
557
|
+
if (list) deps.push(...list);
|
|
558
|
+
} else if (entry.kind === "source") {
|
|
559
|
+
const meta = entry.meta;
|
|
560
|
+
const list = meta.deps;
|
|
561
|
+
if (list) deps.push(...list);
|
|
562
|
+
} else if (entry.kind === "link") {
|
|
563
|
+
deps.push(entry.meta.from);
|
|
564
|
+
} else if (entry.kind === "check") {
|
|
565
|
+
const meta = entry.meta;
|
|
566
|
+
const rules = meta?.rules ?? {};
|
|
567
|
+
for (const name of Object.keys(rules)) {
|
|
568
|
+
const rule = rules[name];
|
|
569
|
+
if (rule && typeof rule === "object") {
|
|
570
|
+
const list = rule.deps;
|
|
571
|
+
if (list) deps.push(...list);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return {
|
|
576
|
+
fieldId: entry.fieldPath,
|
|
577
|
+
kind: entry.kind,
|
|
578
|
+
// Keep meta identical to Entry.meta at runtime so install can reuse it directly.
|
|
579
|
+
meta: entry.meta,
|
|
580
|
+
deps
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
var buildGraph = (entries, nodeMetaByFieldPath) => {
|
|
584
|
+
const fieldMap = /* @__PURE__ */ new Map();
|
|
585
|
+
const nodes = [];
|
|
586
|
+
const edges = [];
|
|
587
|
+
const resourcesById = /* @__PURE__ */ new Map();
|
|
588
|
+
const planSteps = [];
|
|
589
|
+
const ensureField = (fieldPath) => {
|
|
590
|
+
let field = fieldMap.get(fieldPath);
|
|
591
|
+
if (!field) {
|
|
592
|
+
field = {
|
|
593
|
+
id: fieldPath,
|
|
594
|
+
path: fieldPath,
|
|
595
|
+
traits: []
|
|
596
|
+
};
|
|
597
|
+
fieldMap.set(fieldPath, field);
|
|
598
|
+
}
|
|
599
|
+
return field;
|
|
600
|
+
};
|
|
601
|
+
for (const entry of entries) {
|
|
602
|
+
const fieldPath = entry.fieldPath;
|
|
603
|
+
const field = ensureField(fieldPath);
|
|
604
|
+
const trait = toFieldTrait(entry);
|
|
605
|
+
field.traits.push(trait);
|
|
606
|
+
if (entry.kind === "computed") {
|
|
607
|
+
const stepId = `computed:${fieldPath}`;
|
|
608
|
+
planSteps.push({
|
|
609
|
+
id: stepId,
|
|
610
|
+
kind: "computed-update",
|
|
611
|
+
targetFieldPath: fieldPath
|
|
612
|
+
// Note: the current version does not statically analyze computed dependencies; sourceFieldPaths remains empty.
|
|
613
|
+
});
|
|
614
|
+
const deps = entry.meta.deps;
|
|
615
|
+
if (deps) {
|
|
616
|
+
for (const dep of deps) {
|
|
617
|
+
ensureField(dep);
|
|
618
|
+
edges.push({
|
|
619
|
+
id: `computed:${dep}->${fieldPath}`,
|
|
620
|
+
from: dep,
|
|
621
|
+
to: fieldPath,
|
|
622
|
+
kind: "computed"
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
} else if (entry.kind === "link") {
|
|
627
|
+
const from = entry.meta.from;
|
|
628
|
+
ensureField(from);
|
|
629
|
+
const edgeId = `link:${from}->${fieldPath}`;
|
|
630
|
+
edges.push({
|
|
631
|
+
id: edgeId,
|
|
632
|
+
from,
|
|
633
|
+
to: fieldPath,
|
|
634
|
+
kind: "link"
|
|
635
|
+
});
|
|
636
|
+
planSteps.push({
|
|
637
|
+
id: `link:${fieldPath}`,
|
|
638
|
+
kind: "link-propagate",
|
|
639
|
+
targetFieldPath: fieldPath,
|
|
640
|
+
sourceFieldPaths: [from],
|
|
641
|
+
debugInfo: {
|
|
642
|
+
graphEdgeId: edgeId
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
} else if (entry.kind === "source") {
|
|
646
|
+
const resourceId = entry.meta.resource;
|
|
647
|
+
const resourceMeta = sanitize(entry.meta.meta);
|
|
648
|
+
const existing = resourcesById.get(resourceId);
|
|
649
|
+
if (existing) {
|
|
650
|
+
const ownerFields = [...existing.ownerFields, fieldPath];
|
|
651
|
+
let meta = existing.meta;
|
|
652
|
+
let metaOrigin = existing.metaOrigin;
|
|
653
|
+
let metaConflicts = existing.metaConflicts;
|
|
654
|
+
if (resourceMeta) {
|
|
655
|
+
const merged = mergeCanonical(
|
|
656
|
+
{ meta, origin: metaOrigin, conflicts: metaConflicts },
|
|
657
|
+
{ origin: fieldPath, meta: resourceMeta }
|
|
658
|
+
);
|
|
659
|
+
meta = merged.meta;
|
|
660
|
+
metaOrigin = merged.origin;
|
|
661
|
+
metaConflicts = merged.conflicts;
|
|
662
|
+
}
|
|
663
|
+
resourcesById.set(resourceId, {
|
|
664
|
+
...existing,
|
|
665
|
+
ownerFields,
|
|
666
|
+
meta,
|
|
667
|
+
metaOrigin,
|
|
668
|
+
metaConflicts
|
|
669
|
+
});
|
|
670
|
+
} else {
|
|
671
|
+
resourcesById.set(resourceId, {
|
|
672
|
+
resourceId,
|
|
673
|
+
// Use a simple identifier string for now; may evolve into a structured form based on key rules.
|
|
674
|
+
keySelector: `StateTrait.source@${fieldPath}`,
|
|
675
|
+
ownerFields: [fieldPath],
|
|
676
|
+
meta: resourceMeta,
|
|
677
|
+
metaOrigin: resourceMeta ? fieldPath : void 0
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
planSteps.push({
|
|
681
|
+
id: `source:${fieldPath}`,
|
|
682
|
+
kind: "source-refresh",
|
|
683
|
+
targetFieldPath: fieldPath,
|
|
684
|
+
resourceId,
|
|
685
|
+
keySelectorId: `StateTrait.source@${fieldPath}`
|
|
686
|
+
});
|
|
687
|
+
const deps = entry.meta.deps;
|
|
688
|
+
if (deps) {
|
|
689
|
+
for (const dep of deps) {
|
|
690
|
+
ensureField(dep);
|
|
691
|
+
edges.push({
|
|
692
|
+
id: `source-dep:${dep}->${fieldPath}`,
|
|
693
|
+
from: dep,
|
|
694
|
+
to: fieldPath,
|
|
695
|
+
kind: "source-dep"
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
} else if (entry.kind === "check") {
|
|
700
|
+
planSteps.push({
|
|
701
|
+
id: `check:${fieldPath}`,
|
|
702
|
+
kind: "check-validate",
|
|
703
|
+
targetFieldPath: fieldPath
|
|
704
|
+
});
|
|
705
|
+
if (trait.deps.length > 0) {
|
|
706
|
+
for (const dep of trait.deps) {
|
|
707
|
+
ensureField(dep);
|
|
708
|
+
edges.push({
|
|
709
|
+
id: `check-dep:${dep}->${fieldPath}`,
|
|
710
|
+
from: dep,
|
|
711
|
+
to: fieldPath,
|
|
712
|
+
kind: "check-dep"
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
for (const field of fieldMap.values()) {
|
|
719
|
+
nodes.push({
|
|
720
|
+
id: field.id,
|
|
721
|
+
field,
|
|
722
|
+
traits: field.traits,
|
|
723
|
+
meta: nodeMetaByFieldPath.get(field.id)
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
const graph = {
|
|
727
|
+
_tag: "StateTraitGraph",
|
|
728
|
+
nodes,
|
|
729
|
+
edges,
|
|
730
|
+
resources: Array.from(resourcesById.values())
|
|
731
|
+
};
|
|
732
|
+
const plan = {
|
|
733
|
+
_tag: "StateTraitPlan",
|
|
734
|
+
steps: planSteps
|
|
735
|
+
};
|
|
736
|
+
return { graph, plan };
|
|
737
|
+
};
|
|
738
|
+
var assertNoLinkCycles = (edges) => {
|
|
739
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
740
|
+
for (const edge of edges) {
|
|
741
|
+
if (edge.kind !== "link") continue;
|
|
742
|
+
const list = adjacency.get(edge.from) ?? [];
|
|
743
|
+
list.push(edge.to);
|
|
744
|
+
adjacency.set(edge.from, list);
|
|
745
|
+
}
|
|
746
|
+
const visited = /* @__PURE__ */ new Set();
|
|
747
|
+
const stack = /* @__PURE__ */ new Set();
|
|
748
|
+
const dfs = (node) => {
|
|
749
|
+
if (stack.has(node)) {
|
|
750
|
+
throw new Error(
|
|
751
|
+
`[StateTrait.build] link cycle detected at field "${node}". Please check link traits for circular dependencies.`
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
if (visited.has(node)) return;
|
|
755
|
+
visited.add(node);
|
|
756
|
+
stack.add(node);
|
|
757
|
+
const nexts = adjacency.get(node);
|
|
758
|
+
if (nexts) {
|
|
759
|
+
for (const to of nexts) {
|
|
760
|
+
dfs(to);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
stack.delete(node);
|
|
764
|
+
};
|
|
765
|
+
for (const node of adjacency.keys()) {
|
|
766
|
+
if (!visited.has(node)) {
|
|
767
|
+
dfs(node);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
var collectSchemaPaths = (entries) => {
|
|
772
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
773
|
+
const add = (ref) => {
|
|
774
|
+
if (!ref.path) return;
|
|
775
|
+
const k = `${ref.kind}|${ref.entryKind}|${ref.entryFieldPath}|${ref.ruleName ?? ""}|${ref.path}`;
|
|
776
|
+
byKey.set(k, ref);
|
|
777
|
+
};
|
|
778
|
+
const getCheckWritebackPath = (entry) => {
|
|
779
|
+
const wb = entry.meta?.writeback;
|
|
780
|
+
const p = wb && typeof wb === "object" ? wb.path : void 0;
|
|
781
|
+
const writebackPath = typeof p === "string" && p.startsWith("errors.") ? p : void 0;
|
|
782
|
+
if (writebackPath) return writebackPath;
|
|
783
|
+
const fieldPath = entry.fieldPath;
|
|
784
|
+
if (fieldPath.endsWith("[]")) {
|
|
785
|
+
return `errors.${fieldPath.slice(0, -2)}`;
|
|
786
|
+
}
|
|
787
|
+
return `errors.${fieldPath}`;
|
|
788
|
+
};
|
|
789
|
+
for (const entry of entries) {
|
|
790
|
+
add({
|
|
791
|
+
kind: "fieldPath",
|
|
792
|
+
entryKind: entry.kind,
|
|
793
|
+
entryFieldPath: entry.fieldPath,
|
|
794
|
+
path: entry.fieldPath
|
|
795
|
+
});
|
|
796
|
+
if (entry.kind === "computed" || entry.kind === "source") {
|
|
797
|
+
const deps = entry.meta?.deps ?? [];
|
|
798
|
+
for (const dep of deps) {
|
|
799
|
+
add({
|
|
800
|
+
kind: "dep",
|
|
801
|
+
entryKind: entry.kind,
|
|
802
|
+
entryFieldPath: entry.fieldPath,
|
|
803
|
+
path: dep
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
if (entry.kind === "link") {
|
|
808
|
+
add({
|
|
809
|
+
kind: "link_from",
|
|
810
|
+
entryKind: "link",
|
|
811
|
+
entryFieldPath: entry.fieldPath,
|
|
812
|
+
path: entry.meta.from
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
if (entry.kind === "check") {
|
|
816
|
+
add({
|
|
817
|
+
kind: "check_writeback",
|
|
818
|
+
entryKind: "check",
|
|
819
|
+
entryFieldPath: entry.fieldPath,
|
|
820
|
+
path: getCheckWritebackPath(entry)
|
|
821
|
+
});
|
|
822
|
+
const rules = entry.meta?.rules ?? {};
|
|
823
|
+
for (const name of Object.keys(rules)) {
|
|
824
|
+
const rule = rules[name];
|
|
825
|
+
if (!rule || typeof rule !== "object") continue;
|
|
826
|
+
const deps = rule.deps ?? [];
|
|
827
|
+
for (const dep of deps) {
|
|
828
|
+
add({
|
|
829
|
+
kind: "dep",
|
|
830
|
+
entryKind: "check",
|
|
831
|
+
entryFieldPath: entry.fieldPath,
|
|
832
|
+
ruleName: name,
|
|
833
|
+
path: dep
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return Array.from(byKey.entries()).sort((a, b) => a[0].localeCompare(b[0])).map(([, v]) => v);
|
|
840
|
+
};
|
|
841
|
+
var build = (stateSchema, spec) => {
|
|
842
|
+
const entries = normalizeSpec(spec);
|
|
843
|
+
const nodeMetaByFieldPath = collectNodeMeta(spec);
|
|
844
|
+
for (const entry of entries) {
|
|
845
|
+
if (entry.kind === "computed") {
|
|
846
|
+
const deps = entry.meta.deps;
|
|
847
|
+
if (deps === void 0) {
|
|
848
|
+
throw new Error(
|
|
849
|
+
`[StateTrait.build] Missing explicit deps for computed "${entry.fieldPath}". Please use StateTrait.computed({ deps: [...], get: ... }).`
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
if (entry.kind === "source") {
|
|
854
|
+
const deps = entry.meta.deps;
|
|
855
|
+
if (deps === void 0) {
|
|
856
|
+
throw new Error(
|
|
857
|
+
`[StateTrait.build] Missing explicit deps for source "${entry.fieldPath}". Please provide meta.deps for StateTrait.source({ deps: [...], ... }).`
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
if (entry.kind === "check") {
|
|
862
|
+
const rules = entry.meta?.rules ?? {};
|
|
863
|
+
for (const name of Object.keys(rules)) {
|
|
864
|
+
const rule = rules[name];
|
|
865
|
+
if (typeof rule === "function" || !rule || typeof rule !== "object") {
|
|
866
|
+
throw new Error(
|
|
867
|
+
`[StateTrait.build] Missing explicit deps for check "${entry.fieldPath}" rule "${name}". Please use { deps: [...], validate: ... } form.`
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
if (rule.deps === void 0) {
|
|
871
|
+
throw new Error(
|
|
872
|
+
`[StateTrait.build] Missing explicit deps for check "${entry.fieldPath}" rule "${name}". Please provide deps: [...].`
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const { graph, plan } = buildGraph(entries, nodeMetaByFieldPath);
|
|
879
|
+
assertNoLinkCycles(graph.edges);
|
|
880
|
+
return {
|
|
881
|
+
stateSchema,
|
|
882
|
+
spec,
|
|
883
|
+
entries,
|
|
884
|
+
graph,
|
|
885
|
+
plan,
|
|
886
|
+
convergeIr: buildConvergeIr(stateSchema, entries),
|
|
887
|
+
schemaPaths: collectSchemaPaths(entries)
|
|
888
|
+
};
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
// src/internal/state-trait/source.ts
|
|
892
|
+
import { Effect, Fiber, FiberRef, Option } from "effect";
|
|
893
|
+
import { create } from "mutative";
|
|
894
|
+
|
|
895
|
+
// src/internal/state-trait/deps-trace.ts
|
|
896
|
+
var isTraceableObject = (value) => {
|
|
897
|
+
if (!value || typeof value !== "object") return false;
|
|
898
|
+
if (Array.isArray(value)) return true;
|
|
899
|
+
if (value instanceof Date) return false;
|
|
900
|
+
if (value instanceof RegExp) return false;
|
|
901
|
+
if (value instanceof Error) return false;
|
|
902
|
+
if (value instanceof Map) return false;
|
|
903
|
+
if (value instanceof Set) return false;
|
|
904
|
+
if (value instanceof WeakMap) return false;
|
|
905
|
+
if (value instanceof WeakSet) return false;
|
|
906
|
+
return true;
|
|
907
|
+
};
|
|
908
|
+
var shouldIgnoreKey = (key) => key === "__proto__" || key === "prototype" || key === "constructor";
|
|
909
|
+
var normalizeReads = (reads) => {
|
|
910
|
+
const all = Array.from(reads).filter((p) => typeof p === "string" && p.length > 0);
|
|
911
|
+
all.sort();
|
|
912
|
+
const isPrefix = (prefix, full) => full !== prefix && full.startsWith(prefix + ".");
|
|
913
|
+
const pruned = [];
|
|
914
|
+
for (const p of all) {
|
|
915
|
+
let hasMoreSpecific = false;
|
|
916
|
+
for (const other of all) {
|
|
917
|
+
if (isPrefix(p, other)) {
|
|
918
|
+
hasMoreSpecific = true;
|
|
919
|
+
break;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (!hasMoreSpecific) {
|
|
923
|
+
pruned.push(p);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
pruned.sort();
|
|
927
|
+
return pruned;
|
|
928
|
+
};
|
|
929
|
+
var covers = (declared, read) => declared === read || read.startsWith(declared + ".");
|
|
930
|
+
var diffDeps = (declared, reads) => {
|
|
931
|
+
const declaredList = Array.from(new Set(declared)).filter((p) => typeof p === "string" && p.length > 0);
|
|
932
|
+
declaredList.sort();
|
|
933
|
+
const readList = Array.from(new Set(reads)).filter((p) => typeof p === "string" && p.length > 0);
|
|
934
|
+
readList.sort();
|
|
935
|
+
const missing = readList.filter((r) => declaredList.every((d) => !covers(d, r)));
|
|
936
|
+
const unused = declaredList.filter((d) => readList.every((r) => !covers(d, r)));
|
|
937
|
+
if (missing.length === 0 && unused.length === 0) return void 0;
|
|
938
|
+
return {
|
|
939
|
+
reads: readList,
|
|
940
|
+
declared: declaredList,
|
|
941
|
+
missing,
|
|
942
|
+
unused
|
|
943
|
+
};
|
|
944
|
+
};
|
|
945
|
+
var trace = (fn, state) => {
|
|
946
|
+
if (!isTraceableObject(state)) {
|
|
947
|
+
return { value: fn(state), reads: [] };
|
|
948
|
+
}
|
|
949
|
+
const reads = /* @__PURE__ */ new Set();
|
|
950
|
+
const proxyCache = /* @__PURE__ */ new WeakMap();
|
|
951
|
+
const proxyToTarget = /* @__PURE__ */ new WeakMap();
|
|
952
|
+
const wrap = (value2, path) => {
|
|
953
|
+
if (!isTraceableObject(value2)) return value2;
|
|
954
|
+
return getProxy(value2, path);
|
|
955
|
+
};
|
|
956
|
+
const unwrap = (value2) => {
|
|
957
|
+
if (value2 && (typeof value2 === "object" || typeof value2 === "function")) {
|
|
958
|
+
const target = proxyToTarget.get(value2);
|
|
959
|
+
if (target) return target;
|
|
960
|
+
}
|
|
961
|
+
return value2;
|
|
962
|
+
};
|
|
963
|
+
const getProxy = (target, basePath) => {
|
|
964
|
+
let byPath = proxyCache.get(target);
|
|
965
|
+
if (!byPath) {
|
|
966
|
+
byPath = /* @__PURE__ */ new Map();
|
|
967
|
+
proxyCache.set(target, byPath);
|
|
968
|
+
}
|
|
969
|
+
const cached = byPath.get(basePath);
|
|
970
|
+
if (cached) return cached;
|
|
971
|
+
const record2 = (path) => {
|
|
972
|
+
if (path) reads.add(path);
|
|
973
|
+
};
|
|
974
|
+
const proxy = new Proxy(target, {
|
|
975
|
+
get: (t, prop, receiver) => {
|
|
976
|
+
if (typeof prop === "symbol") {
|
|
977
|
+
return Reflect.get(t, prop, receiver);
|
|
978
|
+
}
|
|
979
|
+
const key = String(prop);
|
|
980
|
+
if (shouldIgnoreKey(key)) {
|
|
981
|
+
return Reflect.get(t, prop, receiver);
|
|
982
|
+
}
|
|
983
|
+
const nextPath = basePath ? `${basePath}.${key}` : key;
|
|
984
|
+
record2(nextPath);
|
|
985
|
+
const value2 = Reflect.get(t, prop, receiver);
|
|
986
|
+
return wrap(value2, nextPath);
|
|
987
|
+
},
|
|
988
|
+
has: (t, prop) => {
|
|
989
|
+
if (typeof prop === "symbol") return Reflect.has(t, prop);
|
|
990
|
+
const key = String(prop);
|
|
991
|
+
if (!shouldIgnoreKey(key)) {
|
|
992
|
+
const nextPath = basePath ? `${basePath}.${key}` : key;
|
|
993
|
+
record2(nextPath);
|
|
994
|
+
}
|
|
995
|
+
return Reflect.has(t, prop);
|
|
996
|
+
},
|
|
997
|
+
ownKeys: (t) => {
|
|
998
|
+
if (basePath) record2(basePath);
|
|
999
|
+
return Reflect.ownKeys(t);
|
|
1000
|
+
},
|
|
1001
|
+
getOwnPropertyDescriptor: (t, prop) => {
|
|
1002
|
+
if (typeof prop === "symbol") {
|
|
1003
|
+
return Reflect.getOwnPropertyDescriptor(t, prop);
|
|
1004
|
+
}
|
|
1005
|
+
const key = String(prop);
|
|
1006
|
+
if (!shouldIgnoreKey(key)) {
|
|
1007
|
+
const nextPath = basePath ? `${basePath}.${key}` : key;
|
|
1008
|
+
record2(nextPath);
|
|
1009
|
+
}
|
|
1010
|
+
return Reflect.getOwnPropertyDescriptor(t, prop);
|
|
1011
|
+
},
|
|
1012
|
+
set: () => {
|
|
1013
|
+
throw new Error(
|
|
1014
|
+
"[deps-trace] Attempted to mutate state during deps tracing (state is readonly in dev-mode diagnostics)."
|
|
1015
|
+
);
|
|
1016
|
+
},
|
|
1017
|
+
defineProperty: () => {
|
|
1018
|
+
throw new Error(
|
|
1019
|
+
"[deps-trace] Attempted to define property on state during deps tracing (state is readonly in dev-mode diagnostics)."
|
|
1020
|
+
);
|
|
1021
|
+
},
|
|
1022
|
+
deleteProperty: () => {
|
|
1023
|
+
throw new Error(
|
|
1024
|
+
"[deps-trace] Attempted to delete property on state during deps tracing (state is readonly in dev-mode diagnostics)."
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
byPath.set(basePath, proxy);
|
|
1029
|
+
proxyToTarget.set(proxy, target);
|
|
1030
|
+
return proxy;
|
|
1031
|
+
};
|
|
1032
|
+
const root = getProxy(state, "");
|
|
1033
|
+
const value = unwrap(fn(root));
|
|
1034
|
+
return {
|
|
1035
|
+
value,
|
|
1036
|
+
reads: normalizeReads(reads)
|
|
1037
|
+
};
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
// src/internal/state-trait/source.ts
|
|
1041
|
+
var onceInRunSession = (key) => Effect.serviceOption(RunSessionTag).pipe(
|
|
1042
|
+
Effect.map((maybe) => Option.isSome(maybe) ? maybe.value.local.once(key) : true)
|
|
1043
|
+
);
|
|
1044
|
+
var formatList = (items, limit = 10) => {
|
|
1045
|
+
if (items.length === 0) return "";
|
|
1046
|
+
if (items.length <= limit) return items.join(", ");
|
|
1047
|
+
return `${items.slice(0, limit).join(", ")}, \u2026(+${items.length - limit})`;
|
|
1048
|
+
};
|
|
1049
|
+
var emitDepsMismatch = (params) => Effect.gen(function* () {
|
|
1050
|
+
const key = `${params.instanceId ?? "unknown"}::${params.kind}::${params.fieldPath}`;
|
|
1051
|
+
const shouldEmit = yield* onceInRunSession(`deps_mismatch:${key}`);
|
|
1052
|
+
if (!shouldEmit) return;
|
|
1053
|
+
yield* record({
|
|
1054
|
+
type: "diagnostic",
|
|
1055
|
+
moduleId: params.moduleId,
|
|
1056
|
+
instanceId: params.instanceId,
|
|
1057
|
+
code: "state_trait::deps_mismatch",
|
|
1058
|
+
severity: "warning",
|
|
1059
|
+
message: `[deps] ${params.kind} "${params.fieldPath}" declared=[${formatList(params.diff.declared)}] reads=[${formatList(params.diff.reads)}] missing=[${formatList(params.diff.missing)}] unused=[${formatList(params.diff.unused)}]`,
|
|
1060
|
+
hint: 'deps is the single source of truth for dependencies: incremental scheduling / reverse closures / performance optimizations rely on deps only. Keep deps consistent with actual reads; if you really depend on the whole object, declare a coarser-grained dep (e.g. "profile") to cover sub-field reads.',
|
|
1061
|
+
kind: `deps_mismatch:${params.kind}`
|
|
1062
|
+
});
|
|
1063
|
+
});
|
|
1064
|
+
var getMiddlewareStack = () => Effect.serviceOption(EffectOpMiddlewareTag).pipe(
|
|
1065
|
+
Effect.map((maybe) => Option.isSome(maybe) ? maybe.value.stack : [])
|
|
1066
|
+
);
|
|
1067
|
+
var recordTraitPatch = (bound, path, reason, from, to, traitNodeId) => {
|
|
1068
|
+
const normalized = normalizeFieldPath(path) ?? [];
|
|
1069
|
+
try {
|
|
1070
|
+
const internals = getBoundInternals(bound);
|
|
1071
|
+
internals.txn.recordStatePatch(normalized, reason, from, to, traitNodeId);
|
|
1072
|
+
} catch {
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
var recordReplayEvent = (bound, event) => {
|
|
1076
|
+
try {
|
|
1077
|
+
const internals = getBoundInternals(bound);
|
|
1078
|
+
internals.txn.recordReplayEvent(event);
|
|
1079
|
+
} catch {
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
var getBoundScope = (bound) => {
|
|
1083
|
+
try {
|
|
1084
|
+
const internals = getBoundInternals(bound);
|
|
1085
|
+
return { moduleId: internals.moduleId, instanceId: internals.instanceId };
|
|
1086
|
+
} catch {
|
|
1087
|
+
return { moduleId: void 0, instanceId: void 0 };
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
var setSnapshotInTxn = (bound, fieldPath, next, reason, stepId, traitNodeId) => Effect.gen(function* () {
|
|
1091
|
+
let wrote = false;
|
|
1092
|
+
yield* bound.state.mutate((draft) => {
|
|
1093
|
+
const prev = getAtPath(draft, fieldPath);
|
|
1094
|
+
if (Object.is(prev, next)) return;
|
|
1095
|
+
wrote = true;
|
|
1096
|
+
setAtPathMutating(draft, fieldPath, next);
|
|
1097
|
+
recordTraitPatch(bound, fieldPath, reason, prev, next, traitNodeId);
|
|
1098
|
+
});
|
|
1099
|
+
return wrote;
|
|
1100
|
+
});
|
|
1101
|
+
var writebackIfCurrentKeyHash = (bound, fieldPath, keyHash2, next, reason, stepId, traitNodeId, replayEvent) => Effect.gen(function* () {
|
|
1102
|
+
let wrote = false;
|
|
1103
|
+
yield* bound.state.mutate((draft) => {
|
|
1104
|
+
const current = getAtPath(draft, fieldPath);
|
|
1105
|
+
const currentKeyHash = current && typeof current === "object" ? current.keyHash : void 0;
|
|
1106
|
+
if (currentKeyHash !== keyHash2) return;
|
|
1107
|
+
const prev = current;
|
|
1108
|
+
if (Object.is(prev, next)) return;
|
|
1109
|
+
wrote = true;
|
|
1110
|
+
setAtPathMutating(draft, fieldPath, next);
|
|
1111
|
+
if (replayEvent) {
|
|
1112
|
+
recordReplayEvent(bound, replayEvent);
|
|
1113
|
+
}
|
|
1114
|
+
recordTraitPatch(bound, fieldPath, reason, prev, next, traitNodeId);
|
|
1115
|
+
});
|
|
1116
|
+
return wrote;
|
|
1117
|
+
});
|
|
1118
|
+
var syncIdleInTransaction = (program, ctx) => Effect.sync(() => {
|
|
1119
|
+
const draft = ctx.getDraft();
|
|
1120
|
+
const updates = [];
|
|
1121
|
+
for (const entry of program.entries) {
|
|
1122
|
+
if (entry.kind !== "source") continue;
|
|
1123
|
+
const fieldPath = entry.fieldPath;
|
|
1124
|
+
const listItem = parseListItemFieldPath(fieldPath);
|
|
1125
|
+
if (listItem) {
|
|
1126
|
+
const listValue = getAtPath(draft, listItem.listPath);
|
|
1127
|
+
const items = Array.isArray(listValue) ? listValue : [];
|
|
1128
|
+
for (let index = 0; index < items.length; index++) {
|
|
1129
|
+
const item = items[index];
|
|
1130
|
+
let key2;
|
|
1131
|
+
try {
|
|
1132
|
+
key2 = entry.meta.key(item);
|
|
1133
|
+
} catch {
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
if (key2 !== void 0) continue;
|
|
1137
|
+
const concretePath = toListItemValuePath(listItem.listPath, index, listItem.itemPath);
|
|
1138
|
+
const prev2 = getAtPath(draft, concretePath);
|
|
1139
|
+
const prevStatus2 = prev2 && typeof prev2 === "object" ? prev2.status : void 0;
|
|
1140
|
+
if (prevStatus2 === "idle") {
|
|
1141
|
+
const data = prev2?.data;
|
|
1142
|
+
const error = prev2?.error;
|
|
1143
|
+
if (data === void 0 && error === void 0) {
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
updates.push({ fieldPath: concretePath, prev: prev2 });
|
|
1148
|
+
}
|
|
1149
|
+
continue;
|
|
1150
|
+
}
|
|
1151
|
+
let key;
|
|
1152
|
+
try {
|
|
1153
|
+
key = entry.meta.key(draft);
|
|
1154
|
+
} catch {
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
1157
|
+
if (key !== void 0) continue;
|
|
1158
|
+
const prev = getAtPath(draft, fieldPath);
|
|
1159
|
+
const prevStatus = prev && typeof prev === "object" ? prev.status : void 0;
|
|
1160
|
+
if (prevStatus === "idle") {
|
|
1161
|
+
const data = prev?.data;
|
|
1162
|
+
const error = prev?.error;
|
|
1163
|
+
if (data === void 0 && error === void 0) {
|
|
1164
|
+
continue;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
updates.push({ fieldPath, prev });
|
|
1168
|
+
}
|
|
1169
|
+
if (updates.length === 0) return;
|
|
1170
|
+
const reason = "source-refresh";
|
|
1171
|
+
const nextDraft = create(draft, (next) => {
|
|
1172
|
+
for (const u of updates) {
|
|
1173
|
+
setAtPathMutating(next, u.fieldPath, Snapshot.idle());
|
|
1174
|
+
}
|
|
1175
|
+
});
|
|
1176
|
+
ctx.setDraft(nextDraft);
|
|
1177
|
+
for (const u of updates) {
|
|
1178
|
+
const normalized = normalizeFieldPath(u.fieldPath) ?? [];
|
|
1179
|
+
ctx.recordPatch(normalized, reason, u.prev, Snapshot.idle(), `source:${u.fieldPath}:idle`);
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
var installSourceRefresh = (bound, step, entry) => {
|
|
1183
|
+
if (!step.targetFieldPath) return Effect.void;
|
|
1184
|
+
const fieldPath = step.targetFieldPath;
|
|
1185
|
+
const resourceId = step.resourceId ?? entry.meta.resource;
|
|
1186
|
+
const listItem = parseListItemFieldPath(fieldPath);
|
|
1187
|
+
let internals;
|
|
1188
|
+
try {
|
|
1189
|
+
internals = getBoundInternals(bound);
|
|
1190
|
+
} catch {
|
|
1191
|
+
return Effect.void;
|
|
1192
|
+
}
|
|
1193
|
+
const register = internals.traits.registerSourceRefresh;
|
|
1194
|
+
const recordSnapshot = (replayMode, replayLog, input) => {
|
|
1195
|
+
if (!replayLog) return Effect.void;
|
|
1196
|
+
if (replayMode !== "live") return Effect.void;
|
|
1197
|
+
const event = input && typeof input === "object" && input._tag === "ResourceSnapshot" ? input : {
|
|
1198
|
+
_tag: "ResourceSnapshot",
|
|
1199
|
+
resourceId,
|
|
1200
|
+
fieldPath: input.fieldPath,
|
|
1201
|
+
keyHash: input.keyHash,
|
|
1202
|
+
concurrency: input.concurrency,
|
|
1203
|
+
phase: input.phase,
|
|
1204
|
+
snapshot: input.snapshot,
|
|
1205
|
+
timestamp: Date.now(),
|
|
1206
|
+
moduleId: input.moduleId,
|
|
1207
|
+
instanceId: input.instanceId
|
|
1208
|
+
};
|
|
1209
|
+
return replayLog.record(event);
|
|
1210
|
+
};
|
|
1211
|
+
if (listItem) {
|
|
1212
|
+
const store = internals.traits.rowIdStore;
|
|
1213
|
+
if (!store) {
|
|
1214
|
+
return Effect.void;
|
|
1215
|
+
}
|
|
1216
|
+
const listPath = listItem.listPath;
|
|
1217
|
+
const itemPath = listItem.itemPath;
|
|
1218
|
+
if (!itemPath) {
|
|
1219
|
+
return Effect.void;
|
|
1220
|
+
}
|
|
1221
|
+
const concurrency2 = entry.meta.concurrency;
|
|
1222
|
+
const mode2 = concurrency2 ?? "switch";
|
|
1223
|
+
const inFlight2 = /* @__PURE__ */ new Map();
|
|
1224
|
+
const trailing2 = /* @__PURE__ */ new Map();
|
|
1225
|
+
let gen2 = 0;
|
|
1226
|
+
store.onRemoved(listPath, (rowId) => {
|
|
1227
|
+
trailing2.delete(rowId);
|
|
1228
|
+
inFlight2.delete(rowId);
|
|
1229
|
+
});
|
|
1230
|
+
const setSnapshotForRowInTxn = (rowId, next, reason, stepId) => Effect.gen(function* () {
|
|
1231
|
+
let wrotePath;
|
|
1232
|
+
yield* bound.state.mutate((draft) => {
|
|
1233
|
+
const index = store.getIndex(listPath, rowId);
|
|
1234
|
+
if (index === void 0) return;
|
|
1235
|
+
const concretePath = toListItemValuePath(listPath, index, itemPath);
|
|
1236
|
+
const prev = getAtPath(draft, concretePath);
|
|
1237
|
+
if (Object.is(prev, next)) return;
|
|
1238
|
+
wrotePath = concretePath;
|
|
1239
|
+
setAtPathMutating(draft, concretePath, next);
|
|
1240
|
+
recordTraitPatch(bound, concretePath, reason, prev, next, step.debugInfo?.graphNodeId);
|
|
1241
|
+
});
|
|
1242
|
+
return wrotePath;
|
|
1243
|
+
});
|
|
1244
|
+
const writebackIfCurrentKeyHashForRow = (rowId, keyHash2, next, reason, stepId, phase) => Effect.gen(function* () {
|
|
1245
|
+
let wrotePath;
|
|
1246
|
+
yield* bound.state.mutate((draft) => {
|
|
1247
|
+
const index = store.getIndex(listPath, rowId);
|
|
1248
|
+
if (index === void 0) return;
|
|
1249
|
+
const concretePath = toListItemValuePath(listPath, index, itemPath);
|
|
1250
|
+
const current = getAtPath(draft, concretePath);
|
|
1251
|
+
const currentKeyHash = current && typeof current === "object" ? current.keyHash : void 0;
|
|
1252
|
+
if (currentKeyHash !== keyHash2) return;
|
|
1253
|
+
const prev = current;
|
|
1254
|
+
if (Object.is(prev, next)) return;
|
|
1255
|
+
wrotePath = concretePath;
|
|
1256
|
+
setAtPathMutating(draft, concretePath, next);
|
|
1257
|
+
if (phase) {
|
|
1258
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1259
|
+
recordReplayEvent(bound, {
|
|
1260
|
+
_tag: "ResourceSnapshot",
|
|
1261
|
+
resourceId,
|
|
1262
|
+
fieldPath: concretePath,
|
|
1263
|
+
keyHash: keyHash2,
|
|
1264
|
+
concurrency: mode2,
|
|
1265
|
+
phase,
|
|
1266
|
+
snapshot: next,
|
|
1267
|
+
timestamp: Date.now(),
|
|
1268
|
+
moduleId,
|
|
1269
|
+
instanceId
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
recordTraitPatch(bound, concretePath, reason, prev, next, step.debugInfo?.graphNodeId);
|
|
1273
|
+
});
|
|
1274
|
+
return wrotePath;
|
|
1275
|
+
});
|
|
1276
|
+
const startFetch2 = (rowId, key, keyHash2, replayMode, replayLog) => Effect.gen(function* () {
|
|
1277
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1278
|
+
const indexForLog = store.getIndex(listPath, rowId);
|
|
1279
|
+
const logFieldPath = indexForLog === void 0 ? void 0 : toListItemValuePath(listPath, indexForLog, itemPath);
|
|
1280
|
+
let loadingSnapshot = Snapshot.loading({ keyHash: keyHash2 });
|
|
1281
|
+
if (replayMode === "replay" && replayLog && logFieldPath) {
|
|
1282
|
+
const replayLoading = yield* replayLog.consumeNextResourceSnapshot({
|
|
1283
|
+
resourceId,
|
|
1284
|
+
fieldPath: logFieldPath,
|
|
1285
|
+
keyHash: keyHash2,
|
|
1286
|
+
phase: "loading"
|
|
1287
|
+
});
|
|
1288
|
+
if (replayLoading) {
|
|
1289
|
+
loadingSnapshot = replayLoading.snapshot;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
const wroteLoadingPath = yield* setSnapshotForRowInTxn(
|
|
1293
|
+
rowId,
|
|
1294
|
+
loadingSnapshot,
|
|
1295
|
+
"source-refresh",
|
|
1296
|
+
`source:${fieldPath}:${rowId}:loading`
|
|
1297
|
+
);
|
|
1298
|
+
if (wroteLoadingPath) {
|
|
1299
|
+
const event = {
|
|
1300
|
+
_tag: "ResourceSnapshot",
|
|
1301
|
+
resourceId,
|
|
1302
|
+
fieldPath: wroteLoadingPath,
|
|
1303
|
+
keyHash: keyHash2,
|
|
1304
|
+
concurrency: mode2,
|
|
1305
|
+
phase: "loading",
|
|
1306
|
+
snapshot: loadingSnapshot,
|
|
1307
|
+
timestamp: Date.now(),
|
|
1308
|
+
moduleId,
|
|
1309
|
+
instanceId
|
|
1310
|
+
};
|
|
1311
|
+
recordReplayEvent(bound, event);
|
|
1312
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1313
|
+
}
|
|
1314
|
+
const io = Effect.gen(function* () {
|
|
1315
|
+
if (replayMode === "replay" && replayLog) {
|
|
1316
|
+
yield* Effect.yieldNow();
|
|
1317
|
+
const consumePath = wroteLoadingPath ?? logFieldPath;
|
|
1318
|
+
if (!consumePath) return yield* Effect.void;
|
|
1319
|
+
const replayed = yield* replayLog.consumeNextResourceSnapshot({
|
|
1320
|
+
resourceId,
|
|
1321
|
+
fieldPath: consumePath,
|
|
1322
|
+
keyHash: keyHash2
|
|
1323
|
+
});
|
|
1324
|
+
if (!replayed) return yield* Effect.void;
|
|
1325
|
+
if (replayed.phase === "success") {
|
|
1326
|
+
yield* writebackIfCurrentKeyHashForRow(
|
|
1327
|
+
rowId,
|
|
1328
|
+
keyHash2,
|
|
1329
|
+
replayed.snapshot,
|
|
1330
|
+
"source-refresh",
|
|
1331
|
+
`source:${fieldPath}:${rowId}:success`,
|
|
1332
|
+
"success"
|
|
1333
|
+
);
|
|
1334
|
+
} else if (replayed.phase === "error") {
|
|
1335
|
+
yield* writebackIfCurrentKeyHashForRow(
|
|
1336
|
+
rowId,
|
|
1337
|
+
keyHash2,
|
|
1338
|
+
replayed.snapshot,
|
|
1339
|
+
"source-refresh",
|
|
1340
|
+
`source:${fieldPath}:${rowId}:error`,
|
|
1341
|
+
"error"
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
return yield* Effect.void;
|
|
1345
|
+
}
|
|
1346
|
+
const stack = yield* getMiddlewareStack();
|
|
1347
|
+
const registryOpt = yield* Effect.serviceOption(internal.ResourceRegistryTag);
|
|
1348
|
+
const registry = Option.isSome(registryOpt) ? registryOpt.value : void 0;
|
|
1349
|
+
const spec = registry?.specs.get(resourceId);
|
|
1350
|
+
if (!spec) {
|
|
1351
|
+
return yield* Effect.void;
|
|
1352
|
+
}
|
|
1353
|
+
const loadEffect = spec.load(key);
|
|
1354
|
+
const meta = {
|
|
1355
|
+
moduleId,
|
|
1356
|
+
instanceId,
|
|
1357
|
+
fieldPath,
|
|
1358
|
+
resourceId,
|
|
1359
|
+
key,
|
|
1360
|
+
keyHash: keyHash2,
|
|
1361
|
+
rowId,
|
|
1362
|
+
traitNodeId: step.debugInfo?.graphNodeId,
|
|
1363
|
+
stepId: step.id
|
|
1364
|
+
};
|
|
1365
|
+
if (!(typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq))) {
|
|
1366
|
+
const sessionOpt = yield* Effect.serviceOption(RunSessionTag);
|
|
1367
|
+
if (Option.isSome(sessionOpt)) {
|
|
1368
|
+
const seqKey = instanceId ?? "global";
|
|
1369
|
+
meta.opSeq = sessionOpt.value.local.nextSeq("opSeq", seqKey);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
const op = make({
|
|
1373
|
+
kind: "service",
|
|
1374
|
+
name: resourceId,
|
|
1375
|
+
effect: loadEffect,
|
|
1376
|
+
meta
|
|
1377
|
+
});
|
|
1378
|
+
const exit = yield* Effect.exit(run(op, stack));
|
|
1379
|
+
if (exit._tag === "Success") {
|
|
1380
|
+
const successSnapshot = Snapshot.success({ keyHash: keyHash2, data: exit.value });
|
|
1381
|
+
const wroteSuccessPath = yield* writebackIfCurrentKeyHashForRow(
|
|
1382
|
+
rowId,
|
|
1383
|
+
keyHash2,
|
|
1384
|
+
successSnapshot,
|
|
1385
|
+
"source-refresh",
|
|
1386
|
+
`source:${fieldPath}:${rowId}:success`,
|
|
1387
|
+
"success"
|
|
1388
|
+
);
|
|
1389
|
+
if (wroteSuccessPath) {
|
|
1390
|
+
yield* recordSnapshot(replayMode, replayLog, {
|
|
1391
|
+
_tag: "ResourceSnapshot",
|
|
1392
|
+
resourceId,
|
|
1393
|
+
fieldPath: wroteSuccessPath,
|
|
1394
|
+
keyHash: keyHash2,
|
|
1395
|
+
concurrency: mode2,
|
|
1396
|
+
phase: "success",
|
|
1397
|
+
snapshot: successSnapshot,
|
|
1398
|
+
timestamp: Date.now(),
|
|
1399
|
+
moduleId,
|
|
1400
|
+
instanceId
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
} else {
|
|
1404
|
+
const errorSnapshot = Snapshot.error({ keyHash: keyHash2, error: exit.cause });
|
|
1405
|
+
const wroteErrorPath = yield* writebackIfCurrentKeyHashForRow(
|
|
1406
|
+
rowId,
|
|
1407
|
+
keyHash2,
|
|
1408
|
+
errorSnapshot,
|
|
1409
|
+
"source-refresh",
|
|
1410
|
+
`source:${fieldPath}:${rowId}:error`,
|
|
1411
|
+
"error"
|
|
1412
|
+
);
|
|
1413
|
+
if (wroteErrorPath) {
|
|
1414
|
+
yield* recordSnapshot(replayMode, replayLog, {
|
|
1415
|
+
_tag: "ResourceSnapshot",
|
|
1416
|
+
resourceId,
|
|
1417
|
+
fieldPath: wroteErrorPath,
|
|
1418
|
+
keyHash: keyHash2,
|
|
1419
|
+
concurrency: mode2,
|
|
1420
|
+
phase: "error",
|
|
1421
|
+
snapshot: errorSnapshot,
|
|
1422
|
+
timestamp: Date.now(),
|
|
1423
|
+
moduleId,
|
|
1424
|
+
instanceId
|
|
1425
|
+
});
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}).pipe(Effect.catchAllCause(() => Effect.void));
|
|
1429
|
+
const fiber = yield* Effect.forkScoped(Effect.locally(inSyncTransactionFiber, false)(io));
|
|
1430
|
+
const myGen = gen2 += 1;
|
|
1431
|
+
inFlight2.set(rowId, { gen: myGen, fiber, keyHash: keyHash2 });
|
|
1432
|
+
yield* Effect.forkScoped(
|
|
1433
|
+
Effect.locally(
|
|
1434
|
+
inSyncTransactionFiber,
|
|
1435
|
+
false
|
|
1436
|
+
)(
|
|
1437
|
+
Fiber.await(fiber).pipe(
|
|
1438
|
+
Effect.zipRight(
|
|
1439
|
+
Effect.sync(() => {
|
|
1440
|
+
const current = inFlight2.get(rowId);
|
|
1441
|
+
if (current && current.gen === myGen) {
|
|
1442
|
+
inFlight2.delete(rowId);
|
|
1443
|
+
}
|
|
1444
|
+
})
|
|
1445
|
+
),
|
|
1446
|
+
Effect.zipRight(
|
|
1447
|
+
mode2 === "exhaust-trailing" ? Effect.gen(function* () {
|
|
1448
|
+
const next = trailing2.get(rowId);
|
|
1449
|
+
trailing2.delete(rowId);
|
|
1450
|
+
if (next) {
|
|
1451
|
+
yield* startFetch2(rowId, next.key, next.keyHash, replayMode, replayLog);
|
|
1452
|
+
}
|
|
1453
|
+
}) : Effect.void
|
|
1454
|
+
),
|
|
1455
|
+
Effect.catchAllCause(() => Effect.void)
|
|
1456
|
+
)
|
|
1457
|
+
)
|
|
1458
|
+
);
|
|
1459
|
+
});
|
|
1460
|
+
register(
|
|
1461
|
+
fieldPath,
|
|
1462
|
+
(state) => Effect.gen(function* () {
|
|
1463
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1464
|
+
const replayModeOpt = yield* Effect.serviceOption(ReplayModeConfigTag);
|
|
1465
|
+
const replayMode = Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
|
|
1466
|
+
const replayLogOpt = yield* Effect.serviceOption(ReplayLog);
|
|
1467
|
+
const replayLog = Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
|
|
1468
|
+
const force = yield* FiberRef.get(forceSourceRefresh);
|
|
1469
|
+
const listValue = getAtPath(state, listPath);
|
|
1470
|
+
const items = Array.isArray(listValue) ? listValue : [];
|
|
1471
|
+
const ids = store.ensureList(listPath, items);
|
|
1472
|
+
const traceKey = `${instanceId ?? "unknown"}::source::${fieldPath}`;
|
|
1473
|
+
if (isDevEnv() && (yield* onceInRunSession(`deps_trace_settled:${traceKey}`))) {
|
|
1474
|
+
try {
|
|
1475
|
+
const sample = items[0];
|
|
1476
|
+
if (sample !== void 0) {
|
|
1477
|
+
const traced = trace((s) => entry.meta.key(s), sample);
|
|
1478
|
+
const prefixedReads = traced.reads.map((r) => r ? `${listPath}[].${r}` : `${listPath}[]`);
|
|
1479
|
+
const diff = diffDeps(entry.meta.deps ?? [], prefixedReads);
|
|
1480
|
+
if (diff) {
|
|
1481
|
+
yield* emitDepsMismatch({
|
|
1482
|
+
moduleId,
|
|
1483
|
+
instanceId,
|
|
1484
|
+
kind: "source",
|
|
1485
|
+
fieldPath,
|
|
1486
|
+
diff
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
} catch {
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
for (let index = 0; index < items.length; index++) {
|
|
1494
|
+
const rowId = ids[index];
|
|
1495
|
+
if (!rowId) continue;
|
|
1496
|
+
const concretePath = toListItemValuePath(listPath, index, itemPath);
|
|
1497
|
+
const prevSnapshot = getAtPath(state, concretePath);
|
|
1498
|
+
let key;
|
|
1499
|
+
try {
|
|
1500
|
+
key = entry.meta.key(items[index]);
|
|
1501
|
+
} catch {
|
|
1502
|
+
key = void 0;
|
|
1503
|
+
}
|
|
1504
|
+
const current = inFlight2.get(rowId);
|
|
1505
|
+
if (key === void 0) {
|
|
1506
|
+
trailing2.delete(rowId);
|
|
1507
|
+
inFlight2.delete(rowId);
|
|
1508
|
+
if (prevSnapshot && typeof prevSnapshot === "object" && prevSnapshot.status === "idle" && prevSnapshot.data === void 0 && prevSnapshot.error === void 0) {
|
|
1509
|
+
continue;
|
|
1510
|
+
}
|
|
1511
|
+
const idleSnapshot = Snapshot.idle();
|
|
1512
|
+
const wroteIdlePath = yield* setSnapshotForRowInTxn(
|
|
1513
|
+
rowId,
|
|
1514
|
+
idleSnapshot,
|
|
1515
|
+
"source-refresh",
|
|
1516
|
+
`source:${fieldPath}:${rowId}:idle`
|
|
1517
|
+
);
|
|
1518
|
+
if (wroteIdlePath) {
|
|
1519
|
+
const event = {
|
|
1520
|
+
_tag: "ResourceSnapshot",
|
|
1521
|
+
resourceId,
|
|
1522
|
+
fieldPath: wroteIdlePath,
|
|
1523
|
+
keyHash: void 0,
|
|
1524
|
+
concurrency: mode2,
|
|
1525
|
+
phase: "idle",
|
|
1526
|
+
snapshot: idleSnapshot,
|
|
1527
|
+
timestamp: Date.now(),
|
|
1528
|
+
moduleId,
|
|
1529
|
+
instanceId
|
|
1530
|
+
};
|
|
1531
|
+
recordReplayEvent(bound, event);
|
|
1532
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1533
|
+
}
|
|
1534
|
+
continue;
|
|
1535
|
+
}
|
|
1536
|
+
const h = keyHash(key);
|
|
1537
|
+
if (!force && current && current.keyHash === h) {
|
|
1538
|
+
continue;
|
|
1539
|
+
}
|
|
1540
|
+
const prevKeyHash = prevSnapshot && typeof prevSnapshot === "object" ? prevSnapshot.keyHash : void 0;
|
|
1541
|
+
if (!force && !current && prevKeyHash === h) {
|
|
1542
|
+
continue;
|
|
1543
|
+
}
|
|
1544
|
+
if (mode2 === "exhaust-trailing" && current) {
|
|
1545
|
+
trailing2.set(rowId, { key, keyHash: h });
|
|
1546
|
+
const loadingSnapshot = Snapshot.loading({ keyHash: h });
|
|
1547
|
+
const wroteLoadingPath = yield* setSnapshotForRowInTxn(
|
|
1548
|
+
rowId,
|
|
1549
|
+
loadingSnapshot,
|
|
1550
|
+
"source-refresh",
|
|
1551
|
+
`source:${fieldPath}:${rowId}:loading`
|
|
1552
|
+
);
|
|
1553
|
+
if (wroteLoadingPath) {
|
|
1554
|
+
const event = {
|
|
1555
|
+
_tag: "ResourceSnapshot",
|
|
1556
|
+
resourceId,
|
|
1557
|
+
fieldPath: wroteLoadingPath,
|
|
1558
|
+
keyHash: h,
|
|
1559
|
+
concurrency: mode2,
|
|
1560
|
+
phase: "loading",
|
|
1561
|
+
snapshot: loadingSnapshot,
|
|
1562
|
+
timestamp: Date.now(),
|
|
1563
|
+
moduleId,
|
|
1564
|
+
instanceId
|
|
1565
|
+
};
|
|
1566
|
+
recordReplayEvent(bound, event);
|
|
1567
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1568
|
+
}
|
|
1569
|
+
continue;
|
|
1570
|
+
}
|
|
1571
|
+
if (mode2 === "switch" && current) {
|
|
1572
|
+
trailing2.delete(rowId);
|
|
1573
|
+
inFlight2.delete(rowId);
|
|
1574
|
+
}
|
|
1575
|
+
yield* startFetch2(rowId, key, h, replayMode, replayLog);
|
|
1576
|
+
}
|
|
1577
|
+
})
|
|
1578
|
+
);
|
|
1579
|
+
return Effect.void;
|
|
1580
|
+
}
|
|
1581
|
+
let inFlight;
|
|
1582
|
+
let gen = 0;
|
|
1583
|
+
let trailing;
|
|
1584
|
+
const concurrency = entry.meta.concurrency;
|
|
1585
|
+
const mode = concurrency ?? "switch";
|
|
1586
|
+
const startFetch = (key, keyHash2, replayMode, replayLog) => Effect.gen(function* () {
|
|
1587
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1588
|
+
let loadingSnapshot = Snapshot.loading({ keyHash: keyHash2 });
|
|
1589
|
+
if (replayMode === "replay" && replayLog) {
|
|
1590
|
+
const replayLoading = yield* replayLog.consumeNextResourceSnapshot({
|
|
1591
|
+
resourceId,
|
|
1592
|
+
fieldPath,
|
|
1593
|
+
keyHash: keyHash2,
|
|
1594
|
+
phase: "loading"
|
|
1595
|
+
});
|
|
1596
|
+
if (replayLoading) {
|
|
1597
|
+
loadingSnapshot = replayLoading.snapshot;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
const wroteLoading = yield* setSnapshotInTxn(
|
|
1601
|
+
bound,
|
|
1602
|
+
fieldPath,
|
|
1603
|
+
loadingSnapshot,
|
|
1604
|
+
"source-refresh",
|
|
1605
|
+
`source:${fieldPath}:loading`,
|
|
1606
|
+
step.debugInfo?.graphNodeId
|
|
1607
|
+
);
|
|
1608
|
+
if (wroteLoading) {
|
|
1609
|
+
const event = {
|
|
1610
|
+
_tag: "ResourceSnapshot",
|
|
1611
|
+
resourceId,
|
|
1612
|
+
fieldPath,
|
|
1613
|
+
keyHash: keyHash2,
|
|
1614
|
+
concurrency: mode,
|
|
1615
|
+
phase: "loading",
|
|
1616
|
+
snapshot: loadingSnapshot,
|
|
1617
|
+
timestamp: Date.now(),
|
|
1618
|
+
moduleId,
|
|
1619
|
+
instanceId
|
|
1620
|
+
};
|
|
1621
|
+
recordReplayEvent(bound, event);
|
|
1622
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1623
|
+
}
|
|
1624
|
+
const io = Effect.gen(function* () {
|
|
1625
|
+
if (replayMode === "replay" && replayLog) {
|
|
1626
|
+
yield* Effect.yieldNow();
|
|
1627
|
+
const replayed = yield* replayLog.consumeNextResourceSnapshot({
|
|
1628
|
+
resourceId,
|
|
1629
|
+
fieldPath,
|
|
1630
|
+
keyHash: keyHash2
|
|
1631
|
+
});
|
|
1632
|
+
if (!replayed) return yield* Effect.void;
|
|
1633
|
+
if (replayed.phase === "success") {
|
|
1634
|
+
const event = {
|
|
1635
|
+
_tag: "ResourceSnapshot",
|
|
1636
|
+
resourceId,
|
|
1637
|
+
fieldPath,
|
|
1638
|
+
keyHash: keyHash2,
|
|
1639
|
+
concurrency: mode,
|
|
1640
|
+
phase: "success",
|
|
1641
|
+
snapshot: replayed.snapshot,
|
|
1642
|
+
timestamp: Date.now(),
|
|
1643
|
+
moduleId,
|
|
1644
|
+
instanceId
|
|
1645
|
+
};
|
|
1646
|
+
yield* writebackIfCurrentKeyHash(
|
|
1647
|
+
bound,
|
|
1648
|
+
fieldPath,
|
|
1649
|
+
keyHash2,
|
|
1650
|
+
replayed.snapshot,
|
|
1651
|
+
"source-refresh",
|
|
1652
|
+
`source:${fieldPath}:success`,
|
|
1653
|
+
step.debugInfo?.graphNodeId,
|
|
1654
|
+
event
|
|
1655
|
+
);
|
|
1656
|
+
} else if (replayed.phase === "error") {
|
|
1657
|
+
const event = {
|
|
1658
|
+
_tag: "ResourceSnapshot",
|
|
1659
|
+
resourceId,
|
|
1660
|
+
fieldPath,
|
|
1661
|
+
keyHash: keyHash2,
|
|
1662
|
+
concurrency: mode,
|
|
1663
|
+
phase: "error",
|
|
1664
|
+
snapshot: replayed.snapshot,
|
|
1665
|
+
timestamp: Date.now(),
|
|
1666
|
+
moduleId,
|
|
1667
|
+
instanceId
|
|
1668
|
+
};
|
|
1669
|
+
yield* writebackIfCurrentKeyHash(
|
|
1670
|
+
bound,
|
|
1671
|
+
fieldPath,
|
|
1672
|
+
keyHash2,
|
|
1673
|
+
replayed.snapshot,
|
|
1674
|
+
"source-refresh",
|
|
1675
|
+
`source:${fieldPath}:error`,
|
|
1676
|
+
step.debugInfo?.graphNodeId,
|
|
1677
|
+
event
|
|
1678
|
+
);
|
|
1679
|
+
}
|
|
1680
|
+
return yield* Effect.void;
|
|
1681
|
+
}
|
|
1682
|
+
const stack = yield* getMiddlewareStack();
|
|
1683
|
+
const registryOpt = yield* Effect.serviceOption(internal.ResourceRegistryTag);
|
|
1684
|
+
const registry = Option.isSome(registryOpt) ? registryOpt.value : void 0;
|
|
1685
|
+
const spec = registry?.specs.get(resourceId);
|
|
1686
|
+
if (!spec) {
|
|
1687
|
+
return yield* Effect.void;
|
|
1688
|
+
}
|
|
1689
|
+
const loadEffect = spec.load(key);
|
|
1690
|
+
const meta = {
|
|
1691
|
+
moduleId,
|
|
1692
|
+
instanceId,
|
|
1693
|
+
fieldPath,
|
|
1694
|
+
resourceId,
|
|
1695
|
+
key,
|
|
1696
|
+
keyHash: keyHash2,
|
|
1697
|
+
traitNodeId: step.debugInfo?.graphNodeId,
|
|
1698
|
+
stepId: step.id
|
|
1699
|
+
};
|
|
1700
|
+
if (!(typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq))) {
|
|
1701
|
+
const sessionOpt = yield* Effect.serviceOption(RunSessionTag);
|
|
1702
|
+
if (Option.isSome(sessionOpt)) {
|
|
1703
|
+
const seqKey = instanceId ?? "global";
|
|
1704
|
+
meta.opSeq = sessionOpt.value.local.nextSeq("opSeq", seqKey);
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
const op = make({
|
|
1708
|
+
kind: "trait-source",
|
|
1709
|
+
name: resourceId,
|
|
1710
|
+
effect: loadEffect,
|
|
1711
|
+
meta
|
|
1712
|
+
});
|
|
1713
|
+
const exit = yield* Effect.exit(run(op, stack));
|
|
1714
|
+
if (exit._tag === "Success") {
|
|
1715
|
+
const successSnapshot = Snapshot.success({ keyHash: keyHash2, data: exit.value });
|
|
1716
|
+
const event = {
|
|
1717
|
+
_tag: "ResourceSnapshot",
|
|
1718
|
+
resourceId,
|
|
1719
|
+
fieldPath,
|
|
1720
|
+
keyHash: keyHash2,
|
|
1721
|
+
concurrency: mode,
|
|
1722
|
+
phase: "success",
|
|
1723
|
+
snapshot: successSnapshot,
|
|
1724
|
+
timestamp: Date.now(),
|
|
1725
|
+
moduleId,
|
|
1726
|
+
instanceId
|
|
1727
|
+
};
|
|
1728
|
+
const wroteSuccess = yield* writebackIfCurrentKeyHash(
|
|
1729
|
+
bound,
|
|
1730
|
+
fieldPath,
|
|
1731
|
+
keyHash2,
|
|
1732
|
+
successSnapshot,
|
|
1733
|
+
"source-refresh",
|
|
1734
|
+
`source:${fieldPath}:success`,
|
|
1735
|
+
step.debugInfo?.graphNodeId,
|
|
1736
|
+
event
|
|
1737
|
+
);
|
|
1738
|
+
if (wroteSuccess) {
|
|
1739
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1740
|
+
}
|
|
1741
|
+
} else {
|
|
1742
|
+
const errorSnapshot = Snapshot.error({ keyHash: keyHash2, error: exit.cause });
|
|
1743
|
+
const event = {
|
|
1744
|
+
_tag: "ResourceSnapshot",
|
|
1745
|
+
resourceId,
|
|
1746
|
+
fieldPath,
|
|
1747
|
+
keyHash: keyHash2,
|
|
1748
|
+
concurrency: mode,
|
|
1749
|
+
phase: "error",
|
|
1750
|
+
snapshot: errorSnapshot,
|
|
1751
|
+
timestamp: Date.now(),
|
|
1752
|
+
moduleId,
|
|
1753
|
+
instanceId
|
|
1754
|
+
};
|
|
1755
|
+
const wroteError = yield* writebackIfCurrentKeyHash(
|
|
1756
|
+
bound,
|
|
1757
|
+
fieldPath,
|
|
1758
|
+
keyHash2,
|
|
1759
|
+
errorSnapshot,
|
|
1760
|
+
"source-refresh",
|
|
1761
|
+
`source:${fieldPath}:error`,
|
|
1762
|
+
step.debugInfo?.graphNodeId,
|
|
1763
|
+
event
|
|
1764
|
+
);
|
|
1765
|
+
if (wroteError) {
|
|
1766
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}).pipe(Effect.catchAllCause(() => Effect.void));
|
|
1770
|
+
const fiber = yield* Effect.forkScoped(Effect.locally(inSyncTransactionFiber, false)(io));
|
|
1771
|
+
const myGen = gen += 1;
|
|
1772
|
+
inFlight = { gen: myGen, fiber, keyHash: keyHash2 };
|
|
1773
|
+
yield* Effect.forkScoped(
|
|
1774
|
+
Effect.locally(
|
|
1775
|
+
inSyncTransactionFiber,
|
|
1776
|
+
false
|
|
1777
|
+
)(
|
|
1778
|
+
Fiber.await(fiber).pipe(
|
|
1779
|
+
Effect.zipRight(
|
|
1780
|
+
Effect.sync(() => {
|
|
1781
|
+
if (inFlight && inFlight.gen === myGen) {
|
|
1782
|
+
inFlight = void 0;
|
|
1783
|
+
}
|
|
1784
|
+
})
|
|
1785
|
+
),
|
|
1786
|
+
Effect.zipRight(
|
|
1787
|
+
mode === "exhaust-trailing" ? Effect.gen(function* () {
|
|
1788
|
+
const next = trailing;
|
|
1789
|
+
trailing = void 0;
|
|
1790
|
+
if (next) {
|
|
1791
|
+
yield* startFetch(next.key, next.keyHash, replayMode, replayLog);
|
|
1792
|
+
}
|
|
1793
|
+
}) : Effect.void
|
|
1794
|
+
),
|
|
1795
|
+
Effect.catchAllCause(() => Effect.void)
|
|
1796
|
+
)
|
|
1797
|
+
)
|
|
1798
|
+
);
|
|
1799
|
+
});
|
|
1800
|
+
register(
|
|
1801
|
+
fieldPath,
|
|
1802
|
+
(state) => Effect.gen(function* () {
|
|
1803
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1804
|
+
const replayModeOpt = yield* Effect.serviceOption(ReplayModeConfigTag);
|
|
1805
|
+
const replayMode = Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
|
|
1806
|
+
const replayLogOpt = yield* Effect.serviceOption(ReplayLog);
|
|
1807
|
+
const replayLog = Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
|
|
1808
|
+
const force = yield* FiberRef.get(forceSourceRefresh);
|
|
1809
|
+
let key;
|
|
1810
|
+
try {
|
|
1811
|
+
key = entry.meta.key(state);
|
|
1812
|
+
} catch {
|
|
1813
|
+
key = void 0;
|
|
1814
|
+
}
|
|
1815
|
+
const traceKey = `${instanceId ?? "unknown"}::source::${fieldPath}`;
|
|
1816
|
+
if (isDevEnv() && (yield* onceInRunSession(`deps_trace_settled:${traceKey}`))) {
|
|
1817
|
+
try {
|
|
1818
|
+
const traced = trace((s) => entry.meta.key(s), state);
|
|
1819
|
+
const diff = diffDeps(entry.meta.deps ?? [], traced.reads);
|
|
1820
|
+
if (diff) {
|
|
1821
|
+
yield* emitDepsMismatch({
|
|
1822
|
+
moduleId,
|
|
1823
|
+
instanceId,
|
|
1824
|
+
kind: "source",
|
|
1825
|
+
fieldPath,
|
|
1826
|
+
diff
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
} catch {
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
if (key === void 0) {
|
|
1833
|
+
if (inFlight) {
|
|
1834
|
+
yield* Fiber.interruptFork(inFlight.fiber);
|
|
1835
|
+
inFlight = void 0;
|
|
1836
|
+
}
|
|
1837
|
+
trailing = void 0;
|
|
1838
|
+
const idleSnapshot = Snapshot.idle();
|
|
1839
|
+
const wroteIdle = yield* setSnapshotInTxn(
|
|
1840
|
+
bound,
|
|
1841
|
+
fieldPath,
|
|
1842
|
+
idleSnapshot,
|
|
1843
|
+
"source-refresh",
|
|
1844
|
+
`source:${fieldPath}:idle`,
|
|
1845
|
+
step.debugInfo?.graphNodeId
|
|
1846
|
+
);
|
|
1847
|
+
if (wroteIdle) {
|
|
1848
|
+
const event = {
|
|
1849
|
+
_tag: "ResourceSnapshot",
|
|
1850
|
+
resourceId,
|
|
1851
|
+
fieldPath,
|
|
1852
|
+
keyHash: void 0,
|
|
1853
|
+
concurrency: mode,
|
|
1854
|
+
phase: "idle",
|
|
1855
|
+
snapshot: idleSnapshot,
|
|
1856
|
+
timestamp: Date.now(),
|
|
1857
|
+
moduleId,
|
|
1858
|
+
instanceId
|
|
1859
|
+
};
|
|
1860
|
+
recordReplayEvent(bound, event);
|
|
1861
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1862
|
+
}
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
const h = keyHash(key);
|
|
1866
|
+
if (!force) {
|
|
1867
|
+
if (inFlight && inFlight.keyHash === h) {
|
|
1868
|
+
return;
|
|
1869
|
+
}
|
|
1870
|
+
const currentSnapshot = getAtPath(state, fieldPath);
|
|
1871
|
+
const currentKeyHash = currentSnapshot && typeof currentSnapshot === "object" ? currentSnapshot.keyHash : void 0;
|
|
1872
|
+
const currentStatus = currentSnapshot && typeof currentSnapshot === "object" ? currentSnapshot.status : void 0;
|
|
1873
|
+
if (currentStatus && currentStatus !== "idle" && currentKeyHash === h) {
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
if (mode === "exhaust-trailing" && inFlight) {
|
|
1878
|
+
trailing = { key, keyHash: h };
|
|
1879
|
+
const loadingSnapshot = Snapshot.loading({ keyHash: h });
|
|
1880
|
+
const wroteLoading = yield* setSnapshotInTxn(
|
|
1881
|
+
bound,
|
|
1882
|
+
fieldPath,
|
|
1883
|
+
loadingSnapshot,
|
|
1884
|
+
"source-refresh",
|
|
1885
|
+
`source:${fieldPath}:loading`,
|
|
1886
|
+
step.debugInfo?.graphNodeId
|
|
1887
|
+
);
|
|
1888
|
+
if (wroteLoading) {
|
|
1889
|
+
const event = {
|
|
1890
|
+
_tag: "ResourceSnapshot",
|
|
1891
|
+
resourceId,
|
|
1892
|
+
fieldPath,
|
|
1893
|
+
keyHash: h,
|
|
1894
|
+
concurrency: mode,
|
|
1895
|
+
phase: "loading",
|
|
1896
|
+
snapshot: loadingSnapshot,
|
|
1897
|
+
timestamp: Date.now(),
|
|
1898
|
+
moduleId,
|
|
1899
|
+
instanceId
|
|
1900
|
+
};
|
|
1901
|
+
recordReplayEvent(bound, event);
|
|
1902
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1903
|
+
}
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
if (mode === "switch" && inFlight) {
|
|
1907
|
+
yield* Fiber.interruptFork(inFlight.fiber);
|
|
1908
|
+
inFlight = void 0;
|
|
1909
|
+
trailing = void 0;
|
|
1910
|
+
}
|
|
1911
|
+
yield* startFetch(key, h, replayMode, replayLog);
|
|
1912
|
+
})
|
|
1913
|
+
);
|
|
1914
|
+
return Effect.void;
|
|
1915
|
+
};
|
|
1916
|
+
|
|
1917
|
+
export {
|
|
1918
|
+
diffDeps,
|
|
1919
|
+
trace,
|
|
1920
|
+
syncIdleInTransaction,
|
|
1921
|
+
installSourceRefresh,
|
|
1922
|
+
build
|
|
1923
|
+
};
|
|
1924
|
+
//# sourceMappingURL=chunk-PYOE4VSI.js.map
|