@graphrefly/graphrefly 0.38.0 → 0.40.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/dist/budget-gate-CmmVtasH.d.ts +115 -0
- package/dist/budget-gate-DiP_nK0n.d.cts +115 -0
- package/dist/{cascading-BsJ4GbnS.d.ts → cascading-BNfxffgc.d.ts} +2 -2
- package/dist/{cascading-B25wxpRa.d.cts → cascading-Cxs1eztH.d.cts} +2 -2
- package/dist/chunk-2BX4NB34.js +3 -0
- package/dist/{chunk-6VFC334U.js → chunk-2DMKW2AD.js} +1 -1
- package/dist/{chunk-4BDQXBXE.js → chunk-2QXRYP7Q.js} +1 -1
- package/dist/chunk-32N3JALT.js +1 -0
- package/dist/chunk-35JTVPOX.js +1 -0
- package/dist/chunk-3G5U5QNE.js +5 -0
- package/dist/{chunk-PHXZRR6C.js → chunk-4I45FVQS.js} +1 -1
- package/dist/{chunk-B5S7KTGP.js → chunk-6I726LZU.js} +1 -1
- package/dist/{chunk-NV63VQHI.js → chunk-6VWBPSSY.js} +1 -1
- package/dist/chunk-6XVD5TZV.js +1 -0
- package/dist/chunk-756D5TFD.js +1 -0
- package/dist/{chunk-DSOVKKTI.js → chunk-7Q4ZD3YW.js} +1 -1
- package/dist/{chunk-TMVY7OWG.js → chunk-B7LCDQEV.js} +1 -1
- package/dist/chunk-C72GO4IZ.js +1 -0
- package/dist/{chunk-RZ5HKPGI.js → chunk-CKFQS2CJ.js} +1 -1
- package/dist/chunk-D27JNOLZ.js +1 -0
- package/dist/chunk-ECQRP2UT.js +1 -0
- package/dist/{chunk-6773HURD.js → chunk-FHRBBHJN.js} +1 -1
- package/dist/{chunk-UVLZX2OU.js → chunk-I2DEVPMU.js} +1 -1
- package/dist/chunk-INQFTVZA.js +61 -0
- package/dist/{chunk-6KZZ6XQE.js → chunk-J63M5U46.js} +1 -1
- package/dist/{chunk-POCWFIJ7.js → chunk-JKBOIJ22.js} +1 -1
- package/dist/chunk-K2Z7UENB.js +1 -0
- package/dist/chunk-L6NSJVJZ.js +1 -0
- package/dist/{chunk-K5C67OGE.js → chunk-LCGAVGGV.js} +2 -2
- package/dist/chunk-LYM4PBMV.js +1 -0
- package/dist/{chunk-O2BLVQU4.js → chunk-MNZIKXK4.js} +1 -1
- package/dist/chunk-N43XM7BM.js +1 -0
- package/dist/{chunk-FWGIZP3W.js → chunk-OSZ22J7O.js} +1 -1
- package/dist/{chunk-FAYEMS5M.js → chunk-PPUYQ66A.js} +1 -1
- package/dist/{chunk-SP5O2MIX.js → chunk-QSK3RRII.js} +1 -1
- package/dist/chunk-RZJDIV2G.js +1 -0
- package/dist/chunk-SSCGRYJ2.js +1 -0
- package/dist/chunk-SVFKHUCW.js +1 -0
- package/dist/chunk-TSOYJ743.js +1 -0
- package/dist/{chunk-O245YLM5.js → chunk-UWA6D7UF.js} +1 -1
- package/dist/chunk-VMF23LGB.js +1 -0
- package/dist/chunk-WL6LFPJB.js +1 -0
- package/dist/chunk-WUT362QV.js +1 -0
- package/dist/chunk-XJLYLLIJ.js +1 -0
- package/dist/{chunk-IBGE62GZ.js → chunk-XW4YDF6G.js} +1 -1
- package/dist/chunk-YKD7WUYJ.js +43 -0
- package/dist/{chunk-7KZZLWZ6.js → chunk-YXDRGKXP.js} +1 -1
- package/dist/chunk-Z4F3DOWS.js +84 -0
- package/dist/compat/index.cjs +9 -13
- package/dist/compat/index.d.cts +16 -16
- package/dist/compat/index.d.ts +16 -16
- package/dist/compat/index.js +1 -1
- package/dist/compat/jotai/index.d.cts +2 -2
- package/dist/compat/jotai/index.d.ts +2 -2
- package/dist/compat/nanostores/index.d.cts +2 -2
- package/dist/compat/nanostores/index.d.ts +2 -2
- package/dist/compat/nestjs/index.cjs +7 -11
- package/dist/compat/nestjs/index.d.cts +8 -8
- package/dist/compat/nestjs/index.d.ts +8 -8
- package/dist/compat/nestjs/index.js +1 -1
- package/dist/compat/react/index.d.cts +2 -2
- package/dist/compat/react/index.d.ts +2 -2
- package/dist/compat/solid/index.d.cts +2 -2
- package/dist/compat/solid/index.d.ts +2 -2
- package/dist/compat/svelte/index.d.cts +2 -2
- package/dist/compat/svelte/index.d.ts +2 -2
- package/dist/compat/vue/index.d.cts +2 -2
- package/dist/compat/vue/index.d.ts +2 -2
- package/dist/compat/zustand/index.cjs +3 -7
- package/dist/compat/zustand/index.d.cts +4 -4
- package/dist/compat/zustand/index.d.ts +4 -4
- package/dist/compat/zustand/index.js +1 -1
- package/dist/core/index.cjs +1 -1
- package/dist/core/index.d.cts +4 -4
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +1 -1
- package/dist/{composite-DTOlDuch.d.ts → decay-BnrlbxSv.d.ts} +39 -3
- package/dist/{composite-CgG0MqHm.d.cts → decay-C25AyNAj.d.cts} +39 -3
- package/dist/extra/browser.d.cts +1 -1
- package/dist/extra/browser.d.ts +1 -1
- package/dist/extra/index.cjs +16 -20
- package/dist/extra/index.d.cts +11 -9
- package/dist/extra/index.d.ts +11 -9
- package/dist/extra/index.js +1 -1
- package/dist/extra/node.cjs +2 -2
- package/dist/extra/node.d.cts +1 -1
- package/dist/extra/node.d.ts +1 -1
- package/dist/extra/node.js +1 -1
- package/dist/extra/operators.cjs +1 -1
- package/dist/extra/operators.d.cts +1 -1
- package/dist/extra/operators.d.ts +1 -1
- package/dist/extra/operators.js +1 -1
- package/dist/extra/reactive.cjs +1 -1
- package/dist/extra/reactive.d.cts +3 -3
- package/dist/extra/reactive.d.ts +3 -3
- package/dist/extra/reactive.js +1 -1
- package/dist/extra/render/index.cjs +5 -0
- package/dist/extra/render/index.d.cts +183 -0
- package/dist/extra/render/index.d.ts +183 -0
- package/dist/extra/render/index.js +1 -0
- package/dist/extra/sources.cjs +1 -1
- package/dist/extra/sources.d.cts +1 -1
- package/dist/extra/sources.d.ts +1 -1
- package/dist/extra/sources.js +1 -1
- package/dist/extra/storage-browser.d.cts +1 -1
- package/dist/extra/storage-browser.d.ts +1 -1
- package/dist/{fallback-axI2cXwt.d.cts → fallback-8JYU8tlT.d.cts} +1 -1
- package/dist/{fallback-DuEXfA4F.d.ts → fallback-CMZl39L5.d.ts} +1 -1
- package/dist/graph/index.cjs +7 -7
- package/dist/graph/index.d.cts +5 -5
- package/dist/graph/index.d.ts +5 -5
- package/dist/graph/index.js +1 -1
- package/dist/{graph-BjW1taJl.d.ts → graph-BkIkog4h.d.ts} +76 -100
- package/dist/{graph-CHsVwf9S.d.cts → graph-E6likq7w.d.cts} +76 -100
- package/dist/{index-CIcu6fIR.d.ts → index-2n8Eai6M.d.ts} +1 -1
- package/dist/{index-BwOsJfLJ.d.ts → index-3k4Gg6-n.d.ts} +3 -3
- package/dist/{index-BUFCHvOR.d.ts → index-40ZT4MHj.d.ts} +3 -3
- package/dist/index-8s-Qm-gz.d.ts +218 -0
- package/dist/index-A3U3CSve.d.cts +113 -0
- package/dist/{index-CDvC1m5p.d.ts → index-B2RUoIUz.d.ts} +1 -1
- package/dist/{index-Byp771zP.d.ts → index-B6iTqKtJ.d.ts} +2 -2
- package/dist/{index-D-B7U42V.d.cts → index-B72TQQHd.d.cts} +2 -2
- package/dist/{resilience-Bys63Cpd.d.ts → index-BAQrjuZF.d.ts} +202 -26
- package/dist/{index-BiomL7AW.d.ts → index-BJSZxSFX.d.ts} +1 -1
- package/dist/index-BQ1fR4li.d.ts +210 -0
- package/dist/{index-D7-RSD93.d.cts → index-BTHOTC0Q.d.cts} +4 -4
- package/dist/{index-CEVzBWeB.d.ts → index-BaA-xpSw.d.ts} +26 -19
- package/dist/{index-CAV-3RpJ.d.cts → index-Bd91Nmf4.d.cts} +4 -4
- package/dist/{index-BI1wMfyc.d.ts → index-BgjS2b8N.d.ts} +3 -3
- package/dist/{index-Bpr0Pwgl.d.cts → index-BiHUBEKq.d.cts} +3 -3
- package/dist/{index-UsU9ptzs.d.cts → index-BilOa6AE.d.cts} +55 -9
- package/dist/{index-DJVQ-t07.d.ts → index-BmSQLAZo.d.cts} +41 -48
- package/dist/{index-DTDVDzhA.d.ts → index-C-dkXOpB.d.cts} +56 -54
- package/dist/{index-B-ORMr3k.d.ts → index-C5cQ7Gfx.d.ts} +4 -4
- package/dist/{index-ML6vHKXK.d.ts → index-C6ZUaos7.d.ts} +1 -1
- package/dist/{index-Vz7KPfgz.d.ts → index-CAP3UGsq.d.ts} +1 -1
- package/dist/{index-BFaALJxR.d.ts → index-CD2dBMet.d.ts} +10 -8
- package/dist/index-CGhMJNHb.d.cts +128 -0
- package/dist/{index-B3D_z0Z6.d.cts → index-CL7oilfm.d.cts} +1 -1
- package/dist/{index-Bn0uZEL4.d.ts → index-CQtWm7jS.d.ts} +9 -9
- package/dist/{index-CM-i58FY.d.cts → index-CRm0YIzC.d.cts} +9 -9
- package/dist/index-CUIkE1l9.d.cts +230 -0
- package/dist/{index-CijfwEWx.d.ts → index-Cczxgd2D.d.ts} +2 -2
- package/dist/{index-CAbHN_rP.d.cts → index-CgnCFhr2.d.cts} +1 -1
- package/dist/{index-B2IUcH13.d.cts → index-Ck35nA-T.d.ts} +41 -48
- package/dist/{index-BpMZzX9P.d.cts → index-Cnr1WrlX.d.cts} +3 -3
- package/dist/{index-JYtN9uqM.d.ts → index-CoM4rzyB.d.ts} +1 -1
- package/dist/{index-Ckil6miL.d.cts → index-CtFNGe-m.d.cts} +2 -2
- package/dist/{index-BjWZARLy.d.ts → index-Ctb7_2sG.d.ts} +1 -1
- package/dist/index-CuPUehFa.d.cts +218 -0
- package/dist/index-D1Gc7wV5.d.ts +230 -0
- package/dist/{index-DqICM_I7.d.ts → index-D1IEZUsj.d.ts} +67 -9
- package/dist/{index-BFuVcqL8.d.cts → index-D3ayz3hy.d.cts} +1 -1
- package/dist/{index-CQsqqEVz.d.cts → index-D4uimgee.d.cts} +1 -1
- package/dist/{resilience-BWP2c7Af.d.cts → index-DGTo1yka.d.cts} +202 -26
- package/dist/{index-BmWuVdER.d.ts → index-DH4fm2Ck.d.ts} +2 -2
- package/dist/{index-BkQqf1EF.d.cts → index-DJ_MPOJ5.d.cts} +67 -9
- package/dist/{index-9xhIaM-w.d.cts → index-DOBLxOti.d.cts} +1 -1
- package/dist/{index-BqcgiSQg.d.cts → index-DQQCOIt8.d.cts} +10 -8
- package/dist/{index-DJNAWzcH.d.cts → index-DVAlsmEU.d.cts} +26 -19
- package/dist/index-DVDapw2k.d.cts +210 -0
- package/dist/{index-D_QQ_dTD.d.cts → index-DYTBbF8T.d.cts} +1 -1
- package/dist/{index-BgzPO43H.d.cts → index-DgJc8Zgc.d.cts} +6 -6
- package/dist/{index-Czk3r0yA.d.cts → index-DhLyOHYZ.d.ts} +56 -54
- package/dist/{index-CrlHFsiT.d.ts → index-DhnsQfa3.d.ts} +100 -118
- package/dist/{index-Bub6x_D4.d.cts → index-DktLSZOc.d.cts} +37 -90
- package/dist/{index-BaSy4L6w.d.cts → index-DpiGqtrs.d.cts} +100 -118
- package/dist/{index-D-HZ7sP4.d.ts → index-I1cCY3ZI.d.ts} +6 -6
- package/dist/{index-D9vBTuzo.d.ts → index-IUCY0OFN.d.ts} +4 -4
- package/dist/{index-DeSsvHDD.d.cts → index-MxYuWOrf.d.cts} +3 -3
- package/dist/index-N2MAxt7_.d.ts +128 -0
- package/dist/{index-CpZKtdMw.d.cts → index-PgwvGWa1.d.cts} +1 -1
- package/dist/{index-AUqWe_fX.d.ts → index-WSlcjhQF.d.ts} +55 -9
- package/dist/{index-Di7OdwlO.d.ts → index-bXXLSvor.d.ts} +37 -90
- package/dist/index-da2V5vPy.d.ts +113 -0
- package/dist/{index-DY2f2b9z.d.ts → index-eaQuGJnv.d.ts} +3 -3
- package/dist/{index-BsgxnHN8.d.cts → index-t6L2qpHh.d.cts} +3 -3
- package/dist/{index-C-3UXnHT.d.cts → index-tV3AA9hI.d.cts} +2 -2
- package/dist/{index-8OxXae3g.d.ts → index-yLt-aPMp.d.ts} +1 -1
- package/dist/{index-CqSJ25A9.d.cts → index-z8WFPVI8.d.cts} +1 -1
- package/dist/index.cjs +63 -59
- package/dist/index.d.cts +48 -47
- package/dist/index.d.ts +48 -47
- package/dist/index.js +1 -1
- package/dist/{meta-DreaEM_a.d.cts → meta-Ct9nqQS5.d.cts} +11 -7
- package/dist/{meta-BYqlATmg.d.ts → meta-D8OyedKp.d.ts} +11 -7
- package/dist/{node-fSc-hCv8.d.cts → node-BYInONRr.d.cts} +3 -3
- package/dist/{node-fSc-hCv8.d.ts → node-BYInONRr.d.ts} +3 -3
- package/dist/{observable-Cqty11jG.d.cts → observable-DMIlYJV1.d.cts} +1 -1
- package/dist/{observable-EAV_rNfM.d.ts → observable-DO8DDEzv.d.ts} +1 -1
- package/dist/patterns/ai/browser.cjs +5 -5
- package/dist/patterns/ai/browser.d.cts +4 -4
- package/dist/patterns/ai/browser.d.ts +4 -4
- package/dist/patterns/ai/browser.js +1 -1
- package/dist/patterns/ai/index.cjs +16 -20
- package/dist/patterns/ai/index.d.cts +17 -17
- package/dist/patterns/ai/index.d.ts +17 -17
- package/dist/patterns/ai/index.js +1 -1
- package/dist/patterns/ai/node.cjs +1 -1
- package/dist/patterns/ai/node.d.cts +4 -4
- package/dist/patterns/ai/node.d.ts +4 -4
- package/dist/patterns/ai/node.js +1 -1
- package/dist/patterns/audit/index.cjs +3 -7
- package/dist/patterns/audit/index.d.cts +6 -6
- package/dist/patterns/audit/index.d.ts +6 -6
- package/dist/patterns/audit/index.js +1 -1
- package/dist/patterns/cqrs/index.cjs +3 -7
- package/dist/patterns/cqrs/index.d.cts +6 -6
- package/dist/patterns/cqrs/index.d.ts +6 -6
- package/dist/patterns/cqrs/index.js +1 -1
- package/dist/patterns/demo-shell/index.cjs +5 -8
- package/dist/patterns/demo-shell/index.d.cts +5 -5
- package/dist/patterns/demo-shell/index.d.ts +5 -5
- package/dist/patterns/demo-shell/index.js +1 -1
- package/dist/patterns/domain-templates/index.cjs +3 -7
- package/dist/patterns/domain-templates/index.d.cts +4 -4
- package/dist/patterns/domain-templates/index.d.ts +4 -4
- package/dist/patterns/domain-templates/index.js +1 -1
- package/dist/patterns/graphspec/index.cjs +37 -37
- package/dist/patterns/graphspec/index.d.cts +5 -5
- package/dist/patterns/graphspec/index.d.ts +5 -5
- package/dist/patterns/graphspec/index.js +1 -1
- package/dist/patterns/guarded-execution/index.cjs +3 -7
- package/dist/patterns/guarded-execution/index.d.cts +7 -7
- package/dist/patterns/guarded-execution/index.d.ts +7 -7
- package/dist/patterns/guarded-execution/index.js +1 -1
- package/dist/patterns/harness/index.cjs +8 -12
- package/dist/patterns/harness/index.d.cts +12 -12
- package/dist/patterns/harness/index.d.ts +12 -12
- package/dist/patterns/harness/index.js +1 -1
- package/dist/patterns/job-queue/index.cjs +3 -7
- package/dist/patterns/job-queue/index.d.cts +6 -6
- package/dist/patterns/job-queue/index.d.ts +6 -6
- package/dist/patterns/job-queue/index.js +1 -1
- package/dist/patterns/lens/index.cjs +3 -7
- package/dist/patterns/lens/index.d.cts +5 -6
- package/dist/patterns/lens/index.d.ts +5 -6
- package/dist/patterns/lens/index.js +1 -1
- package/dist/patterns/memory/index.cjs +3 -7
- package/dist/patterns/memory/index.d.cts +6 -6
- package/dist/patterns/memory/index.d.ts +6 -6
- package/dist/patterns/memory/index.js +1 -1
- package/dist/patterns/messaging/index.cjs +3 -7
- package/dist/patterns/messaging/index.d.cts +5 -5
- package/dist/patterns/messaging/index.d.ts +5 -5
- package/dist/patterns/messaging/index.js +1 -1
- package/dist/patterns/orchestration/index.cjs +3 -7
- package/dist/patterns/orchestration/index.d.cts +8 -8
- package/dist/patterns/orchestration/index.d.ts +8 -8
- package/dist/patterns/orchestration/index.js +1 -1
- package/dist/patterns/process/index.cjs +1 -1
- package/dist/patterns/process/index.d.cts +7 -7
- package/dist/patterns/process/index.d.ts +7 -7
- package/dist/patterns/process/index.js +1 -1
- package/dist/patterns/reactive-layout/index.cjs +4 -8
- package/dist/patterns/reactive-layout/index.d.cts +5 -5
- package/dist/patterns/reactive-layout/index.d.ts +5 -5
- package/dist/patterns/reactive-layout/index.js +1 -1
- package/dist/patterns/reduction/index.cjs +3 -7
- package/dist/patterns/reduction/index.d.cts +4 -4
- package/dist/patterns/reduction/index.d.ts +4 -4
- package/dist/patterns/reduction/index.js +1 -1
- package/dist/patterns/refine-loop/index.cjs +5 -9
- package/dist/patterns/refine-loop/index.d.cts +6 -6
- package/dist/patterns/refine-loop/index.d.ts +6 -6
- package/dist/patterns/refine-loop/index.js +1 -1
- package/dist/patterns/resilient-pipeline/index.cjs +3 -1
- package/dist/patterns/resilient-pipeline/index.d.cts +6 -6
- package/dist/patterns/resilient-pipeline/index.d.ts +6 -6
- package/dist/patterns/resilient-pipeline/index.js +1 -1
- package/dist/patterns/surface/index.cjs +12 -16
- package/dist/patterns/surface/index.d.cts +6 -6
- package/dist/patterns/surface/index.d.ts +6 -6
- package/dist/patterns/surface/index.js +1 -1
- package/dist/{pipeline-graph-9JBbmRxA.d.ts → pipeline-graph-CB4La-UW.d.ts} +34 -17
- package/dist/{pipeline-graph-DuHpXSOn.d.cts → pipeline-graph-MWrQZXCq.d.cts} +34 -17
- package/dist/{reactive-layout-BMLDB4Vd.d.cts → reactive-layout-BtZfUKuL.d.cts} +2 -2
- package/dist/{reactive-layout-D-tRiNhg.d.ts → reactive-layout-KJj4E2dT.d.ts} +2 -2
- package/dist/{reactive-log-BgWSA1fg.d.ts → reactive-log-BlAsPLl2.d.ts} +2 -2
- package/dist/{reactive-log-C3IMAGpT.d.cts → reactive-log-_zeEnB9H.d.cts} +2 -2
- package/dist/{reactive-map-DmgeADH8.d.cts → reactive-map-6P_k3AQM.d.cts} +2 -2
- package/dist/{reactive-map-CHyeCf4D.d.ts → reactive-map-CjXByDV-.d.ts} +2 -2
- package/dist/resilience-S33JV6XC.js +1 -0
- package/dist/{sugar-D13E2M_z.d.ts → sugar-BhfjgetH.d.ts} +1 -1
- package/dist/{sugar-DgaGJcI6.d.cts → sugar-DzePN5-g.d.cts} +1 -1
- package/dist/{topology-tree-jrZue3ao.d.cts → topology-tree-3LBKFsUo.d.cts} +1 -1
- package/dist/{topology-tree-D47-nI6Z.d.ts → topology-tree-mF7Emqzm.d.ts} +1 -1
- package/dist/{types-BMSGPlpO.d.cts → types-1Dhoi7HM.d.cts} +1 -1
- package/dist/{types-CidcBDuk.d.ts → types-39jk0kaV.d.ts} +1 -1
- package/package.json +11 -1
- package/dist/chunk-2YFDSYEF.js +0 -1
- package/dist/chunk-5BGFS2XH.js +0 -1
- package/dist/chunk-CMTN3KPT.js +0 -80
- package/dist/chunk-DQJLC6YY.js +0 -1
- package/dist/chunk-G7JN6LCB.js +0 -1
- package/dist/chunk-KJEAIIIY.js +0 -43
- package/dist/chunk-LV3ACS5J.js +0 -1
- package/dist/chunk-NBGPXQSP.js +0 -1
- package/dist/chunk-NN3QPJ6U.js +0 -1
- package/dist/chunk-NSAZ6PR6.js +0 -1
- package/dist/chunk-O32GJOUJ.js +0 -1
- package/dist/chunk-QEVSIVSF.js +0 -1
- package/dist/chunk-QMC2PLNM.js +0 -7
- package/dist/chunk-QOJFR6GS.js +0 -1
- package/dist/chunk-SFK7MN7S.js +0 -1
- package/dist/chunk-TB7JKSVS.js +0 -61
- package/dist/chunk-UAXFKMAG.js +0 -1
- package/dist/chunk-XIMFHEKV.js +0 -1
- package/dist/chunk-XLMYQB6F.js +0 -1
- package/dist/chunk-XLYF4LBH.js +0 -1
- package/dist/imperative-audit-ahAE65a9.d.cts +0 -28
- package/dist/imperative-audit-ahAE65a9.d.ts +0 -28
- package/dist/index-5dNRlW7J.d.ts +0 -135
- package/dist/index-BWUMIt7J.d.cts +0 -135
- package/dist/index-BhzwpIJc.d.cts +0 -105
- package/dist/index-BsZk9T8y.d.ts +0 -105
- package/dist/index-C56XZiDe.d.cts +0 -163
- package/dist/index-CpdnP-0y.d.cts +0 -186
- package/dist/index-DKrIuF-r.d.ts +0 -163
- package/dist/index-DOU1Ee_k.d.ts +0 -186
- package/dist/resilience-LGBK236C.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { N as Node } from './node-BYInONRr.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Backoff strategies for {@link retry} (roadmap §3.1). Delays are in **nanoseconds**.
|
|
@@ -153,11 +153,29 @@ declare function withMaxAttempts(strategy: BackoffStrategy, maxAttempts: number)
|
|
|
153
153
|
*/
|
|
154
154
|
declare function resolveBackoffPreset(name: BackoffPreset): BackoffStrategy;
|
|
155
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Resilience utilities — roadmap §3.1 + §3.1c (retry, breaker, rate limit, status,
|
|
158
|
+
* fallback, cache, timeout, budgetGate).
|
|
159
|
+
*/
|
|
160
|
+
|
|
156
161
|
type RetryOptions = {
|
|
157
|
-
/**
|
|
162
|
+
/**
|
|
163
|
+
* Max retry attempts after each terminal `ERROR` (not counting the first failure).
|
|
164
|
+
*
|
|
165
|
+
* **Required when `backoff` is set.** Pass `Infinity` to opt in to unbounded retries
|
|
166
|
+
* — the explicit value rules out the silent-infinite-budget footgun (a flaky provider
|
|
167
|
+
* + exponential backoff + omitted `count` would previously default to ~2.1B retries).
|
|
168
|
+
*/
|
|
158
169
|
count?: number;
|
|
159
170
|
/** Delay between attempts; strategies use **nanoseconds**. */
|
|
160
171
|
backoff?: BackoffStrategy | BackoffPreset;
|
|
172
|
+
/**
|
|
173
|
+
* Caller-supplied metadata merged into the produced node's `meta` (Tier 5.2
|
|
174
|
+
* D8 widening). Use {@link domainMeta} to tag the layer for `describe()`
|
|
175
|
+
* grouping. The primitive's `factoryTag("retry", …)` always wins against
|
|
176
|
+
* caller keys.
|
|
177
|
+
*/
|
|
178
|
+
meta?: Record<string, unknown>;
|
|
161
179
|
};
|
|
162
180
|
/** Factory-mode-only options. `initial` seeds the outer node's cache before the first attempt. */
|
|
163
181
|
type RetryFactoryOptions<T> = RetryOptions & {
|
|
@@ -177,12 +195,16 @@ type RetryFactoryOptions<T> = RetryOptions & {
|
|
|
177
195
|
* same retry pipeline as inner-node ERROR.
|
|
178
196
|
*
|
|
179
197
|
* @param input - Upstream node or factory that returns a fresh node per attempt.
|
|
180
|
-
* @param opts - `count` caps attempts; `backoff` supplies delay in **nanoseconds** (or a preset name); `initial` seeds the outer node cache (factory mode only).
|
|
198
|
+
* @param opts - `count` caps attempts (**required when `backoff` is set**; pass `Infinity` to opt in to unbounded); `backoff` supplies delay in **nanoseconds** (or a preset name); `initial` seeds the outer node cache (factory mode only).
|
|
181
199
|
* @returns Node that retries on error.
|
|
182
200
|
*
|
|
201
|
+
* @throws {RangeError} when `backoff` is provided without an explicit `count` (unbounded-retry footgun guard) or when `count < 0`.
|
|
202
|
+
*
|
|
183
203
|
* @remarks
|
|
184
204
|
* **Protocol:** Forwards unknown message tuples unchanged; handles `DIRTY`, `DATA`, `RESOLVED`, `COMPLETE`, `ERROR`.
|
|
185
205
|
*
|
|
206
|
+
* **Backoff floor:** every scheduled delay is floored at 1ms via `Math.max(1, delayNs / NS_PER_MS)` even when the strategy returns 0ns. This avoids 0-delay re-entrancy on the active stack frame on a tight ERROR loop. Strategies that return `null`/`undefined` stop retrying immediately and forward the original error.
|
|
207
|
+
*
|
|
186
208
|
* @example
|
|
187
209
|
* ```ts
|
|
188
210
|
* // Source mode — resubscribe the same node:
|
|
@@ -226,7 +248,12 @@ interface CircuitBreakerOptions {
|
|
|
226
248
|
cooldown?: BackoffStrategy;
|
|
227
249
|
/** Max trial requests allowed in half-open state. Default: 1. */
|
|
228
250
|
halfOpenMax?: number;
|
|
229
|
-
/**
|
|
251
|
+
/**
|
|
252
|
+
* Clock function returning **nanoseconds** with `monotonicNs()` semantics
|
|
253
|
+
* (monotonically non-decreasing; suitable for elapsed-time arithmetic — never
|
|
254
|
+
* use `Date.now()` because wall-clock skew can flip elapsed math negative).
|
|
255
|
+
* Default: `monotonicNs` from `core/clock`. Override for deterministic tests.
|
|
256
|
+
*/
|
|
230
257
|
now?: () => number;
|
|
231
258
|
}
|
|
232
259
|
interface CircuitBreaker {
|
|
@@ -236,7 +263,13 @@ interface CircuitBreaker {
|
|
|
236
263
|
recordSuccess(): void;
|
|
237
264
|
/** Record a failed execution. May transition to open. */
|
|
238
265
|
recordFailure(error?: unknown): void;
|
|
239
|
-
/**
|
|
266
|
+
/**
|
|
267
|
+
* Current circuit state (read-only, does not trigger transitions).
|
|
268
|
+
*
|
|
269
|
+
* **Telemetry:** wrap with {@link withBreaker} to surface this as a reactive
|
|
270
|
+
* `Node<CircuitState>` companion (`bundle.breakerState`) — every state
|
|
271
|
+
* transition (`closed`/`open`/`half-open`) emits to subscribers.
|
|
272
|
+
*/
|
|
240
273
|
readonly state: CircuitState;
|
|
241
274
|
/** Number of consecutive failures in the current closed period. */
|
|
242
275
|
readonly failureCount: number;
|
|
@@ -282,6 +315,8 @@ type WithBreakerBundle<T> = {
|
|
|
282
315
|
* @remarks
|
|
283
316
|
* **Success path:** `COMPLETE` calls {@link CircuitBreaker.recordSuccess}. **Failure path:** upstream `ERROR` calls {@link CircuitBreaker.recordFailure} and is forwarded.
|
|
284
317
|
*
|
|
318
|
+
* **State telemetry:** `breakerState: Node<CircuitState>` is a reactive companion that mirrors `breaker.state` — every transition (`closed`/`open`/`half-open`) emits a `DATA`. Also accessible via `node.meta.breakerState` for `describe()` traversal.
|
|
319
|
+
*
|
|
285
320
|
* @example
|
|
286
321
|
* ```ts
|
|
287
322
|
* import { state, withBreaker, circuitBreaker } from "@graphrefly/graphrefly-ts";
|
|
@@ -295,9 +330,17 @@ type WithBreakerBundle<T> = {
|
|
|
295
330
|
*/
|
|
296
331
|
declare function withBreaker<T>(breaker: CircuitBreaker, options?: {
|
|
297
332
|
onOpen?: "skip" | "error";
|
|
333
|
+
meta?: Record<string, unknown>;
|
|
298
334
|
}): (source: Node<T>) => WithBreakerBundle<T>;
|
|
299
335
|
interface TokenBucket {
|
|
300
|
-
/**
|
|
336
|
+
/**
|
|
337
|
+
* Number of tokens currently available (after refill).
|
|
338
|
+
*
|
|
339
|
+
* **Float-valued.** When `refillPerSecond` is fractional (or `capacity` × elapsed-fraction
|
|
340
|
+
* yields a non-integer), the bucket accumulates fractional refill credit between
|
|
341
|
+
* `tryConsume`s. Consumers should not assume integer tokens — e.g. with
|
|
342
|
+
* `tokenBucket(10, 2.5)` after 100ms of elapsed time `available()` may report `0.25`.
|
|
343
|
+
*/
|
|
301
344
|
available(): number;
|
|
302
345
|
/** Try to consume `cost` tokens. Returns `true` if successful. */
|
|
303
346
|
tryConsume(cost?: number): boolean;
|
|
@@ -310,35 +353,79 @@ interface TokenBucket {
|
|
|
310
353
|
*/
|
|
311
354
|
putBack(cost?: number): void;
|
|
312
355
|
}
|
|
356
|
+
/** Optional configuration for {@link tokenBucket}. */
|
|
357
|
+
interface TokenBucketOptions {
|
|
358
|
+
/**
|
|
359
|
+
* Clock function returning **nanoseconds** with `monotonicNs()` semantics
|
|
360
|
+
* (monotonically non-decreasing). Default: `monotonicNs` from `core/clock`.
|
|
361
|
+
* Override for deterministic tests — eliminates the need for `vi.useFakeTimers`
|
|
362
|
+
* to drive token-refill scheduling.
|
|
363
|
+
*/
|
|
364
|
+
clock?: () => number;
|
|
365
|
+
}
|
|
313
366
|
/**
|
|
314
367
|
* Token-bucket meter (capacity + refill rate per second). Use with {@link rateLimiter} or custom gates.
|
|
315
368
|
*
|
|
316
369
|
* @param capacity - Maximum tokens (must be positive).
|
|
317
|
-
* @param refillPerSecond - Tokens added per elapsed second (non-negative).
|
|
370
|
+
* @param refillPerSecond - Tokens added per elapsed second (non-negative; may be fractional).
|
|
371
|
+
* @param opts - Optional `clock` override for deterministic testing.
|
|
318
372
|
* @returns {@link TokenBucket} instance.
|
|
319
373
|
*
|
|
374
|
+
* @remarks
|
|
375
|
+
* **Float behavior:** the internal token counter is float-valued — fractional refill
|
|
376
|
+
* accumulates between `tryConsume` calls. See {@link TokenBucket.available} for caveats.
|
|
377
|
+
*
|
|
378
|
+
* **Clock injection:** pass `opts.clock` to drive refill scheduling deterministically
|
|
379
|
+
* in tests. The contract matches {@link circuitBreaker}'s `now` option: must return
|
|
380
|
+
* `monotonicNs()`-style nanoseconds, never `Date.now()` (wall-clock skew breaks
|
|
381
|
+
* elapsed math).
|
|
382
|
+
*
|
|
320
383
|
* @example
|
|
321
384
|
* ```ts
|
|
322
385
|
* import { tokenBucket } from "@graphrefly/graphrefly-ts";
|
|
323
386
|
*
|
|
324
387
|
* const bucket = tokenBucket(10, 2); // capacity 10, refill 2 tokens/sec
|
|
325
388
|
* bucket.tryConsume(3); // true — 7 tokens remaining
|
|
326
|
-
* bucket.available(); // ~7 (plus any elapsed refill)
|
|
389
|
+
* bucket.available(); // ~7 (plus any elapsed refill — float-valued)
|
|
390
|
+
*
|
|
391
|
+
* // Deterministic test:
|
|
392
|
+
* let t = 0;
|
|
393
|
+
* const tb = tokenBucket(5, 1, { clock: () => t });
|
|
394
|
+
* tb.tryConsume(5); // exhausts
|
|
395
|
+
* t = 1_000_000_000; // advance 1s → +1 refill
|
|
396
|
+
* tb.tryConsume(1); // true
|
|
327
397
|
* ```
|
|
328
398
|
*
|
|
329
399
|
* @category extra
|
|
330
400
|
*/
|
|
331
|
-
declare function tokenBucket(capacity: number, refillPerSecond: number): TokenBucket;
|
|
401
|
+
declare function tokenBucket(capacity: number, refillPerSecond: number, opts?: TokenBucketOptions): TokenBucket;
|
|
332
402
|
type RateLimiterOverflowPolicy = "drop-oldest" | "drop-newest" | "error";
|
|
333
403
|
type RateLimiterOptions = {
|
|
334
404
|
/** Maximum `DATA` emissions per window (must be > 0). */
|
|
335
405
|
maxEvents: number;
|
|
336
406
|
/** Window length in nanoseconds (must be > 0). */
|
|
337
407
|
windowNs: number;
|
|
338
|
-
/**
|
|
339
|
-
|
|
408
|
+
/**
|
|
409
|
+
* Cap on items queued while waiting for token refill.
|
|
410
|
+
*
|
|
411
|
+
* **Required.** Pass a finite positive integer (>= 1) for a bounded queue, OR
|
|
412
|
+
* the literal `Infinity` to opt in to an unbounded queue (caller acknowledges
|
|
413
|
+
* the unbounded-memory-growth risk on a high-rate source). Omitting this
|
|
414
|
+
* throws at construction time — the silent-unbounded-buffer footgun is the
|
|
415
|
+
* most common rateLimiter mis-configuration.
|
|
416
|
+
*/
|
|
417
|
+
maxBuffer: number;
|
|
340
418
|
/** Overflow policy when `maxBuffer` is exceeded. Default: `"drop-newest"`. */
|
|
341
419
|
onOverflow?: RateLimiterOverflowPolicy;
|
|
420
|
+
/**
|
|
421
|
+
* Caller-supplied metadata merged into the produced node's `meta` (Tier 5.2
|
|
422
|
+
* D8 widening). Use {@link domainMeta} to tag the layer for `describe()` /
|
|
423
|
+
* mermaid grouping (e.g. `domainMeta("resilient", "rate-limit")`). The
|
|
424
|
+
* primitive's own `factoryTag("rateLimiter", opts)` and the `droppedCount`
|
|
425
|
+
* / `rateLimitState` companion seeds always win against caller-supplied
|
|
426
|
+
* keys so the audit trail can't be silently overwritten.
|
|
427
|
+
*/
|
|
428
|
+
meta?: Record<string, unknown>;
|
|
342
429
|
};
|
|
343
430
|
/**
|
|
344
431
|
* Thrown by {@link rateLimiter} when `onOverflow: "error"` and the pending buffer is full.
|
|
@@ -349,19 +436,78 @@ declare class RateLimiterOverflowError extends Error {
|
|
|
349
436
|
name: string;
|
|
350
437
|
constructor(maxBuffer: number);
|
|
351
438
|
}
|
|
439
|
+
/**
|
|
440
|
+
* Combined runtime state surfaced by {@link rateLimiter} alongside `droppedCount`.
|
|
441
|
+
* Tier 5.2 D7 widening — exposes pending-buffer occupancy and a `paused`
|
|
442
|
+
* flag so consumers can render backpressure (UI), feed `lens.health`, or
|
|
443
|
+
* gate downstream effects.
|
|
444
|
+
*/
|
|
445
|
+
type RateLimiterState = {
|
|
446
|
+
/** Cumulative `DATA` items dropped due to overflow since this subscription cycle started. */
|
|
447
|
+
droppedCount: number;
|
|
448
|
+
/** Items currently buffered awaiting a token refill. `0` when the limiter is passing through. */
|
|
449
|
+
pendingCount: number;
|
|
450
|
+
/** `true` when at least one item is queued (the limiter is actively throttling). */
|
|
451
|
+
paused: boolean;
|
|
452
|
+
};
|
|
453
|
+
/** Bundle returned by {@link rateLimiter}. */
|
|
454
|
+
type RateLimiterBundle<T> = {
|
|
455
|
+
/** The throttled stream — at most `maxEvents` `DATA` per `windowNs`. */
|
|
456
|
+
node: Node<T>;
|
|
457
|
+
/**
|
|
458
|
+
* Reactive companion: count of `DATA` items dropped since the producer
|
|
459
|
+
* activated.
|
|
460
|
+
*
|
|
461
|
+
* - Increments on every drop under any overflow policy (`drop-newest`,
|
|
462
|
+
* `drop-oldest`). The `error` policy terminates the stream after a single
|
|
463
|
+
* overflow, so `droppedCount` increments at most once in that path.
|
|
464
|
+
* - **Lifecycle scoping (qa A1 + EC7):** the counter retains its final
|
|
465
|
+
* value through terminal (`COMPLETE` / `ERROR` / `TEARDOWN`) so consumers
|
|
466
|
+
* see the final drop count, not zero. The closure-held counter resets to
|
|
467
|
+
* `0` only when the producer fn re-runs — which only happens on a new
|
|
468
|
+
* subscription cycle, and only if the producer was constructed with
|
|
469
|
+
* `resubscribable: true`. The default `rateLimiter` producer is NOT
|
|
470
|
+
* resubscribable, so a single producer-fn run is the typical lifetime.
|
|
471
|
+
* - Producer-pattern note: this companion is invisible to `describe()`
|
|
472
|
+
* traversal from `node` (effect-mirror limitation; same shape as
|
|
473
|
+
* `withBreaker.breakerState` and `withStatus.status`). Surface it via
|
|
474
|
+
* `node.meta.droppedCount` if you need it in topology snapshots.
|
|
475
|
+
*/
|
|
476
|
+
droppedCount: Node<number>;
|
|
477
|
+
/**
|
|
478
|
+
* Reactive companion: combined `{droppedCount, pendingCount, paused}` view.
|
|
479
|
+
*
|
|
480
|
+
* - `pendingCount` reflects the live buffer occupancy and updates on every
|
|
481
|
+
* push / shift / overflow drop; `paused` is shorthand for
|
|
482
|
+
* `pendingCount > 0`.
|
|
483
|
+
* - Equality-deduped — re-emits only when one of the three fields actually
|
|
484
|
+
* changes (so a busy steady-state where every DATA passes immediately
|
|
485
|
+
* produces one `paused: false` emission, not one per DATA).
|
|
486
|
+
* - **Lifecycle scoping (qa EC7):** same contract as `droppedCount` —
|
|
487
|
+
* retains its final value through terminal; resets to the initial
|
|
488
|
+
* `{droppedCount: 0, pendingCount: 0, paused: false}` only on a new
|
|
489
|
+
* producer-fn run (resubscribable upstream required).
|
|
490
|
+
* - Same producer-pattern caveat as `droppedCount` re: `describe()` visibility.
|
|
491
|
+
*/
|
|
492
|
+
rateLimitState: Node<RateLimiterState>;
|
|
493
|
+
};
|
|
352
494
|
/**
|
|
353
495
|
* Token-bucket rate limiter: at most `maxEvents` `DATA` values per `windowNs`.
|
|
354
496
|
*
|
|
355
497
|
* Uses {@link tokenBucket} internally (capacity = `maxEvents`, refill = `maxEvents / windowSeconds`).
|
|
356
|
-
* Excess items are queued FIFO
|
|
357
|
-
*
|
|
498
|
+
* Excess items are queued FIFO (in a fixed-capacity {@link RingBuffer} for O(1) push/shift)
|
|
499
|
+
* until a token is available. The queue is bounded by the **required** `maxBuffer` option
|
|
500
|
+
* with a configurable overflow policy.
|
|
358
501
|
*
|
|
359
502
|
* @param source - Upstream node.
|
|
360
|
-
* @param opts - Rate +
|
|
361
|
-
* @returns
|
|
503
|
+
* @param opts - Rate + bounded-buffer configuration. `maxBuffer` is required (use `Infinity` to opt in to unbounded).
|
|
504
|
+
* @returns `{ node, droppedCount }` bundle. Subscribe to `node` for the throttled stream and to `droppedCount` for backpressure pressure.
|
|
505
|
+
*
|
|
506
|
+
* @throws {RangeError} when `maxEvents` / `windowNs` is non-positive, when `maxBuffer` is omitted, or when `maxBuffer` is a finite value < 1.
|
|
362
507
|
*
|
|
363
508
|
* @remarks
|
|
364
|
-
* **Terminal:** `COMPLETE` / `ERROR` cancel the refill timer, drop the pending queue,
|
|
509
|
+
* **Terminal:** `COMPLETE` / `ERROR` cancel the refill timer, drop the pending queue,
|
|
510
|
+
* reset `droppedCount` to `0`, and propagate.
|
|
365
511
|
*
|
|
366
512
|
* @example
|
|
367
513
|
* ```ts
|
|
@@ -369,13 +515,18 @@ declare class RateLimiterOverflowError extends Error {
|
|
|
369
515
|
*
|
|
370
516
|
* const src = state(0);
|
|
371
517
|
* // Allow at most 5 DATA values per second; queue up to 100 excess items, drop newest beyond.
|
|
372
|
-
* const limited = rateLimiter(src, {
|
|
518
|
+
* const { node: limited, droppedCount } = rateLimiter(src, {
|
|
519
|
+
* maxEvents: 5,
|
|
520
|
+
* windowNs: NS_PER_SEC,
|
|
521
|
+
* maxBuffer: 100,
|
|
522
|
+
* });
|
|
523
|
+
* droppedCount.subscribe(([m]) => console.log("dropped so far:", m[1]));
|
|
373
524
|
* ```
|
|
374
525
|
*
|
|
375
526
|
* @category extra
|
|
376
527
|
*/
|
|
377
|
-
declare function rateLimiter<T>(source: Node<T>, opts: RateLimiterOptions):
|
|
378
|
-
type StatusValue = "pending" | "
|
|
528
|
+
declare function rateLimiter<T>(source: Node<T>, opts: RateLimiterOptions): RateLimiterBundle<T>;
|
|
529
|
+
type StatusValue = "pending" | "running" | "completed" | "errored";
|
|
379
530
|
type WithStatusBundle<T> = {
|
|
380
531
|
node: Node<T>;
|
|
381
532
|
status: Node<StatusValue>;
|
|
@@ -386,10 +537,25 @@ type WithStatusBundle<T> = {
|
|
|
386
537
|
*
|
|
387
538
|
* @param src - Upstream node to mirror.
|
|
388
539
|
* @param options - `initialStatus` defaults to `"pending"`.
|
|
389
|
-
* @returns `{ node, status, error }` where `
|
|
540
|
+
* @returns `{ node, status, error }` where `out` is the mirrored stream, `status` is a
|
|
541
|
+
* reactive `Node<StatusValue>` (`"pending" | "running" | "completed" | "errored"`),
|
|
542
|
+
* and `error` holds the last `ERROR` payload (cleared to `null` on the next `DATA`
|
|
543
|
+
* after `errored`).
|
|
390
544
|
*
|
|
391
545
|
* @remarks
|
|
392
|
-
* **
|
|
546
|
+
* **Lifecycle:** `pending` (no DATA yet) → `running` (on first DATA) → `completed`
|
|
547
|
+
* (on COMPLETE) or `errored` (on ERROR). After `errored`, the next `DATA` clears
|
|
548
|
+
* `error` and re-enters `running` inside a {@link batch} so subscribers see one
|
|
549
|
+
* consistent transition (matches graphrefly-py).
|
|
550
|
+
*
|
|
551
|
+
* **Producer-pattern visibility:** `out` is built via `node([], fn, …)`, so `src`
|
|
552
|
+
* appears as the source dependency in `describe()` traversal but the `status` /
|
|
553
|
+
* `error` companions are mirrored via subscribe-callback effects — they appear
|
|
554
|
+
* under `out.meta.status` / `out.meta.error` (and as `<name>::__meta__::status`
|
|
555
|
+
* paths in `describe()`) rather than as separate top-level edges. Subscribers
|
|
556
|
+
* to `out` see the throttled DATA stream; `status` / `error` companions may not
|
|
557
|
+
* appear as edges in `describe()` if no consumer subscribes to them (per
|
|
558
|
+
* COMPOSITION-GUIDE §1, push-on-subscribe semantics).
|
|
393
559
|
*
|
|
394
560
|
* @example
|
|
395
561
|
* ```ts
|
|
@@ -399,13 +565,14 @@ type WithStatusBundle<T> = {
|
|
|
399
565
|
* const { node, status, error } = withStatus(src);
|
|
400
566
|
*
|
|
401
567
|
* status.subscribe((msgs) => console.log("status:", msgs));
|
|
402
|
-
* src.down([[DATA, 42]]); // status → "
|
|
568
|
+
* src.down([[DATA, 42]]); // status → "running"
|
|
403
569
|
* ```
|
|
404
570
|
*
|
|
405
571
|
* @category extra
|
|
406
572
|
*/
|
|
407
573
|
declare function withStatus<T>(src: Node<T>, options?: {
|
|
408
574
|
initialStatus?: StatusValue;
|
|
575
|
+
meta?: Record<string, unknown>;
|
|
409
576
|
}): WithStatusBundle<T>;
|
|
410
577
|
/**
|
|
411
578
|
* Thrown by {@link timeout} when no `DATA` arrives within the deadline.
|
|
@@ -449,7 +616,9 @@ type FallbackInput<T> = T | Node<T> | PromiseLike<T> | AsyncIterable<T>;
|
|
|
449
616
|
*
|
|
450
617
|
* @category extra
|
|
451
618
|
*/
|
|
452
|
-
declare function fallback<T>(source: Node<T>, fb: FallbackInput<T
|
|
619
|
+
declare function fallback<T>(source: Node<T>, fb: FallbackInput<T>, options?: {
|
|
620
|
+
meta?: Record<string, unknown>;
|
|
621
|
+
}): Node<T>;
|
|
453
622
|
/**
|
|
454
623
|
* Emits `ERROR` with {@link TimeoutError} if no `DATA` arrives within the deadline.
|
|
455
624
|
*
|
|
@@ -457,9 +626,14 @@ declare function fallback<T>(source: Node<T>, fb: FallbackInput<T>): Node<T>;
|
|
|
457
626
|
* the timer. Terminal messages (`COMPLETE`/`ERROR`) cancel the timer.
|
|
458
627
|
*
|
|
459
628
|
* @param source - Upstream node.
|
|
460
|
-
* @param timeoutNs - Deadline in nanoseconds.
|
|
629
|
+
* @param timeoutNs - Deadline in **nanoseconds** (must be > 0). Internally converted to milliseconds for `setTimeout` scheduling.
|
|
461
630
|
* @returns Node that errors on timeout.
|
|
462
631
|
*
|
|
632
|
+
* @throws {RangeError} when `timeoutNs <= 0`.
|
|
633
|
+
*
|
|
634
|
+
* @remarks
|
|
635
|
+
* **Scheduling:** internally uses {@link ResettableTimer} (raw `setTimeout`) per spec §5.10's resilience-operator carve-out. The deadline is `timeoutNs / NS_PER_MS` ms; sub-millisecond `timeoutNs` values get the same minimum-1ms host-scheduler granularity that `setTimeout` provides.
|
|
636
|
+
*
|
|
463
637
|
* @example
|
|
464
638
|
* ```ts
|
|
465
639
|
* import { timeout, never, NS_PER_SEC } from "@graphrefly/graphrefly-ts";
|
|
@@ -470,6 +644,8 @@ declare function fallback<T>(source: Node<T>, fb: FallbackInput<T>): Node<T>;
|
|
|
470
644
|
*
|
|
471
645
|
* @category extra
|
|
472
646
|
*/
|
|
473
|
-
declare function timeout<T>(source: Node<T>, timeoutNs: number
|
|
647
|
+
declare function timeout<T>(source: Node<T>, timeoutNs: number, options?: {
|
|
648
|
+
meta?: Record<string, unknown>;
|
|
649
|
+
}): Node<T>;
|
|
474
650
|
|
|
475
|
-
export { type BackoffPreset as B, type CircuitState as C, type ExponentialBackoffOptions as E, type FallbackInput as F, type JitterMode as J, NS_PER_MS as N, type
|
|
651
|
+
export { type BackoffPreset as B, type CircuitState as C, type ExponentialBackoffOptions as E, type FallbackInput as F, type JitterMode as J, NS_PER_MS as N, type RateLimiterState as R, type StatusValue as S, TimeoutError as T, type WithBreakerBundle as W, type RateLimiterOptions as a, type CircuitBreakerOptions as b, type RetryOptions as c, NS_PER_SEC as d, type BackoffStrategy as e, type CircuitBreaker as f, CircuitOpenError as g, RateLimiterOverflowError as h, type RateLimiterOverflowPolicy as i, type TokenBucket as j, type WithStatusBundle as k, circuitBreaker as l, constant as m, decorrelatedJitter as n, exponential as o, fallback as p, fibonacci as q, linear as r, rateLimiter as s, resolveBackoffPreset as t, retry as u, timeout as v, tokenBucket as w, withBreaker as x, withMaxAttempts as y, withStatus as z };
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { b as NodeGuard, N as Node } from './node-BYInONRr.js';
|
|
2
|
+
import { G as Graph } from './graph-BkIkog4h.js';
|
|
3
|
+
import { R as ReactiveLogOptions, a as ReactiveLogBundle } from './reactive-log-BlAsPLl2.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Audited-mutation framework (Audit 2 — locked 2026-04-24; promoted to
|
|
7
|
+
* `extra/mutation/` per consolidation plan §1, Tier 2.2).
|
|
8
|
+
*
|
|
9
|
+
* Phase-4 primitives share the same shape: imperative mutation methods +
|
|
10
|
+
* closure state + reactive audit log + freeze-at-entry + rollback-on-throw.
|
|
11
|
+
* This module factors out the common machinery so each primitive becomes
|
|
12
|
+
* declarative wiring over typed audit records:
|
|
13
|
+
* - `approvalGate`, `pipeline.approvalGate` (Wave A.2 Unit 8)
|
|
14
|
+
* - `JobQueueGraph` (Wave B.3 Unit 15)
|
|
15
|
+
* - `CqrsGraph.dispatch` (Wave C.2 Unit 20)
|
|
16
|
+
* - `CqrsGraph.saga` (Wave C.3 Unit 22)
|
|
17
|
+
* - `processManager` (Wave 7)
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Bounded increment for a self-owned counter state node.
|
|
22
|
+
*
|
|
23
|
+
* Reads `counter.cache`, bumps by 1 if under `cap`, writes back. Returns
|
|
24
|
+
* `false` when the cap is reached. Documented P3 exception: the counter is
|
|
25
|
+
* not a declared dep of the caller — it's a private budget read+written from
|
|
26
|
+
* a single call site. This helper keeps the `.cache` access in one named
|
|
27
|
+
* place.
|
|
28
|
+
*
|
|
29
|
+
* **Safety today:**
|
|
30
|
+
* 1. Single-threaded JS runner never invokes the caller concurrently.
|
|
31
|
+
* 2. `counter.down` writes the cache synchronously before returning, so
|
|
32
|
+
* synchronous re-entry through a downstream publish reads the
|
|
33
|
+
* freshly-incremented value — no double-count.
|
|
34
|
+
*
|
|
35
|
+
* **Future risk:** under a free-threaded runner (PY no-GIL or hypothetical
|
|
36
|
+
* concurrent TS runner), two concurrent firings could still race. Revisit
|
|
37
|
+
* when that surfaces.
|
|
38
|
+
*/
|
|
39
|
+
declare function tryIncrementBounded(counter: Node<number>, cap: number): boolean;
|
|
40
|
+
/** Shared base shape for every audit record. Per-primitive types extend this. */
|
|
41
|
+
interface BaseAuditRecord {
|
|
42
|
+
readonly t_ns: number;
|
|
43
|
+
readonly seq?: number;
|
|
44
|
+
readonly handlerVersion?: {
|
|
45
|
+
id: string;
|
|
46
|
+
version: string | number;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Allow `observe` and `signal`; deny external `write` on the audit log so
|
|
51
|
+
* consumers can subscribe + signal-bridge but cannot inject fake records.
|
|
52
|
+
*/
|
|
53
|
+
declare const DEFAULT_AUDIT_GUARD: NodeGuard;
|
|
54
|
+
type AuditLogOpts<R extends BaseAuditRecord> = {
|
|
55
|
+
name: string;
|
|
56
|
+
/** Bounded retention; default 1024 per Audit 2 / cross-cutting bounded-default policy. */
|
|
57
|
+
retainedLimit?: number;
|
|
58
|
+
/** Override the default audit guard. */
|
|
59
|
+
guard?: NodeGuard;
|
|
60
|
+
/** Mount the audit `entries` Node under this graph (and activate withLatest). */
|
|
61
|
+
graph?: Graph;
|
|
62
|
+
/** Pass-through to {@link reactiveLog}. */
|
|
63
|
+
versioning?: ReactiveLogOptions<R>["versioning"];
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Build a reactive audit log with sane defaults: bounded retention, deny-write
|
|
67
|
+
* guard, `withLatest()` companions activated. Returns the {@link ReactiveLogBundle}
|
|
68
|
+
* directly — primitives expose this as `<primitive>.events` / `.decisions` /
|
|
69
|
+
* `.dispatches` / `.invocations` and alias it as `.audit`.
|
|
70
|
+
*
|
|
71
|
+
* @category internal
|
|
72
|
+
*/
|
|
73
|
+
declare function createAuditLog<R extends BaseAuditRecord>(opts: AuditLogOpts<R>): ReactiveLogBundle<R>;
|
|
74
|
+
type FailureMeta = {
|
|
75
|
+
t_ns: number;
|
|
76
|
+
seq?: number;
|
|
77
|
+
errorType: string;
|
|
78
|
+
};
|
|
79
|
+
type SuccessMeta = {
|
|
80
|
+
t_ns: number;
|
|
81
|
+
seq?: number;
|
|
82
|
+
};
|
|
83
|
+
/** Common opts shared by both tiers. */
|
|
84
|
+
type MutationOpts<TArgs extends readonly unknown[], R extends BaseAuditRecord> = {
|
|
85
|
+
/** Where to emit the audit record on success / failure. */
|
|
86
|
+
audit: ReactiveLogBundle<R>;
|
|
87
|
+
/** Build the success record from the action's args + result + meta. */
|
|
88
|
+
onSuccess?: (args: TArgs, result: unknown, meta: SuccessMeta) => R | undefined;
|
|
89
|
+
/** Build the failure record from the args + error + meta. */
|
|
90
|
+
onFailure?: (args: TArgs, error: unknown, meta: FailureMeta) => R | undefined;
|
|
91
|
+
/** Freeze inputs at entry (default `true`). Pass `false` for hot paths. */
|
|
92
|
+
freeze?: boolean;
|
|
93
|
+
/** Optional sequence cursor — auto-advanced and stamped onto records. */
|
|
94
|
+
seq?: Node<number>;
|
|
95
|
+
/** Optional handler version — stamped into the record (Audit 5). */
|
|
96
|
+
handlerVersion?: {
|
|
97
|
+
id: string;
|
|
98
|
+
version: string | number;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
type WrapMutationOpts<TArgs extends readonly unknown[], R extends BaseAuditRecord> = MutationOpts<TArgs, R>;
|
|
102
|
+
type LightMutationOpts<TArgs extends readonly unknown[], R extends BaseAuditRecord> = MutationOpts<TArgs, R>;
|
|
103
|
+
/**
|
|
104
|
+
* Advance a cursor node and return the new value. Emits `[DIRTY], [DATA, next]`
|
|
105
|
+
* directly on the cursor — atomic outside a batch, rollback-discardable inside.
|
|
106
|
+
*
|
|
107
|
+
* Resets to `0` if the cursor cache is missing, non-numeric, `NaN`, or
|
|
108
|
+
* non-finite (e.g. corrupted by `restore()` from a malformed snapshot, or
|
|
109
|
+
* by a misbehaving codec). `??` alone would let `NaN` and `""` pass through
|
|
110
|
+
* and silently corrupt audit ordering downstream.
|
|
111
|
+
*
|
|
112
|
+
* Works whether or not the cursor has any subscribers — `down` updates the
|
|
113
|
+
* cache regardless, so primitives that bump before consumers attach (e.g.
|
|
114
|
+
* `JobQueueGraph.enqueue`) still see a coherent sequence.
|
|
115
|
+
*
|
|
116
|
+
* @category internal
|
|
117
|
+
*/
|
|
118
|
+
declare function bumpCursor(seq: Node<number>): number;
|
|
119
|
+
/**
|
|
120
|
+
* Build a record via the supplied builder, stamp `handlerVersion` if present,
|
|
121
|
+
* and append it to the audit log. `undefined` records are skipped (callers
|
|
122
|
+
* pass an `onSuccess` / `onFailure` that returns `undefined` to opt out per
|
|
123
|
+
* call).
|
|
124
|
+
*
|
|
125
|
+
* @category internal
|
|
126
|
+
*/
|
|
127
|
+
declare function appendAudit<TArgs extends readonly unknown[], TValue, R extends BaseAuditRecord, M extends SuccessMeta | FailureMeta>(audit: ReactiveLogBundle<R>, builder: (args: TArgs, value: TValue, meta: M) => R | undefined, args: TArgs, value: TValue, meta: M, handlerVersion?: {
|
|
128
|
+
id: string;
|
|
129
|
+
version: string | number;
|
|
130
|
+
}): void;
|
|
131
|
+
/**
|
|
132
|
+
* Substrate-tier wrapper: run `action`, append a typed audit record on
|
|
133
|
+
* success or failure, advance an optional `seq` cursor. No batch frame — this
|
|
134
|
+
* is the hot-path-friendly variant for atomic single-write mutations.
|
|
135
|
+
*
|
|
136
|
+
* Behavior contract:
|
|
137
|
+
* 1. Freeze args at entry (default `true`; opt out with `freeze: false` for
|
|
138
|
+
* hot paths — e.g. wrapping `vectorIndex.upsert(id, vector[768], meta)`
|
|
139
|
+
* where the deep-freeze of a 768-dim vector is a measurable tax).
|
|
140
|
+
* 2. Bump `seq` (if provided) BEFORE the action runs. There is no batch frame,
|
|
141
|
+
* so the bump persists even on throw — the failure-audit record stamps the
|
|
142
|
+
* same `seq` so audit consumers see a contiguous sequence.
|
|
143
|
+
* 3. Run `action(args)`. On success, `appendAudit(onSuccess, ...)`.
|
|
144
|
+
* 4. On throw, `appendAudit(onFailure, ...)` then re-throw so callers see the
|
|
145
|
+
* failure.
|
|
146
|
+
*
|
|
147
|
+
* **Distinguish from {@link wrapMutation}:** `wrapMutation` opens a `batch()`
|
|
148
|
+
* frame (rollback-on-throw, seq advance discarded on rollback) and is the
|
|
149
|
+
* right choice when the action runs a user-supplied handler or a multi-step
|
|
150
|
+
* sequence that could leave inconsistent state mid-throw.
|
|
151
|
+
*
|
|
152
|
+
* **Cursor / log alignment caveat (substrate-tier):** `seq` is bumped BEFORE
|
|
153
|
+
* `action()` runs, and the audit-log append happens AFTER. There is no batch
|
|
154
|
+
* frame, so a synchronous subscriber to `seq` that fires between the two —
|
|
155
|
+
* including a subscriber on `audit.entries` itself if the substrate causes
|
|
156
|
+
* it to fire transitively — observes `seq=N` while the corresponding record
|
|
157
|
+
* is not yet in the log. Audit consumers that join `seq` and `audit.entries`
|
|
158
|
+
* reactively must tolerate this one-tick lag, or use {@link wrapMutation}
|
|
159
|
+
* (whose `batch()` frame defers downstream delivery until commit, so cursor
|
|
160
|
+
* and log appear together to subscribers). The same caveat applies to
|
|
161
|
+
* **re-entrant** invocation: if an `audit.entries` / `seq` subscriber
|
|
162
|
+
* triggers another `lightMutation`, the inner record can land on the log
|
|
163
|
+
* before the outer call's success/failure record.
|
|
164
|
+
*
|
|
165
|
+
* @category internal
|
|
166
|
+
*/
|
|
167
|
+
declare function lightMutation<TArgs extends readonly unknown[], TResult, R extends BaseAuditRecord>(action: (...args: TArgs) => TResult, opts: LightMutationOpts<TArgs, R>): (...args: TArgs) => TResult;
|
|
168
|
+
/**
|
|
169
|
+
* Orchestration-tier wrapper: like {@link lightMutation} but adds a `batch()`
|
|
170
|
+
* frame around the action so an in-flight throw rolls back partial state.
|
|
171
|
+
*
|
|
172
|
+
* Behavior contract:
|
|
173
|
+
* 1. Freeze args at entry (default `true`).
|
|
174
|
+
* 2. Open a batch frame (rollback-on-throw via core batch — Audit 2 #6).
|
|
175
|
+
* 3. Bump `seq` INSIDE the batch so a framework-level rollback discards the
|
|
176
|
+
* cursor advance (cursor stays in sync with audit log). M5.
|
|
177
|
+
* 4. Run `action(args)` and capture result.
|
|
178
|
+
* 5. On success: `appendAudit(onSuccess, ...)` inside the batch.
|
|
179
|
+
* 6. On throw: catch OUTSIDE the batch so the failure record emits in a
|
|
180
|
+
* fresh transaction after rollback — it persists. Re-throw so callers see
|
|
181
|
+
* the failure.
|
|
182
|
+
*
|
|
183
|
+
* **Distinguish from the file-private `wrapMutation` in
|
|
184
|
+
* `src/extra/reactive-map.ts:540`:** that helper is a transactional wrapper
|
|
185
|
+
* for the reactiveMap version counter (`pre/post-version` snapshot diffing,
|
|
186
|
+
* read vs. mutation gating). Different concern, file-private, not exported.
|
|
187
|
+
* This `wrapMutation` is the public Phase-4 audit framework.
|
|
188
|
+
*
|
|
189
|
+
* @category internal
|
|
190
|
+
*/
|
|
191
|
+
declare function wrapMutation<TArgs extends readonly unknown[], TResult, R extends BaseAuditRecord>(action: (...args: TArgs) => TResult, opts: WrapMutationOpts<TArgs, R>): (...args: TArgs) => TResult;
|
|
192
|
+
/**
|
|
193
|
+
* Promote a closure counter to a state node mounted under `graph`.
|
|
194
|
+
* Replaces ad-hoc `let _seq = 0` patterns with a node observable in
|
|
195
|
+
* `describe()` and persistable via storage tiers.
|
|
196
|
+
*
|
|
197
|
+
* @category internal
|
|
198
|
+
*/
|
|
199
|
+
declare function registerCursor(graph: Graph, name: string, initial?: number): Node<number>;
|
|
200
|
+
/**
|
|
201
|
+
* Promote a closure `Map<K, number>` to N state nodes (one per key) mounted
|
|
202
|
+
* under `<graph>::<name>::<key>`. Used by saga (per-event-type cursor).
|
|
203
|
+
*
|
|
204
|
+
* @category internal
|
|
205
|
+
*/
|
|
206
|
+
declare function registerCursorMap<K extends string>(graph: Graph, name: string, keys: readonly K[], initial?: number): {
|
|
207
|
+
readonly [P in K]: Node<number>;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export { type AuditLogOpts as A, type BaseAuditRecord as B, DEFAULT_AUDIT_GUARD as D, type FailureMeta as F, type LightMutationOpts as L, type MutationOpts as M, type SuccessMeta as S, type WrapMutationOpts as W, appendAudit as a, bumpCursor as b, createAuditLog as c, registerCursorMap as d, lightMutation as l, registerCursor as r, tryIncrementBounded as t, wrapMutation as w };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { N as Node } from './node-BYInONRr.cjs';
|
|
2
|
+
import { B as BaseAuditRecord } from './index-DVDapw2k.cjs';
|
|
3
|
+
import { a as ReactiveLogBundle } from './reactive-log-_zeEnB9H.cjs';
|
|
3
4
|
import { NodeInput } from './extra/sources.cjs';
|
|
4
5
|
import { AppendLogStorageTier } from './extra/storage-tiers.cjs';
|
|
5
|
-
import { G as Graph, a as GraphOptions } from './graph-
|
|
6
|
-
import { B as BaseAuditRecord } from './imperative-audit-ahAE65a9.cjs';
|
|
6
|
+
import { G as Graph, a as GraphOptions } from './graph-E6likq7w.cjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Job queue patterns (roadmap §4.2).
|