@graphrefly/graphrefly 0.45.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/_internal-B23BagFd.d.cts +33 -0
- package/dist/_internal-B23BagFd.d.ts +33 -0
- package/dist/adaptive-rate-limiter-Dch_xYIi.d.cts +111 -0
- package/dist/adaptive-rate-limiter-Dch_xYIi.d.ts +111 -0
- package/dist/agents-C0Ji9ldU.d.cts +629 -0
- package/dist/agents-C9zexT7I.d.ts +629 -0
- package/dist/audit-BAXb3VOg.d.ts +246 -0
- package/dist/audit-C_bPfkqS.d.cts +246 -0
- package/dist/backoff-7KIK3WQW.js +24 -0
- package/dist/backoff-7KIK3WQW.js.map +1 -0
- package/dist/backoff-Bnb9OoPh.d.cts +6 -0
- package/dist/backoff-Bnb9OoPh.d.ts +6 -0
- package/dist/base/composition/index.cjs +811 -0
- package/dist/base/composition/index.cjs.map +1 -0
- package/dist/base/composition/index.d.cts +469 -0
- package/dist/base/composition/index.d.ts +469 -0
- package/dist/base/composition/index.js +40 -0
- package/dist/base/composition/index.js.map +1 -0
- package/dist/base/index.cjs +6336 -0
- package/dist/base/index.cjs.map +1 -0
- package/dist/base/index.d.cts +22 -0
- package/dist/base/index.d.ts +22 -0
- package/dist/base/index.js +259 -0
- package/dist/base/index.js.map +1 -0
- package/dist/base/io/index.cjs +3270 -0
- package/dist/base/io/index.cjs.map +1 -0
- package/dist/base/io/index.d.cts +2245 -0
- package/dist/base/io/index.d.ts +2245 -0
- package/dist/base/io/index.js +117 -0
- package/dist/base/io/index.js.map +1 -0
- package/dist/base/meta/index.cjs +43 -0
- package/dist/base/meta/index.cjs.map +1 -0
- package/dist/base/meta/index.d.cts +45 -0
- package/dist/base/meta/index.d.ts +45 -0
- package/dist/base/meta/index.js +13 -0
- package/dist/base/meta/index.js.map +1 -0
- package/dist/base/mutation/index.cjs +200 -0
- package/dist/base/mutation/index.cjs.map +1 -0
- package/dist/base/mutation/index.d.cts +177 -0
- package/dist/base/mutation/index.d.ts +177 -0
- package/dist/base/mutation/index.js +22 -0
- package/dist/base/mutation/index.js.map +1 -0
- package/dist/base/render/index.cjs +1120 -0
- package/dist/base/render/index.cjs.map +1 -0
- package/dist/base/render/index.d.cts +227 -0
- package/dist/base/render/index.d.ts +227 -0
- package/dist/base/render/index.js +24 -0
- package/dist/base/render/index.js.map +1 -0
- package/dist/base/sources/browser/index.cjs +172 -0
- package/dist/base/sources/browser/index.cjs.map +1 -0
- package/dist/base/sources/browser/index.d.cts +84 -0
- package/dist/base/sources/browser/index.d.ts +84 -0
- package/dist/base/sources/browser/index.js +151 -0
- package/dist/base/sources/browser/index.js.map +1 -0
- package/dist/base/sources/event/index.cjs +98 -0
- package/dist/base/sources/event/index.cjs.map +1 -0
- package/dist/base/sources/event/index.d.cts +91 -0
- package/dist/base/sources/event/index.d.ts +91 -0
- package/dist/base/sources/event/index.js +13 -0
- package/dist/base/sources/event/index.js.map +1 -0
- package/dist/base/sources/index.cjs +755 -0
- package/dist/base/sources/index.cjs.map +1 -0
- package/dist/base/sources/index.d.cts +357 -0
- package/dist/base/sources/index.d.ts +357 -0
- package/dist/base/sources/index.js +42 -0
- package/dist/base/sources/index.js.map +1 -0
- package/dist/base/sources/node/index.cjs +320 -0
- package/dist/base/sources/node/index.cjs.map +1 -0
- package/dist/base/sources/node/index.d.cts +185 -0
- package/dist/base/sources/node/index.d.ts +185 -0
- package/dist/base/sources/node/index.js +306 -0
- package/dist/base/sources/node/index.js.map +1 -0
- package/dist/base/utils/index.cjs +37 -0
- package/dist/base/utils/index.cjs.map +1 -0
- package/dist/base/utils/index.d.cts +37 -0
- package/dist/base/utils/index.d.ts +37 -0
- package/dist/base/utils/index.js +11 -0
- package/dist/base/utils/index.js.map +1 -0
- package/dist/base/worker/index.cjs +548 -0
- package/dist/base/worker/index.cjs.map +1 -0
- package/dist/base/worker/index.d.cts +207 -0
- package/dist/base/worker/index.d.ts +207 -0
- package/dist/base/worker/index.js +20 -0
- package/dist/base/worker/index.js.map +1 -0
- package/dist/breaker-C9skL3d8.d.ts +175 -0
- package/dist/breaker-ugSdq54q.d.cts +175 -0
- package/dist/cascading-CSSbKGrJ.d.ts +199 -0
- package/dist/cascading-baGkiihI.d.cts +199 -0
- package/dist/chunk-255UCBG4.js +58 -0
- package/dist/chunk-255UCBG4.js.map +1 -0
- package/dist/chunk-2LO3EL4W.js +1 -0
- package/dist/chunk-2LO3EL4W.js.map +1 -0
- package/dist/chunk-2OB3CEJS.js +1065 -0
- package/dist/chunk-2OB3CEJS.js.map +1 -0
- package/dist/chunk-36NMM65U.js +144 -0
- package/dist/chunk-36NMM65U.js.map +1 -0
- package/dist/chunk-3CEXCBN6.js +1 -0
- package/dist/chunk-3CEXCBN6.js.map +1 -0
- package/dist/chunk-3MUSLI6E.js +105 -0
- package/dist/chunk-3MUSLI6E.js.map +1 -0
- package/dist/chunk-3PSLNJDU.js +884 -0
- package/dist/chunk-3PSLNJDU.js.map +1 -0
- package/dist/chunk-3QZY5BI7.js +92 -0
- package/dist/chunk-3QZY5BI7.js.map +1 -0
- package/dist/chunk-42FQ27MQ.js +594 -0
- package/dist/chunk-42FQ27MQ.js.map +1 -0
- package/dist/chunk-4GYMCUDZ.js +1085 -0
- package/dist/chunk-4GYMCUDZ.js.map +1 -0
- package/dist/chunk-4S53H2KR.js +382 -0
- package/dist/chunk-4S53H2KR.js.map +1 -0
- package/dist/chunk-4XCHZRUJ.js +128 -0
- package/dist/chunk-4XCHZRUJ.js.map +1 -0
- package/dist/chunk-5THCXDWY.js +725 -0
- package/dist/chunk-5THCXDWY.js.map +1 -0
- package/dist/chunk-6XZYT4SW.js +256 -0
- package/dist/chunk-6XZYT4SW.js.map +1 -0
- package/dist/chunk-7EGRP2VX.js +76 -0
- package/dist/chunk-7EGRP2VX.js.map +1 -0
- package/dist/chunk-A7KV5UK4.js +150 -0
- package/dist/chunk-A7KV5UK4.js.map +1 -0
- package/dist/chunk-APY2SS5X.js +156 -0
- package/dist/chunk-APY2SS5X.js.map +1 -0
- package/dist/chunk-AZDQPQ3V.js +66 -0
- package/dist/chunk-AZDQPQ3V.js.map +1 -0
- package/dist/chunk-BU3SEFA5.js +90 -0
- package/dist/chunk-BU3SEFA5.js.map +1 -0
- package/dist/chunk-BXGZFGZ4.js +189 -0
- package/dist/chunk-BXGZFGZ4.js.map +1 -0
- package/dist/chunk-CGHORL6G.js +579 -0
- package/dist/chunk-CGHORL6G.js.map +1 -0
- package/dist/chunk-CXANAIZU.js +530 -0
- package/dist/chunk-CXANAIZU.js.map +1 -0
- package/dist/chunk-CZQHCKKG.js +1 -0
- package/dist/chunk-CZQHCKKG.js.map +1 -0
- package/dist/chunk-DKNHAICT.js +133 -0
- package/dist/chunk-DKNHAICT.js.map +1 -0
- package/dist/chunk-DM4OMPWK.js +584 -0
- package/dist/chunk-DM4OMPWK.js.map +1 -0
- package/dist/chunk-DMSNO6ZB.js +452 -0
- package/dist/chunk-DMSNO6ZB.js.map +1 -0
- package/dist/chunk-E5OZPDIW.js +229 -0
- package/dist/chunk-E5OZPDIW.js.map +1 -0
- package/dist/chunk-EVYY4X5A.js +509 -0
- package/dist/chunk-EVYY4X5A.js.map +1 -0
- package/dist/chunk-FDFD67UO.js +1 -0
- package/dist/chunk-FDFD67UO.js.map +1 -0
- package/dist/chunk-FMPF42Q4.js +13 -0
- package/dist/chunk-FMPF42Q4.js.map +1 -0
- package/dist/chunk-FR6RGA3B.js +1277 -0
- package/dist/chunk-FR6RGA3B.js.map +1 -0
- package/dist/chunk-FW23JYNQ.js +454 -0
- package/dist/chunk-FW23JYNQ.js.map +1 -0
- package/dist/chunk-GBCENOLN.js +1575 -0
- package/dist/chunk-GBCENOLN.js.map +1 -0
- package/dist/chunk-HL7HUJIX.js +1 -0
- package/dist/chunk-HL7HUJIX.js.map +1 -0
- package/dist/chunk-HULCUY35.js +2508 -0
- package/dist/chunk-HULCUY35.js.map +1 -0
- package/dist/chunk-IHTWQEDR.js +169 -0
- package/dist/chunk-IHTWQEDR.js.map +1 -0
- package/dist/chunk-IJRR6YAI.js +128 -0
- package/dist/chunk-IJRR6YAI.js.map +1 -0
- package/dist/chunk-JGFRAFDL.js +221 -0
- package/dist/chunk-JGFRAFDL.js.map +1 -0
- package/dist/chunk-KIIXR252.js +211 -0
- package/dist/chunk-KIIXR252.js.map +1 -0
- package/dist/chunk-KN3H5CNT.js +11 -0
- package/dist/chunk-KN3H5CNT.js.map +1 -0
- package/dist/chunk-KPG3DGLA.js +1 -0
- package/dist/chunk-KPG3DGLA.js.map +1 -0
- package/dist/chunk-KRNQ6RGQ.js +1 -0
- package/dist/chunk-KRNQ6RGQ.js.map +1 -0
- package/dist/chunk-LBAJK24K.js +1071 -0
- package/dist/chunk-LBAJK24K.js.map +1 -0
- package/dist/chunk-MLTPJMH6.js +417 -0
- package/dist/chunk-MLTPJMH6.js.map +1 -0
- package/dist/chunk-N3SZ7BMH.js +95 -0
- package/dist/chunk-N3SZ7BMH.js.map +1 -0
- package/dist/chunk-NDUD3IMO.js +540 -0
- package/dist/chunk-NDUD3IMO.js.map +1 -0
- package/dist/chunk-NY2PYHNC.js +873 -0
- package/dist/chunk-NY2PYHNC.js.map +1 -0
- package/dist/chunk-O3MT7DYI.js +225 -0
- package/dist/chunk-O3MT7DYI.js.map +1 -0
- package/dist/chunk-OCUDSN63.js +2386 -0
- package/dist/chunk-OCUDSN63.js.map +1 -0
- package/dist/chunk-OIWU3NYV.js +199 -0
- package/dist/chunk-OIWU3NYV.js.map +1 -0
- package/dist/chunk-OO5BM6CJ.js +1153 -0
- package/dist/chunk-OO5BM6CJ.js.map +1 -0
- package/dist/chunk-OQUIJT7A.js +1 -0
- package/dist/chunk-OQUIJT7A.js.map +1 -0
- package/dist/chunk-P5LBT622.js +105 -0
- package/dist/chunk-P5LBT622.js.map +1 -0
- package/dist/chunk-PKGQG5QQ.js +519 -0
- package/dist/chunk-PKGQG5QQ.js.map +1 -0
- package/dist/chunk-PKPO3JTZ.js +561 -0
- package/dist/chunk-PKPO3JTZ.js.map +1 -0
- package/dist/chunk-PL5UDIQ5.js +118 -0
- package/dist/chunk-PL5UDIQ5.js.map +1 -0
- package/dist/chunk-PZWISPIQ.js +432 -0
- package/dist/chunk-PZWISPIQ.js.map +1 -0
- package/dist/chunk-Q3EYOCZB.js +510 -0
- package/dist/chunk-Q3EYOCZB.js.map +1 -0
- package/dist/chunk-QMBYUVRL.js +15 -0
- package/dist/chunk-QMBYUVRL.js.map +1 -0
- package/dist/chunk-RAGGHLCV.js +200 -0
- package/dist/chunk-RAGGHLCV.js.map +1 -0
- package/dist/chunk-RGL53X5G.js +574 -0
- package/dist/chunk-RGL53X5G.js.map +1 -0
- package/dist/chunk-RJOG4IJU.js +1039 -0
- package/dist/chunk-RJOG4IJU.js.map +1 -0
- package/dist/chunk-SOOKUYVM.js +403 -0
- package/dist/chunk-SOOKUYVM.js.map +1 -0
- package/dist/chunk-T5BN5KG7.js +1 -0
- package/dist/chunk-T5BN5KG7.js.map +1 -0
- package/dist/chunk-TP7244Y6.js +207 -0
- package/dist/chunk-TP7244Y6.js.map +1 -0
- package/dist/chunk-TSBFTJKM.js +57 -0
- package/dist/chunk-TSBFTJKM.js.map +1 -0
- package/dist/chunk-URQ2CBBF.js +143 -0
- package/dist/chunk-URQ2CBBF.js.map +1 -0
- package/dist/chunk-W2BOPXTI.js +1 -0
- package/dist/chunk-W2BOPXTI.js.map +1 -0
- package/dist/chunk-WKSWLSCX.js +207 -0
- package/dist/chunk-WKSWLSCX.js.map +1 -0
- package/dist/chunk-Y52CS6YA.js +88 -0
- package/dist/chunk-Y52CS6YA.js.map +1 -0
- package/dist/chunk-YCBUWK77.js +92 -0
- package/dist/chunk-YCBUWK77.js.map +1 -0
- package/dist/chunk-YJ4U2D2C.js +314 -0
- package/dist/chunk-YJ4U2D2C.js.map +1 -0
- package/dist/chunk-Z4YXAUDN.js +239 -0
- package/dist/chunk-Z4YXAUDN.js.map +1 -0
- package/dist/chunk-Z6EGP5D7.js +92 -0
- package/dist/chunk-Z6EGP5D7.js.map +1 -0
- package/dist/compat/index.cjs +3083 -2
- package/dist/compat/index.cjs.map +1 -1
- package/dist/compat/index.d.cts +116 -1
- package/dist/compat/index.d.ts +116 -1
- package/dist/compat/index.js +175 -2
- package/dist/compat/index.js.map +1 -1
- package/dist/compat/jotai/index.cjs +130 -2
- package/dist/compat/jotai/index.cjs.map +1 -1
- package/dist/compat/jotai/index.d.cts +2 -1
- package/dist/compat/jotai/index.d.ts +2 -1
- package/dist/compat/jotai/index.js +7 -2
- package/dist/compat/jotai/index.js.map +1 -1
- package/dist/compat/nanostores/index.cjs +186 -2
- package/dist/compat/nanostores/index.cjs.map +1 -1
- package/dist/compat/nanostores/index.d.cts +2 -1
- package/dist/compat/nanostores/index.d.ts +2 -1
- package/dist/compat/nanostores/index.js +21 -2
- package/dist/compat/nanostores/index.js.map +1 -1
- package/dist/compat/nestjs/index.cjs +2224 -2
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +10 -1
- package/dist/compat/nestjs/index.d.ts +10 -1
- package/dist/compat/nestjs/index.js +77 -2
- package/dist/compat/nestjs/index.js.map +1 -1
- package/dist/compat/react/index.cjs +95 -2
- package/dist/compat/react/index.cjs.map +1 -1
- package/dist/compat/react/index.d.cts +2 -1
- package/dist/compat/react/index.d.ts +2 -1
- package/dist/compat/react/index.js +11 -2
- package/dist/compat/react/index.js.map +1 -1
- package/dist/compat/solid/index.cjs +82 -2
- package/dist/compat/solid/index.cjs.map +1 -1
- package/dist/compat/solid/index.d.cts +2 -1
- package/dist/compat/solid/index.d.ts +2 -1
- package/dist/compat/solid/index.js +11 -2
- package/dist/compat/solid/index.js.map +1 -1
- package/dist/compat/svelte/index.cjs +85 -2
- package/dist/compat/svelte/index.cjs.map +1 -1
- package/dist/compat/svelte/index.d.cts +2 -1
- package/dist/compat/svelte/index.d.ts +2 -1
- package/dist/compat/svelte/index.js +11 -2
- package/dist/compat/svelte/index.js.map +1 -1
- package/dist/compat/vue/index.cjs +100 -2
- package/dist/compat/vue/index.cjs.map +1 -1
- package/dist/compat/vue/index.d.cts +3 -1
- package/dist/compat/vue/index.d.ts +3 -1
- package/dist/compat/vue/index.js +11 -2
- package/dist/compat/vue/index.js.map +1 -1
- package/dist/compat/zustand/index.cjs +50 -2
- package/dist/compat/zustand/index.cjs.map +1 -1
- package/dist/compat/zustand/index.d.cts +2 -1
- package/dist/compat/zustand/index.d.ts +2 -1
- package/dist/compat/zustand/index.js +7 -2
- package/dist/compat/zustand/index.js.map +1 -1
- package/dist/distill-De6Rnn15.d.cts +48 -0
- package/dist/distill-De6Rnn15.d.ts +48 -0
- package/dist/external-register-CWyroXb_.d.cts +138 -0
- package/dist/external-register-CWyroXb_.d.ts +138 -0
- package/dist/fallback-Bx46zqky.d.cts +243 -0
- package/dist/fallback-pIWW8A2d.d.ts +243 -0
- package/dist/guarded-execution-BcdtxeBk.d.ts +207 -0
- package/dist/guarded-execution-C-3hnP6A.d.cts +207 -0
- package/dist/index-5SU_O78r.d.cts +754 -0
- package/dist/index-B6pxYJzO.d.cts +36 -0
- package/dist/index-B6pxYJzO.d.ts +36 -0
- package/dist/index-BFsng6v1.d.cts +44 -0
- package/dist/index-BFsng6v1.d.ts +44 -0
- package/dist/index-Bg-LwEt-.d.cts +45 -0
- package/dist/index-Bg-LwEt-.d.ts +45 -0
- package/dist/index-Brp888t0.d.cts +127 -0
- package/dist/index-Brp888t0.d.ts +127 -0
- package/dist/index-CDfk6jHN.d.cts +37 -0
- package/dist/index-CDfk6jHN.d.ts +37 -0
- package/dist/index-CEXCtYYJ.d.ts +754 -0
- package/dist/index-DLAxYaN5.d.cts +169 -0
- package/dist/index-DLAxYaN5.d.ts +169 -0
- package/dist/index-DeWbQzMe.d.cts +34 -0
- package/dist/index-DeWbQzMe.d.ts +34 -0
- package/dist/index-dX9IzPqj.d.cts +86 -0
- package/dist/index-dX9IzPqj.d.ts +86 -0
- package/dist/index.cjs +25950 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -42
- package/dist/index.d.ts +56 -42
- package/dist/index.js +849 -0
- package/dist/index.js.map +1 -1
- package/dist/layout-types-B5aiHYgk.d.cts +72 -0
- package/dist/layout-types-B5aiHYgk.d.ts +72 -0
- package/dist/memory-composers-BryDrRBX.d.cts +529 -0
- package/dist/memory-composers-CVQqPYEV.d.ts +529 -0
- package/dist/observable-BXQoW1P-.d.cts +36 -0
- package/dist/observable-BXQoW1P-.d.ts +36 -0
- package/dist/pipeline-graph-Ce47CB6Y.d.cts +145 -0
- package/dist/pipeline-graph-DXCwY9vG.d.ts +145 -0
- package/dist/presets/ai/index.cjs +4377 -0
- package/dist/presets/ai/index.cjs.map +1 -0
- package/dist/presets/ai/index.d.cts +98 -0
- package/dist/presets/ai/index.d.ts +98 -0
- package/dist/presets/ai/index.js +54 -0
- package/dist/presets/ai/index.js.map +1 -0
- package/dist/presets/harness/index.cjs +5929 -0
- package/dist/presets/harness/index.cjs.map +1 -0
- package/dist/presets/harness/index.d.cts +566 -0
- package/dist/presets/harness/index.d.ts +566 -0
- package/dist/presets/harness/index.js +71 -0
- package/dist/presets/harness/index.js.map +1 -0
- package/dist/presets/index.cjs +9782 -0
- package/dist/presets/index.cjs.map +1 -0
- package/dist/presets/index.d.cts +28 -0
- package/dist/presets/index.d.ts +28 -0
- package/dist/presets/index.js +129 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/inspect/index.cjs +1087 -0
- package/dist/presets/inspect/index.cjs.map +1 -0
- package/dist/presets/inspect/index.d.cts +172 -0
- package/dist/presets/inspect/index.d.ts +172 -0
- package/dist/presets/inspect/index.js +21 -0
- package/dist/presets/inspect/index.js.map +1 -0
- package/dist/presets/resilience/index.cjs +1593 -0
- package/dist/presets/resilience/index.cjs.map +1 -0
- package/dist/presets/resilience/index.d.cts +205 -0
- package/dist/presets/resilience/index.d.ts +205 -0
- package/dist/presets/resilience/index.js +18 -0
- package/dist/presets/resilience/index.js.map +1 -0
- package/dist/rate-limiter-CEALq4N1.d.ts +559 -0
- package/dist/rate-limiter-DpVbSYdH.d.cts +559 -0
- package/dist/reactive-layout-fswlBUvX.d.cts +195 -0
- package/dist/reactive-layout-fswlBUvX.d.ts +195 -0
- package/dist/retry-BDbRZ_gx.d.ts +125 -0
- package/dist/retry-DWuhjvsA.d.cts +125 -0
- package/dist/solutions/index.cjs +8200 -0
- package/dist/solutions/index.cjs.map +1 -0
- package/dist/solutions/index.d.cts +23 -0
- package/dist/solutions/index.d.ts +23 -0
- package/dist/solutions/index.js +55 -0
- package/dist/solutions/index.js.map +1 -0
- package/dist/spawnable-5mDY501F.d.cts +746 -0
- package/dist/spawnable-D3lR0oQu.d.ts +746 -0
- package/dist/status-U-rUI79b.d.cts +84 -0
- package/dist/status-U-rUI79b.d.ts +84 -0
- package/dist/timeout-U5O4ESK3.js +12 -0
- package/dist/timeout-U5O4ESK3.js.map +1 -0
- package/dist/types-BB5Lw-pB.d.cts +442 -0
- package/dist/types-BB5Lw-pB.d.ts +442 -0
- package/dist/types-CJWIMJiZ.d.ts +548 -0
- package/dist/types-vCq7ShIm.d.cts +548 -0
- package/dist/utils/ai/browser.cjs +2169 -0
- package/dist/utils/ai/browser.cjs.map +1 -0
- package/dist/utils/ai/browser.d.cts +129 -0
- package/dist/utils/ai/browser.d.ts +129 -0
- package/dist/utils/ai/browser.js +255 -0
- package/dist/utils/ai/browser.js.map +1 -0
- package/dist/utils/ai/index.cjs +8468 -0
- package/dist/utils/ai/index.cjs.map +1 -0
- package/dist/utils/ai/index.d.cts +1777 -0
- package/dist/utils/ai/index.d.ts +1777 -0
- package/dist/utils/ai/index.js +173 -0
- package/dist/utils/ai/index.js.map +1 -0
- package/dist/utils/ai/node.cjs +648 -0
- package/dist/utils/ai/node.cjs.map +1 -0
- package/dist/utils/ai/node.d.cts +57 -0
- package/dist/utils/ai/node.d.ts +57 -0
- package/dist/utils/ai/node.js +84 -0
- package/dist/utils/ai/node.js.map +1 -0
- package/dist/utils/cqrs/index.cjs +1036 -0
- package/dist/utils/cqrs/index.cjs.map +1 -0
- package/dist/utils/cqrs/index.d.cts +438 -0
- package/dist/utils/cqrs/index.d.ts +438 -0
- package/dist/utils/cqrs/index.js +18 -0
- package/dist/utils/cqrs/index.js.map +1 -0
- package/dist/utils/demo-shell/index.cjs +865 -0
- package/dist/utils/demo-shell/index.cjs.map +1 -0
- package/dist/utils/demo-shell/index.d.cts +90 -0
- package/dist/utils/demo-shell/index.d.ts +90 -0
- package/dist/utils/demo-shell/index.js +13 -0
- package/dist/utils/demo-shell/index.js.map +1 -0
- package/dist/utils/domain-templates/index.cjs +732 -0
- package/dist/utils/domain-templates/index.cjs.map +1 -0
- package/dist/utils/domain-templates/index.d.cts +214 -0
- package/dist/utils/domain-templates/index.d.ts +214 -0
- package/dist/utils/domain-templates/index.js +17 -0
- package/dist/utils/domain-templates/index.js.map +1 -0
- package/dist/utils/graphspec/index.cjs +1174 -0
- package/dist/utils/graphspec/index.cjs.map +1 -0
- package/dist/utils/graphspec/index.d.cts +449 -0
- package/dist/utils/graphspec/index.d.ts +449 -0
- package/dist/utils/graphspec/index.js +35 -0
- package/dist/utils/graphspec/index.js.map +1 -0
- package/dist/utils/harness/index.cjs +656 -0
- package/dist/utils/harness/index.cjs.map +1 -0
- package/dist/utils/harness/index.d.cts +542 -0
- package/dist/utils/harness/index.d.ts +542 -0
- package/dist/utils/harness/index.js +56 -0
- package/dist/utils/harness/index.js.map +1 -0
- package/dist/utils/index.cjs +17609 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +96 -0
- package/dist/utils/index.d.ts +96 -0
- package/dist/utils/index.js +514 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/inspect/index.cjs +807 -0
- package/dist/utils/inspect/index.cjs.map +1 -0
- package/dist/utils/inspect/index.d.cts +123 -0
- package/dist/utils/inspect/index.d.ts +123 -0
- package/dist/utils/inspect/index.js +30 -0
- package/dist/utils/inspect/index.js.map +1 -0
- package/dist/utils/job-queue/index.cjs +717 -0
- package/dist/utils/job-queue/index.cjs.map +1 -0
- package/dist/utils/job-queue/index.d.cts +200 -0
- package/dist/utils/job-queue/index.d.ts +200 -0
- package/dist/utils/job-queue/index.js +18 -0
- package/dist/utils/job-queue/index.js.map +1 -0
- package/dist/utils/memory/index.cjs +1451 -0
- package/dist/utils/memory/index.cjs.map +1 -0
- package/dist/utils/memory/index.d.cts +582 -0
- package/dist/utils/memory/index.d.ts +582 -0
- package/dist/utils/memory/index.js +19 -0
- package/dist/utils/memory/index.js.map +1 -0
- package/dist/utils/messaging/index.cjs +666 -0
- package/dist/utils/messaging/index.cjs.map +1 -0
- package/dist/utils/messaging/index.d.cts +562 -0
- package/dist/utils/messaging/index.d.ts +562 -0
- package/dist/utils/messaging/index.js +50 -0
- package/dist/utils/messaging/index.js.map +1 -0
- package/dist/utils/orchestration/index.cjs +876 -0
- package/dist/utils/orchestration/index.cjs.map +1 -0
- package/dist/utils/orchestration/index.d.cts +233 -0
- package/dist/utils/orchestration/index.d.ts +233 -0
- package/dist/utils/orchestration/index.js +19 -0
- package/dist/utils/orchestration/index.js.map +1 -0
- package/dist/utils/process/index.cjs +743 -0
- package/dist/utils/process/index.cjs.map +1 -0
- package/dist/utils/process/index.d.cts +411 -0
- package/dist/utils/process/index.d.ts +411 -0
- package/dist/utils/process/index.js +14 -0
- package/dist/utils/process/index.js.map +1 -0
- package/dist/utils/reactive-layout/index.cjs +1607 -0
- package/dist/utils/reactive-layout/index.cjs.map +1 -0
- package/dist/utils/reactive-layout/index.d.cts +492 -0
- package/dist/utils/reactive-layout/index.d.ts +492 -0
- package/dist/utils/reactive-layout/index.js +52 -0
- package/dist/utils/reactive-layout/index.js.map +1 -0
- package/dist/utils/reduction/index.cjs +203 -0
- package/dist/utils/reduction/index.cjs.map +1 -0
- package/dist/utils/reduction/index.d.cts +102 -0
- package/dist/utils/reduction/index.d.ts +102 -0
- package/dist/utils/reduction/index.js +14 -0
- package/dist/utils/reduction/index.js.map +1 -0
- package/dist/utils/resilience/index.cjs +1617 -0
- package/dist/utils/resilience/index.cjs.map +1 -0
- package/dist/utils/resilience/index.d.cts +9 -0
- package/dist/utils/resilience/index.d.ts +9 -0
- package/dist/utils/resilience/index.js +44 -0
- package/dist/utils/resilience/index.js.map +1 -0
- package/dist/utils/surface/index.cjs +1070 -0
- package/dist/utils/surface/index.cjs.map +1 -0
- package/dist/utils/surface/index.d.cts +240 -0
- package/dist/utils/surface/index.d.ts +240 -0
- package/dist/utils/surface/index.js +30 -0
- package/dist/utils/surface/index.js.map +1 -0
- package/dist/utils/topology-view/index.cjs +620 -0
- package/dist/utils/topology-view/index.cjs.map +1 -0
- package/dist/utils/topology-view/index.d.cts +68 -0
- package/dist/utils/topology-view/index.d.ts +68 -0
- package/dist/utils/topology-view/index.js +11 -0
- package/dist/utils/topology-view/index.js.map +1 -0
- package/package.json +293 -237
- package/dist/core/index.cjs +0 -21
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +0 -3
- package/dist/core/index.js.map +0 -1
- package/dist/extra/browser.cjs +0 -21
- package/dist/extra/browser.cjs.map +0 -1
- package/dist/extra/browser.d.cts +0 -1
- package/dist/extra/browser.d.ts +0 -1
- package/dist/extra/browser.js +0 -3
- package/dist/extra/browser.js.map +0 -1
- package/dist/extra/index.cjs +0 -21
- package/dist/extra/index.cjs.map +0 -1
- package/dist/extra/index.d.cts +0 -1
- package/dist/extra/index.d.ts +0 -1
- package/dist/extra/index.js +0 -3
- package/dist/extra/index.js.map +0 -1
- package/dist/extra/node.cjs +0 -21
- package/dist/extra/node.cjs.map +0 -1
- package/dist/extra/node.d.cts +0 -1
- package/dist/extra/node.d.ts +0 -1
- package/dist/extra/node.js +0 -3
- package/dist/extra/node.js.map +0 -1
- package/dist/extra/operators.cjs +0 -21
- package/dist/extra/operators.cjs.map +0 -1
- package/dist/extra/operators.d.cts +0 -1
- package/dist/extra/operators.d.ts +0 -1
- package/dist/extra/operators.js +0 -3
- package/dist/extra/operators.js.map +0 -1
- package/dist/extra/reactive.cjs +0 -21
- package/dist/extra/reactive.cjs.map +0 -1
- package/dist/extra/reactive.d.cts +0 -1
- package/dist/extra/reactive.d.ts +0 -1
- package/dist/extra/reactive.js +0 -3
- package/dist/extra/reactive.js.map +0 -1
- package/dist/extra/render/index.cjs +0 -21
- package/dist/extra/render/index.cjs.map +0 -1
- package/dist/extra/render/index.d.cts +0 -1
- package/dist/extra/render/index.d.ts +0 -1
- package/dist/extra/render/index.js +0 -3
- package/dist/extra/render/index.js.map +0 -1
- package/dist/extra/sources.cjs +0 -21
- package/dist/extra/sources.cjs.map +0 -1
- package/dist/extra/sources.d.cts +0 -1
- package/dist/extra/sources.d.ts +0 -1
- package/dist/extra/sources.js +0 -3
- package/dist/extra/sources.js.map +0 -1
- package/dist/extra/storage-browser.cjs +0 -21
- package/dist/extra/storage-browser.cjs.map +0 -1
- package/dist/extra/storage-browser.d.cts +0 -1
- package/dist/extra/storage-browser.d.ts +0 -1
- package/dist/extra/storage-browser.js +0 -3
- package/dist/extra/storage-browser.js.map +0 -1
- package/dist/extra/storage-core.cjs +0 -21
- package/dist/extra/storage-core.cjs.map +0 -1
- package/dist/extra/storage-core.d.cts +0 -1
- package/dist/extra/storage-core.d.ts +0 -1
- package/dist/extra/storage-core.js +0 -3
- package/dist/extra/storage-core.js.map +0 -1
- package/dist/extra/storage-node.cjs +0 -21
- package/dist/extra/storage-node.cjs.map +0 -1
- package/dist/extra/storage-node.d.cts +0 -1
- package/dist/extra/storage-node.d.ts +0 -1
- package/dist/extra/storage-node.js +0 -3
- package/dist/extra/storage-node.js.map +0 -1
- package/dist/extra/storage-tiers-browser.cjs +0 -21
- package/dist/extra/storage-tiers-browser.cjs.map +0 -1
- package/dist/extra/storage-tiers-browser.d.cts +0 -1
- package/dist/extra/storage-tiers-browser.d.ts +0 -1
- package/dist/extra/storage-tiers-browser.js +0 -3
- package/dist/extra/storage-tiers-browser.js.map +0 -1
- package/dist/extra/storage-tiers-node.cjs +0 -21
- package/dist/extra/storage-tiers-node.cjs.map +0 -1
- package/dist/extra/storage-tiers-node.d.cts +0 -1
- package/dist/extra/storage-tiers-node.d.ts +0 -1
- package/dist/extra/storage-tiers-node.js +0 -3
- package/dist/extra/storage-tiers-node.js.map +0 -1
- package/dist/extra/storage-tiers.cjs +0 -21
- package/dist/extra/storage-tiers.cjs.map +0 -1
- package/dist/extra/storage-tiers.d.cts +0 -1
- package/dist/extra/storage-tiers.d.ts +0 -1
- package/dist/extra/storage-tiers.js +0 -3
- package/dist/extra/storage-tiers.js.map +0 -1
- package/dist/extra/storage-wal.cjs +0 -21
- package/dist/extra/storage-wal.cjs.map +0 -1
- package/dist/extra/storage-wal.d.cts +0 -1
- package/dist/extra/storage-wal.d.ts +0 -1
- package/dist/extra/storage-wal.js +0 -3
- package/dist/extra/storage-wal.js.map +0 -1
- package/dist/graph/index.cjs +0 -21
- package/dist/graph/index.cjs.map +0 -1
- package/dist/graph/index.d.cts +0 -1
- package/dist/graph/index.d.ts +0 -1
- package/dist/graph/index.js +0 -3
- package/dist/graph/index.js.map +0 -1
- package/dist/patterns/ai/browser.cjs +0 -21
- package/dist/patterns/ai/browser.cjs.map +0 -1
- package/dist/patterns/ai/browser.d.cts +0 -1
- package/dist/patterns/ai/browser.d.ts +0 -1
- package/dist/patterns/ai/browser.js +0 -3
- package/dist/patterns/ai/browser.js.map +0 -1
- package/dist/patterns/ai/index.cjs +0 -21
- package/dist/patterns/ai/index.cjs.map +0 -1
- package/dist/patterns/ai/index.d.cts +0 -1
- package/dist/patterns/ai/index.d.ts +0 -1
- package/dist/patterns/ai/index.js +0 -3
- package/dist/patterns/ai/index.js.map +0 -1
- package/dist/patterns/ai/node.cjs +0 -21
- package/dist/patterns/ai/node.cjs.map +0 -1
- package/dist/patterns/ai/node.d.cts +0 -1
- package/dist/patterns/ai/node.d.ts +0 -1
- package/dist/patterns/ai/node.js +0 -3
- package/dist/patterns/ai/node.js.map +0 -1
- package/dist/patterns/cqrs/index.cjs +0 -21
- package/dist/patterns/cqrs/index.cjs.map +0 -1
- package/dist/patterns/cqrs/index.d.cts +0 -1
- package/dist/patterns/cqrs/index.d.ts +0 -1
- package/dist/patterns/cqrs/index.js +0 -3
- package/dist/patterns/cqrs/index.js.map +0 -1
- package/dist/patterns/demo-shell/index.cjs +0 -21
- package/dist/patterns/demo-shell/index.cjs.map +0 -1
- package/dist/patterns/demo-shell/index.d.cts +0 -1
- package/dist/patterns/demo-shell/index.d.ts +0 -1
- package/dist/patterns/demo-shell/index.js +0 -3
- package/dist/patterns/demo-shell/index.js.map +0 -1
- package/dist/patterns/domain-templates/index.cjs +0 -21
- package/dist/patterns/domain-templates/index.cjs.map +0 -1
- package/dist/patterns/domain-templates/index.d.cts +0 -1
- package/dist/patterns/domain-templates/index.d.ts +0 -1
- package/dist/patterns/domain-templates/index.js +0 -3
- package/dist/patterns/domain-templates/index.js.map +0 -1
- package/dist/patterns/graphspec/index.cjs +0 -21
- package/dist/patterns/graphspec/index.cjs.map +0 -1
- package/dist/patterns/graphspec/index.d.cts +0 -1
- package/dist/patterns/graphspec/index.d.ts +0 -1
- package/dist/patterns/graphspec/index.js +0 -3
- package/dist/patterns/graphspec/index.js.map +0 -1
- package/dist/patterns/harness/index.cjs +0 -21
- package/dist/patterns/harness/index.cjs.map +0 -1
- package/dist/patterns/harness/index.d.cts +0 -1
- package/dist/patterns/harness/index.d.ts +0 -1
- package/dist/patterns/harness/index.js +0 -3
- package/dist/patterns/harness/index.js.map +0 -1
- package/dist/patterns/inspect/index.cjs +0 -21
- package/dist/patterns/inspect/index.cjs.map +0 -1
- package/dist/patterns/inspect/index.d.cts +0 -1
- package/dist/patterns/inspect/index.d.ts +0 -1
- package/dist/patterns/inspect/index.js +0 -3
- package/dist/patterns/inspect/index.js.map +0 -1
- package/dist/patterns/job-queue/index.cjs +0 -21
- package/dist/patterns/job-queue/index.cjs.map +0 -1
- package/dist/patterns/job-queue/index.d.cts +0 -1
- package/dist/patterns/job-queue/index.d.ts +0 -1
- package/dist/patterns/job-queue/index.js +0 -3
- package/dist/patterns/job-queue/index.js.map +0 -1
- package/dist/patterns/memory/index.cjs +0 -21
- package/dist/patterns/memory/index.cjs.map +0 -1
- package/dist/patterns/memory/index.d.cts +0 -1
- package/dist/patterns/memory/index.d.ts +0 -1
- package/dist/patterns/memory/index.js +0 -3
- package/dist/patterns/memory/index.js.map +0 -1
- package/dist/patterns/messaging/index.cjs +0 -21
- package/dist/patterns/messaging/index.cjs.map +0 -1
- package/dist/patterns/messaging/index.d.cts +0 -1
- package/dist/patterns/messaging/index.d.ts +0 -1
- package/dist/patterns/messaging/index.js +0 -3
- package/dist/patterns/messaging/index.js.map +0 -1
- package/dist/patterns/orchestration/index.cjs +0 -21
- package/dist/patterns/orchestration/index.cjs.map +0 -1
- package/dist/patterns/orchestration/index.d.cts +0 -1
- package/dist/patterns/orchestration/index.d.ts +0 -1
- package/dist/patterns/orchestration/index.js +0 -3
- package/dist/patterns/orchestration/index.js.map +0 -1
- package/dist/patterns/process/index.cjs +0 -21
- package/dist/patterns/process/index.cjs.map +0 -1
- package/dist/patterns/process/index.d.cts +0 -1
- package/dist/patterns/process/index.d.ts +0 -1
- package/dist/patterns/process/index.js +0 -3
- package/dist/patterns/process/index.js.map +0 -1
- package/dist/patterns/reactive-layout/index.cjs +0 -21
- package/dist/patterns/reactive-layout/index.cjs.map +0 -1
- package/dist/patterns/reactive-layout/index.d.cts +0 -1
- package/dist/patterns/reactive-layout/index.d.ts +0 -1
- package/dist/patterns/reactive-layout/index.js +0 -3
- package/dist/patterns/reactive-layout/index.js.map +0 -1
- package/dist/patterns/reduction/index.cjs +0 -21
- package/dist/patterns/reduction/index.cjs.map +0 -1
- package/dist/patterns/reduction/index.d.cts +0 -1
- package/dist/patterns/reduction/index.d.ts +0 -1
- package/dist/patterns/reduction/index.js +0 -3
- package/dist/patterns/reduction/index.js.map +0 -1
- package/dist/patterns/surface/index.cjs +0 -21
- package/dist/patterns/surface/index.cjs.map +0 -1
- package/dist/patterns/surface/index.d.cts +0 -1
- package/dist/patterns/surface/index.d.ts +0 -1
- package/dist/patterns/surface/index.js +0 -3
- package/dist/patterns/surface/index.js.map +0 -1
- package/dist/patterns/topology-view/index.cjs +0 -21
- package/dist/patterns/topology-view/index.cjs.map +0 -1
- package/dist/patterns/topology-view/index.d.cts +0 -1
- package/dist/patterns/topology-view/index.d.ts +0 -1
- package/dist/patterns/topology-view/index.js +0 -3
- package/dist/patterns/topology-view/index.js.map +0 -1
- package/dist/testing/index.cjs +0 -21
- package/dist/testing/index.cjs.map +0 -1
- package/dist/testing/index.d.cts +0 -1
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -3
- package/dist/testing/index.js.map +0 -1
|
@@ -0,0 +1,3270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/base/io/index.ts
|
|
21
|
+
var io_exports = {};
|
|
22
|
+
__export(io_exports, {
|
|
23
|
+
checkpointToRedis: () => checkpointToRedis,
|
|
24
|
+
checkpointToS3: () => checkpointToS3,
|
|
25
|
+
csvRows: () => csvRows,
|
|
26
|
+
fromCSV: () => fromCSV,
|
|
27
|
+
fromClickHouseWatch: () => fromClickHouseWatch,
|
|
28
|
+
fromDrizzle: () => fromDrizzle,
|
|
29
|
+
fromHTTP: () => fromHTTP,
|
|
30
|
+
fromHTTPPoll: () => fromHTTPPoll,
|
|
31
|
+
fromHTTPStream: () => fromHTTPStream,
|
|
32
|
+
fromKafka: () => fromKafka,
|
|
33
|
+
fromKysely: () => fromKysely,
|
|
34
|
+
fromMCP: () => fromMCP,
|
|
35
|
+
fromNATS: () => fromNATS,
|
|
36
|
+
fromNDJSON: () => fromNDJSON,
|
|
37
|
+
fromOTel: () => fromOTel,
|
|
38
|
+
fromPrisma: () => fromPrisma,
|
|
39
|
+
fromPrometheus: () => fromPrometheus,
|
|
40
|
+
fromPulsar: () => fromPulsar,
|
|
41
|
+
fromRabbitMQ: () => fromRabbitMQ,
|
|
42
|
+
fromRedisStream: () => fromRedisStream,
|
|
43
|
+
fromSSE: () => fromSSE,
|
|
44
|
+
fromSqlite: () => fromSqlite,
|
|
45
|
+
fromSqliteCursor: () => fromSqliteCursor,
|
|
46
|
+
fromStatsD: () => fromStatsD,
|
|
47
|
+
fromSyslog: () => fromSyslog,
|
|
48
|
+
fromWebSocket: () => fromWebSocket,
|
|
49
|
+
fromWebSocketReconnect: () => fromWebSocketReconnect,
|
|
50
|
+
fromWebhook: () => fromWebhook,
|
|
51
|
+
ndjsonRows: () => ndjsonRows,
|
|
52
|
+
parsePrometheusText: () => parsePrometheusText,
|
|
53
|
+
parseSSEStream: () => parseSSEStream,
|
|
54
|
+
parseStatsD: () => parseStatsD,
|
|
55
|
+
parseSyslog: () => parseSyslog,
|
|
56
|
+
toCSV: () => toCSV,
|
|
57
|
+
toClickHouse: () => toClickHouse,
|
|
58
|
+
toFile: () => toFile,
|
|
59
|
+
toHTTP: () => toHTTP,
|
|
60
|
+
toKafka: () => toKafka,
|
|
61
|
+
toLoki: () => toLoki,
|
|
62
|
+
toMongo: () => toMongo,
|
|
63
|
+
toNATS: () => toNATS,
|
|
64
|
+
toPostgres: () => toPostgres,
|
|
65
|
+
toPulsar: () => toPulsar,
|
|
66
|
+
toRabbitMQ: () => toRabbitMQ,
|
|
67
|
+
toReadableStream: () => toReadableStream,
|
|
68
|
+
toRedisStream: () => toRedisStream,
|
|
69
|
+
toS3: () => toS3,
|
|
70
|
+
toSSE: () => toSSE,
|
|
71
|
+
toSSEBytes: () => toSSEBytes,
|
|
72
|
+
toSqlite: () => toSqlite,
|
|
73
|
+
toTempo: () => toTempo,
|
|
74
|
+
toWebSocket: () => toWebSocket
|
|
75
|
+
});
|
|
76
|
+
module.exports = __toCommonJS(io_exports);
|
|
77
|
+
|
|
78
|
+
// src/base/io/checkpoint.ts
|
|
79
|
+
var import_core = require("@graphrefly/pure-ts/core");
|
|
80
|
+
function checkpointToS3(graph, client, bucket, opts) {
|
|
81
|
+
const { prefix = "checkpoints/", debounceMs = 500, compactEvery = 10, onError } = opts ?? {};
|
|
82
|
+
const tier = {
|
|
83
|
+
name: `s3:${bucket}`,
|
|
84
|
+
debounceMs,
|
|
85
|
+
compactEvery,
|
|
86
|
+
save(record) {
|
|
87
|
+
const ms = Math.floor((0, import_core.wallClockNs)() / 1e6);
|
|
88
|
+
const s3Key = `${prefix}${graph.name}/checkpoint-${ms}.json`;
|
|
89
|
+
let body;
|
|
90
|
+
try {
|
|
91
|
+
body = JSON.stringify(record);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
onError?.(err);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
void client.putObject({
|
|
97
|
+
Bucket: bucket,
|
|
98
|
+
Key: s3Key,
|
|
99
|
+
Body: body,
|
|
100
|
+
ContentType: "application/json"
|
|
101
|
+
}).catch((err) => onError?.(err));
|
|
102
|
+
}
|
|
103
|
+
// S3 tier is write-only here — one object per checkpoint timestamp,
|
|
104
|
+
// no canonical "latest" key for load.
|
|
105
|
+
};
|
|
106
|
+
return graph.attachSnapshotStorage([{ snapshot: tier }], {
|
|
107
|
+
onError: (err) => onError?.(err)
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function checkpointToRedis(graph, client, opts) {
|
|
111
|
+
const {
|
|
112
|
+
prefix = "graphrefly:checkpoint:",
|
|
113
|
+
debounceMs = 500,
|
|
114
|
+
compactEvery = 10,
|
|
115
|
+
onError
|
|
116
|
+
} = opts ?? {};
|
|
117
|
+
const redisKey = `${prefix}${graph.name}`;
|
|
118
|
+
const tier = {
|
|
119
|
+
name: `redis:${redisKey}`,
|
|
120
|
+
debounceMs,
|
|
121
|
+
compactEvery,
|
|
122
|
+
save(record) {
|
|
123
|
+
let body;
|
|
124
|
+
try {
|
|
125
|
+
body = JSON.stringify(record);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
onError?.(err);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
void client.set(redisKey, body).catch((err) => onError?.(err));
|
|
131
|
+
},
|
|
132
|
+
async load() {
|
|
133
|
+
const raw = await client.get(redisKey);
|
|
134
|
+
if (raw == null) return void 0;
|
|
135
|
+
try {
|
|
136
|
+
return JSON.parse(raw);
|
|
137
|
+
} catch {
|
|
138
|
+
return void 0;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
return graph.attachSnapshotStorage([{ snapshot: tier }], {
|
|
143
|
+
onError: (err) => onError?.(err)
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/base/io/clickhouse-watch.ts
|
|
148
|
+
var import_core2 = require("@graphrefly/pure-ts/core");
|
|
149
|
+
var import_extra = require("@graphrefly/pure-ts/extra");
|
|
150
|
+
|
|
151
|
+
// src/base/resilience/backoff.ts
|
|
152
|
+
var NS_PER_MS = 1e6;
|
|
153
|
+
var NS_PER_SEC = 1e9;
|
|
154
|
+
function clampNonNegative(value) {
|
|
155
|
+
return value < 0 ? 0 : value;
|
|
156
|
+
}
|
|
157
|
+
function applyJitter(delay, jitter) {
|
|
158
|
+
if (jitter === "none") return delay;
|
|
159
|
+
if (jitter === "full") return Math.random() * delay;
|
|
160
|
+
return delay / 2 + Math.random() * (delay / 2);
|
|
161
|
+
}
|
|
162
|
+
function randomBetween(min, max) {
|
|
163
|
+
return min + Math.random() * (max - min);
|
|
164
|
+
}
|
|
165
|
+
function constant(delayNs) {
|
|
166
|
+
const safe = clampNonNegative(delayNs);
|
|
167
|
+
return () => safe;
|
|
168
|
+
}
|
|
169
|
+
function linear(baseNs, stepNs) {
|
|
170
|
+
const safeBase = clampNonNegative(baseNs);
|
|
171
|
+
const safeStep = stepNs === void 0 ? safeBase : clampNonNegative(stepNs);
|
|
172
|
+
return (attempt) => safeBase + safeStep * Math.max(0, attempt);
|
|
173
|
+
}
|
|
174
|
+
function exponential(options) {
|
|
175
|
+
const baseNs = clampNonNegative(options?.baseNs ?? 100 * NS_PER_MS);
|
|
176
|
+
const factor = options?.factor !== void 0 && options.factor < 1 ? 1 : options?.factor ?? 2;
|
|
177
|
+
const maxDelayNs = clampNonNegative(options?.maxDelayNs ?? 30 * NS_PER_SEC);
|
|
178
|
+
const jitter = options?.jitter ?? "none";
|
|
179
|
+
return (attempt) => {
|
|
180
|
+
let delay;
|
|
181
|
+
if (baseNs === 0) {
|
|
182
|
+
delay = 0;
|
|
183
|
+
} else if (factor === 1) {
|
|
184
|
+
delay = baseNs;
|
|
185
|
+
} else {
|
|
186
|
+
const capRatio = maxDelayNs / baseNs;
|
|
187
|
+
let growth = 1;
|
|
188
|
+
for (let i = 0; i < Math.max(0, attempt); i++) {
|
|
189
|
+
if (growth >= capRatio) {
|
|
190
|
+
growth = capRatio;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
growth *= factor;
|
|
194
|
+
}
|
|
195
|
+
delay = baseNs * growth;
|
|
196
|
+
if (delay > maxDelayNs) delay = maxDelayNs;
|
|
197
|
+
}
|
|
198
|
+
return applyJitter(delay, jitter);
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function fibonacci(baseNs = 100 * NS_PER_MS, maxDelayNs = 30 * NS_PER_SEC) {
|
|
202
|
+
const safeBase = clampNonNegative(baseNs);
|
|
203
|
+
const safeMax = clampNonNegative(maxDelayNs);
|
|
204
|
+
function fibUnit(attempt) {
|
|
205
|
+
if (attempt <= 0) return 1;
|
|
206
|
+
let prev = 1;
|
|
207
|
+
let cur = 2;
|
|
208
|
+
for (let i = 1; i < attempt; i++) {
|
|
209
|
+
const next = prev + cur;
|
|
210
|
+
prev = cur;
|
|
211
|
+
cur = next;
|
|
212
|
+
}
|
|
213
|
+
return cur;
|
|
214
|
+
}
|
|
215
|
+
return (attempt) => {
|
|
216
|
+
const raw = fibUnit(attempt) * safeBase;
|
|
217
|
+
return raw <= safeMax ? raw : safeMax;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function decorrelatedJitter(baseNs = 100 * NS_PER_MS, maxNs = 30 * NS_PER_SEC) {
|
|
221
|
+
return (_attempt, _error, prevDelayNs) => {
|
|
222
|
+
const last = prevDelayNs ?? baseNs;
|
|
223
|
+
const ceiling = Math.min(maxNs, last * 3);
|
|
224
|
+
return randomBetween(baseNs, ceiling);
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function resolveBackoffPreset(name) {
|
|
228
|
+
if (name === "constant") return constant(1 * NS_PER_SEC);
|
|
229
|
+
if (name === "linear") return linear(1 * NS_PER_SEC);
|
|
230
|
+
if (name === "exponential") return exponential();
|
|
231
|
+
if (name === "fibonacci") return fibonacci();
|
|
232
|
+
if (name === "decorrelatedJitter") return decorrelatedJitter();
|
|
233
|
+
throw new Error(
|
|
234
|
+
`Unknown backoff preset: "${String(name)}". Use one of: constant, linear, exponential, fibonacci, decorrelatedJitter`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/base/io/clickhouse-watch.ts
|
|
239
|
+
function fromClickHouseWatch(client, query, opts) {
|
|
240
|
+
const {
|
|
241
|
+
intervalNs = 5 * NS_PER_SEC,
|
|
242
|
+
format = "JSONEachRow",
|
|
243
|
+
signal: externalSignal,
|
|
244
|
+
maxConsecutiveErrors = 1
|
|
245
|
+
} = opts ?? {};
|
|
246
|
+
const intervalMs = Math.ceil(intervalNs / NS_PER_MS);
|
|
247
|
+
let consecutiveErrors = 0;
|
|
248
|
+
return (0, import_extra.switchMap)(
|
|
249
|
+
(0, import_extra.fromTimer)(0, { period: intervalMs, signal: externalSignal }),
|
|
250
|
+
() => (0, import_core2.node)([], (_data, a) => {
|
|
251
|
+
let active = true;
|
|
252
|
+
const run = async () => {
|
|
253
|
+
try {
|
|
254
|
+
const result = await client.query({ query, format });
|
|
255
|
+
if (!active) return;
|
|
256
|
+
const rows = await result.json();
|
|
257
|
+
if (!active) return;
|
|
258
|
+
for (const row of rows) a.emit(row);
|
|
259
|
+
consecutiveErrors = 0;
|
|
260
|
+
a.down([[import_core2.COMPLETE]]);
|
|
261
|
+
} catch (err) {
|
|
262
|
+
if (!active) return;
|
|
263
|
+
consecutiveErrors += 1;
|
|
264
|
+
if (consecutiveErrors >= maxConsecutiveErrors) {
|
|
265
|
+
a.down([[import_core2.ERROR, err]]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
void run();
|
|
270
|
+
return () => {
|
|
271
|
+
active = false;
|
|
272
|
+
};
|
|
273
|
+
})
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/base/io/csv.ts
|
|
278
|
+
var import_core3 = require("@graphrefly/pure-ts/core");
|
|
279
|
+
|
|
280
|
+
// src/base/io/_internal.ts
|
|
281
|
+
function sourceOpts(opts) {
|
|
282
|
+
return { describeKind: "producer", ...opts };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// src/base/io/csv.ts
|
|
286
|
+
function fromCSV(source, opts) {
|
|
287
|
+
const {
|
|
288
|
+
delimiter = ",",
|
|
289
|
+
hasHeader = true,
|
|
290
|
+
columns: explicitColumns,
|
|
291
|
+
parseLine,
|
|
292
|
+
...rest
|
|
293
|
+
} = opts ?? {};
|
|
294
|
+
const parse = parseLine ?? ((line) => parseCSVLine(line, delimiter));
|
|
295
|
+
return (0, import_core3.node)(
|
|
296
|
+
[],
|
|
297
|
+
(_data, a) => {
|
|
298
|
+
let cancelled = false;
|
|
299
|
+
const run = async () => {
|
|
300
|
+
try {
|
|
301
|
+
let headers = explicitColumns;
|
|
302
|
+
let buffer = "";
|
|
303
|
+
for await (const chunk of source) {
|
|
304
|
+
if (cancelled) return;
|
|
305
|
+
buffer += chunk;
|
|
306
|
+
const lines = buffer.split(/\r?\n/);
|
|
307
|
+
buffer = lines.pop() ?? "";
|
|
308
|
+
for (const line of lines) {
|
|
309
|
+
if (cancelled) return;
|
|
310
|
+
if (!line.trim()) continue;
|
|
311
|
+
const values = parse(line);
|
|
312
|
+
if (!headers && hasHeader) {
|
|
313
|
+
headers = values;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (!headers) {
|
|
317
|
+
headers = values.map((_, i) => `col${i}`);
|
|
318
|
+
}
|
|
319
|
+
const row = {};
|
|
320
|
+
for (let i = 0; i < headers.length; i++) {
|
|
321
|
+
row[headers[i]] = values[i] ?? "";
|
|
322
|
+
}
|
|
323
|
+
a.emit(row);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (!cancelled && buffer.trim()) {
|
|
327
|
+
const values = parse(buffer);
|
|
328
|
+
if (headers) {
|
|
329
|
+
const row = {};
|
|
330
|
+
for (let i = 0; i < headers.length; i++) {
|
|
331
|
+
row[headers[i]] = values[i] ?? "";
|
|
332
|
+
}
|
|
333
|
+
a.emit(row);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (!cancelled) a.down([[import_core3.COMPLETE]]);
|
|
337
|
+
} catch (err) {
|
|
338
|
+
if (!cancelled) a.down([[import_core3.ERROR, err]]);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
void run();
|
|
342
|
+
return () => {
|
|
343
|
+
cancelled = true;
|
|
344
|
+
};
|
|
345
|
+
},
|
|
346
|
+
sourceOpts(rest)
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
function csvRows(source, opts) {
|
|
350
|
+
const {
|
|
351
|
+
delimiter = ",",
|
|
352
|
+
hasHeader = true,
|
|
353
|
+
columns: explicitColumns,
|
|
354
|
+
parseLine,
|
|
355
|
+
...rest
|
|
356
|
+
} = opts ?? {};
|
|
357
|
+
const parse = parseLine ?? ((line) => parseCSVLine(line, delimiter));
|
|
358
|
+
let cleanup;
|
|
359
|
+
return (0, import_core3.node)(
|
|
360
|
+
[source],
|
|
361
|
+
(data, a, ctx) => {
|
|
362
|
+
if (cleanup === void 0) {
|
|
363
|
+
const store = ctx.store;
|
|
364
|
+
cleanup = {
|
|
365
|
+
onDeactivation: () => {
|
|
366
|
+
delete store.buffer;
|
|
367
|
+
delete store.headers;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const batch0 = data[0];
|
|
372
|
+
if (batch0 == null || batch0.length === 0) return cleanup;
|
|
373
|
+
const s = ctx.store;
|
|
374
|
+
if (typeof s.buffer !== "string") s.buffer = "";
|
|
375
|
+
if (s.headers === void 0 && explicitColumns) s.headers = explicitColumns.slice();
|
|
376
|
+
for (const chunkRaw of batch0) {
|
|
377
|
+
s.buffer = s.buffer + chunkRaw;
|
|
378
|
+
const lines = s.buffer.split(/\r?\n/);
|
|
379
|
+
s.buffer = lines.pop() ?? "";
|
|
380
|
+
for (const line of lines) {
|
|
381
|
+
if (!line.trim()) continue;
|
|
382
|
+
const values = parse(line);
|
|
383
|
+
if (!s.headers && hasHeader) {
|
|
384
|
+
s.headers = values;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (!s.headers) s.headers = values.map((_, i) => `col${i}`);
|
|
388
|
+
const row = {};
|
|
389
|
+
for (let i = 0; i < s.headers.length; i++) row[s.headers[i]] = values[i] ?? "";
|
|
390
|
+
a.emit(row);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return cleanup;
|
|
394
|
+
},
|
|
395
|
+
{ describeKind: "derived", ...rest }
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
function parseCSVLine(line, delimiter) {
|
|
399
|
+
const values = [];
|
|
400
|
+
let current = "";
|
|
401
|
+
let inQuotes = false;
|
|
402
|
+
for (let i = 0; i < line.length; i++) {
|
|
403
|
+
const ch = line[i];
|
|
404
|
+
if (inQuotes) {
|
|
405
|
+
if (ch === '"') {
|
|
406
|
+
if (line[i + 1] === '"') {
|
|
407
|
+
current += '"';
|
|
408
|
+
i++;
|
|
409
|
+
} else {
|
|
410
|
+
inQuotes = false;
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
current += ch;
|
|
414
|
+
}
|
|
415
|
+
} else if (ch === '"') {
|
|
416
|
+
inQuotes = true;
|
|
417
|
+
} else if (ch === delimiter) {
|
|
418
|
+
values.push(current);
|
|
419
|
+
current = "";
|
|
420
|
+
} else {
|
|
421
|
+
current += ch;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
values.push(current);
|
|
425
|
+
return values;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/base/io/drizzle.ts
|
|
429
|
+
var import_core4 = require("@graphrefly/pure-ts/core");
|
|
430
|
+
function fromDrizzle(query, opts) {
|
|
431
|
+
const { mapRow = (r) => r, ...rest } = opts ?? {};
|
|
432
|
+
return (0, import_core4.node)(
|
|
433
|
+
[],
|
|
434
|
+
(_data, a) => {
|
|
435
|
+
let active = true;
|
|
436
|
+
void query.execute().then((rows) => {
|
|
437
|
+
if (!active) return;
|
|
438
|
+
a.emit(rows.map(mapRow));
|
|
439
|
+
a.down([[import_core4.COMPLETE]]);
|
|
440
|
+
}).catch((err) => {
|
|
441
|
+
if (!active) return;
|
|
442
|
+
try {
|
|
443
|
+
a.down([[import_core4.ERROR, err instanceof Error ? err : new Error(String(err))]]);
|
|
444
|
+
} catch {
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
return () => {
|
|
448
|
+
active = false;
|
|
449
|
+
};
|
|
450
|
+
},
|
|
451
|
+
{ ...rest, describeKind: "producer", completeWhenDepsComplete: false }
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// src/base/io/http.ts
|
|
456
|
+
var import_core8 = require("@graphrefly/pure-ts/core");
|
|
457
|
+
var import_extra2 = require("@graphrefly/pure-ts/extra");
|
|
458
|
+
|
|
459
|
+
// src/base/resilience/status.ts
|
|
460
|
+
var import_core6 = require("@graphrefly/pure-ts/core");
|
|
461
|
+
|
|
462
|
+
// src/base/resilience/_internal.ts
|
|
463
|
+
var import_core5 = require("@graphrefly/pure-ts/core");
|
|
464
|
+
function operatorOpts(opts) {
|
|
465
|
+
return { describeKind: "derived", ...opts };
|
|
466
|
+
}
|
|
467
|
+
function msgVal(m) {
|
|
468
|
+
return m[1];
|
|
469
|
+
}
|
|
470
|
+
function coerceDelayNs(raw) {
|
|
471
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
|
472
|
+
throw new TypeError("backoff strategy must return a finite number");
|
|
473
|
+
}
|
|
474
|
+
return raw < 0 ? 0 : raw;
|
|
475
|
+
}
|
|
476
|
+
function isNode(x) {
|
|
477
|
+
return x != null && typeof x === "object" && "cache" in x && typeof x.subscribe === "function";
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// src/base/resilience/status.ts
|
|
481
|
+
function withStatus(src, options) {
|
|
482
|
+
const initialStatus = options?.initialStatus ?? "pending";
|
|
483
|
+
const callerMeta = options?.meta;
|
|
484
|
+
const out = (0, import_core6.node)(
|
|
485
|
+
[],
|
|
486
|
+
(_deps, a) => {
|
|
487
|
+
let currentStatus = initialStatus;
|
|
488
|
+
out.meta.status.down([[import_core6.DATA, initialStatus]]);
|
|
489
|
+
out.meta.error.down([[import_core6.DATA, null]]);
|
|
490
|
+
const unsub = src.subscribe((msgs) => {
|
|
491
|
+
for (const m of msgs) {
|
|
492
|
+
const t = m[0];
|
|
493
|
+
if (t === import_core6.DIRTY) a.down([[import_core6.DIRTY]]);
|
|
494
|
+
else if (t === import_core6.DATA) {
|
|
495
|
+
if (currentStatus === "errored") {
|
|
496
|
+
(0, import_core6.batch)(() => {
|
|
497
|
+
out.meta.error.down([[import_core6.DATA, null]]);
|
|
498
|
+
out.meta.status.down([[import_core6.DATA, "running"]]);
|
|
499
|
+
a.emit(m[1]);
|
|
500
|
+
});
|
|
501
|
+
currentStatus = "running";
|
|
502
|
+
} else if (currentStatus !== "running") {
|
|
503
|
+
(0, import_core6.batch)(() => {
|
|
504
|
+
out.meta.status.down([[import_core6.DATA, "running"]]);
|
|
505
|
+
a.emit(m[1]);
|
|
506
|
+
});
|
|
507
|
+
currentStatus = "running";
|
|
508
|
+
} else {
|
|
509
|
+
a.emit(m[1]);
|
|
510
|
+
}
|
|
511
|
+
} else if (t === import_core6.RESOLVED) a.down([[import_core6.RESOLVED]]);
|
|
512
|
+
else if (t === import_core6.COMPLETE) {
|
|
513
|
+
out.meta.status.down([[import_core6.DATA, "completed"]]);
|
|
514
|
+
currentStatus = "completed";
|
|
515
|
+
a.down([[import_core6.COMPLETE]]);
|
|
516
|
+
} else if (t === import_core6.ERROR) {
|
|
517
|
+
const err = msgVal(m);
|
|
518
|
+
(0, import_core6.batch)(() => {
|
|
519
|
+
out.meta.error.down([[import_core6.DATA, err]]);
|
|
520
|
+
out.meta.status.down([[import_core6.DATA, "errored"]]);
|
|
521
|
+
});
|
|
522
|
+
currentStatus = "errored";
|
|
523
|
+
a.down([m]);
|
|
524
|
+
} else a.down([m]);
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
return unsub;
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
...operatorOpts(),
|
|
531
|
+
meta: {
|
|
532
|
+
...callerMeta ?? {},
|
|
533
|
+
status: initialStatus,
|
|
534
|
+
error: null,
|
|
535
|
+
...(0, import_core6.factoryTag)("withStatus", { initialStatus })
|
|
536
|
+
},
|
|
537
|
+
completeWhenDepsComplete: false,
|
|
538
|
+
resubscribable: true,
|
|
539
|
+
initial: src.cache
|
|
540
|
+
}
|
|
541
|
+
);
|
|
542
|
+
return {
|
|
543
|
+
node: out,
|
|
544
|
+
status: out.meta.status,
|
|
545
|
+
error: out.meta.error
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// src/base/io/_sink.ts
|
|
550
|
+
var import_core7 = require("@graphrefly/pure-ts/core");
|
|
551
|
+
var BackpressureBuffer = class {
|
|
552
|
+
ring;
|
|
553
|
+
arr;
|
|
554
|
+
constructor(cap) {
|
|
555
|
+
if (cap === Number.POSITIVE_INFINITY || cap <= 0) {
|
|
556
|
+
this.arr = [];
|
|
557
|
+
this.ring = null;
|
|
558
|
+
} else {
|
|
559
|
+
this.ring = new import_core7.RingBuffer(cap);
|
|
560
|
+
this.arr = null;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
get length() {
|
|
564
|
+
return this.ring != null ? this.ring.size : this.arr.length;
|
|
565
|
+
}
|
|
566
|
+
push(item) {
|
|
567
|
+
if (this.ring != null) this.ring.push(item);
|
|
568
|
+
else this.arr.push(item);
|
|
569
|
+
}
|
|
570
|
+
/** Drop-oldest — O(1) in bounded mode. Returns undefined when empty. */
|
|
571
|
+
shift() {
|
|
572
|
+
if (this.ring != null) return this.ring.shift();
|
|
573
|
+
return this.arr.shift();
|
|
574
|
+
}
|
|
575
|
+
/** Full drain — returns contents, resets to empty. */
|
|
576
|
+
drain() {
|
|
577
|
+
if (this.ring != null) {
|
|
578
|
+
const out2 = this.ring.toArray();
|
|
579
|
+
this.ring.clear();
|
|
580
|
+
return out2;
|
|
581
|
+
}
|
|
582
|
+
const out = this.arr;
|
|
583
|
+
this.arr = [];
|
|
584
|
+
return out;
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
function coerceError(err) {
|
|
588
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
589
|
+
}
|
|
590
|
+
function resolveBackoff(backoff) {
|
|
591
|
+
if (backoff === void 0) return null;
|
|
592
|
+
if (typeof backoff === "string") return resolveBackoffPreset(backoff);
|
|
593
|
+
return backoff;
|
|
594
|
+
}
|
|
595
|
+
function reactiveSink(source, config) {
|
|
596
|
+
const {
|
|
597
|
+
name,
|
|
598
|
+
onTransportError,
|
|
599
|
+
retry: retry2,
|
|
600
|
+
backpressure,
|
|
601
|
+
batchSize = Number.POSITIVE_INFINITY,
|
|
602
|
+
flushIntervalMs = 0,
|
|
603
|
+
serialize,
|
|
604
|
+
stopOn,
|
|
605
|
+
onUpstreamMessage,
|
|
606
|
+
onDispose,
|
|
607
|
+
send,
|
|
608
|
+
sendBatch,
|
|
609
|
+
ctx: ctxValue
|
|
610
|
+
} = config;
|
|
611
|
+
if (!send && !sendBatch) {
|
|
612
|
+
throw new Error("reactiveSink: `send` or `sendBatch` must be provided");
|
|
613
|
+
}
|
|
614
|
+
const ctx = ctxValue;
|
|
615
|
+
const maxAttempts = Math.max(1, retry2?.maxAttempts ?? 1);
|
|
616
|
+
const backoffStrategy = resolveBackoff(
|
|
617
|
+
retry2?.backoff ?? (maxAttempts > 1 ? "exponential" : void 0)
|
|
618
|
+
);
|
|
619
|
+
const shouldRetry = retry2?.shouldRetry ?? (() => true);
|
|
620
|
+
const useBuffering = sendBatch !== void 0 || batchSize < Number.POSITIVE_INFINITY || flushIntervalMs > 0;
|
|
621
|
+
const nameFor = (suffix) => name ? `${name}::${suffix}` : void 0;
|
|
622
|
+
const sent = (0, import_core7.node)([], {
|
|
623
|
+
initial: void 0,
|
|
624
|
+
equals: () => false,
|
|
625
|
+
name: nameFor("sent")
|
|
626
|
+
});
|
|
627
|
+
const failed = (0, import_core7.node)([], { initial: null, name: nameFor("failed") });
|
|
628
|
+
const inFlightCountNode = (0, import_core7.node)([], { initial: 0, name: nameFor("inFlight") });
|
|
629
|
+
const errorsNode = (0, import_core7.node)([], {
|
|
630
|
+
initial: null,
|
|
631
|
+
name: nameFor("errors")
|
|
632
|
+
});
|
|
633
|
+
const bufferedNode = useBuffering ? (0, import_core7.node)([], { initial: 0, name: nameFor("buffered") }) : void 0;
|
|
634
|
+
const pausedNode = backpressure ? (0, import_core7.node)([], { initial: false, name: nameFor("paused") }) : void 0;
|
|
635
|
+
let inFlightCount = 0;
|
|
636
|
+
const bumpInFlight = (delta) => {
|
|
637
|
+
inFlightCount += delta;
|
|
638
|
+
inFlightCountNode.down([[import_core7.DATA, inFlightCount]]);
|
|
639
|
+
};
|
|
640
|
+
const reportError = (err) => {
|
|
641
|
+
try {
|
|
642
|
+
onTransportError?.(err);
|
|
643
|
+
} catch {
|
|
644
|
+
}
|
|
645
|
+
try {
|
|
646
|
+
errorsNode.down([[import_core7.DATA, err]]);
|
|
647
|
+
} catch {
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
const inFlightPromises = /* @__PURE__ */ new Set();
|
|
651
|
+
const trackPromise = (p) => {
|
|
652
|
+
inFlightPromises.add(p);
|
|
653
|
+
const done = () => inFlightPromises.delete(p);
|
|
654
|
+
p.then(done, done);
|
|
655
|
+
};
|
|
656
|
+
const scheduleRetry = (runAgain, attempt, error) => {
|
|
657
|
+
const raw = backoffStrategy ? backoffStrategy(attempt - 1, error, null) : 0;
|
|
658
|
+
const delayNs = raw === null || raw === void 0 ? 0 : typeof raw === "number" && raw > 0 ? raw : 0;
|
|
659
|
+
const delayMs = Math.max(1, Math.ceil(delayNs / NS_PER_MS));
|
|
660
|
+
return new Promise((resolve) => {
|
|
661
|
+
setTimeout(() => resolve(runAgain()), delayMs);
|
|
662
|
+
});
|
|
663
|
+
};
|
|
664
|
+
const isThenable = (v) => v != null && typeof v === "object" && typeof v.then === "function";
|
|
665
|
+
const performSend = (value) => {
|
|
666
|
+
let payload;
|
|
667
|
+
try {
|
|
668
|
+
payload = serialize ? serialize(value) : value;
|
|
669
|
+
} catch (rawErr) {
|
|
670
|
+
const error = coerceError(rawErr);
|
|
671
|
+
reportError({ stage: "serialize", error, value });
|
|
672
|
+
failed.down([[import_core7.DATA, { value, error, attempts: 0 }]]);
|
|
673
|
+
return Promise.resolve();
|
|
674
|
+
}
|
|
675
|
+
let attempt = 0;
|
|
676
|
+
const onError = (rawErr) => {
|
|
677
|
+
bumpInFlight(-1);
|
|
678
|
+
const error = coerceError(rawErr);
|
|
679
|
+
reportError({ stage: "send", error, value, attempt });
|
|
680
|
+
const more = attempt < maxAttempts && shouldRetry(error, attempt);
|
|
681
|
+
if (!more) {
|
|
682
|
+
failed.down([[import_core7.DATA, { value, error, attempts: attempt }]]);
|
|
683
|
+
return void 0;
|
|
684
|
+
}
|
|
685
|
+
return scheduleRetry(run, attempt, error);
|
|
686
|
+
};
|
|
687
|
+
const onSuccess = () => {
|
|
688
|
+
bumpInFlight(-1);
|
|
689
|
+
sent.down([[import_core7.DATA, value]]);
|
|
690
|
+
};
|
|
691
|
+
function run() {
|
|
692
|
+
attempt += 1;
|
|
693
|
+
bumpInFlight(1);
|
|
694
|
+
let result;
|
|
695
|
+
try {
|
|
696
|
+
result = send(payload, ctx);
|
|
697
|
+
} catch (rawErr) {
|
|
698
|
+
return onError(rawErr) ?? Promise.resolve();
|
|
699
|
+
}
|
|
700
|
+
if (isThenable(result)) {
|
|
701
|
+
return result.then(onSuccess, (rawErr) => onError(rawErr));
|
|
702
|
+
}
|
|
703
|
+
onSuccess();
|
|
704
|
+
return Promise.resolve();
|
|
705
|
+
}
|
|
706
|
+
return run();
|
|
707
|
+
};
|
|
708
|
+
const maxBuf = backpressure?.maxBuffer ?? Number.POSITIVE_INFINITY;
|
|
709
|
+
const buffer = new BackpressureBuffer(maxBuf);
|
|
710
|
+
let flushTimer;
|
|
711
|
+
let disposed = false;
|
|
712
|
+
const updateBuffered = () => {
|
|
713
|
+
bufferedNode?.down([[import_core7.DATA, buffer.length]]);
|
|
714
|
+
};
|
|
715
|
+
const markPaused = (paused) => {
|
|
716
|
+
if (!pausedNode) return;
|
|
717
|
+
pausedNode.down([[import_core7.DATA, paused]]);
|
|
718
|
+
};
|
|
719
|
+
const bpStrategy = backpressure?.strategy ?? "drop-oldest";
|
|
720
|
+
const pushWithBackpressure = (value, payload) => {
|
|
721
|
+
const entry = { value, payload };
|
|
722
|
+
if (buffer.length < maxBuf) {
|
|
723
|
+
buffer.push(entry);
|
|
724
|
+
updateBuffered();
|
|
725
|
+
return true;
|
|
726
|
+
}
|
|
727
|
+
if (bpStrategy === "drop-oldest") {
|
|
728
|
+
const dropped = buffer.shift();
|
|
729
|
+
buffer.push(entry);
|
|
730
|
+
updateBuffered();
|
|
731
|
+
markPaused(true);
|
|
732
|
+
failed.down([
|
|
733
|
+
[
|
|
734
|
+
import_core7.DATA,
|
|
735
|
+
{
|
|
736
|
+
value: dropped.value,
|
|
737
|
+
error: new Error("backpressure: buffer overflow \u2014 dropped oldest"),
|
|
738
|
+
attempts: 0
|
|
739
|
+
}
|
|
740
|
+
]
|
|
741
|
+
]);
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
if (bpStrategy === "drop-newest") {
|
|
745
|
+
markPaused(true);
|
|
746
|
+
failed.down([
|
|
747
|
+
[
|
|
748
|
+
import_core7.DATA,
|
|
749
|
+
{
|
|
750
|
+
value,
|
|
751
|
+
error: new Error("backpressure: buffer overflow \u2014 dropped newest"),
|
|
752
|
+
attempts: 0
|
|
753
|
+
}
|
|
754
|
+
]
|
|
755
|
+
]);
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
const err = new Error("backpressure: buffer overflow");
|
|
759
|
+
reportError({ stage: "send", error: err, value });
|
|
760
|
+
failed.down([[import_core7.DATA, { value, error: err, attempts: 0 }]]);
|
|
761
|
+
markPaused(true);
|
|
762
|
+
return false;
|
|
763
|
+
};
|
|
764
|
+
const performBufferedBatchFlush = (chunk) => {
|
|
765
|
+
let attempt = 0;
|
|
766
|
+
const payloads = chunk.map((e) => e.payload);
|
|
767
|
+
const onError = (rawErr) => {
|
|
768
|
+
bumpInFlight(-1);
|
|
769
|
+
const error = coerceError(rawErr);
|
|
770
|
+
reportError({ stage: "send", error, value: chunk.map((e) => e.value), attempt });
|
|
771
|
+
const more = attempt < maxAttempts && shouldRetry(error, attempt);
|
|
772
|
+
if (!more) {
|
|
773
|
+
for (const { value: v } of chunk) {
|
|
774
|
+
failed.down([[import_core7.DATA, { value: v, error, attempts: attempt }]]);
|
|
775
|
+
}
|
|
776
|
+
return void 0;
|
|
777
|
+
}
|
|
778
|
+
return scheduleRetry(run, attempt, error);
|
|
779
|
+
};
|
|
780
|
+
const onSuccess = () => {
|
|
781
|
+
bumpInFlight(-1);
|
|
782
|
+
for (const { value: v } of chunk) sent.down([[import_core7.DATA, v]]);
|
|
783
|
+
};
|
|
784
|
+
function run() {
|
|
785
|
+
attempt += 1;
|
|
786
|
+
bumpInFlight(1);
|
|
787
|
+
let result;
|
|
788
|
+
try {
|
|
789
|
+
result = sendBatch(payloads, ctx);
|
|
790
|
+
} catch (rawErr) {
|
|
791
|
+
return onError(rawErr) ?? Promise.resolve();
|
|
792
|
+
}
|
|
793
|
+
if (isThenable(result)) {
|
|
794
|
+
return result.then(onSuccess, (rawErr) => onError(rawErr));
|
|
795
|
+
}
|
|
796
|
+
onSuccess();
|
|
797
|
+
return Promise.resolve();
|
|
798
|
+
}
|
|
799
|
+
return run();
|
|
800
|
+
};
|
|
801
|
+
const performBufferedPerRecordFlush = async (chunk) => {
|
|
802
|
+
for (const entry of chunk) {
|
|
803
|
+
await performPreSerializedSend(entry.value, entry.payload);
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
const performPreSerializedSend = (value, payload) => {
|
|
807
|
+
let attempt = 0;
|
|
808
|
+
const onError = (rawErr) => {
|
|
809
|
+
bumpInFlight(-1);
|
|
810
|
+
const error = coerceError(rawErr);
|
|
811
|
+
reportError({ stage: "send", error, value, attempt });
|
|
812
|
+
const more = attempt < maxAttempts && shouldRetry(error, attempt);
|
|
813
|
+
if (!more) {
|
|
814
|
+
failed.down([[import_core7.DATA, { value, error, attempts: attempt }]]);
|
|
815
|
+
return void 0;
|
|
816
|
+
}
|
|
817
|
+
return scheduleRetry(run, attempt, error);
|
|
818
|
+
};
|
|
819
|
+
const onSuccess = () => {
|
|
820
|
+
bumpInFlight(-1);
|
|
821
|
+
sent.down([[import_core7.DATA, value]]);
|
|
822
|
+
};
|
|
823
|
+
function run() {
|
|
824
|
+
attempt += 1;
|
|
825
|
+
bumpInFlight(1);
|
|
826
|
+
let result;
|
|
827
|
+
try {
|
|
828
|
+
result = send(payload, ctx);
|
|
829
|
+
} catch (rawErr) {
|
|
830
|
+
return onError(rawErr) ?? Promise.resolve();
|
|
831
|
+
}
|
|
832
|
+
if (isThenable(result)) {
|
|
833
|
+
return result.then(onSuccess, (rawErr) => onError(rawErr));
|
|
834
|
+
}
|
|
835
|
+
onSuccess();
|
|
836
|
+
return Promise.resolve();
|
|
837
|
+
}
|
|
838
|
+
return run();
|
|
839
|
+
};
|
|
840
|
+
const doFlush = () => {
|
|
841
|
+
if (disposed || buffer.length === 0) return Promise.resolve();
|
|
842
|
+
const chunk = buffer.drain();
|
|
843
|
+
updateBuffered();
|
|
844
|
+
markPaused(false);
|
|
845
|
+
if (sendBatch !== void 0) {
|
|
846
|
+
const p2 = performBufferedBatchFlush(chunk);
|
|
847
|
+
trackPromise(p2);
|
|
848
|
+
return p2;
|
|
849
|
+
}
|
|
850
|
+
const p = performBufferedPerRecordFlush(chunk);
|
|
851
|
+
trackPromise(p);
|
|
852
|
+
return p;
|
|
853
|
+
};
|
|
854
|
+
const scheduleFlush = () => {
|
|
855
|
+
if (flushTimer !== void 0 || disposed) return;
|
|
856
|
+
if (flushIntervalMs <= 0) return;
|
|
857
|
+
flushTimer = setTimeout(() => {
|
|
858
|
+
flushTimer = void 0;
|
|
859
|
+
void doFlush();
|
|
860
|
+
}, flushIntervalMs);
|
|
861
|
+
};
|
|
862
|
+
const unsub = source.subscribe((msgs) => {
|
|
863
|
+
for (const msg of msgs) {
|
|
864
|
+
const type = msg[0];
|
|
865
|
+
if (type !== import_core7.DATA) {
|
|
866
|
+
try {
|
|
867
|
+
onUpstreamMessage?.(msg);
|
|
868
|
+
} catch {
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (type === import_core7.DATA) {
|
|
872
|
+
const value = msg[1];
|
|
873
|
+
if (useBuffering) {
|
|
874
|
+
let payload;
|
|
875
|
+
if (serialize) {
|
|
876
|
+
try {
|
|
877
|
+
payload = serialize(value);
|
|
878
|
+
} catch (rawErr) {
|
|
879
|
+
const error = coerceError(rawErr);
|
|
880
|
+
reportError({ stage: "serialize", error, value });
|
|
881
|
+
failed.down([[import_core7.DATA, { value, error, attempts: 0 }]]);
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
} else {
|
|
885
|
+
payload = value;
|
|
886
|
+
}
|
|
887
|
+
const admitted = pushWithBackpressure(value, payload);
|
|
888
|
+
if (!admitted) continue;
|
|
889
|
+
if (buffer.length >= batchSize) void doFlush();
|
|
890
|
+
else scheduleFlush();
|
|
891
|
+
} else {
|
|
892
|
+
const p = performSend(value);
|
|
893
|
+
trackPromise(p);
|
|
894
|
+
}
|
|
895
|
+
} else if (import_core7.defaultConfig.messageTier(type) >= 3) {
|
|
896
|
+
if (useBuffering) {
|
|
897
|
+
if (flushTimer !== void 0) {
|
|
898
|
+
clearTimeout(flushTimer);
|
|
899
|
+
flushTimer = void 0;
|
|
900
|
+
}
|
|
901
|
+
void doFlush();
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
let stopUnsub;
|
|
907
|
+
if (stopOn) {
|
|
908
|
+
let firstBatchSeen = false;
|
|
909
|
+
stopUnsub = stopOn.subscribe((msgs) => {
|
|
910
|
+
if (!firstBatchSeen) {
|
|
911
|
+
firstBatchSeen = true;
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
if (msgs.length > 0 && !teardownRequested) dispose();
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
let teardownRequested = false;
|
|
918
|
+
const dispose = () => {
|
|
919
|
+
if (teardownRequested) return;
|
|
920
|
+
teardownRequested = true;
|
|
921
|
+
if (flushTimer !== void 0) {
|
|
922
|
+
clearTimeout(flushTimer);
|
|
923
|
+
flushTimer = void 0;
|
|
924
|
+
}
|
|
925
|
+
if (useBuffering) void doFlush();
|
|
926
|
+
disposed = true;
|
|
927
|
+
stopUnsub?.();
|
|
928
|
+
unsub();
|
|
929
|
+
const tearDown = (n) => {
|
|
930
|
+
try {
|
|
931
|
+
n.down([[import_core7.TEARDOWN]]);
|
|
932
|
+
} catch {
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
tearDown(errorsNode);
|
|
936
|
+
tearDown(failed);
|
|
937
|
+
tearDown(sent);
|
|
938
|
+
tearDown(inFlightCountNode);
|
|
939
|
+
if (bufferedNode) tearDown(bufferedNode);
|
|
940
|
+
if (pausedNode) tearDown(pausedNode);
|
|
941
|
+
try {
|
|
942
|
+
onDispose?.();
|
|
943
|
+
} catch {
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
const handle = {
|
|
947
|
+
dispose,
|
|
948
|
+
sent,
|
|
949
|
+
failed,
|
|
950
|
+
inFlight: inFlightCountNode,
|
|
951
|
+
errors: errorsNode
|
|
952
|
+
};
|
|
953
|
+
if (useBuffering) {
|
|
954
|
+
handle.buffered = bufferedNode;
|
|
955
|
+
handle.flush = async () => {
|
|
956
|
+
if (disposed) return;
|
|
957
|
+
await doFlush();
|
|
958
|
+
await Promise.all(inFlightPromises);
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
if (pausedNode) handle.paused = pausedNode;
|
|
962
|
+
void import_core7.COMPLETE;
|
|
963
|
+
void import_core7.ERROR;
|
|
964
|
+
return handle;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// src/base/io/http.ts
|
|
968
|
+
function fromHTTP(url, opts) {
|
|
969
|
+
const {
|
|
970
|
+
method = "GET",
|
|
971
|
+
headers,
|
|
972
|
+
body: bodyOpt,
|
|
973
|
+
transform = (r) => r.json(),
|
|
974
|
+
timeoutNs = 30 * NS_PER_SEC,
|
|
975
|
+
signal: externalSignal,
|
|
976
|
+
completeAfterFetch = false,
|
|
977
|
+
refetchOnSubscribe = false,
|
|
978
|
+
...rest
|
|
979
|
+
} = opts ?? {};
|
|
980
|
+
const fetchCount = (0, import_core8.node)([], { initial: 0, name: `${rest.name ?? "http"}/fetchCount` });
|
|
981
|
+
const lastUpdated = (0, import_core8.node)([], { initial: 0, name: `${rest.name ?? "http"}/lastUpdated` });
|
|
982
|
+
const fetched = (0, import_core8.node)([], { initial: false, name: `${rest.name ?? "http"}/fetched` });
|
|
983
|
+
let fetchCountLocal = 0;
|
|
984
|
+
const body = bodyOpt !== void 0 ? typeof bodyOpt === "string" ? bodyOpt : JSON.stringify(bodyOpt) : void 0;
|
|
985
|
+
const runFetch = (a) => {
|
|
986
|
+
const abort = new AbortController();
|
|
987
|
+
let active = true;
|
|
988
|
+
if (externalSignal?.aborted) {
|
|
989
|
+
active = false;
|
|
990
|
+
a.down([[import_core8.ERROR, externalSignal.reason ?? new Error("Aborted")]]);
|
|
991
|
+
return () => {
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
externalSignal?.addEventListener("abort", () => abort.abort(externalSignal.reason), {
|
|
995
|
+
once: true
|
|
996
|
+
});
|
|
997
|
+
const timeoutId = setTimeout(
|
|
998
|
+
() => abort.abort(new Error("Request timeout")),
|
|
999
|
+
Math.ceil(timeoutNs / NS_PER_MS)
|
|
1000
|
+
);
|
|
1001
|
+
fetch(url, { method, headers, body, signal: abort.signal }).then(async (res) => {
|
|
1002
|
+
clearTimeout(timeoutId);
|
|
1003
|
+
if (!active) return;
|
|
1004
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
1005
|
+
const data = await transform(res);
|
|
1006
|
+
if (!active) return;
|
|
1007
|
+
(0, import_core8.batch)(() => {
|
|
1008
|
+
fetchCountLocal += 1;
|
|
1009
|
+
fetchCount.down([[import_core8.DATA, fetchCountLocal]]);
|
|
1010
|
+
lastUpdated.down([[import_core8.DATA, (0, import_core8.wallClockNs)()]]);
|
|
1011
|
+
fetched.down([[import_core8.DATA, true]]);
|
|
1012
|
+
a.emit(data);
|
|
1013
|
+
});
|
|
1014
|
+
if (completeAfterFetch) a.down([[import_core8.COMPLETE]]);
|
|
1015
|
+
}).catch((err) => {
|
|
1016
|
+
clearTimeout(timeoutId);
|
|
1017
|
+
if (!active) return;
|
|
1018
|
+
if (err && err.name === "AbortError") return;
|
|
1019
|
+
a.down([[import_core8.ERROR, err]]);
|
|
1020
|
+
});
|
|
1021
|
+
return () => {
|
|
1022
|
+
active = false;
|
|
1023
|
+
abort.abort();
|
|
1024
|
+
};
|
|
1025
|
+
};
|
|
1026
|
+
const sourceNode = (0, import_core8.node)(
|
|
1027
|
+
[],
|
|
1028
|
+
(_data, a) => runFetch({
|
|
1029
|
+
emit: (v) => a.emit(v),
|
|
1030
|
+
down: (msgs) => a.down(msgs)
|
|
1031
|
+
}),
|
|
1032
|
+
{
|
|
1033
|
+
...sourceOpts(rest),
|
|
1034
|
+
// `resubscribable: true` when refetchOnSubscribe — each new activation
|
|
1035
|
+
// (subscribe after full deactivation) re-runs the producer fn → fresh
|
|
1036
|
+
// fetch. Default (cache-once) stays non-resubscribable: producer runs
|
|
1037
|
+
// once on first activation, cached DATA replays to late subscribers.
|
|
1038
|
+
resubscribable: refetchOnSubscribe
|
|
1039
|
+
}
|
|
1040
|
+
);
|
|
1041
|
+
const tracked = withStatus(sourceNode);
|
|
1042
|
+
return {
|
|
1043
|
+
...tracked,
|
|
1044
|
+
fetchCount,
|
|
1045
|
+
lastUpdated,
|
|
1046
|
+
fetched
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
function toHTTP(source, url, opts) {
|
|
1050
|
+
const {
|
|
1051
|
+
method = "POST",
|
|
1052
|
+
headers = { "Content-Type": "application/json" },
|
|
1053
|
+
serialize = (v) => JSON.stringify(v),
|
|
1054
|
+
timeoutNs,
|
|
1055
|
+
batchFormat = "json-array",
|
|
1056
|
+
batchSize,
|
|
1057
|
+
flushIntervalMs,
|
|
1058
|
+
retry: retry2,
|
|
1059
|
+
onTransportError
|
|
1060
|
+
} = opts ?? {};
|
|
1061
|
+
const sendOne = async (body) => {
|
|
1062
|
+
const controller = timeoutNs !== void 0 ? new AbortController() : void 0;
|
|
1063
|
+
let timeoutId;
|
|
1064
|
+
if (controller && timeoutNs !== void 0) {
|
|
1065
|
+
timeoutId = setTimeout(
|
|
1066
|
+
() => controller.abort(new Error("Request timeout")),
|
|
1067
|
+
Math.ceil(timeoutNs / NS_PER_MS)
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
try {
|
|
1071
|
+
const res = await fetch(url, {
|
|
1072
|
+
method,
|
|
1073
|
+
headers,
|
|
1074
|
+
body,
|
|
1075
|
+
signal: controller?.signal
|
|
1076
|
+
});
|
|
1077
|
+
const drain = async () => {
|
|
1078
|
+
try {
|
|
1079
|
+
await res.arrayBuffer?.();
|
|
1080
|
+
} catch {
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
if (!res.ok) {
|
|
1084
|
+
await drain();
|
|
1085
|
+
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
1086
|
+
}
|
|
1087
|
+
await drain();
|
|
1088
|
+
} finally {
|
|
1089
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
const buffered = batchSize !== void 0 || flushIntervalMs !== void 0;
|
|
1093
|
+
if (buffered) {
|
|
1094
|
+
return reactiveSink(source, {
|
|
1095
|
+
onTransportError,
|
|
1096
|
+
retry: retry2,
|
|
1097
|
+
batchSize,
|
|
1098
|
+
flushIntervalMs,
|
|
1099
|
+
sendBatch: async (chunk) => {
|
|
1100
|
+
let body;
|
|
1101
|
+
if (batchFormat === "ndjson") {
|
|
1102
|
+
body = chunk.map((v) => {
|
|
1103
|
+
const s = serialize(v);
|
|
1104
|
+
return typeof s === "string" ? s : new TextDecoder().decode(s);
|
|
1105
|
+
}).join("\n");
|
|
1106
|
+
} else {
|
|
1107
|
+
body = JSON.stringify(chunk);
|
|
1108
|
+
}
|
|
1109
|
+
await sendOne(body);
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
return reactiveSink(source, {
|
|
1114
|
+
onTransportError,
|
|
1115
|
+
retry: retry2,
|
|
1116
|
+
serialize,
|
|
1117
|
+
send: async (payload) => {
|
|
1118
|
+
await sendOne(payload);
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
function fromHTTPStream(url, opts) {
|
|
1123
|
+
const { method = "GET", headers, body: bodyOpt, signal: externalSignal, ...rest } = opts ?? {};
|
|
1124
|
+
return (0, import_core8.node)(
|
|
1125
|
+
[],
|
|
1126
|
+
(_data, a) => {
|
|
1127
|
+
let active = true;
|
|
1128
|
+
const abort = new AbortController();
|
|
1129
|
+
if (externalSignal?.aborted) {
|
|
1130
|
+
a.down([[import_core8.ERROR, externalSignal.reason ?? new Error("Aborted")]]);
|
|
1131
|
+
return () => {
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
externalSignal?.addEventListener("abort", () => abort.abort(externalSignal.reason), {
|
|
1135
|
+
once: true
|
|
1136
|
+
});
|
|
1137
|
+
const body = bodyOpt !== void 0 ? typeof bodyOpt === "string" ? bodyOpt : JSON.stringify(bodyOpt) : void 0;
|
|
1138
|
+
const run = async () => {
|
|
1139
|
+
try {
|
|
1140
|
+
const res = await fetch(url, { method, headers, body, signal: abort.signal });
|
|
1141
|
+
if (!active) return;
|
|
1142
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
1143
|
+
if (!res.body) throw new Error("HTTP response has no body");
|
|
1144
|
+
const reader = res.body.getReader();
|
|
1145
|
+
while (active) {
|
|
1146
|
+
const { value, done } = await reader.read();
|
|
1147
|
+
if (done) break;
|
|
1148
|
+
if (value) a.emit(value);
|
|
1149
|
+
}
|
|
1150
|
+
if (active) a.down([[import_core8.COMPLETE]]);
|
|
1151
|
+
} catch (err) {
|
|
1152
|
+
if (!active) return;
|
|
1153
|
+
if (err && err.name === "AbortError") return;
|
|
1154
|
+
a.down([[import_core8.ERROR, err]]);
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
void run();
|
|
1158
|
+
return () => {
|
|
1159
|
+
active = false;
|
|
1160
|
+
abort.abort();
|
|
1161
|
+
};
|
|
1162
|
+
},
|
|
1163
|
+
sourceOpts(rest)
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
function fromHTTPPoll(url, opts) {
|
|
1167
|
+
const { intervalMs = 5e3, ...httpOpts } = opts ?? {};
|
|
1168
|
+
return (0, import_extra2.switchMap)(
|
|
1169
|
+
(0, import_extra2.fromTimer)(intervalMs, { period: intervalMs }),
|
|
1170
|
+
() => fromHTTP(url, { ...httpOpts, completeAfterFetch: true }).node
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// src/base/io/kafka.ts
|
|
1175
|
+
var import_core9 = require("@graphrefly/pure-ts/core");
|
|
1176
|
+
function fromKafka(consumer, topic, opts) {
|
|
1177
|
+
const {
|
|
1178
|
+
fromBeginning = false,
|
|
1179
|
+
deserialize = (buf) => {
|
|
1180
|
+
if (buf === null) return null;
|
|
1181
|
+
try {
|
|
1182
|
+
return JSON.parse(buf.toString());
|
|
1183
|
+
} catch {
|
|
1184
|
+
return buf.toString();
|
|
1185
|
+
}
|
|
1186
|
+
},
|
|
1187
|
+
...rest
|
|
1188
|
+
} = opts ?? {};
|
|
1189
|
+
return (0, import_core9.node)(
|
|
1190
|
+
[],
|
|
1191
|
+
(_data, a) => {
|
|
1192
|
+
let active = true;
|
|
1193
|
+
const start = async () => {
|
|
1194
|
+
try {
|
|
1195
|
+
await consumer.subscribe({ topic, fromBeginning });
|
|
1196
|
+
await consumer.run({
|
|
1197
|
+
eachMessage: async ({ topic: t, partition, message: msg }) => {
|
|
1198
|
+
if (!active) return;
|
|
1199
|
+
const headers = {};
|
|
1200
|
+
if (msg.headers) {
|
|
1201
|
+
for (const [k, v] of Object.entries(msg.headers)) {
|
|
1202
|
+
if (v !== void 0) headers[k] = typeof v === "string" ? v : v.toString();
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
a.emit({
|
|
1206
|
+
topic: t,
|
|
1207
|
+
partition,
|
|
1208
|
+
key: msg.key?.toString() ?? null,
|
|
1209
|
+
value: deserialize(msg.value),
|
|
1210
|
+
headers,
|
|
1211
|
+
offset: msg.offset,
|
|
1212
|
+
timestamp: msg.timestamp,
|
|
1213
|
+
timestampNs: (0, import_core9.wallClockNs)()
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
} catch (err) {
|
|
1218
|
+
if (active) a.down([[import_core9.ERROR, err]]);
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
void start();
|
|
1222
|
+
return () => {
|
|
1223
|
+
active = false;
|
|
1224
|
+
};
|
|
1225
|
+
},
|
|
1226
|
+
sourceOpts(rest)
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
1229
|
+
function toKafka(source, kafkaProducer, topic, opts) {
|
|
1230
|
+
const { serialize = (v) => JSON.stringify(v), keyExtractor, onTransportError } = opts ?? {};
|
|
1231
|
+
return reactiveSink(source, {
|
|
1232
|
+
onTransportError,
|
|
1233
|
+
send: async (value) => {
|
|
1234
|
+
const key = keyExtractor?.(value) ?? null;
|
|
1235
|
+
const serialized = serialize(value);
|
|
1236
|
+
await kafkaProducer.send({
|
|
1237
|
+
topic,
|
|
1238
|
+
messages: [{ key, value: Buffer.from(serialized) }]
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// src/base/io/kysely.ts
|
|
1245
|
+
var import_core10 = require("@graphrefly/pure-ts/core");
|
|
1246
|
+
function fromKysely(query, opts) {
|
|
1247
|
+
const { mapRow = (r) => r, ...rest } = opts ?? {};
|
|
1248
|
+
return (0, import_core10.node)(
|
|
1249
|
+
[],
|
|
1250
|
+
(_data, a) => {
|
|
1251
|
+
let active = true;
|
|
1252
|
+
void query.execute().then((rows) => {
|
|
1253
|
+
if (!active) return;
|
|
1254
|
+
a.emit(rows.map(mapRow));
|
|
1255
|
+
a.down([[import_core10.COMPLETE]]);
|
|
1256
|
+
}).catch((err) => {
|
|
1257
|
+
if (!active) return;
|
|
1258
|
+
try {
|
|
1259
|
+
a.down([[import_core10.ERROR, err instanceof Error ? err : new Error(String(err))]]);
|
|
1260
|
+
} catch {
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
return () => {
|
|
1264
|
+
active = false;
|
|
1265
|
+
};
|
|
1266
|
+
},
|
|
1267
|
+
{ ...rest, describeKind: "producer", completeWhenDepsComplete: false }
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// src/base/composition/external-register.ts
|
|
1272
|
+
var import_core11 = require("@graphrefly/pure-ts/core");
|
|
1273
|
+
function sourceOpts2(opts) {
|
|
1274
|
+
return { describeKind: "producer", ...opts };
|
|
1275
|
+
}
|
|
1276
|
+
function externalProducer(register, opts) {
|
|
1277
|
+
return (0, import_core11.node)((_data, a) => {
|
|
1278
|
+
let active = true;
|
|
1279
|
+
const triad = {
|
|
1280
|
+
emit(value) {
|
|
1281
|
+
if (!active) return;
|
|
1282
|
+
a.emit(value);
|
|
1283
|
+
},
|
|
1284
|
+
error(err) {
|
|
1285
|
+
if (!active) return;
|
|
1286
|
+
active = false;
|
|
1287
|
+
a.down([[import_core11.ERROR, err]]);
|
|
1288
|
+
},
|
|
1289
|
+
complete() {
|
|
1290
|
+
if (!active) return;
|
|
1291
|
+
active = false;
|
|
1292
|
+
a.down([[import_core11.COMPLETE]]);
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
let cleanup;
|
|
1296
|
+
try {
|
|
1297
|
+
const ret = register(triad);
|
|
1298
|
+
cleanup = typeof ret === "function" ? ret : void 0;
|
|
1299
|
+
} catch (err) {
|
|
1300
|
+
triad.error(err);
|
|
1301
|
+
return () => {
|
|
1302
|
+
active = false;
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
return () => {
|
|
1306
|
+
active = false;
|
|
1307
|
+
try {
|
|
1308
|
+
cleanup?.();
|
|
1309
|
+
} catch {
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
}, sourceOpts2(opts));
|
|
1313
|
+
}
|
|
1314
|
+
function externalBundle(register, channels, opts) {
|
|
1315
|
+
let active = true;
|
|
1316
|
+
let cleanup;
|
|
1317
|
+
let activatedCount = 0;
|
|
1318
|
+
let teardownCount = 0;
|
|
1319
|
+
const nodes = {};
|
|
1320
|
+
const channelNodes = [];
|
|
1321
|
+
const finishCleanup = () => {
|
|
1322
|
+
const fn = cleanup;
|
|
1323
|
+
cleanup = void 0;
|
|
1324
|
+
try {
|
|
1325
|
+
fn?.();
|
|
1326
|
+
} catch {
|
|
1327
|
+
}
|
|
1328
|
+
};
|
|
1329
|
+
for (const ch of channels) {
|
|
1330
|
+
const name = opts?.name ? `${opts.name}::${ch}` : ch;
|
|
1331
|
+
const chOpts = opts?.channelOpts?.[ch];
|
|
1332
|
+
const n = (0, import_core11.node)(
|
|
1333
|
+
(_data, _a) => {
|
|
1334
|
+
activatedCount++;
|
|
1335
|
+
return () => {
|
|
1336
|
+
teardownCount++;
|
|
1337
|
+
if (activatedCount > 0 && teardownCount >= activatedCount && teardownCount >= channels.length) {
|
|
1338
|
+
finishCleanup();
|
|
1339
|
+
}
|
|
1340
|
+
};
|
|
1341
|
+
},
|
|
1342
|
+
sourceOpts2({ ...chOpts, name })
|
|
1343
|
+
);
|
|
1344
|
+
nodes[ch] = n;
|
|
1345
|
+
channelNodes.push(n);
|
|
1346
|
+
}
|
|
1347
|
+
const bundle = {};
|
|
1348
|
+
for (const ch of channels) {
|
|
1349
|
+
bundle[ch] = (value) => {
|
|
1350
|
+
if (!active) return;
|
|
1351
|
+
nodes[ch].down([[import_core11.DATA, value]]);
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
bundle.error = (err) => {
|
|
1355
|
+
if (!active) return;
|
|
1356
|
+
active = false;
|
|
1357
|
+
(0, import_core11.batch)(() => {
|
|
1358
|
+
for (const n of channelNodes) n.down([[import_core11.ERROR, err]]);
|
|
1359
|
+
});
|
|
1360
|
+
finishCleanup();
|
|
1361
|
+
};
|
|
1362
|
+
bundle.complete = () => {
|
|
1363
|
+
if (!active) return;
|
|
1364
|
+
active = false;
|
|
1365
|
+
(0, import_core11.batch)(() => {
|
|
1366
|
+
for (const n of channelNodes) n.down([[import_core11.COMPLETE]]);
|
|
1367
|
+
});
|
|
1368
|
+
finishCleanup();
|
|
1369
|
+
};
|
|
1370
|
+
const ret = register(bundle);
|
|
1371
|
+
cleanup = typeof ret === "function" ? ret : void 0;
|
|
1372
|
+
const dispose = () => {
|
|
1373
|
+
if (!active) return;
|
|
1374
|
+
active = false;
|
|
1375
|
+
(0, import_core11.batch)(() => {
|
|
1376
|
+
for (const n of channelNodes) {
|
|
1377
|
+
try {
|
|
1378
|
+
n.down([[import_core11.COMPLETE]]);
|
|
1379
|
+
} catch {
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1383
|
+
finishCleanup();
|
|
1384
|
+
};
|
|
1385
|
+
return Object.assign(nodes, { dispose });
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
// src/base/io/mcp.ts
|
|
1389
|
+
function fromMCP(client, opts) {
|
|
1390
|
+
const { method = "notifications/message", onDisconnect, ...rest } = opts ?? {};
|
|
1391
|
+
return externalProducer(({ emit, error }) => {
|
|
1392
|
+
client.setNotificationHandler(method, (notification) => emit(notification));
|
|
1393
|
+
onDisconnect?.((err) => error(err ?? new Error("MCP client disconnected")));
|
|
1394
|
+
return () => client.setNotificationHandler(method, () => {
|
|
1395
|
+
});
|
|
1396
|
+
}, rest);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// src/base/io/nats.ts
|
|
1400
|
+
var import_core12 = require("@graphrefly/pure-ts/core");
|
|
1401
|
+
function fromNATS(client, subject, opts) {
|
|
1402
|
+
const decoder = new TextDecoder();
|
|
1403
|
+
const {
|
|
1404
|
+
queue,
|
|
1405
|
+
deserialize = (data) => {
|
|
1406
|
+
const text = decoder.decode(data);
|
|
1407
|
+
try {
|
|
1408
|
+
return JSON.parse(text);
|
|
1409
|
+
} catch {
|
|
1410
|
+
return text;
|
|
1411
|
+
}
|
|
1412
|
+
},
|
|
1413
|
+
...rest
|
|
1414
|
+
} = opts ?? {};
|
|
1415
|
+
return (0, import_core12.node)(
|
|
1416
|
+
[],
|
|
1417
|
+
(_data, a) => {
|
|
1418
|
+
let active = true;
|
|
1419
|
+
const sub = client.subscribe(subject, queue ? { queue } : void 0);
|
|
1420
|
+
const loop = async () => {
|
|
1421
|
+
try {
|
|
1422
|
+
for await (const msg of sub) {
|
|
1423
|
+
if (!active) return;
|
|
1424
|
+
const headers = {};
|
|
1425
|
+
if (msg.headers) {
|
|
1426
|
+
for (const k of msg.headers.keys()) {
|
|
1427
|
+
headers[k] = msg.headers.get(k);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
a.emit({
|
|
1431
|
+
subject: msg.subject,
|
|
1432
|
+
data: deserialize(msg.data),
|
|
1433
|
+
headers,
|
|
1434
|
+
reply: msg.reply,
|
|
1435
|
+
sid: msg.sid,
|
|
1436
|
+
timestampNs: (0, import_core12.wallClockNs)()
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
if (active) a.down([[import_core12.COMPLETE]]);
|
|
1440
|
+
} catch (err) {
|
|
1441
|
+
if (active) a.down([[import_core12.ERROR, err]]);
|
|
1442
|
+
}
|
|
1443
|
+
};
|
|
1444
|
+
void loop();
|
|
1445
|
+
return () => {
|
|
1446
|
+
active = false;
|
|
1447
|
+
};
|
|
1448
|
+
},
|
|
1449
|
+
sourceOpts(rest)
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
function toNATS(source, client, subject, opts) {
|
|
1453
|
+
const encoder = new TextEncoder();
|
|
1454
|
+
const { serialize = (v) => encoder.encode(JSON.stringify(v)), onTransportError } = opts ?? {};
|
|
1455
|
+
return reactiveSink(source, {
|
|
1456
|
+
onTransportError,
|
|
1457
|
+
send: (value) => {
|
|
1458
|
+
client.publish(subject, serialize(value));
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
// src/base/io/ndjson.ts
|
|
1464
|
+
var import_core13 = require("@graphrefly/pure-ts/core");
|
|
1465
|
+
function ndjsonRows(source, opts) {
|
|
1466
|
+
let cleanup;
|
|
1467
|
+
return (0, import_core13.node)(
|
|
1468
|
+
[source],
|
|
1469
|
+
(data, a, ctx) => {
|
|
1470
|
+
if (cleanup === void 0) {
|
|
1471
|
+
const store = ctx.store;
|
|
1472
|
+
cleanup = {
|
|
1473
|
+
onDeactivation: () => {
|
|
1474
|
+
delete store.buffer;
|
|
1475
|
+
}
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
const batch0 = data[0];
|
|
1479
|
+
if (batch0 == null || batch0.length === 0) return cleanup;
|
|
1480
|
+
const s = ctx.store;
|
|
1481
|
+
if (typeof s.buffer !== "string") s.buffer = "";
|
|
1482
|
+
for (const chunkRaw of batch0) {
|
|
1483
|
+
s.buffer = s.buffer + chunkRaw;
|
|
1484
|
+
const lines = s.buffer.split(/\r?\n/);
|
|
1485
|
+
s.buffer = lines.pop() ?? "";
|
|
1486
|
+
for (const line of lines) {
|
|
1487
|
+
if (!line.trim()) continue;
|
|
1488
|
+
try {
|
|
1489
|
+
a.emit(JSON.parse(line));
|
|
1490
|
+
} catch (err) {
|
|
1491
|
+
a.down([[import_core13.ERROR, err]]);
|
|
1492
|
+
return cleanup;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return cleanup;
|
|
1497
|
+
},
|
|
1498
|
+
{ describeKind: "derived", ...opts ?? {} }
|
|
1499
|
+
);
|
|
1500
|
+
}
|
|
1501
|
+
function fromNDJSON(source, opts) {
|
|
1502
|
+
return (0, import_core13.node)(
|
|
1503
|
+
[],
|
|
1504
|
+
(_data, a) => {
|
|
1505
|
+
let cancelled = false;
|
|
1506
|
+
const run = async () => {
|
|
1507
|
+
try {
|
|
1508
|
+
let buffer = "";
|
|
1509
|
+
for await (const chunk of source) {
|
|
1510
|
+
if (cancelled) return;
|
|
1511
|
+
buffer += chunk;
|
|
1512
|
+
const lines = buffer.split(/\r?\n/);
|
|
1513
|
+
buffer = lines.pop() ?? "";
|
|
1514
|
+
for (const line of lines) {
|
|
1515
|
+
if (cancelled) return;
|
|
1516
|
+
const trimmed = line.trim();
|
|
1517
|
+
if (!trimmed) continue;
|
|
1518
|
+
a.emit(JSON.parse(trimmed));
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
if (!cancelled && buffer.trim()) {
|
|
1522
|
+
a.emit(JSON.parse(buffer.trim()));
|
|
1523
|
+
}
|
|
1524
|
+
if (!cancelled) a.down([[import_core13.COMPLETE]]);
|
|
1525
|
+
} catch (err) {
|
|
1526
|
+
if (!cancelled) a.down([[import_core13.ERROR, err]]);
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
void run();
|
|
1530
|
+
return () => {
|
|
1531
|
+
cancelled = true;
|
|
1532
|
+
};
|
|
1533
|
+
},
|
|
1534
|
+
sourceOpts(opts)
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
// src/base/io/otel.ts
|
|
1539
|
+
var import_core14 = require("@graphrefly/pure-ts/core");
|
|
1540
|
+
function fromOTel(register, opts) {
|
|
1541
|
+
const nodes = externalBundle(
|
|
1542
|
+
({ traces, metrics, logs, error }) => {
|
|
1543
|
+
return register({
|
|
1544
|
+
onTraces: (spans) => {
|
|
1545
|
+
(0, import_core14.batch)(() => {
|
|
1546
|
+
for (const s of spans) traces(s);
|
|
1547
|
+
});
|
|
1548
|
+
},
|
|
1549
|
+
onMetrics: (ms) => {
|
|
1550
|
+
(0, import_core14.batch)(() => {
|
|
1551
|
+
for (const m of ms) metrics(m);
|
|
1552
|
+
});
|
|
1553
|
+
},
|
|
1554
|
+
onLogs: (ls) => {
|
|
1555
|
+
(0, import_core14.batch)(() => {
|
|
1556
|
+
for (const l of ls) logs(l);
|
|
1557
|
+
});
|
|
1558
|
+
},
|
|
1559
|
+
onError: error
|
|
1560
|
+
}) ?? void 0;
|
|
1561
|
+
},
|
|
1562
|
+
["traces", "metrics", "logs"],
|
|
1563
|
+
opts?.name ? { name: opts.name } : void 0
|
|
1564
|
+
);
|
|
1565
|
+
return nodes;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
// src/base/io/prisma.ts
|
|
1569
|
+
var import_core15 = require("@graphrefly/pure-ts/core");
|
|
1570
|
+
function fromPrisma(model, opts) {
|
|
1571
|
+
const { args, mapRow = (r) => r, ...rest } = opts ?? {};
|
|
1572
|
+
return (0, import_core15.node)(
|
|
1573
|
+
[],
|
|
1574
|
+
(_data, a) => {
|
|
1575
|
+
let active = true;
|
|
1576
|
+
void model.findMany(args).then((rows) => {
|
|
1577
|
+
if (!active) return;
|
|
1578
|
+
a.emit(rows.map(mapRow));
|
|
1579
|
+
a.down([[import_core15.COMPLETE]]);
|
|
1580
|
+
}).catch((err) => {
|
|
1581
|
+
if (!active) return;
|
|
1582
|
+
try {
|
|
1583
|
+
a.down([[import_core15.ERROR, err instanceof Error ? err : new Error(String(err))]]);
|
|
1584
|
+
} catch {
|
|
1585
|
+
}
|
|
1586
|
+
});
|
|
1587
|
+
return () => {
|
|
1588
|
+
active = false;
|
|
1589
|
+
};
|
|
1590
|
+
},
|
|
1591
|
+
{ ...rest, describeKind: "producer", completeWhenDepsComplete: false }
|
|
1592
|
+
);
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// src/base/io/prometheus.ts
|
|
1596
|
+
var import_core16 = require("@graphrefly/pure-ts/core");
|
|
1597
|
+
var import_extra3 = require("@graphrefly/pure-ts/extra");
|
|
1598
|
+
function fromPrometheus(endpoint, opts) {
|
|
1599
|
+
const {
|
|
1600
|
+
intervalNs = 15 * NS_PER_SEC,
|
|
1601
|
+
headers,
|
|
1602
|
+
timeoutNs = 10 * NS_PER_SEC,
|
|
1603
|
+
signal: externalSignal,
|
|
1604
|
+
maxConsecutiveErrors = 1
|
|
1605
|
+
} = opts ?? {};
|
|
1606
|
+
const intervalMs = Math.ceil(intervalNs / NS_PER_MS);
|
|
1607
|
+
let consecutiveErrors = 0;
|
|
1608
|
+
return (0, import_extra3.switchMap)(
|
|
1609
|
+
(0, import_extra3.fromTimer)(0, { period: intervalMs, signal: externalSignal }),
|
|
1610
|
+
() => (0, import_core16.node)([], (_data, a) => {
|
|
1611
|
+
let active = true;
|
|
1612
|
+
const abort = new AbortController();
|
|
1613
|
+
const timeoutId = setTimeout(
|
|
1614
|
+
() => abort.abort(new Error("Scrape timeout")),
|
|
1615
|
+
Math.ceil(timeoutNs / NS_PER_MS)
|
|
1616
|
+
);
|
|
1617
|
+
const run = async () => {
|
|
1618
|
+
try {
|
|
1619
|
+
const res = await fetch(endpoint, {
|
|
1620
|
+
headers: { Accept: "text/plain", ...headers },
|
|
1621
|
+
signal: abort.signal
|
|
1622
|
+
});
|
|
1623
|
+
clearTimeout(timeoutId);
|
|
1624
|
+
if (!active) return;
|
|
1625
|
+
if (!res.ok) throw new Error(`Prometheus scrape ${res.status}: ${res.statusText}`);
|
|
1626
|
+
const text = await res.text();
|
|
1627
|
+
if (!active) return;
|
|
1628
|
+
const metrics = parsePrometheusText(text);
|
|
1629
|
+
for (const m of metrics) a.emit(m);
|
|
1630
|
+
consecutiveErrors = 0;
|
|
1631
|
+
a.down([[import_core16.COMPLETE]]);
|
|
1632
|
+
} catch (err) {
|
|
1633
|
+
clearTimeout(timeoutId);
|
|
1634
|
+
if (!active) return;
|
|
1635
|
+
if (err instanceof Error && err.name === "AbortError") return;
|
|
1636
|
+
consecutiveErrors += 1;
|
|
1637
|
+
if (consecutiveErrors >= maxConsecutiveErrors) {
|
|
1638
|
+
a.down([[import_core16.ERROR, err]]);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
};
|
|
1642
|
+
void run();
|
|
1643
|
+
return () => {
|
|
1644
|
+
active = false;
|
|
1645
|
+
clearTimeout(timeoutId);
|
|
1646
|
+
abort.abort();
|
|
1647
|
+
};
|
|
1648
|
+
})
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1651
|
+
function parsePrometheusText(text) {
|
|
1652
|
+
const results = [];
|
|
1653
|
+
const types = /* @__PURE__ */ new Map();
|
|
1654
|
+
const helps = /* @__PURE__ */ new Map();
|
|
1655
|
+
for (const rawLine of text.split("\n")) {
|
|
1656
|
+
const line = rawLine.trim();
|
|
1657
|
+
if (!line) continue;
|
|
1658
|
+
if (line.startsWith("# TYPE ")) {
|
|
1659
|
+
const rest = line.slice(7);
|
|
1660
|
+
const spaceIdx = rest.indexOf(" ");
|
|
1661
|
+
if (spaceIdx > 0) {
|
|
1662
|
+
types.set(rest.slice(0, spaceIdx), rest.slice(spaceIdx + 1).trim());
|
|
1663
|
+
}
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
if (line.startsWith("# HELP ")) {
|
|
1667
|
+
const rest = line.slice(7);
|
|
1668
|
+
const spaceIdx = rest.indexOf(" ");
|
|
1669
|
+
if (spaceIdx > 0) {
|
|
1670
|
+
helps.set(rest.slice(0, spaceIdx), rest.slice(spaceIdx + 1).trim());
|
|
1671
|
+
}
|
|
1672
|
+
continue;
|
|
1673
|
+
}
|
|
1674
|
+
if (line.startsWith("#")) continue;
|
|
1675
|
+
let name;
|
|
1676
|
+
let labels = {};
|
|
1677
|
+
let valueStr;
|
|
1678
|
+
let tsStr;
|
|
1679
|
+
const braceIdx = line.indexOf("{");
|
|
1680
|
+
if (braceIdx >= 0) {
|
|
1681
|
+
name = line.slice(0, braceIdx);
|
|
1682
|
+
const closeBrace = line.indexOf("}", braceIdx);
|
|
1683
|
+
if (closeBrace < 0) continue;
|
|
1684
|
+
const labelStr = line.slice(braceIdx + 1, closeBrace);
|
|
1685
|
+
labels = parsePrometheusLabels(labelStr);
|
|
1686
|
+
const after = line.slice(closeBrace + 1).trim().split(/\s+/);
|
|
1687
|
+
valueStr = after[0] ?? "";
|
|
1688
|
+
tsStr = after[1];
|
|
1689
|
+
} else {
|
|
1690
|
+
const parts = line.split(/\s+/);
|
|
1691
|
+
name = parts[0] ?? "";
|
|
1692
|
+
valueStr = parts[1] ?? "";
|
|
1693
|
+
tsStr = parts[2];
|
|
1694
|
+
}
|
|
1695
|
+
if (!name || !valueStr) continue;
|
|
1696
|
+
const baseName = name.replace(/(_total|_count|_sum|_bucket|_created|_info)$/, "");
|
|
1697
|
+
results.push({
|
|
1698
|
+
name,
|
|
1699
|
+
labels,
|
|
1700
|
+
value: Number(valueStr),
|
|
1701
|
+
timestampMs: tsStr ? Number(tsStr) : void 0,
|
|
1702
|
+
type: types.get(baseName) ?? types.get(name),
|
|
1703
|
+
help: helps.get(baseName) ?? helps.get(name),
|
|
1704
|
+
timestampNs: (0, import_core16.wallClockNs)()
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
return results;
|
|
1708
|
+
}
|
|
1709
|
+
function parsePrometheusLabels(str) {
|
|
1710
|
+
const labels = {};
|
|
1711
|
+
const re = /(\w+)="((?:[^"\\]|\\.)*)"/g;
|
|
1712
|
+
let m = re.exec(str);
|
|
1713
|
+
while (m !== null) {
|
|
1714
|
+
labels[m[1]] = m[2].replace(/\\(.)/g, "$1");
|
|
1715
|
+
m = re.exec(str);
|
|
1716
|
+
}
|
|
1717
|
+
return labels;
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
// src/base/io/pulsar.ts
|
|
1721
|
+
var import_core17 = require("@graphrefly/pure-ts/core");
|
|
1722
|
+
function fromPulsar(consumer, opts) {
|
|
1723
|
+
const {
|
|
1724
|
+
autoAck = true,
|
|
1725
|
+
deserialize = (buf) => {
|
|
1726
|
+
try {
|
|
1727
|
+
return JSON.parse(buf.toString());
|
|
1728
|
+
} catch {
|
|
1729
|
+
return buf.toString();
|
|
1730
|
+
}
|
|
1731
|
+
},
|
|
1732
|
+
onAckError,
|
|
1733
|
+
...rest
|
|
1734
|
+
} = opts ?? {};
|
|
1735
|
+
const reportAckError = (err) => {
|
|
1736
|
+
if (!onAckError) return;
|
|
1737
|
+
try {
|
|
1738
|
+
onAckError(err instanceof Error ? err : new Error(String(err)));
|
|
1739
|
+
} catch {
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
return (0, import_core17.node)(
|
|
1743
|
+
[],
|
|
1744
|
+
(_data, a) => {
|
|
1745
|
+
let active = true;
|
|
1746
|
+
const loop = async () => {
|
|
1747
|
+
while (active) {
|
|
1748
|
+
try {
|
|
1749
|
+
const rawMsg = await consumer.receive();
|
|
1750
|
+
if (!active) return;
|
|
1751
|
+
const structured = {
|
|
1752
|
+
topic: rawMsg.getTopicName(),
|
|
1753
|
+
messageId: rawMsg.getMessageId().toString(),
|
|
1754
|
+
key: rawMsg.getPartitionKey(),
|
|
1755
|
+
value: deserialize(rawMsg.getData()),
|
|
1756
|
+
properties: rawMsg.getProperties(),
|
|
1757
|
+
publishTime: rawMsg.getPublishTimestamp(),
|
|
1758
|
+
eventTime: rawMsg.getEventTimestamp(),
|
|
1759
|
+
timestampNs: (0, import_core17.wallClockNs)()
|
|
1760
|
+
};
|
|
1761
|
+
if (autoAck) {
|
|
1762
|
+
a.emit(structured);
|
|
1763
|
+
void consumer.acknowledge(rawMsg).catch(reportAckError);
|
|
1764
|
+
} else {
|
|
1765
|
+
let settled = false;
|
|
1766
|
+
const envelope = {
|
|
1767
|
+
value: structured,
|
|
1768
|
+
ack() {
|
|
1769
|
+
if (settled) return;
|
|
1770
|
+
settled = true;
|
|
1771
|
+
void consumer.acknowledge(rawMsg).catch(reportAckError);
|
|
1772
|
+
},
|
|
1773
|
+
nack(_opts) {
|
|
1774
|
+
if (settled) return;
|
|
1775
|
+
settled = true;
|
|
1776
|
+
const anyConsumer = consumer;
|
|
1777
|
+
try {
|
|
1778
|
+
const result = anyConsumer.negativeAcknowledge?.(rawMsg);
|
|
1779
|
+
if (result && typeof result.then === "function") {
|
|
1780
|
+
void result.catch(reportAckError);
|
|
1781
|
+
}
|
|
1782
|
+
} catch (err) {
|
|
1783
|
+
reportAckError(err);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
a.emit(envelope);
|
|
1788
|
+
}
|
|
1789
|
+
} catch (err) {
|
|
1790
|
+
if (active) a.down([[import_core17.ERROR, err]]);
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
void loop();
|
|
1796
|
+
return () => {
|
|
1797
|
+
active = false;
|
|
1798
|
+
};
|
|
1799
|
+
},
|
|
1800
|
+
sourceOpts(rest)
|
|
1801
|
+
);
|
|
1802
|
+
}
|
|
1803
|
+
function toPulsar(source, pulsarProducer, opts) {
|
|
1804
|
+
const {
|
|
1805
|
+
serialize = (v) => Buffer.from(JSON.stringify(v)),
|
|
1806
|
+
keyExtractor,
|
|
1807
|
+
propertiesExtractor,
|
|
1808
|
+
onTransportError
|
|
1809
|
+
} = opts ?? {};
|
|
1810
|
+
return reactiveSink(source, {
|
|
1811
|
+
onTransportError,
|
|
1812
|
+
send: async (value) => {
|
|
1813
|
+
await pulsarProducer.send({
|
|
1814
|
+
data: serialize(value),
|
|
1815
|
+
partitionKey: keyExtractor?.(value),
|
|
1816
|
+
properties: propertiesExtractor?.(value)
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
});
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
// src/base/io/rabbitmq.ts
|
|
1823
|
+
var import_core18 = require("@graphrefly/pure-ts/core");
|
|
1824
|
+
function fromRabbitMQ(channel, queue, opts) {
|
|
1825
|
+
const {
|
|
1826
|
+
autoAck = true,
|
|
1827
|
+
deserialize = (buf) => {
|
|
1828
|
+
try {
|
|
1829
|
+
return JSON.parse(buf.toString());
|
|
1830
|
+
} catch {
|
|
1831
|
+
return buf.toString();
|
|
1832
|
+
}
|
|
1833
|
+
},
|
|
1834
|
+
onAckError,
|
|
1835
|
+
...rest
|
|
1836
|
+
} = opts ?? {};
|
|
1837
|
+
const reportAckError = (err) => {
|
|
1838
|
+
if (!onAckError) return;
|
|
1839
|
+
try {
|
|
1840
|
+
onAckError(err instanceof Error ? err : new Error(String(err)));
|
|
1841
|
+
} catch {
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1844
|
+
return (0, import_core18.node)(
|
|
1845
|
+
[],
|
|
1846
|
+
(_data, a) => {
|
|
1847
|
+
let active = true;
|
|
1848
|
+
let consumerTag;
|
|
1849
|
+
const start = async () => {
|
|
1850
|
+
try {
|
|
1851
|
+
const result = await channel.consume(
|
|
1852
|
+
queue,
|
|
1853
|
+
(rawMsg) => {
|
|
1854
|
+
if (!active) return;
|
|
1855
|
+
if (rawMsg === null) {
|
|
1856
|
+
if (active) a.down([[import_core18.ERROR, new Error("Consumer cancelled by broker")]]);
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
const structured = {
|
|
1860
|
+
queue,
|
|
1861
|
+
routingKey: rawMsg.fields.routingKey,
|
|
1862
|
+
exchange: rawMsg.fields.exchange,
|
|
1863
|
+
content: deserialize(rawMsg.content),
|
|
1864
|
+
properties: rawMsg.properties,
|
|
1865
|
+
deliveryTag: rawMsg.fields.deliveryTag,
|
|
1866
|
+
redelivered: rawMsg.fields.redelivered,
|
|
1867
|
+
timestampNs: (0, import_core18.wallClockNs)()
|
|
1868
|
+
};
|
|
1869
|
+
if (autoAck) {
|
|
1870
|
+
a.emit(structured);
|
|
1871
|
+
try {
|
|
1872
|
+
channel.ack(rawMsg);
|
|
1873
|
+
} catch (err) {
|
|
1874
|
+
reportAckError(err);
|
|
1875
|
+
}
|
|
1876
|
+
} else {
|
|
1877
|
+
let settled = false;
|
|
1878
|
+
const channelWithNack = channel;
|
|
1879
|
+
const envelope = {
|
|
1880
|
+
value: structured,
|
|
1881
|
+
ack() {
|
|
1882
|
+
if (settled) return;
|
|
1883
|
+
settled = true;
|
|
1884
|
+
try {
|
|
1885
|
+
channel.ack(rawMsg);
|
|
1886
|
+
} catch (err) {
|
|
1887
|
+
reportAckError(err);
|
|
1888
|
+
}
|
|
1889
|
+
},
|
|
1890
|
+
nack(nackOpts) {
|
|
1891
|
+
if (settled) return;
|
|
1892
|
+
settled = true;
|
|
1893
|
+
const requeue = nackOpts?.requeue;
|
|
1894
|
+
if (!channelWithNack.nack) {
|
|
1895
|
+
reportAckError(
|
|
1896
|
+
new Error("RabbitMQ channel does not expose `nack`; cannot negative-ack")
|
|
1897
|
+
);
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1900
|
+
try {
|
|
1901
|
+
channelWithNack.nack(rawMsg, false, requeue);
|
|
1902
|
+
} catch (err) {
|
|
1903
|
+
reportAckError(err);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
};
|
|
1907
|
+
a.emit(envelope);
|
|
1908
|
+
}
|
|
1909
|
+
},
|
|
1910
|
+
{ noAck: false }
|
|
1911
|
+
);
|
|
1912
|
+
consumerTag = result.consumerTag;
|
|
1913
|
+
} catch (err) {
|
|
1914
|
+
if (active) a.down([[import_core18.ERROR, err]]);
|
|
1915
|
+
}
|
|
1916
|
+
};
|
|
1917
|
+
void start();
|
|
1918
|
+
return () => {
|
|
1919
|
+
active = false;
|
|
1920
|
+
if (consumerTag !== void 0) {
|
|
1921
|
+
void channel.cancel(consumerTag);
|
|
1922
|
+
}
|
|
1923
|
+
};
|
|
1924
|
+
},
|
|
1925
|
+
sourceOpts(rest)
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
function toRabbitMQ(source, channel, exchange, opts) {
|
|
1929
|
+
const {
|
|
1930
|
+
serialize = (v) => Buffer.from(JSON.stringify(v)),
|
|
1931
|
+
routingKeyExtractor = () => "",
|
|
1932
|
+
onTransportError
|
|
1933
|
+
} = opts ?? {};
|
|
1934
|
+
return reactiveSink(source, {
|
|
1935
|
+
onTransportError,
|
|
1936
|
+
send: (value) => {
|
|
1937
|
+
const routingKey = routingKeyExtractor(value);
|
|
1938
|
+
const content = serialize(value);
|
|
1939
|
+
channel.publish(exchange, routingKey, content);
|
|
1940
|
+
}
|
|
1941
|
+
});
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
// src/base/io/redis-stream.ts
|
|
1945
|
+
var import_core19 = require("@graphrefly/pure-ts/core");
|
|
1946
|
+
function fromRedisStream(client, key, opts) {
|
|
1947
|
+
const {
|
|
1948
|
+
blockMs = 5e3,
|
|
1949
|
+
startId = "$",
|
|
1950
|
+
parse = (fields) => {
|
|
1951
|
+
for (let i = 0; i < fields.length; i += 2) {
|
|
1952
|
+
if (fields[i] === "data") {
|
|
1953
|
+
try {
|
|
1954
|
+
return JSON.parse(fields[i + 1]);
|
|
1955
|
+
} catch {
|
|
1956
|
+
return fields[i + 1];
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
const obj = {};
|
|
1961
|
+
for (let i = 0; i < fields.length; i += 2) {
|
|
1962
|
+
obj[fields[i]] = fields[i + 1];
|
|
1963
|
+
}
|
|
1964
|
+
return obj;
|
|
1965
|
+
},
|
|
1966
|
+
...rest
|
|
1967
|
+
} = opts ?? {};
|
|
1968
|
+
return (0, import_core19.node)(
|
|
1969
|
+
[],
|
|
1970
|
+
(_data, a) => {
|
|
1971
|
+
let active = true;
|
|
1972
|
+
let lastId = startId;
|
|
1973
|
+
const poll = async () => {
|
|
1974
|
+
while (active) {
|
|
1975
|
+
try {
|
|
1976
|
+
const result = await client.xread("BLOCK", blockMs, "STREAMS", key, lastId);
|
|
1977
|
+
if (!active) return;
|
|
1978
|
+
if (result) {
|
|
1979
|
+
for (const [_streamKey, entries] of result) {
|
|
1980
|
+
for (const [id, fields] of entries) {
|
|
1981
|
+
lastId = id;
|
|
1982
|
+
a.emit({
|
|
1983
|
+
id,
|
|
1984
|
+
key,
|
|
1985
|
+
data: parse(fields),
|
|
1986
|
+
timestampNs: (0, import_core19.wallClockNs)()
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
} catch (err) {
|
|
1992
|
+
if (!active) return;
|
|
1993
|
+
a.down([[import_core19.ERROR, err]]);
|
|
1994
|
+
return;
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
};
|
|
1998
|
+
void poll();
|
|
1999
|
+
return () => {
|
|
2000
|
+
active = false;
|
|
2001
|
+
};
|
|
2002
|
+
},
|
|
2003
|
+
sourceOpts(rest)
|
|
2004
|
+
);
|
|
2005
|
+
}
|
|
2006
|
+
function toRedisStream(source, client, key, opts) {
|
|
2007
|
+
const {
|
|
2008
|
+
serialize = (v) => ["data", JSON.stringify(v)],
|
|
2009
|
+
maxLen,
|
|
2010
|
+
onTransportError
|
|
2011
|
+
} = opts ?? {};
|
|
2012
|
+
return reactiveSink(source, {
|
|
2013
|
+
onTransportError,
|
|
2014
|
+
send: async (value) => {
|
|
2015
|
+
const fields = serialize(value);
|
|
2016
|
+
await (maxLen !== void 0 ? client.xadd(key, "MAXLEN", "~", String(maxLen), "*", ...fields) : client.xadd(key, "*", ...fields));
|
|
2017
|
+
}
|
|
2018
|
+
});
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
// src/base/io/sqlite.ts
|
|
2022
|
+
var import_core20 = require("@graphrefly/pure-ts/core");
|
|
2023
|
+
function fromSqlite(db, query, opts) {
|
|
2024
|
+
const { mapRow = (r) => r, params, ...rest } = opts ?? {};
|
|
2025
|
+
return (0, import_core20.node)(
|
|
2026
|
+
[],
|
|
2027
|
+
(_data, a) => {
|
|
2028
|
+
try {
|
|
2029
|
+
const rows = db.query(query, params);
|
|
2030
|
+
const mapped = rows.map(mapRow);
|
|
2031
|
+
a.emit(mapped);
|
|
2032
|
+
a.down([[import_core20.COMPLETE]]);
|
|
2033
|
+
} catch (err) {
|
|
2034
|
+
a.down([[import_core20.ERROR, err instanceof Error ? err : new Error(String(err))]]);
|
|
2035
|
+
}
|
|
2036
|
+
return void 0;
|
|
2037
|
+
},
|
|
2038
|
+
{ describeKind: "producer", completeWhenDepsComplete: false, ...rest }
|
|
2039
|
+
);
|
|
2040
|
+
}
|
|
2041
|
+
function fromSqliteCursor(db, query, opts) {
|
|
2042
|
+
const { mapRow = (r) => r, params, ...rest } = opts ?? {};
|
|
2043
|
+
return (0, import_core20.node)(
|
|
2044
|
+
[],
|
|
2045
|
+
(_data, a) => {
|
|
2046
|
+
try {
|
|
2047
|
+
const it = db.iterate(query, params);
|
|
2048
|
+
(0, import_core20.batch)(() => {
|
|
2049
|
+
for (const row of it) a.emit(mapRow(row));
|
|
2050
|
+
a.down([[import_core20.COMPLETE]]);
|
|
2051
|
+
});
|
|
2052
|
+
} catch (err) {
|
|
2053
|
+
a.down([[import_core20.ERROR, err instanceof Error ? err : new Error(String(err))]]);
|
|
2054
|
+
}
|
|
2055
|
+
return void 0;
|
|
2056
|
+
},
|
|
2057
|
+
{ describeKind: "producer", completeWhenDepsComplete: false, ...rest }
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
function toSqlite(source, db, table, opts) {
|
|
2061
|
+
if (table.includes("\0") || table.length === 0) {
|
|
2062
|
+
throw new Error(`toSqlite: invalid table name: ${JSON.stringify(table)}`);
|
|
2063
|
+
}
|
|
2064
|
+
const {
|
|
2065
|
+
toSQL = (v, t) => ({
|
|
2066
|
+
sql: `INSERT INTO "${t.replace(/"/g, '""')}" (data) VALUES (?)`,
|
|
2067
|
+
params: [JSON.stringify(v)]
|
|
2068
|
+
}),
|
|
2069
|
+
onTransportError,
|
|
2070
|
+
batchInsert = false,
|
|
2071
|
+
maxBatchSize = 1e3,
|
|
2072
|
+
flushIntervalMs = 0
|
|
2073
|
+
} = opts ?? {};
|
|
2074
|
+
const serialize = (value) => toSQL(value, table);
|
|
2075
|
+
if (!batchInsert) {
|
|
2076
|
+
return reactiveSink(source, {
|
|
2077
|
+
onTransportError,
|
|
2078
|
+
serialize,
|
|
2079
|
+
send: (q) => {
|
|
2080
|
+
const query = q;
|
|
2081
|
+
db.query(query.sql, query.params);
|
|
2082
|
+
}
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
2085
|
+
const errorsNode = (0, import_core20.node)([], { initial: null });
|
|
2086
|
+
const sentNode = (0, import_core20.node)([], {
|
|
2087
|
+
initial: void 0,
|
|
2088
|
+
equals: () => false
|
|
2089
|
+
});
|
|
2090
|
+
const failedNode = (0, import_core20.node)([], { initial: null });
|
|
2091
|
+
const inFlightNode = (0, import_core20.node)([], { initial: 0 });
|
|
2092
|
+
const bufferedNode = (0, import_core20.node)([], { initial: 0 });
|
|
2093
|
+
const reportError = (err) => {
|
|
2094
|
+
try {
|
|
2095
|
+
onTransportError?.(err);
|
|
2096
|
+
} catch {
|
|
2097
|
+
}
|
|
2098
|
+
try {
|
|
2099
|
+
errorsNode.down([[import_core20.DATA, err]]);
|
|
2100
|
+
} catch {
|
|
2101
|
+
}
|
|
2102
|
+
};
|
|
2103
|
+
let pending = [];
|
|
2104
|
+
let flushing = false;
|
|
2105
|
+
let timer;
|
|
2106
|
+
let disposed = false;
|
|
2107
|
+
const updateBuffered = () => bufferedNode.down([[import_core20.DATA, pending.length]]);
|
|
2108
|
+
const safeEmitSent = (v) => {
|
|
2109
|
+
if (disposed) return;
|
|
2110
|
+
sentNode.down([[import_core20.DATA, v]]);
|
|
2111
|
+
};
|
|
2112
|
+
const safeEmitFailed = (f) => {
|
|
2113
|
+
if (disposed) return;
|
|
2114
|
+
failedNode.down([[import_core20.DATA, f]]);
|
|
2115
|
+
};
|
|
2116
|
+
const safeSetInFlight = (n) => {
|
|
2117
|
+
if (disposed) return;
|
|
2118
|
+
inFlightNode.down([[import_core20.DATA, n]]);
|
|
2119
|
+
};
|
|
2120
|
+
const safeReportError = (err) => {
|
|
2121
|
+
if (disposed) return;
|
|
2122
|
+
reportError(err);
|
|
2123
|
+
};
|
|
2124
|
+
const flushTransaction = () => {
|
|
2125
|
+
if (pending.length === 0 || flushing) return;
|
|
2126
|
+
flushing = true;
|
|
2127
|
+
safeSetInFlight(1);
|
|
2128
|
+
try {
|
|
2129
|
+
db.query("BEGIN", []);
|
|
2130
|
+
} catch (err) {
|
|
2131
|
+
flushing = false;
|
|
2132
|
+
safeSetInFlight(0);
|
|
2133
|
+
safeReportError({
|
|
2134
|
+
stage: "send",
|
|
2135
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
2136
|
+
value: void 0
|
|
2137
|
+
});
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
const chunk = pending;
|
|
2141
|
+
pending = [];
|
|
2142
|
+
updateBuffered();
|
|
2143
|
+
let firstError;
|
|
2144
|
+
let committedCount = 0;
|
|
2145
|
+
for (const entry of chunk) {
|
|
2146
|
+
try {
|
|
2147
|
+
db.query(entry.query.sql, entry.query.params);
|
|
2148
|
+
committedCount += 1;
|
|
2149
|
+
} catch (err) {
|
|
2150
|
+
firstError = err instanceof Error ? err : new Error(String(err));
|
|
2151
|
+
break;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
if (firstError) {
|
|
2155
|
+
try {
|
|
2156
|
+
db.query("ROLLBACK", []);
|
|
2157
|
+
} catch {
|
|
2158
|
+
}
|
|
2159
|
+
safeReportError({ stage: "send", error: firstError, value: void 0 });
|
|
2160
|
+
for (const entry of chunk) {
|
|
2161
|
+
safeEmitFailed({ value: entry.value, error: firstError, attempts: 1 });
|
|
2162
|
+
}
|
|
2163
|
+
} else {
|
|
2164
|
+
try {
|
|
2165
|
+
db.query("COMMIT", []);
|
|
2166
|
+
for (const entry of chunk) safeEmitSent(entry.value);
|
|
2167
|
+
} catch (err) {
|
|
2168
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
2169
|
+
safeReportError({ stage: "send", error, value: void 0 });
|
|
2170
|
+
for (let i = 0; i < committedCount; i++) {
|
|
2171
|
+
safeEmitFailed({ value: chunk[i].value, error, attempts: 1 });
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
flushing = false;
|
|
2176
|
+
safeSetInFlight(0);
|
|
2177
|
+
};
|
|
2178
|
+
const scheduleFlush = () => {
|
|
2179
|
+
if (flushIntervalMs > 0 && timer === void 0 && !disposed) {
|
|
2180
|
+
timer = setTimeout(() => {
|
|
2181
|
+
timer = void 0;
|
|
2182
|
+
flushTransaction();
|
|
2183
|
+
}, flushIntervalMs);
|
|
2184
|
+
}
|
|
2185
|
+
};
|
|
2186
|
+
const unsub = source.subscribe((msgs) => {
|
|
2187
|
+
for (const msg of msgs) {
|
|
2188
|
+
const t = msg[0];
|
|
2189
|
+
if (t === import_core20.DATA) {
|
|
2190
|
+
const value = msg[1];
|
|
2191
|
+
let query;
|
|
2192
|
+
try {
|
|
2193
|
+
query = serialize(value);
|
|
2194
|
+
} catch (err) {
|
|
2195
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
2196
|
+
reportError({ stage: "serialize", error, value });
|
|
2197
|
+
failedNode.down([[import_core20.DATA, { value, error, attempts: 0 }]]);
|
|
2198
|
+
continue;
|
|
2199
|
+
}
|
|
2200
|
+
pending.push({ value, query });
|
|
2201
|
+
updateBuffered();
|
|
2202
|
+
if (pending.length >= maxBatchSize) flushTransaction();
|
|
2203
|
+
else scheduleFlush();
|
|
2204
|
+
} else if (import_core20.defaultConfig.messageTier(t) >= 3) {
|
|
2205
|
+
flushTransaction();
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
2209
|
+
const dispose = () => {
|
|
2210
|
+
if (disposed) return;
|
|
2211
|
+
if (timer !== void 0) {
|
|
2212
|
+
clearTimeout(timer);
|
|
2213
|
+
timer = void 0;
|
|
2214
|
+
}
|
|
2215
|
+
flushTransaction();
|
|
2216
|
+
disposed = true;
|
|
2217
|
+
unsub();
|
|
2218
|
+
for (const n of [errorsNode, sentNode, failedNode, inFlightNode, bufferedNode]) {
|
|
2219
|
+
try {
|
|
2220
|
+
n.down([[import_core20.TEARDOWN]]);
|
|
2221
|
+
} catch {
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
};
|
|
2225
|
+
return {
|
|
2226
|
+
dispose,
|
|
2227
|
+
sent: sentNode,
|
|
2228
|
+
failed: failedNode,
|
|
2229
|
+
inFlight: inFlightNode,
|
|
2230
|
+
errors: errorsNode,
|
|
2231
|
+
buffered: bufferedNode,
|
|
2232
|
+
flush: async () => {
|
|
2233
|
+
if (!disposed) flushTransaction();
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
// src/base/io/sse.ts
|
|
2239
|
+
var import_core21 = require("@graphrefly/pure-ts/core");
|
|
2240
|
+
function messageTypeLabel(t) {
|
|
2241
|
+
return Symbol.keyFor(t) ?? t.description ?? "message";
|
|
2242
|
+
}
|
|
2243
|
+
function serializeSseData(value, serialize) {
|
|
2244
|
+
if (typeof value === "string") return value;
|
|
2245
|
+
return serialize(value);
|
|
2246
|
+
}
|
|
2247
|
+
function sseFrame(event, data) {
|
|
2248
|
+
let out = `event: ${event}
|
|
2249
|
+
`;
|
|
2250
|
+
if (data !== void 0) {
|
|
2251
|
+
const lines = data.split(/\r?\n/);
|
|
2252
|
+
for (const line of lines) {
|
|
2253
|
+
out += `data: ${line}
|
|
2254
|
+
`;
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
return `${out}
|
|
2258
|
+
`;
|
|
2259
|
+
}
|
|
2260
|
+
function toSSE(source, opts) {
|
|
2261
|
+
const {
|
|
2262
|
+
serialize = (value) => {
|
|
2263
|
+
if (value instanceof Error) return value.message;
|
|
2264
|
+
try {
|
|
2265
|
+
return JSON.stringify(value);
|
|
2266
|
+
} catch {
|
|
2267
|
+
return String(value);
|
|
2268
|
+
}
|
|
2269
|
+
},
|
|
2270
|
+
dataEvent = "data",
|
|
2271
|
+
errorEvent = "error",
|
|
2272
|
+
completeEvent = "complete",
|
|
2273
|
+
includeResolved = false,
|
|
2274
|
+
includeDirty = false,
|
|
2275
|
+
keepAliveMs,
|
|
2276
|
+
signal,
|
|
2277
|
+
eventNameResolver = messageTypeLabel
|
|
2278
|
+
} = opts ?? {};
|
|
2279
|
+
const encoder = new TextEncoder();
|
|
2280
|
+
let stop;
|
|
2281
|
+
return new ReadableStream({
|
|
2282
|
+
start(controller) {
|
|
2283
|
+
let closed = false;
|
|
2284
|
+
let keepAlive;
|
|
2285
|
+
let unsub = () => {
|
|
2286
|
+
};
|
|
2287
|
+
const close = () => {
|
|
2288
|
+
if (closed) return;
|
|
2289
|
+
closed = true;
|
|
2290
|
+
if (keepAlive !== void 0) clearInterval(keepAlive);
|
|
2291
|
+
signal?.removeEventListener("abort", onAbort);
|
|
2292
|
+
unsub();
|
|
2293
|
+
controller.close();
|
|
2294
|
+
};
|
|
2295
|
+
stop = close;
|
|
2296
|
+
const write = (event, data) => {
|
|
2297
|
+
if (closed) return;
|
|
2298
|
+
controller.enqueue(encoder.encode(sseFrame(event, data)));
|
|
2299
|
+
};
|
|
2300
|
+
const onAbort = () => {
|
|
2301
|
+
if (closed) return;
|
|
2302
|
+
close();
|
|
2303
|
+
};
|
|
2304
|
+
unsub = source.subscribe((msgs) => {
|
|
2305
|
+
for (const msg of msgs) {
|
|
2306
|
+
const t = msg[0];
|
|
2307
|
+
if (import_core21.defaultConfig.isLocalOnly(t)) {
|
|
2308
|
+
if (t === import_core21.DIRTY && includeDirty) {
|
|
2309
|
+
} else continue;
|
|
2310
|
+
}
|
|
2311
|
+
if (t === import_core21.DATA) {
|
|
2312
|
+
write(dataEvent, serializeSseData(msg[1], serialize));
|
|
2313
|
+
continue;
|
|
2314
|
+
}
|
|
2315
|
+
if (t === import_core21.ERROR) {
|
|
2316
|
+
write(errorEvent, serializeSseData(msg[1], serialize));
|
|
2317
|
+
close();
|
|
2318
|
+
return;
|
|
2319
|
+
}
|
|
2320
|
+
if (t === import_core21.COMPLETE) {
|
|
2321
|
+
write(completeEvent);
|
|
2322
|
+
close();
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
if (!includeResolved && t === import_core21.RESOLVED) continue;
|
|
2326
|
+
write(
|
|
2327
|
+
eventNameResolver(t),
|
|
2328
|
+
msg.length > 1 ? serializeSseData(msg[1], serialize) : void 0
|
|
2329
|
+
);
|
|
2330
|
+
}
|
|
2331
|
+
});
|
|
2332
|
+
if (keepAliveMs !== void 0 && keepAliveMs > 0) {
|
|
2333
|
+
keepAlive = setInterval(() => {
|
|
2334
|
+
if (closed) return;
|
|
2335
|
+
controller.enqueue(encoder.encode(": keepalive\n\n"));
|
|
2336
|
+
}, keepAliveMs);
|
|
2337
|
+
}
|
|
2338
|
+
if (signal?.aborted) onAbort();
|
|
2339
|
+
else signal?.addEventListener("abort", onAbort, { once: true });
|
|
2340
|
+
},
|
|
2341
|
+
cancel() {
|
|
2342
|
+
stop?.();
|
|
2343
|
+
}
|
|
2344
|
+
});
|
|
2345
|
+
}
|
|
2346
|
+
function toSSEBytes(source, opts) {
|
|
2347
|
+
const {
|
|
2348
|
+
serialize = (value) => {
|
|
2349
|
+
if (value instanceof Error) return value.message;
|
|
2350
|
+
try {
|
|
2351
|
+
return JSON.stringify(value);
|
|
2352
|
+
} catch {
|
|
2353
|
+
return String(value);
|
|
2354
|
+
}
|
|
2355
|
+
},
|
|
2356
|
+
dataEvent = "data",
|
|
2357
|
+
errorEvent = "error",
|
|
2358
|
+
completeEvent = "complete",
|
|
2359
|
+
includeResolved = false,
|
|
2360
|
+
includeDirty = false,
|
|
2361
|
+
keepAliveMs,
|
|
2362
|
+
signal,
|
|
2363
|
+
eventNameResolver = messageTypeLabel
|
|
2364
|
+
} = opts ?? {};
|
|
2365
|
+
const encoder = new TextEncoder();
|
|
2366
|
+
return (0, import_core21.node)([], (_data, a) => {
|
|
2367
|
+
let active = true;
|
|
2368
|
+
let keepAlive;
|
|
2369
|
+
const emitFrame = (event, data) => {
|
|
2370
|
+
if (!active) return;
|
|
2371
|
+
a.emit(encoder.encode(sseFrame(event, data)));
|
|
2372
|
+
};
|
|
2373
|
+
const onAbort = () => {
|
|
2374
|
+
if (!active) return;
|
|
2375
|
+
active = false;
|
|
2376
|
+
a.down([[import_core21.COMPLETE]]);
|
|
2377
|
+
};
|
|
2378
|
+
const unsub = source.subscribe((msgs) => {
|
|
2379
|
+
if (!active) return;
|
|
2380
|
+
for (const msg of msgs) {
|
|
2381
|
+
const t = msg[0];
|
|
2382
|
+
if (import_core21.defaultConfig.isLocalOnly(t)) {
|
|
2383
|
+
if (t === import_core21.DIRTY && includeDirty) {
|
|
2384
|
+
} else continue;
|
|
2385
|
+
}
|
|
2386
|
+
if (t === import_core21.DATA) {
|
|
2387
|
+
emitFrame(dataEvent, serializeSseData(msg[1], serialize));
|
|
2388
|
+
continue;
|
|
2389
|
+
}
|
|
2390
|
+
if (t === import_core21.ERROR) {
|
|
2391
|
+
emitFrame(errorEvent, serializeSseData(msg[1], serialize));
|
|
2392
|
+
active = false;
|
|
2393
|
+
a.down([[import_core21.COMPLETE]]);
|
|
2394
|
+
return;
|
|
2395
|
+
}
|
|
2396
|
+
if (t === import_core21.COMPLETE) {
|
|
2397
|
+
emitFrame(completeEvent);
|
|
2398
|
+
active = false;
|
|
2399
|
+
a.down([[import_core21.COMPLETE]]);
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
if (!includeResolved && t === import_core21.RESOLVED) continue;
|
|
2403
|
+
emitFrame(
|
|
2404
|
+
eventNameResolver(t),
|
|
2405
|
+
msg.length > 1 ? serializeSseData(msg[1], serialize) : void 0
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
});
|
|
2409
|
+
if (keepAliveMs !== void 0 && keepAliveMs > 0) {
|
|
2410
|
+
keepAlive = setInterval(() => {
|
|
2411
|
+
if (!active) return;
|
|
2412
|
+
a.emit(encoder.encode(": keepalive\n\n"));
|
|
2413
|
+
}, keepAliveMs);
|
|
2414
|
+
}
|
|
2415
|
+
if (signal?.aborted) onAbort();
|
|
2416
|
+
else signal?.addEventListener("abort", onAbort, { once: true });
|
|
2417
|
+
return () => {
|
|
2418
|
+
active = false;
|
|
2419
|
+
if (keepAlive !== void 0) clearInterval(keepAlive);
|
|
2420
|
+
signal?.removeEventListener("abort", onAbort);
|
|
2421
|
+
unsub();
|
|
2422
|
+
};
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
function toReadableStream(bytes) {
|
|
2426
|
+
let unsub;
|
|
2427
|
+
let closed = false;
|
|
2428
|
+
return new ReadableStream({
|
|
2429
|
+
start(controller) {
|
|
2430
|
+
unsub = bytes.subscribe((msgs) => {
|
|
2431
|
+
for (const m of msgs) {
|
|
2432
|
+
const t = m[0];
|
|
2433
|
+
if (closed) return;
|
|
2434
|
+
if (t === import_core21.DATA) {
|
|
2435
|
+
try {
|
|
2436
|
+
controller.enqueue(m[1]);
|
|
2437
|
+
} catch {
|
|
2438
|
+
closed = true;
|
|
2439
|
+
unsub?.();
|
|
2440
|
+
}
|
|
2441
|
+
} else if (t === import_core21.ERROR) {
|
|
2442
|
+
closed = true;
|
|
2443
|
+
try {
|
|
2444
|
+
controller.error(m[1]);
|
|
2445
|
+
} catch {
|
|
2446
|
+
}
|
|
2447
|
+
return;
|
|
2448
|
+
} else if (t === import_core21.COMPLETE) {
|
|
2449
|
+
closed = true;
|
|
2450
|
+
try {
|
|
2451
|
+
controller.close();
|
|
2452
|
+
} catch {
|
|
2453
|
+
}
|
|
2454
|
+
return;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
});
|
|
2458
|
+
},
|
|
2459
|
+
cancel() {
|
|
2460
|
+
closed = true;
|
|
2461
|
+
unsub?.();
|
|
2462
|
+
}
|
|
2463
|
+
});
|
|
2464
|
+
}
|
|
2465
|
+
async function* parseSSEStream(source, opts) {
|
|
2466
|
+
const parse = opts?.parse ?? ((raw) => raw);
|
|
2467
|
+
const externalSignal = opts?.signal;
|
|
2468
|
+
const decoder = new TextDecoder();
|
|
2469
|
+
let buffer = "";
|
|
2470
|
+
let currentEvent = "message";
|
|
2471
|
+
let currentData = [];
|
|
2472
|
+
let currentId;
|
|
2473
|
+
let currentRetry;
|
|
2474
|
+
const queue = [];
|
|
2475
|
+
const flushEvent = () => {
|
|
2476
|
+
if (currentData.length === 0 && currentEvent === "message" && currentId === void 0) {
|
|
2477
|
+
currentData = [];
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
const raw = currentData.join("\n");
|
|
2481
|
+
queue.push({
|
|
2482
|
+
event: currentEvent,
|
|
2483
|
+
data: parse(raw),
|
|
2484
|
+
id: currentId,
|
|
2485
|
+
retry: currentRetry
|
|
2486
|
+
});
|
|
2487
|
+
currentEvent = "message";
|
|
2488
|
+
currentData = [];
|
|
2489
|
+
currentId = void 0;
|
|
2490
|
+
currentRetry = void 0;
|
|
2491
|
+
};
|
|
2492
|
+
const processLine = (line) => {
|
|
2493
|
+
if (line === "") {
|
|
2494
|
+
flushEvent();
|
|
2495
|
+
return;
|
|
2496
|
+
}
|
|
2497
|
+
if (line.startsWith(":")) return;
|
|
2498
|
+
const colon = line.indexOf(":");
|
|
2499
|
+
const field = colon < 0 ? line : line.slice(0, colon);
|
|
2500
|
+
let value = colon < 0 ? "" : line.slice(colon + 1);
|
|
2501
|
+
if (value.startsWith(" ")) value = value.slice(1);
|
|
2502
|
+
switch (field) {
|
|
2503
|
+
case "event":
|
|
2504
|
+
currentEvent = value;
|
|
2505
|
+
break;
|
|
2506
|
+
case "data":
|
|
2507
|
+
currentData.push(value);
|
|
2508
|
+
break;
|
|
2509
|
+
case "id":
|
|
2510
|
+
if (!value.includes("\0")) currentId = value;
|
|
2511
|
+
break;
|
|
2512
|
+
case "retry": {
|
|
2513
|
+
const n = Number(value);
|
|
2514
|
+
if (Number.isFinite(n)) currentRetry = n;
|
|
2515
|
+
break;
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
};
|
|
2519
|
+
const processChunk = (chunk, done) => {
|
|
2520
|
+
buffer += decoder.decode(chunk, { stream: !done });
|
|
2521
|
+
const parts = buffer.split(/\r?\n/);
|
|
2522
|
+
buffer = parts.pop() ?? "";
|
|
2523
|
+
for (const line of parts) processLine(line);
|
|
2524
|
+
};
|
|
2525
|
+
const resp = source;
|
|
2526
|
+
const stream = source instanceof ReadableStream ? source : resp && typeof resp === "object" && resp.body instanceof ReadableStream ? resp.body : null;
|
|
2527
|
+
let reader;
|
|
2528
|
+
let iter;
|
|
2529
|
+
let cleanupDone = false;
|
|
2530
|
+
const cleanupReader = () => {
|
|
2531
|
+
if (cleanupDone) return;
|
|
2532
|
+
cleanupDone = true;
|
|
2533
|
+
if (reader) {
|
|
2534
|
+
void reader.cancel().catch(() => void 0);
|
|
2535
|
+
}
|
|
2536
|
+
if (iter && typeof iter.return === "function") {
|
|
2537
|
+
void Promise.resolve(iter.return()).catch(() => void 0);
|
|
2538
|
+
}
|
|
2539
|
+
};
|
|
2540
|
+
const onAbort = () => {
|
|
2541
|
+
cleanupReader();
|
|
2542
|
+
};
|
|
2543
|
+
if (externalSignal) {
|
|
2544
|
+
if (externalSignal.aborted) return;
|
|
2545
|
+
externalSignal.addEventListener("abort", onAbort, { once: true });
|
|
2546
|
+
}
|
|
2547
|
+
try {
|
|
2548
|
+
if (stream) {
|
|
2549
|
+
reader = stream.getReader();
|
|
2550
|
+
while (!externalSignal?.aborted) {
|
|
2551
|
+
const { value, done } = await reader.read();
|
|
2552
|
+
if (done) break;
|
|
2553
|
+
processChunk(value, false);
|
|
2554
|
+
while (queue.length > 0) {
|
|
2555
|
+
const ev = queue.shift();
|
|
2556
|
+
yield ev;
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
processChunk(new Uint8Array(), true);
|
|
2560
|
+
} else {
|
|
2561
|
+
const asyncIter = source;
|
|
2562
|
+
iter = asyncIter[Symbol.asyncIterator]();
|
|
2563
|
+
while (!externalSignal?.aborted) {
|
|
2564
|
+
const step = await iter.next();
|
|
2565
|
+
if (step.done) break;
|
|
2566
|
+
processChunk(step.value, false);
|
|
2567
|
+
while (queue.length > 0) {
|
|
2568
|
+
const ev = queue.shift();
|
|
2569
|
+
yield ev;
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
processChunk(new Uint8Array(), true);
|
|
2573
|
+
}
|
|
2574
|
+
if (buffer.trim()) {
|
|
2575
|
+
for (const line of buffer.split(/\r?\n/)) processLine(line);
|
|
2576
|
+
flushEvent();
|
|
2577
|
+
}
|
|
2578
|
+
while (queue.length > 0) {
|
|
2579
|
+
const ev = queue.shift();
|
|
2580
|
+
yield ev;
|
|
2581
|
+
}
|
|
2582
|
+
} finally {
|
|
2583
|
+
if (externalSignal) {
|
|
2584
|
+
externalSignal.removeEventListener("abort", onAbort);
|
|
2585
|
+
}
|
|
2586
|
+
cleanupReader();
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
function fromSSE(source, opts) {
|
|
2590
|
+
const { parse, ...rest } = opts ?? {};
|
|
2591
|
+
return (0, import_core21.node)(
|
|
2592
|
+
[],
|
|
2593
|
+
(_data, a) => {
|
|
2594
|
+
let active = true;
|
|
2595
|
+
const ctrl = new AbortController();
|
|
2596
|
+
const run = async () => {
|
|
2597
|
+
try {
|
|
2598
|
+
for await (const ev of parseSSEStream(source, { parse, signal: ctrl.signal })) {
|
|
2599
|
+
if (!active) return;
|
|
2600
|
+
a.emit(ev);
|
|
2601
|
+
}
|
|
2602
|
+
if (active) a.down([[import_core21.COMPLETE]]);
|
|
2603
|
+
} catch (err) {
|
|
2604
|
+
if (active) a.down([[import_core21.ERROR, err]]);
|
|
2605
|
+
}
|
|
2606
|
+
};
|
|
2607
|
+
void run();
|
|
2608
|
+
return () => {
|
|
2609
|
+
active = false;
|
|
2610
|
+
ctrl.abort();
|
|
2611
|
+
};
|
|
2612
|
+
},
|
|
2613
|
+
sourceOpts(rest)
|
|
2614
|
+
);
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
// src/base/io/statsd.ts
|
|
2618
|
+
var import_core22 = require("@graphrefly/pure-ts/core");
|
|
2619
|
+
function fromStatsD(register, opts) {
|
|
2620
|
+
return externalProducer(register, opts);
|
|
2621
|
+
}
|
|
2622
|
+
var STATSD_TYPES = {
|
|
2623
|
+
c: "counter",
|
|
2624
|
+
g: "gauge",
|
|
2625
|
+
ms: "timer",
|
|
2626
|
+
h: "histogram",
|
|
2627
|
+
s: "set",
|
|
2628
|
+
d: "distribution"
|
|
2629
|
+
};
|
|
2630
|
+
function parseStatsD(line) {
|
|
2631
|
+
const parts = line.split("|");
|
|
2632
|
+
const [name, valueStr] = (parts[0] ?? "").split(":");
|
|
2633
|
+
if (!name || valueStr === void 0) {
|
|
2634
|
+
throw new Error(`Invalid StatsD line: ${line}`);
|
|
2635
|
+
}
|
|
2636
|
+
const typeCode = parts[1]?.trim() ?? "c";
|
|
2637
|
+
const type = STATSD_TYPES[typeCode] ?? "counter";
|
|
2638
|
+
const value = type === "set" ? 0 : Number(valueStr);
|
|
2639
|
+
let sampleRate;
|
|
2640
|
+
const tags = {};
|
|
2641
|
+
for (let i = 2; i < parts.length; i++) {
|
|
2642
|
+
const part = parts[i].trim();
|
|
2643
|
+
if (part.startsWith("@")) {
|
|
2644
|
+
sampleRate = Number(part.slice(1));
|
|
2645
|
+
} else if (part.startsWith("#")) {
|
|
2646
|
+
for (const tag of part.slice(1).split(",")) {
|
|
2647
|
+
const [k, v] = tag.split(":");
|
|
2648
|
+
if (k) tags[k] = v ?? "";
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
return { name: name.trim(), value, type, sampleRate, tags, timestampNs: (0, import_core22.wallClockNs)() };
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
// src/base/io/syslog.ts
|
|
2656
|
+
var import_core23 = require("@graphrefly/pure-ts/core");
|
|
2657
|
+
function fromSyslog(register, opts) {
|
|
2658
|
+
return externalProducer(register, opts);
|
|
2659
|
+
}
|
|
2660
|
+
function parseSyslog(raw) {
|
|
2661
|
+
const match = raw.match(/^<(\d{1,3})>\d?\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)/s);
|
|
2662
|
+
if (!match) {
|
|
2663
|
+
const nowNs = (0, import_core23.wallClockNs)();
|
|
2664
|
+
return {
|
|
2665
|
+
facility: 1,
|
|
2666
|
+
severity: 6,
|
|
2667
|
+
timestamp: new Date(Math.floor(nowNs / 1e6)).toISOString(),
|
|
2668
|
+
hostname: "-",
|
|
2669
|
+
appName: "-",
|
|
2670
|
+
procId: "-",
|
|
2671
|
+
msgId: "-",
|
|
2672
|
+
message: raw.trim(),
|
|
2673
|
+
timestampNs: nowNs
|
|
2674
|
+
};
|
|
2675
|
+
}
|
|
2676
|
+
const pri = Number(match[1]);
|
|
2677
|
+
return {
|
|
2678
|
+
facility: pri >> 3,
|
|
2679
|
+
severity: pri & 7,
|
|
2680
|
+
timestamp: match[2],
|
|
2681
|
+
hostname: match[3],
|
|
2682
|
+
appName: match[4],
|
|
2683
|
+
procId: match[5],
|
|
2684
|
+
msgId: match[6],
|
|
2685
|
+
message: (match[7] ?? "").trim(),
|
|
2686
|
+
timestampNs: (0, import_core23.wallClockNs)()
|
|
2687
|
+
};
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
// src/base/io/to-clickhouse.ts
|
|
2691
|
+
function toClickHouse(source, client, table, opts) {
|
|
2692
|
+
const {
|
|
2693
|
+
batchSize = 1e3,
|
|
2694
|
+
flushIntervalMs = 5e3,
|
|
2695
|
+
format = "JSONEachRow",
|
|
2696
|
+
transform = (v) => v,
|
|
2697
|
+
onTransportError
|
|
2698
|
+
} = opts ?? {};
|
|
2699
|
+
return reactiveSink(source, {
|
|
2700
|
+
onTransportError,
|
|
2701
|
+
batchSize,
|
|
2702
|
+
flushIntervalMs,
|
|
2703
|
+
serialize: transform,
|
|
2704
|
+
sendBatch: async (batch6) => {
|
|
2705
|
+
await client.insert({ table, values: batch6, format });
|
|
2706
|
+
}
|
|
2707
|
+
});
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2710
|
+
// src/base/io/to-file.ts
|
|
2711
|
+
function toFile(source, writer, opts) {
|
|
2712
|
+
const {
|
|
2713
|
+
serialize = (v) => `${JSON.stringify(v)}
|
|
2714
|
+
`,
|
|
2715
|
+
flushIntervalMs = 0,
|
|
2716
|
+
batchSize = Number.POSITIVE_INFINITY,
|
|
2717
|
+
onTransportError,
|
|
2718
|
+
mode: _mode
|
|
2719
|
+
} = opts ?? {};
|
|
2720
|
+
const buffered = flushIntervalMs > 0 || batchSize < Number.POSITIVE_INFINITY;
|
|
2721
|
+
const handle = buffered ? reactiveSink(source, {
|
|
2722
|
+
onTransportError,
|
|
2723
|
+
batchSize,
|
|
2724
|
+
flushIntervalMs,
|
|
2725
|
+
serialize,
|
|
2726
|
+
sendBatch: (chunk) => {
|
|
2727
|
+
writer.write(chunk.join(""));
|
|
2728
|
+
}
|
|
2729
|
+
}) : reactiveSink(source, {
|
|
2730
|
+
onTransportError,
|
|
2731
|
+
serialize,
|
|
2732
|
+
send: (line) => {
|
|
2733
|
+
writer.write(line);
|
|
2734
|
+
}
|
|
2735
|
+
});
|
|
2736
|
+
const originalDispose = handle.dispose;
|
|
2737
|
+
handle.dispose = () => {
|
|
2738
|
+
originalDispose();
|
|
2739
|
+
try {
|
|
2740
|
+
writer.end();
|
|
2741
|
+
} catch {
|
|
2742
|
+
}
|
|
2743
|
+
};
|
|
2744
|
+
return handle;
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
// src/base/io/to-csv.ts
|
|
2748
|
+
function escapeCSVField(value, delimiter) {
|
|
2749
|
+
if (value.includes(delimiter) || value.includes('"') || value.includes("\n")) {
|
|
2750
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
2751
|
+
}
|
|
2752
|
+
return value;
|
|
2753
|
+
}
|
|
2754
|
+
function toCSV(source, writer, opts) {
|
|
2755
|
+
const {
|
|
2756
|
+
columns,
|
|
2757
|
+
delimiter = ",",
|
|
2758
|
+
writeHeader = true,
|
|
2759
|
+
cellExtractor = (row, col) => String(row[col] ?? ""),
|
|
2760
|
+
flushIntervalMs = 0,
|
|
2761
|
+
batchSize = Number.POSITIVE_INFINITY,
|
|
2762
|
+
onTransportError,
|
|
2763
|
+
...rest
|
|
2764
|
+
} = opts;
|
|
2765
|
+
let headerWritten = false;
|
|
2766
|
+
const serializeRow = (row) => {
|
|
2767
|
+
if (!headerWritten && writeHeader) {
|
|
2768
|
+
headerWritten = true;
|
|
2769
|
+
const header = columns.map((c) => escapeCSVField(c, delimiter)).join(delimiter);
|
|
2770
|
+
const data = columns.map((c) => escapeCSVField(cellExtractor(row, c), delimiter)).join(delimiter);
|
|
2771
|
+
return `${header}
|
|
2772
|
+
${data}
|
|
2773
|
+
`;
|
|
2774
|
+
}
|
|
2775
|
+
return `${columns.map((c) => escapeCSVField(cellExtractor(row, c), delimiter)).join(delimiter)}
|
|
2776
|
+
`;
|
|
2777
|
+
};
|
|
2778
|
+
return toFile(source, writer, {
|
|
2779
|
+
serialize: serializeRow,
|
|
2780
|
+
flushIntervalMs,
|
|
2781
|
+
batchSize,
|
|
2782
|
+
onTransportError,
|
|
2783
|
+
...rest
|
|
2784
|
+
});
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
// src/base/io/to-loki.ts
|
|
2788
|
+
var import_core24 = require("@graphrefly/pure-ts/core");
|
|
2789
|
+
function toLoki(source, client, opts) {
|
|
2790
|
+
const {
|
|
2791
|
+
labels = {},
|
|
2792
|
+
toLine = (v) => JSON.stringify(v),
|
|
2793
|
+
toLabels,
|
|
2794
|
+
onTransportError
|
|
2795
|
+
} = opts ?? {};
|
|
2796
|
+
return reactiveSink(source, {
|
|
2797
|
+
onTransportError,
|
|
2798
|
+
serialize: (value) => ({
|
|
2799
|
+
line: toLine(value),
|
|
2800
|
+
labels: toLabels ? { ...labels, ...toLabels(value) } : labels
|
|
2801
|
+
}),
|
|
2802
|
+
send: async (payload) => {
|
|
2803
|
+
const { line, labels: streamLabels } = payload;
|
|
2804
|
+
const ts = `${(0, import_core24.wallClockNs)()}`;
|
|
2805
|
+
await client.push({ streams: [{ stream: streamLabels, values: [[ts, line]] }] });
|
|
2806
|
+
}
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
// src/base/io/to-mongo.ts
|
|
2811
|
+
function toMongo(source, collection, opts) {
|
|
2812
|
+
const { toDocument = (v) => v, onTransportError } = opts ?? {};
|
|
2813
|
+
return reactiveSink(source, {
|
|
2814
|
+
onTransportError,
|
|
2815
|
+
serialize: toDocument,
|
|
2816
|
+
send: async (doc) => {
|
|
2817
|
+
await collection.insertOne(doc);
|
|
2818
|
+
}
|
|
2819
|
+
});
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
// src/base/io/to-postgres.ts
|
|
2823
|
+
function toPostgres(source, client, table, opts) {
|
|
2824
|
+
const {
|
|
2825
|
+
toSQL = (v, t) => ({
|
|
2826
|
+
sql: `INSERT INTO "${t.replace(/"/g, '""')}" (data) VALUES ($1)`,
|
|
2827
|
+
params: [JSON.stringify(v)]
|
|
2828
|
+
}),
|
|
2829
|
+
onTransportError
|
|
2830
|
+
} = opts ?? {};
|
|
2831
|
+
return reactiveSink(source, {
|
|
2832
|
+
onTransportError,
|
|
2833
|
+
serialize: (value) => toSQL(value, table),
|
|
2834
|
+
send: async (q) => {
|
|
2835
|
+
const query = q;
|
|
2836
|
+
await client.query(query.sql, query.params);
|
|
2837
|
+
}
|
|
2838
|
+
});
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
// src/base/io/to-s3.ts
|
|
2842
|
+
var import_core25 = require("@graphrefly/pure-ts/core");
|
|
2843
|
+
function toS3(source, client, bucket, opts) {
|
|
2844
|
+
const {
|
|
2845
|
+
format = "ndjson",
|
|
2846
|
+
keyGenerator = (seq2, timestampNs) => {
|
|
2847
|
+
const ms = Math.floor(timestampNs / 1e6);
|
|
2848
|
+
const ts = new Date(ms).toISOString().replace(/[:.]/g, "-");
|
|
2849
|
+
return `data/${ts}-${seq2}.${format === "ndjson" ? "ndjson" : "json"}`;
|
|
2850
|
+
},
|
|
2851
|
+
batchSize = 1e3,
|
|
2852
|
+
flushIntervalMs = 1e4,
|
|
2853
|
+
transform = (v) => v,
|
|
2854
|
+
onTransportError
|
|
2855
|
+
} = opts ?? {};
|
|
2856
|
+
const contentType = format === "ndjson" ? "application/x-ndjson" : "application/json";
|
|
2857
|
+
let seq = 0;
|
|
2858
|
+
return reactiveSink(source, {
|
|
2859
|
+
onTransportError,
|
|
2860
|
+
batchSize,
|
|
2861
|
+
flushIntervalMs,
|
|
2862
|
+
serialize: transform,
|
|
2863
|
+
sendBatch: async (batch6) => {
|
|
2864
|
+
seq += 1;
|
|
2865
|
+
const body = format === "ndjson" ? `${batch6.map((v) => JSON.stringify(v)).join("\n")}
|
|
2866
|
+
` : JSON.stringify(batch6);
|
|
2867
|
+
const key = keyGenerator(seq, (0, import_core25.wallClockNs)());
|
|
2868
|
+
await client.putObject({ Bucket: bucket, Key: key, Body: body, ContentType: contentType });
|
|
2869
|
+
}
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
// src/base/io/to-tempo.ts
|
|
2874
|
+
function toTempo(source, client, opts) {
|
|
2875
|
+
const { toResourceSpans = (v) => [v], onTransportError } = opts ?? {};
|
|
2876
|
+
return reactiveSink(source, {
|
|
2877
|
+
onTransportError,
|
|
2878
|
+
serialize: toResourceSpans,
|
|
2879
|
+
send: async (spans) => {
|
|
2880
|
+
await client.push({ resourceSpans: spans });
|
|
2881
|
+
}
|
|
2882
|
+
});
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
// src/base/io/webhook.ts
|
|
2886
|
+
function fromWebhook(register, opts) {
|
|
2887
|
+
return externalProducer(register, opts);
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2890
|
+
// src/base/io/websocket.ts
|
|
2891
|
+
var import_core27 = require("@graphrefly/pure-ts/core");
|
|
2892
|
+
|
|
2893
|
+
// src/base/resilience/retry.ts
|
|
2894
|
+
var import_core26 = require("@graphrefly/pure-ts/core");
|
|
2895
|
+
function resolveRetryConfig(opts) {
|
|
2896
|
+
const count = opts?.count;
|
|
2897
|
+
const backoffOpt = opts?.backoff;
|
|
2898
|
+
if (backoffOpt !== void 0 && count === void 0) {
|
|
2899
|
+
throw new RangeError(
|
|
2900
|
+
"retry({ backoff }) requires explicit count to prevent unbounded retries; pass { count: <n>, backoff: ... }"
|
|
2901
|
+
);
|
|
2902
|
+
}
|
|
2903
|
+
const maxRetries = count !== void 0 ? count : 0;
|
|
2904
|
+
if (maxRetries < 0) throw new RangeError("retry count must be >= 0");
|
|
2905
|
+
const strategy = backoffOpt === void 0 ? null : typeof backoffOpt === "string" ? resolveBackoffPreset(backoffOpt) : backoffOpt;
|
|
2906
|
+
return { maxRetries, strategy };
|
|
2907
|
+
}
|
|
2908
|
+
function retryFactoryArgs(opts) {
|
|
2909
|
+
const args = {};
|
|
2910
|
+
if (opts?.count !== void 0) args.count = opts.count;
|
|
2911
|
+
if (typeof opts?.backoff === "string") args.backoff = opts.backoff;
|
|
2912
|
+
return Object.keys(args).length > 0 ? args : void 0;
|
|
2913
|
+
}
|
|
2914
|
+
function _runRetryStateMachine(getCfg, acquireSource, a, emitState) {
|
|
2915
|
+
let attempt = 0;
|
|
2916
|
+
let stopped = false;
|
|
2917
|
+
let prevDelay = null;
|
|
2918
|
+
let unsub;
|
|
2919
|
+
const timer = new import_core26.ResettableTimer();
|
|
2920
|
+
const publish = (status) => {
|
|
2921
|
+
emitState?.({ status, attempt, lastDelay_ns: prevDelay });
|
|
2922
|
+
};
|
|
2923
|
+
publish("pending");
|
|
2924
|
+
function disconnectUpstream() {
|
|
2925
|
+
unsub?.();
|
|
2926
|
+
unsub = void 0;
|
|
2927
|
+
}
|
|
2928
|
+
function scheduleRetryOrFinish(err) {
|
|
2929
|
+
if (stopped) return;
|
|
2930
|
+
const cfg = getCfg();
|
|
2931
|
+
if (attempt >= cfg.maxRetries) {
|
|
2932
|
+
disconnectUpstream();
|
|
2933
|
+
publish("errored");
|
|
2934
|
+
a.down([[import_core26.ERROR, err]]);
|
|
2935
|
+
return;
|
|
2936
|
+
}
|
|
2937
|
+
const raw = cfg.strategy === null ? 0 : cfg.strategy(attempt, err, prevDelay);
|
|
2938
|
+
if (raw === null || raw === void 0) {
|
|
2939
|
+
disconnectUpstream();
|
|
2940
|
+
publish("errored");
|
|
2941
|
+
a.down([[import_core26.ERROR, err]]);
|
|
2942
|
+
return;
|
|
2943
|
+
}
|
|
2944
|
+
let delayNs;
|
|
2945
|
+
try {
|
|
2946
|
+
delayNs = coerceDelayNs(raw);
|
|
2947
|
+
} catch {
|
|
2948
|
+
disconnectUpstream();
|
|
2949
|
+
publish("errored");
|
|
2950
|
+
a.down([[import_core26.ERROR, err]]);
|
|
2951
|
+
return;
|
|
2952
|
+
}
|
|
2953
|
+
prevDelay = delayNs;
|
|
2954
|
+
attempt += 1;
|
|
2955
|
+
disconnectUpstream();
|
|
2956
|
+
publish("paused");
|
|
2957
|
+
const delayMs = delayNs > 0 ? delayNs / NS_PER_MS : 1;
|
|
2958
|
+
timer.start(delayMs, () => {
|
|
2959
|
+
if (stopped) return;
|
|
2960
|
+
connect();
|
|
2961
|
+
});
|
|
2962
|
+
}
|
|
2963
|
+
function connect() {
|
|
2964
|
+
timer.cancel();
|
|
2965
|
+
disconnectUpstream();
|
|
2966
|
+
let src;
|
|
2967
|
+
try {
|
|
2968
|
+
src = acquireSource();
|
|
2969
|
+
} catch (err) {
|
|
2970
|
+
scheduleRetryOrFinish(err);
|
|
2971
|
+
return;
|
|
2972
|
+
}
|
|
2973
|
+
publish("running");
|
|
2974
|
+
unsub = src.subscribe((msgs) => {
|
|
2975
|
+
if (stopped) return;
|
|
2976
|
+
for (const m of msgs) {
|
|
2977
|
+
const t = m[0];
|
|
2978
|
+
if (t === import_core26.DIRTY) a.down([[import_core26.DIRTY]]);
|
|
2979
|
+
else if (t === import_core26.DATA) {
|
|
2980
|
+
attempt = 0;
|
|
2981
|
+
prevDelay = null;
|
|
2982
|
+
a.emit(m[1]);
|
|
2983
|
+
publish("running");
|
|
2984
|
+
} else if (t === import_core26.RESOLVED) a.down([[import_core26.RESOLVED]]);
|
|
2985
|
+
else if (t === import_core26.COMPLETE) {
|
|
2986
|
+
stopped = true;
|
|
2987
|
+
disconnectUpstream();
|
|
2988
|
+
publish("completed");
|
|
2989
|
+
a.down([[import_core26.COMPLETE]]);
|
|
2990
|
+
} else if (t === import_core26.ERROR) {
|
|
2991
|
+
scheduleRetryOrFinish(msgVal(m));
|
|
2992
|
+
return;
|
|
2993
|
+
} else a.down([m]);
|
|
2994
|
+
}
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2997
|
+
connect();
|
|
2998
|
+
return () => {
|
|
2999
|
+
const wasStopped = stopped;
|
|
3000
|
+
stopped = true;
|
|
3001
|
+
timer.cancel();
|
|
3002
|
+
disconnectUpstream();
|
|
3003
|
+
if (!wasStopped) publish("cancelled");
|
|
3004
|
+
};
|
|
3005
|
+
}
|
|
3006
|
+
function retry(input, opts) {
|
|
3007
|
+
const retryState = (0, import_core26.node)([], {
|
|
3008
|
+
name: "retryState",
|
|
3009
|
+
describeKind: "state",
|
|
3010
|
+
initial: { status: "pending", attempt: 0, lastDelay_ns: null },
|
|
3011
|
+
equals: (a, b) => a === b || a != null && b != null && typeof a === "object" && typeof b === "object" && JSON.stringify(a) === JSON.stringify(b)
|
|
3012
|
+
});
|
|
3013
|
+
const emit = (s) => {
|
|
3014
|
+
retryState.down([[import_core26.DIRTY], [import_core26.DATA, s]]);
|
|
3015
|
+
};
|
|
3016
|
+
if (typeof input === "function") {
|
|
3017
|
+
return {
|
|
3018
|
+
node: _retryFactory(input, opts, emit),
|
|
3019
|
+
retryState
|
|
3020
|
+
};
|
|
3021
|
+
}
|
|
3022
|
+
return {
|
|
3023
|
+
node: _retrySource(input, opts, emit),
|
|
3024
|
+
retryState
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
function makeMergedOptsMirror(arg) {
|
|
3028
|
+
if (arg === void 0) {
|
|
3029
|
+
return { current: () => void 0, unsub: () => void 0 };
|
|
3030
|
+
}
|
|
3031
|
+
if (!isNode(arg)) {
|
|
3032
|
+
return { current: () => arg, unsub: () => void 0 };
|
|
3033
|
+
}
|
|
3034
|
+
const optsNode = arg;
|
|
3035
|
+
let merged = optsNode.cache ?? void 0;
|
|
3036
|
+
const unsub = optsNode.subscribe((msgs) => {
|
|
3037
|
+
for (const m of msgs) {
|
|
3038
|
+
if (m[0] !== import_core26.DATA) continue;
|
|
3039
|
+
const next = m[1];
|
|
3040
|
+
if (next == null || typeof next !== "object") continue;
|
|
3041
|
+
if (Object.keys(next).length === 0) continue;
|
|
3042
|
+
merged = { ...merged ?? {}, ...next };
|
|
3043
|
+
}
|
|
3044
|
+
});
|
|
3045
|
+
return { current: () => merged, unsub };
|
|
3046
|
+
}
|
|
3047
|
+
var _retrySourceNonResubscribableWarned = /* @__PURE__ */ new WeakSet();
|
|
3048
|
+
function _retrySource(source, opts, emitState) {
|
|
3049
|
+
const sourceWithFlag = source;
|
|
3050
|
+
if (sourceWithFlag._resubscribable === false && !_retrySourceNonResubscribableWarned.has(source)) {
|
|
3051
|
+
_retrySourceNonResubscribableWarned.add(source);
|
|
3052
|
+
console.warn(
|
|
3053
|
+
"retry(source, opts): source-mode requires `resubscribable: true` on the upstream node. Retries will be silent no-ops after the first ERROR. Either pass `resubscribable: true` to the source factory, OR use factory-mode retry `retry(() => buildSource(), opts)` so each attempt builds a fresh node."
|
|
3054
|
+
);
|
|
3055
|
+
}
|
|
3056
|
+
const staticOpts = isNode(opts) ? void 0 : opts;
|
|
3057
|
+
if (!isNode(opts)) resolveRetryConfig(staticOpts);
|
|
3058
|
+
return (0, import_core26.node)(
|
|
3059
|
+
(_data, a) => {
|
|
3060
|
+
const merged = makeMergedOptsMirror(opts);
|
|
3061
|
+
const getCfg = () => resolveRetryConfig(merged.current());
|
|
3062
|
+
const inner = _runRetryStateMachine(getCfg, () => source, a, emitState);
|
|
3063
|
+
return () => {
|
|
3064
|
+
inner();
|
|
3065
|
+
merged.unsub();
|
|
3066
|
+
};
|
|
3067
|
+
},
|
|
3068
|
+
{
|
|
3069
|
+
...operatorOpts(),
|
|
3070
|
+
initial: source.cache,
|
|
3071
|
+
meta: {
|
|
3072
|
+
...staticOpts?.meta ?? {},
|
|
3073
|
+
...(0, import_core26.factoryTag)(
|
|
3074
|
+
"retry",
|
|
3075
|
+
isNode(opts) ? { reactiveOpts: true } : retryFactoryArgs(staticOpts)
|
|
3076
|
+
)
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
);
|
|
3080
|
+
}
|
|
3081
|
+
function _retryFactory(factory, opts, emitState) {
|
|
3082
|
+
const staticOpts = isNode(opts) ? void 0 : opts;
|
|
3083
|
+
if (!isNode(opts)) resolveRetryConfig(staticOpts);
|
|
3084
|
+
return (0, import_core26.node)(
|
|
3085
|
+
(_data, a) => {
|
|
3086
|
+
const merged = makeMergedOptsMirror(opts);
|
|
3087
|
+
const getCfg = () => resolveRetryConfig(merged.current());
|
|
3088
|
+
const inner = _runRetryStateMachine(getCfg, factory, a, emitState);
|
|
3089
|
+
return () => {
|
|
3090
|
+
inner();
|
|
3091
|
+
merged.unsub();
|
|
3092
|
+
};
|
|
3093
|
+
},
|
|
3094
|
+
{
|
|
3095
|
+
...operatorOpts(),
|
|
3096
|
+
initial: staticOpts?.initial,
|
|
3097
|
+
meta: {
|
|
3098
|
+
...staticOpts?.meta ?? {},
|
|
3099
|
+
...(0, import_core26.factoryTag)(
|
|
3100
|
+
"retry",
|
|
3101
|
+
isNode(opts) ? { reactiveOpts: true } : retryFactoryArgs(staticOpts)
|
|
3102
|
+
)
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
);
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
// src/base/io/websocket.ts
|
|
3109
|
+
function fromWebSocket(socketOrRegister, opts) {
|
|
3110
|
+
const { parse, closeOnTeardown = false, ...rest } = opts ?? {};
|
|
3111
|
+
return (0, import_core27.node)(
|
|
3112
|
+
[],
|
|
3113
|
+
(_data, a) => {
|
|
3114
|
+
let active = true;
|
|
3115
|
+
let cleanup;
|
|
3116
|
+
const runCleanup = () => {
|
|
3117
|
+
const fn = cleanup;
|
|
3118
|
+
cleanup = void 0;
|
|
3119
|
+
fn?.();
|
|
3120
|
+
};
|
|
3121
|
+
const terminate = (message) => {
|
|
3122
|
+
if (!active) return;
|
|
3123
|
+
active = false;
|
|
3124
|
+
a.down([message]);
|
|
3125
|
+
runCleanup();
|
|
3126
|
+
};
|
|
3127
|
+
const emit = (raw, event = raw) => {
|
|
3128
|
+
if (!active) return;
|
|
3129
|
+
try {
|
|
3130
|
+
const payload = raw !== null && typeof raw === "object" && "data" in raw ? raw.data : raw;
|
|
3131
|
+
const parsed = parse ? parse(payload, event) : payload;
|
|
3132
|
+
a.emit(parsed);
|
|
3133
|
+
} catch (err) {
|
|
3134
|
+
terminate([import_core27.ERROR, err]);
|
|
3135
|
+
}
|
|
3136
|
+
};
|
|
3137
|
+
const error = (err) => {
|
|
3138
|
+
terminate([import_core27.ERROR, err]);
|
|
3139
|
+
};
|
|
3140
|
+
const complete = () => {
|
|
3141
|
+
terminate([import_core27.COMPLETE]);
|
|
3142
|
+
};
|
|
3143
|
+
if (typeof socketOrRegister === "function") {
|
|
3144
|
+
try {
|
|
3145
|
+
cleanup = socketOrRegister(emit, error, complete);
|
|
3146
|
+
if (typeof cleanup !== "function") {
|
|
3147
|
+
throw new Error(
|
|
3148
|
+
"fromWebSocket register contract violation: register must return cleanup callable"
|
|
3149
|
+
);
|
|
3150
|
+
}
|
|
3151
|
+
} catch (err) {
|
|
3152
|
+
terminate([import_core27.ERROR, err]);
|
|
3153
|
+
}
|
|
3154
|
+
return () => {
|
|
3155
|
+
active = false;
|
|
3156
|
+
runCleanup();
|
|
3157
|
+
};
|
|
3158
|
+
}
|
|
3159
|
+
const ws = socketOrRegister;
|
|
3160
|
+
const onMessage = (event) => emit(event, event);
|
|
3161
|
+
const onError = (event) => error(event);
|
|
3162
|
+
const onClose = () => complete();
|
|
3163
|
+
ws.addEventListener("message", onMessage);
|
|
3164
|
+
ws.addEventListener("error", onError);
|
|
3165
|
+
ws.addEventListener("close", onClose);
|
|
3166
|
+
cleanup = () => {
|
|
3167
|
+
ws.removeEventListener("message", onMessage);
|
|
3168
|
+
ws.removeEventListener("error", onError);
|
|
3169
|
+
ws.removeEventListener("close", onClose);
|
|
3170
|
+
if (closeOnTeardown) ws.close();
|
|
3171
|
+
};
|
|
3172
|
+
return () => {
|
|
3173
|
+
active = false;
|
|
3174
|
+
runCleanup();
|
|
3175
|
+
};
|
|
3176
|
+
},
|
|
3177
|
+
sourceOpts(rest)
|
|
3178
|
+
);
|
|
3179
|
+
}
|
|
3180
|
+
function toWebSocket(source, socket, opts) {
|
|
3181
|
+
const {
|
|
3182
|
+
serialize = (value) => {
|
|
3183
|
+
if (typeof value === "string" || value instanceof Blob || value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
|
|
3184
|
+
return value;
|
|
3185
|
+
}
|
|
3186
|
+
try {
|
|
3187
|
+
return JSON.stringify(value);
|
|
3188
|
+
} catch {
|
|
3189
|
+
return String(value);
|
|
3190
|
+
}
|
|
3191
|
+
},
|
|
3192
|
+
closeOnComplete = true,
|
|
3193
|
+
closeOnError = true,
|
|
3194
|
+
closeCode,
|
|
3195
|
+
closeReason,
|
|
3196
|
+
onTransportError,
|
|
3197
|
+
retry: retryOpt,
|
|
3198
|
+
backpressure,
|
|
3199
|
+
stopOn
|
|
3200
|
+
} = opts ?? {};
|
|
3201
|
+
let socketClosed = false;
|
|
3202
|
+
const closeSocket = (trigger) => {
|
|
3203
|
+
if (socketClosed) return;
|
|
3204
|
+
socketClosed = true;
|
|
3205
|
+
try {
|
|
3206
|
+
socket.close(closeCode, closeReason);
|
|
3207
|
+
} catch (err) {
|
|
3208
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
3209
|
+
try {
|
|
3210
|
+
onTransportError?.({ stage: "close", error, value: void 0, message: trigger });
|
|
3211
|
+
} catch {
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
};
|
|
3215
|
+
let externalCloseHandler = null;
|
|
3216
|
+
const removeExternalCloseHandler = () => {
|
|
3217
|
+
if (externalCloseHandler) {
|
|
3218
|
+
try {
|
|
3219
|
+
socket.removeEventListener("close", externalCloseHandler);
|
|
3220
|
+
} catch {
|
|
3221
|
+
}
|
|
3222
|
+
externalCloseHandler = null;
|
|
3223
|
+
}
|
|
3224
|
+
};
|
|
3225
|
+
const handle = reactiveSink(source, {
|
|
3226
|
+
onTransportError,
|
|
3227
|
+
serialize: (value) => {
|
|
3228
|
+
const s = serialize(value);
|
|
3229
|
+
if (s === void 0) {
|
|
3230
|
+
throw new Error("serialize returned undefined");
|
|
3231
|
+
}
|
|
3232
|
+
return s;
|
|
3233
|
+
},
|
|
3234
|
+
retry: retryOpt,
|
|
3235
|
+
backpressure,
|
|
3236
|
+
stopOn,
|
|
3237
|
+
onDispose: removeExternalCloseHandler,
|
|
3238
|
+
send: (payload) => {
|
|
3239
|
+
socket.send(payload);
|
|
3240
|
+
},
|
|
3241
|
+
onUpstreamMessage: (msg) => {
|
|
3242
|
+
if (msg[0] === import_core27.COMPLETE && closeOnComplete) closeSocket(msg);
|
|
3243
|
+
else if (msg[0] === import_core27.ERROR && closeOnError) closeSocket(msg);
|
|
3244
|
+
}
|
|
3245
|
+
});
|
|
3246
|
+
externalCloseHandler = () => {
|
|
3247
|
+
socketClosed = true;
|
|
3248
|
+
handle.dispose();
|
|
3249
|
+
};
|
|
3250
|
+
socket.addEventListener("close", externalCloseHandler);
|
|
3251
|
+
return handle;
|
|
3252
|
+
}
|
|
3253
|
+
function fromWebSocketReconnect(factory, opts) {
|
|
3254
|
+
const {
|
|
3255
|
+
parse,
|
|
3256
|
+
maxRetries,
|
|
3257
|
+
backoff = "exponential",
|
|
3258
|
+
closeOnTeardown = true,
|
|
3259
|
+
...rest
|
|
3260
|
+
} = opts ?? {};
|
|
3261
|
+
return retry(
|
|
3262
|
+
() => fromWebSocket(factory(), {
|
|
3263
|
+
parse,
|
|
3264
|
+
closeOnTeardown,
|
|
3265
|
+
...rest
|
|
3266
|
+
}),
|
|
3267
|
+
{ count: maxRetries, backoff }
|
|
3268
|
+
).node;
|
|
3269
|
+
}
|
|
3270
|
+
//# sourceMappingURL=index.cjs.map
|