@graphrefly/graphrefly 0.47.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base/composition/index.cjs +28 -19
- package/dist/base/composition/index.cjs.map +1 -1
- package/dist/base/composition/index.d.cts +14 -5
- package/dist/base/composition/index.d.ts +14 -5
- package/dist/base/composition/index.js +9 -9
- package/dist/base/index.cjs +294 -164
- package/dist/base/index.cjs.map +1 -1
- package/dist/base/index.d.cts +2 -2
- package/dist/base/index.d.ts +2 -2
- package/dist/base/index.js +77 -72
- package/dist/base/io/index.cjs +145 -85
- package/dist/base/io/index.cjs.map +1 -1
- package/dist/base/io/index.d.cts +32 -5
- package/dist/base/io/index.d.ts +32 -5
- package/dist/base/io/index.js +5 -5
- package/dist/base/mutation/index.cjs +21 -0
- package/dist/base/mutation/index.cjs.map +1 -1
- package/dist/base/mutation/index.d.cts +23 -1
- package/dist/base/mutation/index.d.ts +23 -1
- package/dist/base/mutation/index.js +3 -1
- package/dist/base/sources/browser/index.cjs +18 -12
- package/dist/base/sources/browser/index.cjs.map +1 -1
- package/dist/base/sources/browser/index.d.cts +20 -2
- package/dist/base/sources/browser/index.d.ts +20 -2
- package/dist/base/sources/browser/index.js +18 -12
- package/dist/base/sources/browser/index.js.map +1 -1
- package/dist/base/sources/event/index.cjs +29 -1
- package/dist/base/sources/event/index.cjs.map +1 -1
- package/dist/base/sources/event/index.d.cts +67 -3
- package/dist/base/sources/event/index.d.ts +67 -3
- package/dist/base/sources/event/index.js +5 -2
- package/dist/base/sources/index.cjs +96 -50
- package/dist/base/sources/index.cjs.map +1 -1
- package/dist/base/sources/index.d.cts +1 -1
- package/dist/base/sources/index.d.ts +1 -1
- package/dist/base/sources/index.js +7 -4
- package/dist/base/sources/node/index.cjs +43 -37
- package/dist/base/sources/node/index.cjs.map +1 -1
- package/dist/base/sources/node/index.js +43 -37
- package/dist/base/sources/node/index.js.map +1 -1
- package/dist/{chunk-J5WFUEO4.js → chunk-23MAWVOJ.js} +3 -3
- package/dist/{chunk-YXCPV26R.js → chunk-3REMCHSS.js} +39 -27
- package/dist/chunk-3REMCHSS.js.map +1 -0
- package/dist/{chunk-CEVNQ74M.js → chunk-3YGXPUHW.js} +2 -2
- package/dist/{chunk-CEVNQ74M.js.map → chunk-3YGXPUHW.js.map} +1 -1
- package/dist/{chunk-EVYY4X5A.js → chunk-46X2EFQH.js} +16 -5
- package/dist/chunk-46X2EFQH.js.map +1 -0
- package/dist/{chunk-NY2PYHNC.js → chunk-5UY3PNFY.js} +12 -5
- package/dist/chunk-5UY3PNFY.js.map +1 -0
- package/dist/{chunk-RGMTUZCL.js → chunk-65OM4XLQ.js} +50 -4
- package/dist/chunk-65OM4XLQ.js.map +1 -0
- package/dist/{chunk-3PSLNJDU.js → chunk-6DQYBIHW.js} +314 -49
- package/dist/chunk-6DQYBIHW.js.map +1 -0
- package/dist/{chunk-LDCSZ72P.js → chunk-6YBER5UP.js} +3 -3
- package/dist/{chunk-LDCSZ72P.js.map → chunk-6YBER5UP.js.map} +1 -1
- package/dist/{chunk-7EGRP2VX.js → chunk-7BULJTL6.js} +2 -2
- package/dist/{chunk-7EGRP2VX.js.map → chunk-7BULJTL6.js.map} +1 -1
- package/dist/{chunk-VLAGJZSL.js → chunk-7T7WLEPM.js} +25 -4
- package/dist/chunk-7T7WLEPM.js.map +1 -0
- package/dist/{chunk-PKPO3JTZ.js → chunk-AQAKDE7F.js} +29 -11
- package/dist/chunk-AQAKDE7F.js.map +1 -0
- package/dist/{chunk-2OB3CEJS.js → chunk-B5Y5GPD5.js} +2 -2
- package/dist/{chunk-BXGZFGZ4.js → chunk-C5QD5DQX.js} +22 -1
- package/dist/chunk-C5QD5DQX.js.map +1 -0
- package/dist/{chunk-4XCHZRUJ.js → chunk-D5YGR4TP.js} +58 -7
- package/dist/chunk-D5YGR4TP.js.map +1 -0
- package/dist/{chunk-NPRP3MCV.js → chunk-DHDCOOJU.js} +2 -2
- package/dist/chunk-DHDCOOJU.js.map +1 -0
- package/dist/{chunk-MTTRCEJT.js → chunk-DVTDF5OI.js} +2 -2
- package/dist/{chunk-SOOKUYVM.js → chunk-F7EKHR32.js} +13 -9
- package/dist/chunk-F7EKHR32.js.map +1 -0
- package/dist/{chunk-A7KV5UK4.js → chunk-G7H6PN7P.js} +2 -2
- package/dist/{chunk-OCUDSN63.js → chunk-GGKHHG5Y.js} +110 -64
- package/dist/chunk-GGKHHG5Y.js.map +1 -0
- package/dist/{chunk-RAGGHLCV.js → chunk-GUNIRPEJ.js} +8 -6
- package/dist/{chunk-RAGGHLCV.js.map → chunk-GUNIRPEJ.js.map} +1 -1
- package/dist/{chunk-YJ4U2D2C.js → chunk-J5TBZFBD.js} +9 -7
- package/dist/chunk-J5TBZFBD.js.map +1 -0
- package/dist/{chunk-Y52CS6YA.js → chunk-JA67ZQG2.js} +2 -2
- package/dist/{chunk-Y52CS6YA.js.map → chunk-JA67ZQG2.js.map} +1 -1
- package/dist/{chunk-U225SKB4.js → chunk-K4ZYJ4EM.js} +569 -424
- package/dist/chunk-K4ZYJ4EM.js.map +1 -0
- package/dist/{chunk-Z4YXAUDN.js → chunk-KUFXLAEY.js} +11 -7
- package/dist/{chunk-Z4YXAUDN.js.map → chunk-KUFXLAEY.js.map} +1 -1
- package/dist/{chunk-IHTWQEDR.js → chunk-LTSI7ULC.js} +3 -3
- package/dist/{chunk-IHTWQEDR.js.map → chunk-LTSI7ULC.js.map} +1 -1
- package/dist/{chunk-DKNHAICT.js → chunk-MMHGYX44.js} +25 -9
- package/dist/chunk-MMHGYX44.js.map +1 -0
- package/dist/{chunk-K7PDZYQE.js → chunk-MQMTRKY3.js} +129 -50
- package/dist/chunk-MQMTRKY3.js.map +1 -0
- package/dist/{chunk-42FQ27MQ.js → chunk-MTODGQBR.js} +44 -179
- package/dist/chunk-MTODGQBR.js.map +1 -0
- package/dist/{chunk-O3MT7DYI.js → chunk-N6MNJNHB.js} +2 -2
- package/dist/{chunk-FVINAAKA.js → chunk-NBK6QQMG.js} +14 -13
- package/dist/{chunk-FVINAAKA.js.map → chunk-NBK6QQMG.js.map} +1 -1
- package/dist/{chunk-DM4OMPWK.js → chunk-NSA5K5G2.js} +2 -2
- package/dist/{chunk-MLTPJMH6.js → chunk-QQYULEZL.js} +2 -2
- package/dist/chunk-QSW4DFKE.js +31 -0
- package/dist/chunk-QSW4DFKE.js.map +1 -0
- package/dist/{chunk-PZWISPIQ.js → chunk-S7HN5FHL.js} +17 -11
- package/dist/chunk-S7HN5FHL.js.map +1 -0
- package/dist/{chunk-4S53H2KR.js → chunk-SUNCHMML.js} +2 -2
- package/dist/{chunk-4GYMCUDZ.js → chunk-T2U6N3FV.js} +7 -7
- package/dist/{chunk-RJOG4IJU.js → chunk-T5URUIIY.js} +50 -35
- package/dist/chunk-T5URUIIY.js.map +1 -0
- package/dist/{chunk-B4AKFXGE.js → chunk-TPTZZV25.js} +6 -6
- package/dist/chunk-TPTZZV25.js.map +1 -0
- package/dist/{chunk-BU3SEFA5.js → chunk-V46JWFGV.js} +7 -6
- package/dist/chunk-V46JWFGV.js.map +1 -0
- package/dist/{chunk-IJRR6YAI.js → chunk-VLDRAMP7.js} +18 -12
- package/dist/chunk-VLDRAMP7.js.map +1 -0
- package/dist/{chunk-6XZYT4SW.js → chunk-X6ESZDR6.js} +8 -9
- package/dist/chunk-X6ESZDR6.js.map +1 -0
- package/dist/{chunk-E5OZPDIW.js → chunk-X7BA5PWG.js} +7 -5
- package/dist/chunk-X7BA5PWG.js.map +1 -0
- package/dist/{chunk-CXANAIZU.js → chunk-XEWV254I.js} +3 -3
- package/dist/{chunk-CXANAIZU.js.map → chunk-XEWV254I.js.map} +1 -1
- package/dist/{chunk-V4Y3TM7U.js → chunk-YBJVKMTM.js} +38 -16
- package/dist/chunk-YBJVKMTM.js.map +1 -0
- package/dist/{chunk-7ADWWI2T.js → chunk-ZW32BPXV.js} +17 -6
- package/dist/chunk-ZW32BPXV.js.map +1 -0
- package/dist/compat/index.cjs +52 -5
- package/dist/compat/index.cjs.map +1 -1
- package/dist/compat/index.d.cts +1 -1
- package/dist/compat/index.d.ts +1 -1
- package/dist/compat/index.js +7 -7
- package/dist/compat/nestjs/index.cjs +52 -5
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +1 -1
- package/dist/compat/nestjs/index.d.ts +1 -1
- package/dist/compat/nestjs/index.js +4 -4
- package/dist/{fallback-Bx46zqky.d.cts → fallback-BROR6ZhO.d.cts} +1 -1
- package/dist/{fallback-pIWW8A2d.d.ts → fallback-DO80aM_3.d.ts} +1 -1
- package/dist/{index-B_p8tnvf.d.cts → index-D1z3XcF9.d.cts} +1 -0
- package/dist/{index-_HDSmPyp.d.ts → index-DZ6yua0Q.d.ts} +1 -0
- package/dist/index.cjs +2387 -1707
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +173 -150
- package/dist/index.js.map +1 -1
- package/dist/presets/ai/index.cjs +88 -26
- package/dist/presets/ai/index.cjs.map +1 -1
- package/dist/presets/ai/index.js +14 -14
- package/dist/presets/harness/index.cjs +183 -51
- package/dist/presets/harness/index.cjs.map +1 -1
- package/dist/presets/harness/index.d.cts +15 -5
- package/dist/presets/harness/index.d.ts +15 -5
- package/dist/presets/harness/index.js +26 -26
- package/dist/presets/index.cjs +298 -101
- package/dist/presets/index.cjs.map +1 -1
- package/dist/presets/index.d.cts +2 -2
- package/dist/presets/index.d.ts +2 -2
- package/dist/presets/index.js +49 -49
- package/dist/presets/inspect/index.cjs +63 -14
- package/dist/presets/inspect/index.cjs.map +1 -1
- package/dist/presets/inspect/index.d.cts +1 -1
- package/dist/presets/inspect/index.d.ts +1 -1
- package/dist/presets/inspect/index.js +6 -6
- package/dist/presets/resilience/index.cjs +64 -44
- package/dist/presets/resilience/index.cjs.map +1 -1
- package/dist/presets/resilience/index.d.cts +12 -8
- package/dist/presets/resilience/index.d.ts +12 -8
- package/dist/presets/resilience/index.js +6 -6
- package/dist/{rate-limiter-DpVbSYdH.d.cts → rate-limiter-DC26FM8J.d.cts} +10 -1
- package/dist/{rate-limiter-CEALq4N1.d.ts → rate-limiter-DyWpwpQP.d.ts} +10 -1
- package/dist/{reactive-layout-fswlBUvX.d.ts → reactive-layout-BBBWH0V_.d.cts} +85 -4
- package/dist/{reactive-layout-fswlBUvX.d.cts → reactive-layout-BBBWH0V_.d.ts} +85 -4
- package/dist/solutions/index.cjs +239 -92
- package/dist/solutions/index.cjs.map +1 -1
- package/dist/solutions/index.d.cts +2 -2
- package/dist/solutions/index.d.ts +2 -2
- package/dist/solutions/index.js +32 -32
- package/dist/{spawnable-5mDY501F.d.cts → spawnable-B2IlW60f.d.cts} +23 -2
- package/dist/{spawnable-D3lR0oQu.d.ts → spawnable-tttFz2Nh.d.ts} +23 -2
- package/dist/testing/index.cjs +94 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +59 -0
- package/dist/testing/index.d.ts +59 -0
- package/dist/testing/index.js +73 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/{timeout-U5O4ESK3.js → timeout-BEABACRP.js} +2 -2
- package/dist/utils/ai/browser.cjs.map +1 -1
- package/dist/utils/ai/browser.d.cts +2 -2
- package/dist/utils/ai/browser.d.ts +2 -2
- package/dist/utils/ai/browser.js +10 -10
- package/dist/utils/ai/browser.js.map +1 -1
- package/dist/utils/ai/index.cjs +291 -191
- package/dist/utils/ai/index.cjs.map +1 -1
- package/dist/utils/ai/index.d.cts +108 -12
- package/dist/utils/ai/index.d.ts +108 -12
- package/dist/utils/ai/index.js +23 -21
- package/dist/utils/ai/node.cjs.map +1 -1
- package/dist/utils/ai/node.d.cts +5 -5
- package/dist/utils/ai/node.d.ts +5 -5
- package/dist/utils/ai/node.js +3 -3
- package/dist/utils/ai/node.js.map +1 -1
- package/dist/utils/cqrs/index.cjs +29 -3
- package/dist/utils/cqrs/index.cjs.map +1 -1
- package/dist/utils/cqrs/index.d.cts +12 -7
- package/dist/utils/cqrs/index.d.ts +12 -7
- package/dist/utils/cqrs/index.js +2 -2
- package/dist/utils/demo-shell/index.cjs +45 -19
- package/dist/utils/demo-shell/index.cjs.map +1 -1
- package/dist/utils/demo-shell/index.d.cts +1 -1
- package/dist/utils/demo-shell/index.d.ts +1 -1
- package/dist/utils/demo-shell/index.js +2 -2
- package/dist/utils/domain-templates/index.cjs +1 -1
- package/dist/utils/domain-templates/index.cjs.map +1 -1
- package/dist/utils/domain-templates/index.js +3 -3
- package/dist/utils/graphspec/index.cjs +1 -1
- package/dist/utils/graphspec/index.cjs.map +1 -1
- package/dist/utils/graphspec/index.js +3 -3
- package/dist/utils/harness/index.cjs +16 -10
- package/dist/utils/harness/index.cjs.map +1 -1
- package/dist/utils/harness/index.js +1 -1
- package/dist/utils/index.cjs +1692 -1192
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +7 -7
- package/dist/utils/index.d.ts +7 -7
- package/dist/utils/index.js +77 -59
- package/dist/utils/inspect/index.cjs +52 -4
- package/dist/utils/inspect/index.cjs.map +1 -1
- package/dist/utils/inspect/index.d.cts +32 -3
- package/dist/utils/inspect/index.d.ts +32 -3
- package/dist/utils/inspect/index.js +4 -4
- package/dist/utils/job-queue/index.cjs +46 -9
- package/dist/utils/job-queue/index.cjs.map +1 -1
- package/dist/utils/job-queue/index.d.cts +33 -3
- package/dist/utils/job-queue/index.d.ts +33 -3
- package/dist/utils/job-queue/index.js +2 -2
- package/dist/utils/memory/index.cjs +570 -425
- package/dist/utils/memory/index.cjs.map +1 -1
- package/dist/utils/memory/index.d.cts +261 -33
- package/dist/utils/memory/index.d.ts +261 -33
- package/dist/utils/memory/index.js +10 -2
- package/dist/utils/messaging/index.cjs.map +1 -1
- package/dist/utils/messaging/index.d.cts +4 -3
- package/dist/utils/messaging/index.d.ts +4 -3
- package/dist/utils/messaging/index.js +2 -2
- package/dist/utils/orchestration/index.cjs +14 -3
- package/dist/utils/orchestration/index.cjs.map +1 -1
- package/dist/utils/orchestration/index.js +3 -3
- package/dist/utils/process/index.cjs +32 -2
- package/dist/utils/process/index.cjs.map +1 -1
- package/dist/utils/process/index.d.cts +4 -3
- package/dist/utils/process/index.d.ts +4 -3
- package/dist/utils/process/index.js +3 -3
- package/dist/utils/reactive-layout/index.cjs +184 -55
- package/dist/utils/reactive-layout/index.cjs.map +1 -1
- package/dist/utils/reactive-layout/index.d.cts +128 -3
- package/dist/utils/reactive-layout/index.d.ts +128 -3
- package/dist/utils/reactive-layout/index.js +16 -8
- package/dist/utils/reduction/index.cjs +1 -1
- package/dist/utils/reduction/index.cjs.map +1 -1
- package/dist/utils/reduction/index.js +2 -2
- package/dist/utils/resilience/index.cjs +64 -43
- package/dist/utils/resilience/index.cjs.map +1 -1
- package/dist/utils/resilience/index.d.cts +1 -1
- package/dist/utils/resilience/index.d.ts +1 -1
- package/dist/utils/resilience/index.js +5 -5
- package/dist/utils/surface/index.cjs +1 -1
- package/dist/utils/surface/index.cjs.map +1 -1
- package/dist/utils/surface/index.js +4 -4
- package/package.json +15 -3
- package/dist/chunk-3PSLNJDU.js.map +0 -1
- package/dist/chunk-42FQ27MQ.js.map +0 -1
- package/dist/chunk-4XCHZRUJ.js.map +0 -1
- package/dist/chunk-6XZYT4SW.js.map +0 -1
- package/dist/chunk-7ADWWI2T.js.map +0 -1
- package/dist/chunk-B4AKFXGE.js.map +0 -1
- package/dist/chunk-BU3SEFA5.js.map +0 -1
- package/dist/chunk-BXGZFGZ4.js.map +0 -1
- package/dist/chunk-DKNHAICT.js.map +0 -1
- package/dist/chunk-E5OZPDIW.js.map +0 -1
- package/dist/chunk-EVYY4X5A.js.map +0 -1
- package/dist/chunk-IJRR6YAI.js.map +0 -1
- package/dist/chunk-K7PDZYQE.js.map +0 -1
- package/dist/chunk-NPRP3MCV.js.map +0 -1
- package/dist/chunk-NY2PYHNC.js.map +0 -1
- package/dist/chunk-OCUDSN63.js.map +0 -1
- package/dist/chunk-PKPO3JTZ.js.map +0 -1
- package/dist/chunk-PZWISPIQ.js.map +0 -1
- package/dist/chunk-RGMTUZCL.js.map +0 -1
- package/dist/chunk-RJOG4IJU.js.map +0 -1
- package/dist/chunk-SOOKUYVM.js.map +0 -1
- package/dist/chunk-U225SKB4.js.map +0 -1
- package/dist/chunk-V4Y3TM7U.js.map +0 -1
- package/dist/chunk-VLAGJZSL.js.map +0 -1
- package/dist/chunk-W2BOPXTI.js +0 -1
- package/dist/chunk-YJ4U2D2C.js.map +0 -1
- package/dist/chunk-YXCPV26R.js.map +0 -1
- package/dist/timeout-U5O4ESK3.js.map +0 -1
- /package/dist/{chunk-J5WFUEO4.js.map → chunk-23MAWVOJ.js.map} +0 -0
- /package/dist/{chunk-2OB3CEJS.js.map → chunk-B5Y5GPD5.js.map} +0 -0
- /package/dist/{chunk-MTTRCEJT.js.map → chunk-DVTDF5OI.js.map} +0 -0
- /package/dist/{chunk-A7KV5UK4.js.map → chunk-G7H6PN7P.js.map} +0 -0
- /package/dist/{chunk-O3MT7DYI.js.map → chunk-N6MNJNHB.js.map} +0 -0
- /package/dist/{chunk-DM4OMPWK.js.map → chunk-NSA5K5G2.js.map} +0 -0
- /package/dist/{chunk-MLTPJMH6.js.map → chunk-QQYULEZL.js.map} +0 -0
- /package/dist/{chunk-4S53H2KR.js.map → chunk-SUNCHMML.js.map} +0 -0
- /package/dist/{chunk-4GYMCUDZ.js.map → chunk-T2U6N3FV.js.map} +0 -0
- /package/dist/{chunk-W2BOPXTI.js.map → timeout-BEABACRP.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/base/sources/node/index.ts","../../../../src/base/sources/node/fs-root.ts","../../../../src/base/sources/node/git-hook.ts","../../../../src/base/sources/node/process.ts"],"sourcesContent":["/**\n * Node-only sources — fs, git, git-hook, process.\n *\n * All entries in this subpath may import node:* builtins.\n * Import via @graphrefly/graphrefly/base/sources/node.\n *\n * @module\n */\n\nexport * from \"./fs.js\";\nexport * from \"./git.js\";\nexport * from \"./git-hook.js\";\nexport * from \"./process.js\";\n","/**\n * Filesystem-watching source. Isolated from `./sources.ts` so bundlers\n * targeting the browser can import browser-safe sources (`fromTimer`,\n * `fromRaf`, etc.) without pulling in `node:fs`/`node:path`.\n */\n\nimport { existsSync, watch } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n\tDATA,\n\tERROR,\n\ttype Message,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport { globToRegExp, matchesAnyPattern } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions<unknown>, \"describeKind\">;\n\nfunction sourceOpts<T = unknown>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"producer\", ...opts } as NodeOptions<T>;\n}\n\nexport type FSEventType = \"change\" | \"rename\" | \"create\" | \"delete\";\nexport type FSEvent = {\n\ttype: FSEventType;\n\tpath: string;\n\troot: string;\n\trelative_path: string;\n\tsrc_path?: string;\n\tdest_path?: string;\n\ttimestamp_ns: number;\n};\n\nexport type FromFSWatchOptions = ExtraOpts & {\n\trecursive?: boolean;\n\tdebounce?: number;\n\tinclude?: string[];\n\texclude?: string[];\n};\n\n/**\n * Watches filesystem paths and emits debounced change events.\n *\n * Uses `fs.watch` only (no polling fallback). Teardown closes all watchers.\n *\n * @category extra\n */\nexport function fromFSWatch(paths: string | string[], opts?: FromFSWatchOptions): Node<FSEvent> {\n\tconst list = Array.isArray(paths) ? paths : [paths];\n\tif (list.length === 0) {\n\t\tthrow new RangeError(\"fromFSWatch expects at least one path\");\n\t}\n\tconst { recursive = true, debounce = 100, include, exclude, ...rest } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = (exclude ?? [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\"]).map(\n\t\tglobToRegExp,\n\t);\n\treturn node<FSEvent>((_data, a) => {\n\t\tconst pending = new Map<string, FSEvent>();\n\t\tconst watchers: ReturnType<typeof watch>[] = [];\n\t\tlet stopped = false;\n\t\tlet terminalEmitted = false;\n\t\tlet generation = 0;\n\t\tconst closeWatchers = () => {\n\t\t\tfor (const watcher of watchers.splice(0)) watcher.close();\n\t\t};\n\t\tconst emitError = (err: unknown) => {\n\t\t\tif (terminalEmitted) return;\n\t\t\tterminalEmitted = true;\n\t\t\tstopped = true;\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t\tpending.clear();\n\t\t\tcloseWatchers();\n\t\t\ta.down([[ERROR, err]]);\n\t\t};\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst flush = (token: number) => {\n\t\t\ttimer = undefined;\n\t\t\tif (stopped || terminalEmitted) return;\n\t\t\tif (pending.size === 0) return;\n\t\t\tconst batchMessages: Message[] = [];\n\t\t\tfor (const evt of pending.values()) batchMessages.push([DATA, evt]);\n\t\t\tpending.clear();\n\t\t\tif (stopped || terminalEmitted || token !== generation) return;\n\t\t\ta.down(batchMessages);\n\t\t};\n\t\ttry {\n\t\t\tfor (const basePath of list) {\n\t\t\t\tconst watcher = watch(\n\t\t\t\t\tbasePath,\n\t\t\t\t\t{ recursive },\n\t\t\t\t\t(eventType: \"rename\" | \"change\", fileName: string | Buffer | null) => {\n\t\t\t\t\t\tif (stopped || terminalEmitted) return;\n\t\t\t\t\t\tif (fileName == null) return;\n\t\t\t\t\t\tconst rel = String(fileName).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst abs = resolvePath(basePath, String(fileName));\n\t\t\t\t\t\tconst normalized = abs.replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst root = resolvePath(basePath).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst relForMatch = rel.startsWith(\"./\") ? rel.slice(2) : rel;\n\t\t\t\t\t\tconst included =\n\t\t\t\t\t\t\tincludePatterns.length === 0 ||\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, includePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, includePatterns);\n\t\t\t\t\t\tif (!included) return;\n\t\t\t\t\t\tconst excluded =\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, excludePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, excludePatterns);\n\t\t\t\t\t\tif (excluded) return;\n\t\t\t\t\t\tlet kind: FSEventType = \"change\";\n\t\t\t\t\t\tif (eventType === \"rename\") {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tkind = existsSync(normalized) ? \"create\" : \"delete\";\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tkind = \"rename\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpending.set(normalized, {\n\t\t\t\t\t\t\ttype: kind,\n\t\t\t\t\t\t\tpath: normalized,\n\t\t\t\t\t\t\troot,\n\t\t\t\t\t\t\trelative_path: relForMatch,\n\t\t\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\t\t\tconst token = generation;\n\t\t\t\t\t\ttimer = setTimeout(() => flush(token), debounce);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\twatcher.on(\"error\", (err) => emitError(err));\n\t\t\t\twatchers.push(watcher);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\temitError(err);\n\t\t}\n\t\treturn () => {\n\t\t\tstopped = true;\n\t\t\tgeneration += 1;\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t\tcloseWatchers();\n\t\t\tpending.clear();\n\t\t};\n\t}, sourceOpts(rest));\n}\n","/**\n * Git hook source — Node-only reactive source that polls a repository's HEAD\n * and emits structured `GitEvent`s on every new commit.\n *\n * Isolated from `./adapters.ts` so that the universal `extra/index` barrel\n * stays browser-safe. Access via `@graphrefly/graphrefly/extra/node`, which\n * re-exports this module.\n *\n * @module\n */\n\nimport { ERROR, type Node, type NodeOptions, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromTimer, globToRegExp, matchesAnyPattern, switchMap } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions, \"describeKind\">;\n\n/** Git hook type for {@link fromGitHook}. */\nexport type GitHookType = \"post-commit\" | \"post-merge\" | \"post-checkout\" | \"post-rewrite\";\n\n/** Structured git event emitted by {@link fromGitHook}. */\nexport type GitEvent = {\n\thook: GitHookType;\n\tcommit: string;\n\tfiles: string[];\n\tmessage: string;\n\tauthor: string;\n\ttimestamp_ns: number;\n};\n\n/** Options for {@link fromGitHook}. */\nexport type FromGitHookOptions = ExtraOpts & {\n\tpollMs?: number;\n\tinclude?: string[];\n\texclude?: string[];\n\t/**\n\t * Maximum consecutive poll errors before terminating the source. Prevents\n\t * error storms when the repository is unavailable (e.g. deleted, corrupt,\n\t * permissions lost). Default: `1` (terminate on first error — preserves\n\t * pre-switchMap back-compat). Raise it (or set `Infinity`) to keep\n\t * retrying indefinitely (legacy behavior).\n\t */\n\tmaxConsecutiveErrors?: number;\n};\n\n/**\n * Git change detection as a reactive source.\n *\n * @category extra\n */\nexport function fromGitHook(repoPath: string, opts?: FromGitHookOptions): Node<GitEvent> {\n\tconst { pollMs = 5000, include, exclude, maxConsecutiveErrors = 1 } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = exclude?.map(globToRegExp) ?? [];\n\tconst { execFileSync } = require(\"node:child_process\") as typeof import(\"node:child_process\");\n\n\tconst gitQuery = (args: string[]): string =>\n\t\texecFileSync(\"git\", args, { cwd: repoPath, encoding: \"utf-8\" }).trim();\n\n\t// Shared across ticks: the previous HEAD we committed to. Undefined on the\n\t// very first poll (we record the initial HEAD without emitting).\n\tlet lastSeen: string | undefined;\n\t// Circuit breaker: consecutive error count. Resets on any successful poll.\n\tlet consecutiveErrors = 0;\n\n\t// `fromTimer | switchMap(sync-git-diff)` — ticks drive the poll, switchMap\n\t// cancels any in-flight inner on next tick. First tick at t=0 records the\n\t// baseline HEAD silently; subsequent ticks emit `GitEvent` on HEAD change.\n\treturn switchMap(fromTimer(0, { period: pollMs }), () =>\n\t\tnode<GitEvent>((_data, a) => {\n\t\t\ttry {\n\t\t\t\tconst head = gitQuery([\"rev-parse\", \"HEAD\"]);\n\t\t\t\tif (!head) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\t\t\t\tif (lastSeen === undefined) {\n\t\t\t\t\t// First poll: record baseline; stay idle until next tick\n\t\t\t\t\t// disposes this inner.\n\t\t\t\t\tlastSeen = head;\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\t\t\t\tif (head === lastSeen) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\t\t\t\tlet files = gitQuery([\"diff\", \"--name-only\", `${lastSeen}..${head}`])\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter(Boolean);\n\t\t\t\tif (includePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => matchesAnyPattern(f, includePatterns));\n\t\t\t\t}\n\t\t\t\tif (excludePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => !matchesAnyPattern(f, excludePatterns));\n\t\t\t\t}\n\t\t\t\tconst message = gitQuery([\"log\", \"-1\", \"--format=%s\", head]);\n\t\t\t\tconst author = gitQuery([\"log\", \"-1\", \"--format=%an\", head]);\n\t\t\t\ta.emit({\n\t\t\t\t\thook: \"post-commit\" as GitHookType,\n\t\t\t\t\tcommit: head,\n\t\t\t\t\tfiles,\n\t\t\t\t\tmessage,\n\t\t\t\t\tauthor,\n\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t});\n\t\t\t\tlastSeen = head;\n\t\t\t\tconsecutiveErrors = 0;\n\t\t\t} catch (err) {\n\t\t\t\tconsecutiveErrors += 1;\n\t\t\t\tif (consecutiveErrors >= maxConsecutiveErrors) {\n\t\t\t\t\ta.down([[ERROR, err]]);\n\t\t\t\t}\n\t\t\t\t// else: transient error — next tick will retry; don't spam ERROR.\n\t\t\t}\n\t\t\treturn () => {};\n\t\t}),\n\t);\n}\n","/**\n * Child-process reactive sources — Node-only.\n *\n * Isolated from `./sources.ts` so bundlers targeting the browser can import\n * browser-safe sources without pulling in `node:child_process`.\n *\n * Access via `@graphrefly/graphrefly/extra/node`, which re-exports this module.\n *\n * @module\n */\n\nimport { type SpawnOptions, spawn } from \"node:child_process\";\nimport { COMPLETE, DATA, ERROR, type Messages, type Node, node } from \"@graphrefly/pure-ts/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * SpawnEvent — discriminated stream emitted by {@link fromSpawn}.\n *\n * @category extra\n */\nexport type SpawnEvent =\n\t| { kind: \"stdout\"; chunk: Buffer }\n\t| { kind: \"stderr\"; chunk: Buffer }\n\t| { kind: \"exit\"; code: number | null; signal: NodeJS.Signals | null };\n\n/** Options for {@link fromSpawn}. Mirrors `child_process.SpawnOptions`. */\nexport interface FromSpawnOptions {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\tshell?: boolean | string;\n\t/**\n\t * Optional caller-owned AbortSignal. When fired, the subprocess is sent\n\t * SIGTERM (per `child_process.spawn` signal semantics). The producer's own\n\t * teardown also sends SIGTERM regardless of caller signal — so `switchMap`\n\t * supersede in `actuatorExecutor` cancels in-flight subprocesses without\n\t * the caller wiring extra signals.\n\t */\n\tsignal?: AbortSignal;\n\t/** Extra args forwarded to spawn — e.g. stdio configuration. */\n\tstdio?: \"pipe\" | readonly (\"pipe\" | \"ignore\" | \"inherit\")[];\n}\n\n// ---------------------------------------------------------------------------\n// fromSpawn\n// ---------------------------------------------------------------------------\n\n/**\n * Spawn `cmd args` as a child process and stream stdout/stderr/exit as a\n * single discriminated `SpawnEvent` stream.\n *\n * Lifecycle:\n * - Stdout/stderr chunks emit as `DATA { kind: \"stdout\"|\"stderr\", chunk }`.\n * - Process exit emits one final `DATA { kind: \"exit\", code, signal }` then\n * `COMPLETE`.\n * - Spawn-error (ENOENT, EPERM, …) emits `ERROR`.\n * - Producer teardown sends `SIGTERM` to the subprocess if it is still alive.\n *\n * **Multicast semantics:** `fromSpawn` returns a node backed by a single\n * `producer` activation — the subprocess is spawned once when the first\n * subscriber connects, and all subsequent subscribers share the same event\n * stream. Unsubscribing the last subscriber tears down the subprocess.\n *\n * @example\n * ```ts\n * import { fromSpawn } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const stream = fromSpawn(\"git\", [\"log\", \"--oneline\"]);\n * stream.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value);\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function fromSpawn(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<SpawnEvent> {\n\treturn node<SpawnEvent>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stdout\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stderr\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tactions.down([\n\t\t\t\t\t[DATA, { kind: \"exit\", code: info.code, signal: info.signal }],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tif (alive) {\n\t\t\t\t\talive = false;\n\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t{ name: \"from_spawn\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// runProcess\n// ---------------------------------------------------------------------------\n\n/**\n * Run `cmd args` to completion and emit one DATA with aggregated output.\n *\n * Convenience over {@link fromSpawn} for the \"wait for the process to finish,\n * capture stdout/stderr as strings, get exit code\" case.\n *\n * Aggregation policy: stdout and stderr are concatenated as `Buffer`s and\n * decoded as utf-8 once at exit, so multi-byte sequences split across chunks\n * are handled correctly. Actuators that need byte-exact stdout should use\n * `fromSpawn` directly.\n *\n * @example\n * ```ts\n * import { runProcess } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const result = runProcess(\"git\", [\"rev-parse\", \"HEAD\"]);\n * result.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value.stdout.trim());\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function runProcess(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<{\n\tstdout: string;\n\tstderr: string;\n\texitCode: number | null;\n\tsignal: NodeJS.Signals | null;\n}> {\n\ttype Result = {\n\t\tstdout: string;\n\t\tstderr: string;\n\t\texitCode: number | null;\n\t\tsignal: NodeJS.Signals | null;\n\t};\n\treturn node<Result>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tconst stdoutChunks: Buffer[] = [];\n\t\t\tconst stderrChunks: Buffer[] = [];\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstdoutChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstderrChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tconst stdout = Buffer.concat(stdoutChunks).toString(\"utf8\");\n\t\t\t\tconst stderr = Buffer.concat(stderrChunks).toString(\"utf8\");\n\t\t\t\tactions.down([\n\t\t\t\t\t[\n\t\t\t\t\t\tDATA,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstdout,\n\t\t\t\t\t\t\tstderr,\n\t\t\t\t\t\t\texitCode: info.code,\n\t\t\t\t\t\t\tsignal: info.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tif (alive) {\n\t\t\t\t\talive = false;\n\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t{ name: \"run_process\" },\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMA,qBAAkC;AAClC,uBAAuC;AACvC,kBAQO;AACP,mBAAgD;AAIhD,SAAS,WAAwB,MAAkC;AAClE,SAAO,EAAE,cAAc,YAAY,GAAG,KAAK;AAC5C;AA2BO,SAAS,YAAY,OAA0B,MAA0C;AAC/F,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAClD,MAAI,KAAK,WAAW,GAAG;AACtB,UAAM,IAAI,WAAW,uCAAuC;AAAA,EAC7D;AACA,QAAM,EAAE,YAAY,MAAM,WAAW,KAAK,SAAS,SAAS,GAAG,KAAK,IAAI,QAAQ,CAAC;AACjF,QAAM,kBAAkB,SAAS,IAAI,yBAAY,KAAK,CAAC;AACvD,QAAM,mBAAmB,WAAW,CAAC,sBAAsB,cAAc,YAAY,GAAG;AAAA,IACvF;AAAA,EACD;AACA,aAAO,kBAAc,CAAC,OAAO,MAAM;AAClC,UAAM,UAAU,oBAAI,IAAqB;AACzC,UAAM,WAAuC,CAAC;AAC9C,QAAI,UAAU;AACd,QAAI,kBAAkB;AACtB,QAAI,aAAa;AACjB,UAAM,gBAAgB,MAAM;AAC3B,iBAAW,WAAW,SAAS,OAAO,CAAC,EAAG,SAAQ,MAAM;AAAA,IACzD;AACA,UAAM,YAAY,CAAC,QAAiB;AACnC,UAAI,gBAAiB;AACrB,wBAAkB;AAClB,gBAAU;AACV,UAAI,UAAU,OAAW,cAAa,KAAK;AAC3C,cAAQ;AACR,cAAQ,MAAM;AACd,oBAAc;AACd,QAAE,KAAK,CAAC,CAAC,mBAAO,GAAG,CAAC,CAAC;AAAA,IACtB;AACA,QAAI;AACJ,UAAM,QAAQ,CAAC,UAAkB;AAChC,cAAQ;AACR,UAAI,WAAW,gBAAiB;AAChC,UAAI,QAAQ,SAAS,EAAG;AACxB,YAAM,gBAA2B,CAAC;AAClC,iBAAW,OAAO,QAAQ,OAAO,EAAG,eAAc,KAAK,CAAC,kBAAM,GAAG,CAAC;AAClE,cAAQ,MAAM;AACd,UAAI,WAAW,mBAAmB,UAAU,WAAY;AACxD,QAAE,KAAK,aAAa;AAAA,IACrB;AACA,QAAI;AACH,iBAAW,YAAY,MAAM;AAC5B,cAAM,cAAU;AAAA,UACf;AAAA,UACA,EAAE,UAAU;AAAA,UACZ,CAAC,WAAgC,aAAqC;AACrE,gBAAI,WAAW,gBAAiB;AAChC,gBAAI,YAAY,KAAM;AACtB,kBAAM,MAAM,OAAO,QAAQ,EAAE,WAAW,MAAM,GAAG;AACjD,kBAAM,UAAM,iBAAAA,SAAY,UAAU,OAAO,QAAQ,CAAC;AAClD,kBAAM,aAAa,IAAI,WAAW,MAAM,GAAG;AAC3C,kBAAM,WAAO,iBAAAA,SAAY,QAAQ,EAAE,WAAW,MAAM,GAAG;AACvD,kBAAM,cAAc,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI;AAC1D,kBAAM,WACL,gBAAgB,WAAW,SAC3B,gCAAkB,YAAY,eAAe,SAC7C,gCAAkB,aAAa,eAAe;AAC/C,gBAAI,CAAC,SAAU;AACf,kBAAM,eACL,gCAAkB,YAAY,eAAe,SAC7C,gCAAkB,aAAa,eAAe;AAC/C,gBAAI,SAAU;AACd,gBAAI,OAAoB;AACxB,gBAAI,cAAc,UAAU;AAC3B,kBAAI;AACH,2BAAO,2BAAW,UAAU,IAAI,WAAW;AAAA,cAC5C,QAAQ;AACP,uBAAO;AAAA,cACR;AAAA,YACD;AACA,oBAAQ,IAAI,YAAY;AAAA,cACvB,MAAM;AAAA,cACN,MAAM;AAAA,cACN;AAAA,cACA,eAAe;AAAA,cACf,kBAAc,yBAAY;AAAA,YAC3B,CAAC;AACD,gBAAI,UAAU,OAAW,cAAa,KAAK;AAC3C,kBAAM,QAAQ;AACd,oBAAQ,WAAW,MAAM,MAAM,KAAK,GAAG,QAAQ;AAAA,UAChD;AAAA,QACD;AACA,gBAAQ,GAAG,SAAS,CAAC,QAAQ,UAAU,GAAG,CAAC;AAC3C,iBAAS,KAAK,OAAO;AAAA,MACtB;AAAA,IACD,SAAS,KAAK;AACb,gBAAU,GAAG;AAAA,IACd;AACA,WAAO,MAAM;AACZ,gBAAU;AACV,oBAAc;AACd,UAAI,UAAU,OAAW,cAAa,KAAK;AAC3C,cAAQ;AACR,oBAAc;AACd,cAAQ,MAAM;AAAA,IACf;AAAA,EACD,GAAG,WAAW,IAAI,CAAC;AACpB;;;ACxIA,IAAAC,eAAsE;AACtE,IAAAC,gBAAsE;AAqC/D,SAAS,YAAY,UAAkB,MAA2C;AACxF,QAAM,EAAE,SAAS,KAAM,SAAS,SAAS,uBAAuB,EAAE,IAAI,QAAQ,CAAC;AAC/E,QAAM,kBAAkB,SAAS,IAAI,0BAAY,KAAK,CAAC;AACvD,QAAM,kBAAkB,SAAS,IAAI,0BAAY,KAAK,CAAC;AACvD,QAAM,EAAE,aAAa,IAAI,QAAQ,eAAoB;AAErD,QAAM,WAAW,CAAC,SACjB,aAAa,OAAO,MAAM,EAAE,KAAK,UAAU,UAAU,QAAQ,CAAC,EAAE,KAAK;AAItE,MAAI;AAEJ,MAAI,oBAAoB;AAKxB,aAAO;AAAA,QAAU,yBAAU,GAAG,EAAE,QAAQ,OAAO,CAAC;AAAA,IAAG,UAClD,mBAAe,CAAC,OAAO,MAAM;AAC5B,UAAI;AACH,cAAM,OAAO,SAAS,CAAC,aAAa,MAAM,CAAC;AAC3C,YAAI,CAAC,MAAM;AACV,8BAAoB;AACpB,iBAAO,MAAM;AAAA,UAAC;AAAA,QACf;AACA,YAAI,aAAa,QAAW;AAG3B,qBAAW;AACX,8BAAoB;AACpB,iBAAO,MAAM;AAAA,UAAC;AAAA,QACf;AACA,YAAI,SAAS,UAAU;AACtB,8BAAoB;AACpB,iBAAO,MAAM;AAAA,UAAC;AAAA,QACf;AACA,YAAI,QAAQ,SAAS,CAAC,QAAQ,eAAe,GAAG,QAAQ,KAAK,IAAI,EAAE,CAAC,EAClE,MAAM,IAAI,EACV,OAAO,OAAO;AAChB,YAAI,gBAAgB,SAAS,GAAG;AAC/B,kBAAQ,MAAM,OAAO,CAAC,UAAM,iCAAkB,GAAG,eAAe,CAAC;AAAA,QAClE;AACA,YAAI,gBAAgB,SAAS,GAAG;AAC/B,kBAAQ,MAAM,OAAO,CAAC,MAAM,KAAC,iCAAkB,GAAG,eAAe,CAAC;AAAA,QACnE;AACA,cAAM,UAAU,SAAS,CAAC,OAAO,MAAM,eAAe,IAAI,CAAC;AAC3D,cAAM,SAAS,SAAS,CAAC,OAAO,MAAM,gBAAgB,IAAI,CAAC;AAC3D,UAAE,KAAK;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA,kBAAc,0BAAY;AAAA,QAC3B,CAAC;AACD,mBAAW;AACX,4BAAoB;AAAA,MACrB,SAAS,KAAK;AACb,6BAAqB;AACrB,YAAI,qBAAqB,sBAAsB;AAC9C,YAAE,KAAK,CAAC,CAAC,oBAAO,GAAG,CAAC,CAAC;AAAA,QACtB;AAAA,MAED;AACA,aAAO,MAAM;AAAA,MAAC;AAAA,IACf,CAAC;AAAA,EACF;AACD;;;AC1GA,gCAAyC;AACzC,IAAAC,eAAsE;AAmE/D,SAAS,UACf,KACA,MACA,MACmB;AACnB,aAAO;AAAA,IACN,CAAC,OAAO,YAAY;AACnB,YAAM,YAAQ,iCAAM,KAAK,MAAkB;AAAA,QAC1C,KAAK,MAAM;AAAA,QACX,KAAK,MAAM;AAAA,QACX,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA,QACd,OAAQ,MAAM,SAAmC;AAAA,MAClD,CAAC;AAED,UAAI,QAAQ;AACZ,UAAI,WAA0E;AAE9E,YAAM,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC3C,YAAI,CAAC,MAAO;AACZ,gBAAQ,KAAK,CAAC,CAAC,mBAAM,EAAE,MAAM,UAAU,MAAM,CAAC,CAAC,CAAoB;AAAA,MACpE,CAAC;AAED,YAAM,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC3C,YAAI,CAAC,MAAO;AACZ,gBAAQ,KAAK,CAAC,CAAC,mBAAM,EAAE,MAAM,UAAU,MAAM,CAAC,CAAC,CAAoB;AAAA,MACpE,CAAC;AAED,YAAM,GAAG,SAAS,CAAC,QAAQ;AAC1B,YAAI,CAAC,MAAO;AACZ,gBAAQ;AACR,gBAAQ,KAAK,CAAC,CAAC,oBAAO,GAAG,CAAC,CAAoB;AAAA,MAC/C,CAAC;AAED,YAAM,GAAG,QAAQ,CAAC,MAAM,WAAW;AAGlC,YAAI,YAAY,KAAM,YAAW,EAAE,MAAM,OAAwC;AAAA,MAClF,CAAC;AAED,YAAM,GAAG,SAAS,MAAM;AACvB,YAAI,CAAC,MAAO;AACZ,gBAAQ;AACR,cAAM,OAAO,YAAY,EAAE,MAAM,MAAM,QAAQ,KAAK;AACpD,gBAAQ,KAAK;AAAA,UACZ,CAAC,mBAAM,EAAE,MAAM,QAAQ,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO,CAAC;AAAA,UAC7D,CAAC,qBAAQ;AAAA,QACV,CAAoB;AAAA,MACrB,CAAC;AAED,aAAO,MAAM;AACZ,YAAI,OAAO;AACV,kBAAQ;AACR,gBAAM,QAAQ,mBAAmB;AACjC,gBAAM,QAAQ,mBAAmB;AACjC,gBAAM,mBAAmB,OAAO;AAChC,gBAAM,mBAAmB,MAAM;AAC/B,gBAAM,mBAAmB,OAAO;AAChC,cAAI;AACH,kBAAM,KAAK,SAAS;AAAA,UACrB,QAAQ;AAAA,UAER;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA,EAAE,MAAM,aAAa;AAAA,EACtB;AACD;AA+BO,SAAS,WACf,KACA,MACA,MAME;AAOF,aAAO;AAAA,IACN,CAAC,OAAO,YAAY;AACnB,YAAM,YAAQ,iCAAM,KAAK,MAAkB;AAAA,QAC1C,KAAK,MAAM;AAAA,QACX,KAAK,MAAM;AAAA,QACX,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA,QACd,OAAQ,MAAM,SAAmC;AAAA,MAClD,CAAC;AAED,UAAI,QAAQ;AACZ,YAAM,eAAyB,CAAC;AAChC,YAAM,eAAyB,CAAC;AAChC,UAAI,WAA0E;AAE9E,YAAM,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC3C,YAAI,CAAC,MAAO;AACZ,qBAAa,KAAK,KAAK;AAAA,MACxB,CAAC;AAED,YAAM,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC3C,YAAI,CAAC,MAAO;AACZ,qBAAa,KAAK,KAAK;AAAA,MACxB,CAAC;AAED,YAAM,GAAG,SAAS,CAAC,QAAQ;AAC1B,YAAI,CAAC,MAAO;AACZ,gBAAQ;AACR,gBAAQ,KAAK,CAAC,CAAC,oBAAO,GAAG,CAAC,CAAoB;AAAA,MAC/C,CAAC;AAED,YAAM,GAAG,QAAQ,CAAC,MAAM,WAAW;AAGlC,YAAI,YAAY,KAAM,YAAW,EAAE,MAAM,OAAwC;AAAA,MAClF,CAAC;AAED,YAAM,GAAG,SAAS,MAAM;AACvB,YAAI,CAAC,MAAO;AACZ,gBAAQ;AACR,cAAM,OAAO,YAAY,EAAE,MAAM,MAAM,QAAQ,KAAK;AACpD,cAAM,SAAS,OAAO,OAAO,YAAY,EAAE,SAAS,MAAM;AAC1D,cAAM,SAAS,OAAO,OAAO,YAAY,EAAE,SAAS,MAAM;AAC1D,gBAAQ,KAAK;AAAA,UACZ;AAAA,YACC;AAAA,YACA;AAAA,cACC;AAAA,cACA;AAAA,cACA,UAAU,KAAK;AAAA,cACf,QAAQ,KAAK;AAAA,YACd;AAAA,UACD;AAAA,UACA,CAAC,qBAAQ;AAAA,QACV,CAAoB;AAAA,MACrB,CAAC;AAED,aAAO,MAAM;AACZ,YAAI,OAAO;AACV,kBAAQ;AACR,gBAAM,QAAQ,mBAAmB;AACjC,gBAAM,QAAQ,mBAAmB;AACjC,gBAAM,mBAAmB,OAAO;AAChC,gBAAM,mBAAmB,MAAM;AAC/B,gBAAM,mBAAmB,OAAO;AAChC,cAAI;AACH,kBAAM,KAAK,SAAS;AAAA,UACrB,QAAQ;AAAA,UAER;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA,EAAE,MAAM,cAAc;AAAA,EACvB;AACD;","names":["resolvePath","import_core","import_extra","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/base/sources/node/index.ts","../../../../src/base/sources/node/fs-root.ts","../../../../src/base/sources/node/git-hook.ts","../../../../src/base/sources/node/process.ts"],"sourcesContent":["/**\n * Node-only sources — fs, git, git-hook, process.\n *\n * All entries in this subpath may import node:* builtins.\n * Import via @graphrefly/graphrefly/base/sources/node.\n *\n * @module\n */\n\nexport * from \"./fs.js\";\nexport * from \"./git.js\";\nexport * from \"./git-hook.js\";\nexport * from \"./process.js\";\n","/**\n * Filesystem-watching source. Isolated from `./sources.ts` so bundlers\n * targeting the browser can import browser-safe sources (`fromTimer`,\n * `fromRaf`, etc.) without pulling in `node:fs`/`node:path`.\n */\n\nimport { existsSync, watch } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n\tDATA,\n\tERROR,\n\ttype Message,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport { globToRegExp, matchesAnyPattern } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions<unknown>, \"describeKind\">;\n\nfunction sourceOpts<T = unknown>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"producer\", ...opts } as NodeOptions<T>;\n}\n\nexport type FSEventType = \"change\" | \"rename\" | \"create\" | \"delete\";\nexport type FSEvent = {\n\ttype: FSEventType;\n\tpath: string;\n\troot: string;\n\trelative_path: string;\n\tsrc_path?: string;\n\tdest_path?: string;\n\ttimestamp_ns: number;\n};\n\nexport type FromFSWatchOptions = ExtraOpts & {\n\trecursive?: boolean;\n\tdebounce?: number;\n\tinclude?: string[];\n\texclude?: string[];\n};\n\n/**\n * Watches filesystem paths and emits debounced change events.\n *\n * Uses `fs.watch` only (no polling fallback). Teardown closes all watchers.\n *\n * @category extra\n */\nexport function fromFSWatch(paths: string | string[], opts?: FromFSWatchOptions): Node<FSEvent> {\n\tconst list = Array.isArray(paths) ? paths : [paths];\n\tif (list.length === 0) {\n\t\tthrow new RangeError(\"fromFSWatch expects at least one path\");\n\t}\n\tconst { recursive = true, debounce = 100, include, exclude, ...rest } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = (exclude ?? [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\"]).map(\n\t\tglobToRegExp,\n\t);\n\treturn node<FSEvent>((_data, a) => {\n\t\tconst pending = new Map<string, FSEvent>();\n\t\tconst watchers: ReturnType<typeof watch>[] = [];\n\t\tlet stopped = false;\n\t\tlet terminalEmitted = false;\n\t\tlet generation = 0;\n\t\tconst closeWatchers = () => {\n\t\t\tfor (const watcher of watchers.splice(0)) watcher.close();\n\t\t};\n\t\tconst emitError = (err: unknown) => {\n\t\t\tif (terminalEmitted) return;\n\t\t\tterminalEmitted = true;\n\t\t\tstopped = true;\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t\tpending.clear();\n\t\t\tcloseWatchers();\n\t\t\ta.down([[ERROR, err]]);\n\t\t};\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst flush = (token: number) => {\n\t\t\ttimer = undefined;\n\t\t\tif (stopped || terminalEmitted) return;\n\t\t\tif (pending.size === 0) return;\n\t\t\tconst batchMessages: Message[] = [];\n\t\t\tfor (const evt of pending.values()) batchMessages.push([DATA, evt]);\n\t\t\tpending.clear();\n\t\t\tif (stopped || terminalEmitted || token !== generation) return;\n\t\t\ta.down(batchMessages);\n\t\t};\n\t\ttry {\n\t\t\tfor (const basePath of list) {\n\t\t\t\tconst watcher = watch(\n\t\t\t\t\tbasePath,\n\t\t\t\t\t{ recursive },\n\t\t\t\t\t(eventType: \"rename\" | \"change\", fileName: string | Buffer | null) => {\n\t\t\t\t\t\tif (stopped || terminalEmitted) return;\n\t\t\t\t\t\tif (fileName == null) return;\n\t\t\t\t\t\tconst rel = String(fileName).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst abs = resolvePath(basePath, String(fileName));\n\t\t\t\t\t\tconst normalized = abs.replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst root = resolvePath(basePath).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst relForMatch = rel.startsWith(\"./\") ? rel.slice(2) : rel;\n\t\t\t\t\t\tconst included =\n\t\t\t\t\t\t\tincludePatterns.length === 0 ||\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, includePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, includePatterns);\n\t\t\t\t\t\tif (!included) return;\n\t\t\t\t\t\tconst excluded =\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, excludePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, excludePatterns);\n\t\t\t\t\t\tif (excluded) return;\n\t\t\t\t\t\tlet kind: FSEventType = \"change\";\n\t\t\t\t\t\tif (eventType === \"rename\") {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tkind = existsSync(normalized) ? \"create\" : \"delete\";\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tkind = \"rename\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpending.set(normalized, {\n\t\t\t\t\t\t\ttype: kind,\n\t\t\t\t\t\t\tpath: normalized,\n\t\t\t\t\t\t\troot,\n\t\t\t\t\t\t\trelative_path: relForMatch,\n\t\t\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\t\t\tconst token = generation;\n\t\t\t\t\t\ttimer = setTimeout(() => flush(token), debounce);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\twatcher.on(\"error\", (err) => emitError(err));\n\t\t\t\twatchers.push(watcher);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\temitError(err);\n\t\t}\n\t\treturn {\n\t\t\tonDeactivation: () => {\n\t\t\t\tstopped = true;\n\t\t\t\tgeneration += 1;\n\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\ttimer = undefined;\n\t\t\t\tcloseWatchers();\n\t\t\t\tpending.clear();\n\t\t\t},\n\t\t};\n\t}, sourceOpts(rest));\n}\n","/**\n * Git hook source — Node-only reactive source that polls a repository's HEAD\n * and emits structured `GitEvent`s on every new commit.\n *\n * Isolated from `./adapters.ts` so that the universal `extra/index` barrel\n * stays browser-safe. Access via `@graphrefly/graphrefly/extra/node`, which\n * re-exports this module.\n *\n * @module\n */\n\nimport { ERROR, type Node, type NodeOptions, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromTimer, globToRegExp, matchesAnyPattern, switchMap } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions, \"describeKind\">;\n\n/** Git hook type for {@link fromGitHook}. */\nexport type GitHookType = \"post-commit\" | \"post-merge\" | \"post-checkout\" | \"post-rewrite\";\n\n/** Structured git event emitted by {@link fromGitHook}. */\nexport type GitEvent = {\n\thook: GitHookType;\n\tcommit: string;\n\tfiles: string[];\n\tmessage: string;\n\tauthor: string;\n\ttimestamp_ns: number;\n};\n\n/** Options for {@link fromGitHook}. */\nexport type FromGitHookOptions = ExtraOpts & {\n\tpollMs?: number;\n\tinclude?: string[];\n\texclude?: string[];\n\t/**\n\t * Maximum consecutive poll errors before terminating the source. Prevents\n\t * error storms when the repository is unavailable (e.g. deleted, corrupt,\n\t * permissions lost). Default: `1` (terminate on first error — preserves\n\t * pre-switchMap back-compat). Raise it (or set `Infinity`) to keep\n\t * retrying indefinitely (legacy behavior).\n\t */\n\tmaxConsecutiveErrors?: number;\n};\n\n/**\n * Git change detection as a reactive source.\n *\n * @category extra\n */\nexport function fromGitHook(repoPath: string, opts?: FromGitHookOptions): Node<GitEvent> {\n\tconst { pollMs = 5000, include, exclude, maxConsecutiveErrors = 1 } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = exclude?.map(globToRegExp) ?? [];\n\tconst { execFileSync } = require(\"node:child_process\") as typeof import(\"node:child_process\");\n\n\tconst gitQuery = (args: string[]): string =>\n\t\texecFileSync(\"git\", args, { cwd: repoPath, encoding: \"utf-8\" }).trim();\n\n\t// Shared across ticks: the previous HEAD we committed to. Undefined on the\n\t// very first poll (we record the initial HEAD without emitting).\n\tlet lastSeen: string | undefined;\n\t// Circuit breaker: consecutive error count. Resets on any successful poll.\n\tlet consecutiveErrors = 0;\n\n\t// `fromTimer | switchMap(sync-git-diff)` — ticks drive the poll, switchMap\n\t// cancels any in-flight inner on next tick. First tick at t=0 records the\n\t// baseline HEAD silently; subsequent ticks emit `GitEvent` on HEAD change.\n\treturn switchMap(fromTimer(0, { period: pollMs }), () =>\n\t\tnode<GitEvent>((_data, a) => {\n\t\t\ttry {\n\t\t\t\tconst head = gitQuery([\"rev-parse\", \"HEAD\"]);\n\t\t\t\tif (!head) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn { onDeactivation: () => {} };\n\t\t\t\t}\n\t\t\t\tif (lastSeen === undefined) {\n\t\t\t\t\t// First poll: record baseline; stay idle until next tick\n\t\t\t\t\t// disposes this inner.\n\t\t\t\t\tlastSeen = head;\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn { onDeactivation: () => {} };\n\t\t\t\t}\n\t\t\t\tif (head === lastSeen) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn { onDeactivation: () => {} };\n\t\t\t\t}\n\t\t\t\tlet files = gitQuery([\"diff\", \"--name-only\", `${lastSeen}..${head}`])\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter(Boolean);\n\t\t\t\tif (includePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => matchesAnyPattern(f, includePatterns));\n\t\t\t\t}\n\t\t\t\tif (excludePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => !matchesAnyPattern(f, excludePatterns));\n\t\t\t\t}\n\t\t\t\tconst message = gitQuery([\"log\", \"-1\", \"--format=%s\", head]);\n\t\t\t\tconst author = gitQuery([\"log\", \"-1\", \"--format=%an\", head]);\n\t\t\t\ta.emit({\n\t\t\t\t\thook: \"post-commit\" as GitHookType,\n\t\t\t\t\tcommit: head,\n\t\t\t\t\tfiles,\n\t\t\t\t\tmessage,\n\t\t\t\t\tauthor,\n\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t});\n\t\t\t\tlastSeen = head;\n\t\t\t\tconsecutiveErrors = 0;\n\t\t\t} catch (err) {\n\t\t\t\tconsecutiveErrors += 1;\n\t\t\t\tif (consecutiveErrors >= maxConsecutiveErrors) {\n\t\t\t\t\ta.down([[ERROR, err]]);\n\t\t\t\t}\n\t\t\t\t// else: transient error — next tick will retry; don't spam ERROR.\n\t\t\t}\n\t\t\treturn { onDeactivation: () => {} };\n\t\t}),\n\t);\n}\n","/**\n * Child-process reactive sources — Node-only.\n *\n * Isolated from `./sources.ts` so bundlers targeting the browser can import\n * browser-safe sources without pulling in `node:child_process`.\n *\n * Access via `@graphrefly/graphrefly/extra/node`, which re-exports this module.\n *\n * @module\n */\n\nimport { type SpawnOptions, spawn } from \"node:child_process\";\nimport { COMPLETE, DATA, ERROR, type Messages, type Node, node } from \"@graphrefly/pure-ts/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * SpawnEvent — discriminated stream emitted by {@link fromSpawn}.\n *\n * @category extra\n */\nexport type SpawnEvent =\n\t| { kind: \"stdout\"; chunk: Buffer }\n\t| { kind: \"stderr\"; chunk: Buffer }\n\t| { kind: \"exit\"; code: number | null; signal: NodeJS.Signals | null };\n\n/** Options for {@link fromSpawn}. Mirrors `child_process.SpawnOptions`. */\nexport interface FromSpawnOptions {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\tshell?: boolean | string;\n\t/**\n\t * Optional caller-owned AbortSignal. When fired, the subprocess is sent\n\t * SIGTERM (per `child_process.spawn` signal semantics). The producer's own\n\t * teardown also sends SIGTERM regardless of caller signal — so `switchMap`\n\t * supersede in `actuatorExecutor` cancels in-flight subprocesses without\n\t * the caller wiring extra signals.\n\t */\n\tsignal?: AbortSignal;\n\t/** Extra args forwarded to spawn — e.g. stdio configuration. */\n\tstdio?: \"pipe\" | readonly (\"pipe\" | \"ignore\" | \"inherit\")[];\n}\n\n// ---------------------------------------------------------------------------\n// fromSpawn\n// ---------------------------------------------------------------------------\n\n/**\n * Spawn `cmd args` as a child process and stream stdout/stderr/exit as a\n * single discriminated `SpawnEvent` stream.\n *\n * Lifecycle:\n * - Stdout/stderr chunks emit as `DATA { kind: \"stdout\"|\"stderr\", chunk }`.\n * - Process exit emits one final `DATA { kind: \"exit\", code, signal }` then\n * `COMPLETE`.\n * - Spawn-error (ENOENT, EPERM, …) emits `ERROR`.\n * - Producer teardown sends `SIGTERM` to the subprocess if it is still alive.\n *\n * **Multicast semantics:** `fromSpawn` returns a node backed by a single\n * `producer` activation — the subprocess is spawned once when the first\n * subscriber connects, and all subsequent subscribers share the same event\n * stream. Unsubscribing the last subscriber tears down the subprocess.\n *\n * @example\n * ```ts\n * import { fromSpawn } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const stream = fromSpawn(\"git\", [\"log\", \"--oneline\"]);\n * stream.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value);\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function fromSpawn(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<SpawnEvent> {\n\treturn node<SpawnEvent>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stdout\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stderr\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tactions.down([\n\t\t\t\t\t[DATA, { kind: \"exit\", code: info.code, signal: info.signal }],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tonDeactivation: () => {\n\t\t\t\t\tif (alive) {\n\t\t\t\t\t\talive = false;\n\t\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ name: \"from_spawn\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// runProcess\n// ---------------------------------------------------------------------------\n\n/**\n * Run `cmd args` to completion and emit one DATA with aggregated output.\n *\n * Convenience over {@link fromSpawn} for the \"wait for the process to finish,\n * capture stdout/stderr as strings, get exit code\" case.\n *\n * Aggregation policy: stdout and stderr are concatenated as `Buffer`s and\n * decoded as utf-8 once at exit, so multi-byte sequences split across chunks\n * are handled correctly. Actuators that need byte-exact stdout should use\n * `fromSpawn` directly.\n *\n * @example\n * ```ts\n * import { runProcess } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const result = runProcess(\"git\", [\"rev-parse\", \"HEAD\"]);\n * result.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value.stdout.trim());\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function runProcess(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<{\n\tstdout: string;\n\tstderr: string;\n\texitCode: number | null;\n\tsignal: NodeJS.Signals | null;\n}> {\n\ttype Result = {\n\t\tstdout: string;\n\t\tstderr: string;\n\t\texitCode: number | null;\n\t\tsignal: NodeJS.Signals | null;\n\t};\n\treturn node<Result>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tconst stdoutChunks: Buffer[] = [];\n\t\t\tconst stderrChunks: Buffer[] = [];\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstdoutChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstderrChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tconst stdout = Buffer.concat(stdoutChunks).toString(\"utf8\");\n\t\t\t\tconst stderr = Buffer.concat(stderrChunks).toString(\"utf8\");\n\t\t\t\tactions.down([\n\t\t\t\t\t[\n\t\t\t\t\t\tDATA,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstdout,\n\t\t\t\t\t\t\tstderr,\n\t\t\t\t\t\t\texitCode: info.code,\n\t\t\t\t\t\t\tsignal: info.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tonDeactivation: () => {\n\t\t\t\t\tif (alive) {\n\t\t\t\t\t\talive = false;\n\t\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ name: \"run_process\" },\n\t);\n}\n"],"mappings":"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","names":["resolvePath","import_core","import_extra","import_core"]}
|
|
@@ -98,13 +98,15 @@ function fromFSWatch(paths, opts) {
|
|
|
98
98
|
} catch (err) {
|
|
99
99
|
emitError(err);
|
|
100
100
|
}
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
101
|
+
return {
|
|
102
|
+
onDeactivation: () => {
|
|
103
|
+
stopped = true;
|
|
104
|
+
generation += 1;
|
|
105
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
106
|
+
timer = void 0;
|
|
107
|
+
closeWatchers();
|
|
108
|
+
pending.clear();
|
|
109
|
+
}
|
|
108
110
|
};
|
|
109
111
|
}, sourceOpts(rest));
|
|
110
112
|
}
|
|
@@ -127,19 +129,19 @@ function fromGitHook(repoPath, opts) {
|
|
|
127
129
|
const head = gitQuery(["rev-parse", "HEAD"]);
|
|
128
130
|
if (!head) {
|
|
129
131
|
consecutiveErrors = 0;
|
|
130
|
-
return () => {
|
|
131
|
-
};
|
|
132
|
+
return { onDeactivation: () => {
|
|
133
|
+
} };
|
|
132
134
|
}
|
|
133
135
|
if (lastSeen === void 0) {
|
|
134
136
|
lastSeen = head;
|
|
135
137
|
consecutiveErrors = 0;
|
|
136
|
-
return () => {
|
|
137
|
-
};
|
|
138
|
+
return { onDeactivation: () => {
|
|
139
|
+
} };
|
|
138
140
|
}
|
|
139
141
|
if (head === lastSeen) {
|
|
140
142
|
consecutiveErrors = 0;
|
|
141
|
-
return () => {
|
|
142
|
-
};
|
|
143
|
+
return { onDeactivation: () => {
|
|
144
|
+
} };
|
|
143
145
|
}
|
|
144
146
|
let files = gitQuery(["diff", "--name-only", `${lastSeen}..${head}`]).split("\n").filter(Boolean);
|
|
145
147
|
if (includePatterns.length > 0) {
|
|
@@ -166,8 +168,8 @@ function fromGitHook(repoPath, opts) {
|
|
|
166
168
|
a.down([[ERROR2, err]]);
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
|
-
return () => {
|
|
170
|
-
};
|
|
171
|
+
return { onDeactivation: () => {
|
|
172
|
+
} };
|
|
171
173
|
})
|
|
172
174
|
);
|
|
173
175
|
}
|
|
@@ -212,17 +214,19 @@ function fromSpawn(cmd, args, opts) {
|
|
|
212
214
|
[COMPLETE]
|
|
213
215
|
]);
|
|
214
216
|
});
|
|
215
|
-
return
|
|
216
|
-
|
|
217
|
-
alive
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
217
|
+
return {
|
|
218
|
+
onDeactivation: () => {
|
|
219
|
+
if (alive) {
|
|
220
|
+
alive = false;
|
|
221
|
+
child.stdout?.removeAllListeners();
|
|
222
|
+
child.stderr?.removeAllListeners();
|
|
223
|
+
child.removeAllListeners("error");
|
|
224
|
+
child.removeAllListeners("exit");
|
|
225
|
+
child.removeAllListeners("close");
|
|
226
|
+
try {
|
|
227
|
+
child.kill("SIGTERM");
|
|
228
|
+
} catch {
|
|
229
|
+
}
|
|
226
230
|
}
|
|
227
231
|
}
|
|
228
232
|
};
|
|
@@ -279,17 +283,19 @@ function runProcess(cmd, args, opts) {
|
|
|
279
283
|
[COMPLETE]
|
|
280
284
|
]);
|
|
281
285
|
});
|
|
282
|
-
return
|
|
283
|
-
|
|
284
|
-
alive
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
286
|
+
return {
|
|
287
|
+
onDeactivation: () => {
|
|
288
|
+
if (alive) {
|
|
289
|
+
alive = false;
|
|
290
|
+
child.stdout?.removeAllListeners();
|
|
291
|
+
child.stderr?.removeAllListeners();
|
|
292
|
+
child.removeAllListeners("error");
|
|
293
|
+
child.removeAllListeners("exit");
|
|
294
|
+
child.removeAllListeners("close");
|
|
295
|
+
try {
|
|
296
|
+
child.kill("SIGTERM");
|
|
297
|
+
} catch {
|
|
298
|
+
}
|
|
293
299
|
}
|
|
294
300
|
}
|
|
295
301
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/base/sources/node/fs-root.ts","../../../../src/base/sources/node/git-hook.ts","../../../../src/base/sources/node/process.ts"],"sourcesContent":["/**\n * Filesystem-watching source. Isolated from `./sources.ts` so bundlers\n * targeting the browser can import browser-safe sources (`fromTimer`,\n * `fromRaf`, etc.) without pulling in `node:fs`/`node:path`.\n */\n\nimport { existsSync, watch } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n\tDATA,\n\tERROR,\n\ttype Message,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport { globToRegExp, matchesAnyPattern } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions<unknown>, \"describeKind\">;\n\nfunction sourceOpts<T = unknown>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"producer\", ...opts } as NodeOptions<T>;\n}\n\nexport type FSEventType = \"change\" | \"rename\" | \"create\" | \"delete\";\nexport type FSEvent = {\n\ttype: FSEventType;\n\tpath: string;\n\troot: string;\n\trelative_path: string;\n\tsrc_path?: string;\n\tdest_path?: string;\n\ttimestamp_ns: number;\n};\n\nexport type FromFSWatchOptions = ExtraOpts & {\n\trecursive?: boolean;\n\tdebounce?: number;\n\tinclude?: string[];\n\texclude?: string[];\n};\n\n/**\n * Watches filesystem paths and emits debounced change events.\n *\n * Uses `fs.watch` only (no polling fallback). Teardown closes all watchers.\n *\n * @category extra\n */\nexport function fromFSWatch(paths: string | string[], opts?: FromFSWatchOptions): Node<FSEvent> {\n\tconst list = Array.isArray(paths) ? paths : [paths];\n\tif (list.length === 0) {\n\t\tthrow new RangeError(\"fromFSWatch expects at least one path\");\n\t}\n\tconst { recursive = true, debounce = 100, include, exclude, ...rest } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = (exclude ?? [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\"]).map(\n\t\tglobToRegExp,\n\t);\n\treturn node<FSEvent>((_data, a) => {\n\t\tconst pending = new Map<string, FSEvent>();\n\t\tconst watchers: ReturnType<typeof watch>[] = [];\n\t\tlet stopped = false;\n\t\tlet terminalEmitted = false;\n\t\tlet generation = 0;\n\t\tconst closeWatchers = () => {\n\t\t\tfor (const watcher of watchers.splice(0)) watcher.close();\n\t\t};\n\t\tconst emitError = (err: unknown) => {\n\t\t\tif (terminalEmitted) return;\n\t\t\tterminalEmitted = true;\n\t\t\tstopped = true;\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t\tpending.clear();\n\t\t\tcloseWatchers();\n\t\t\ta.down([[ERROR, err]]);\n\t\t};\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst flush = (token: number) => {\n\t\t\ttimer = undefined;\n\t\t\tif (stopped || terminalEmitted) return;\n\t\t\tif (pending.size === 0) return;\n\t\t\tconst batchMessages: Message[] = [];\n\t\t\tfor (const evt of pending.values()) batchMessages.push([DATA, evt]);\n\t\t\tpending.clear();\n\t\t\tif (stopped || terminalEmitted || token !== generation) return;\n\t\t\ta.down(batchMessages);\n\t\t};\n\t\ttry {\n\t\t\tfor (const basePath of list) {\n\t\t\t\tconst watcher = watch(\n\t\t\t\t\tbasePath,\n\t\t\t\t\t{ recursive },\n\t\t\t\t\t(eventType: \"rename\" | \"change\", fileName: string | Buffer | null) => {\n\t\t\t\t\t\tif (stopped || terminalEmitted) return;\n\t\t\t\t\t\tif (fileName == null) return;\n\t\t\t\t\t\tconst rel = String(fileName).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst abs = resolvePath(basePath, String(fileName));\n\t\t\t\t\t\tconst normalized = abs.replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst root = resolvePath(basePath).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst relForMatch = rel.startsWith(\"./\") ? rel.slice(2) : rel;\n\t\t\t\t\t\tconst included =\n\t\t\t\t\t\t\tincludePatterns.length === 0 ||\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, includePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, includePatterns);\n\t\t\t\t\t\tif (!included) return;\n\t\t\t\t\t\tconst excluded =\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, excludePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, excludePatterns);\n\t\t\t\t\t\tif (excluded) return;\n\t\t\t\t\t\tlet kind: FSEventType = \"change\";\n\t\t\t\t\t\tif (eventType === \"rename\") {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tkind = existsSync(normalized) ? \"create\" : \"delete\";\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tkind = \"rename\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpending.set(normalized, {\n\t\t\t\t\t\t\ttype: kind,\n\t\t\t\t\t\t\tpath: normalized,\n\t\t\t\t\t\t\troot,\n\t\t\t\t\t\t\trelative_path: relForMatch,\n\t\t\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\t\t\tconst token = generation;\n\t\t\t\t\t\ttimer = setTimeout(() => flush(token), debounce);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\twatcher.on(\"error\", (err) => emitError(err));\n\t\t\t\twatchers.push(watcher);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\temitError(err);\n\t\t}\n\t\treturn () => {\n\t\t\tstopped = true;\n\t\t\tgeneration += 1;\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t\tcloseWatchers();\n\t\t\tpending.clear();\n\t\t};\n\t}, sourceOpts(rest));\n}\n","/**\n * Git hook source — Node-only reactive source that polls a repository's HEAD\n * and emits structured `GitEvent`s on every new commit.\n *\n * Isolated from `./adapters.ts` so that the universal `extra/index` barrel\n * stays browser-safe. Access via `@graphrefly/graphrefly/extra/node`, which\n * re-exports this module.\n *\n * @module\n */\n\nimport { ERROR, type Node, type NodeOptions, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromTimer, globToRegExp, matchesAnyPattern, switchMap } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions, \"describeKind\">;\n\n/** Git hook type for {@link fromGitHook}. */\nexport type GitHookType = \"post-commit\" | \"post-merge\" | \"post-checkout\" | \"post-rewrite\";\n\n/** Structured git event emitted by {@link fromGitHook}. */\nexport type GitEvent = {\n\thook: GitHookType;\n\tcommit: string;\n\tfiles: string[];\n\tmessage: string;\n\tauthor: string;\n\ttimestamp_ns: number;\n};\n\n/** Options for {@link fromGitHook}. */\nexport type FromGitHookOptions = ExtraOpts & {\n\tpollMs?: number;\n\tinclude?: string[];\n\texclude?: string[];\n\t/**\n\t * Maximum consecutive poll errors before terminating the source. Prevents\n\t * error storms when the repository is unavailable (e.g. deleted, corrupt,\n\t * permissions lost). Default: `1` (terminate on first error — preserves\n\t * pre-switchMap back-compat). Raise it (or set `Infinity`) to keep\n\t * retrying indefinitely (legacy behavior).\n\t */\n\tmaxConsecutiveErrors?: number;\n};\n\n/**\n * Git change detection as a reactive source.\n *\n * @category extra\n */\nexport function fromGitHook(repoPath: string, opts?: FromGitHookOptions): Node<GitEvent> {\n\tconst { pollMs = 5000, include, exclude, maxConsecutiveErrors = 1 } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = exclude?.map(globToRegExp) ?? [];\n\tconst { execFileSync } = require(\"node:child_process\") as typeof import(\"node:child_process\");\n\n\tconst gitQuery = (args: string[]): string =>\n\t\texecFileSync(\"git\", args, { cwd: repoPath, encoding: \"utf-8\" }).trim();\n\n\t// Shared across ticks: the previous HEAD we committed to. Undefined on the\n\t// very first poll (we record the initial HEAD without emitting).\n\tlet lastSeen: string | undefined;\n\t// Circuit breaker: consecutive error count. Resets on any successful poll.\n\tlet consecutiveErrors = 0;\n\n\t// `fromTimer | switchMap(sync-git-diff)` — ticks drive the poll, switchMap\n\t// cancels any in-flight inner on next tick. First tick at t=0 records the\n\t// baseline HEAD silently; subsequent ticks emit `GitEvent` on HEAD change.\n\treturn switchMap(fromTimer(0, { period: pollMs }), () =>\n\t\tnode<GitEvent>((_data, a) => {\n\t\t\ttry {\n\t\t\t\tconst head = gitQuery([\"rev-parse\", \"HEAD\"]);\n\t\t\t\tif (!head) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\t\t\t\tif (lastSeen === undefined) {\n\t\t\t\t\t// First poll: record baseline; stay idle until next tick\n\t\t\t\t\t// disposes this inner.\n\t\t\t\t\tlastSeen = head;\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\t\t\t\tif (head === lastSeen) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\t\t\t\tlet files = gitQuery([\"diff\", \"--name-only\", `${lastSeen}..${head}`])\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter(Boolean);\n\t\t\t\tif (includePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => matchesAnyPattern(f, includePatterns));\n\t\t\t\t}\n\t\t\t\tif (excludePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => !matchesAnyPattern(f, excludePatterns));\n\t\t\t\t}\n\t\t\t\tconst message = gitQuery([\"log\", \"-1\", \"--format=%s\", head]);\n\t\t\t\tconst author = gitQuery([\"log\", \"-1\", \"--format=%an\", head]);\n\t\t\t\ta.emit({\n\t\t\t\t\thook: \"post-commit\" as GitHookType,\n\t\t\t\t\tcommit: head,\n\t\t\t\t\tfiles,\n\t\t\t\t\tmessage,\n\t\t\t\t\tauthor,\n\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t});\n\t\t\t\tlastSeen = head;\n\t\t\t\tconsecutiveErrors = 0;\n\t\t\t} catch (err) {\n\t\t\t\tconsecutiveErrors += 1;\n\t\t\t\tif (consecutiveErrors >= maxConsecutiveErrors) {\n\t\t\t\t\ta.down([[ERROR, err]]);\n\t\t\t\t}\n\t\t\t\t// else: transient error — next tick will retry; don't spam ERROR.\n\t\t\t}\n\t\t\treturn () => {};\n\t\t}),\n\t);\n}\n","/**\n * Child-process reactive sources — Node-only.\n *\n * Isolated from `./sources.ts` so bundlers targeting the browser can import\n * browser-safe sources without pulling in `node:child_process`.\n *\n * Access via `@graphrefly/graphrefly/extra/node`, which re-exports this module.\n *\n * @module\n */\n\nimport { type SpawnOptions, spawn } from \"node:child_process\";\nimport { COMPLETE, DATA, ERROR, type Messages, type Node, node } from \"@graphrefly/pure-ts/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * SpawnEvent — discriminated stream emitted by {@link fromSpawn}.\n *\n * @category extra\n */\nexport type SpawnEvent =\n\t| { kind: \"stdout\"; chunk: Buffer }\n\t| { kind: \"stderr\"; chunk: Buffer }\n\t| { kind: \"exit\"; code: number | null; signal: NodeJS.Signals | null };\n\n/** Options for {@link fromSpawn}. Mirrors `child_process.SpawnOptions`. */\nexport interface FromSpawnOptions {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\tshell?: boolean | string;\n\t/**\n\t * Optional caller-owned AbortSignal. When fired, the subprocess is sent\n\t * SIGTERM (per `child_process.spawn` signal semantics). The producer's own\n\t * teardown also sends SIGTERM regardless of caller signal — so `switchMap`\n\t * supersede in `actuatorExecutor` cancels in-flight subprocesses without\n\t * the caller wiring extra signals.\n\t */\n\tsignal?: AbortSignal;\n\t/** Extra args forwarded to spawn — e.g. stdio configuration. */\n\tstdio?: \"pipe\" | readonly (\"pipe\" | \"ignore\" | \"inherit\")[];\n}\n\n// ---------------------------------------------------------------------------\n// fromSpawn\n// ---------------------------------------------------------------------------\n\n/**\n * Spawn `cmd args` as a child process and stream stdout/stderr/exit as a\n * single discriminated `SpawnEvent` stream.\n *\n * Lifecycle:\n * - Stdout/stderr chunks emit as `DATA { kind: \"stdout\"|\"stderr\", chunk }`.\n * - Process exit emits one final `DATA { kind: \"exit\", code, signal }` then\n * `COMPLETE`.\n * - Spawn-error (ENOENT, EPERM, …) emits `ERROR`.\n * - Producer teardown sends `SIGTERM` to the subprocess if it is still alive.\n *\n * **Multicast semantics:** `fromSpawn` returns a node backed by a single\n * `producer` activation — the subprocess is spawned once when the first\n * subscriber connects, and all subsequent subscribers share the same event\n * stream. Unsubscribing the last subscriber tears down the subprocess.\n *\n * @example\n * ```ts\n * import { fromSpawn } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const stream = fromSpawn(\"git\", [\"log\", \"--oneline\"]);\n * stream.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value);\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function fromSpawn(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<SpawnEvent> {\n\treturn node<SpawnEvent>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stdout\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stderr\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tactions.down([\n\t\t\t\t\t[DATA, { kind: \"exit\", code: info.code, signal: info.signal }],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tif (alive) {\n\t\t\t\t\talive = false;\n\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t{ name: \"from_spawn\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// runProcess\n// ---------------------------------------------------------------------------\n\n/**\n * Run `cmd args` to completion and emit one DATA with aggregated output.\n *\n * Convenience over {@link fromSpawn} for the \"wait for the process to finish,\n * capture stdout/stderr as strings, get exit code\" case.\n *\n * Aggregation policy: stdout and stderr are concatenated as `Buffer`s and\n * decoded as utf-8 once at exit, so multi-byte sequences split across chunks\n * are handled correctly. Actuators that need byte-exact stdout should use\n * `fromSpawn` directly.\n *\n * @example\n * ```ts\n * import { runProcess } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const result = runProcess(\"git\", [\"rev-parse\", \"HEAD\"]);\n * result.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value.stdout.trim());\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function runProcess(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<{\n\tstdout: string;\n\tstderr: string;\n\texitCode: number | null;\n\tsignal: NodeJS.Signals | null;\n}> {\n\ttype Result = {\n\t\tstdout: string;\n\t\tstderr: string;\n\t\texitCode: number | null;\n\t\tsignal: NodeJS.Signals | null;\n\t};\n\treturn node<Result>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tconst stdoutChunks: Buffer[] = [];\n\t\t\tconst stderrChunks: Buffer[] = [];\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstdoutChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstderrChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tconst stdout = Buffer.concat(stdoutChunks).toString(\"utf8\");\n\t\t\t\tconst stderr = Buffer.concat(stderrChunks).toString(\"utf8\");\n\t\t\t\tactions.down([\n\t\t\t\t\t[\n\t\t\t\t\t\tDATA,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstdout,\n\t\t\t\t\t\t\tstderr,\n\t\t\t\t\t\t\texitCode: info.code,\n\t\t\t\t\t\t\tsignal: info.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tif (alive) {\n\t\t\t\t\talive = false;\n\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t{ name: \"run_process\" },\n\t);\n}\n"],"mappings":"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","names":["ERROR","node","wallClockNs","globToRegExp","matchesAnyPattern","DATA","ERROR","node"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/base/sources/node/fs-root.ts","../../../../src/base/sources/node/git-hook.ts","../../../../src/base/sources/node/process.ts"],"sourcesContent":["/**\n * Filesystem-watching source. Isolated from `./sources.ts` so bundlers\n * targeting the browser can import browser-safe sources (`fromTimer`,\n * `fromRaf`, etc.) without pulling in `node:fs`/`node:path`.\n */\n\nimport { existsSync, watch } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n\tDATA,\n\tERROR,\n\ttype Message,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport { globToRegExp, matchesAnyPattern } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions<unknown>, \"describeKind\">;\n\nfunction sourceOpts<T = unknown>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"producer\", ...opts } as NodeOptions<T>;\n}\n\nexport type FSEventType = \"change\" | \"rename\" | \"create\" | \"delete\";\nexport type FSEvent = {\n\ttype: FSEventType;\n\tpath: string;\n\troot: string;\n\trelative_path: string;\n\tsrc_path?: string;\n\tdest_path?: string;\n\ttimestamp_ns: number;\n};\n\nexport type FromFSWatchOptions = ExtraOpts & {\n\trecursive?: boolean;\n\tdebounce?: number;\n\tinclude?: string[];\n\texclude?: string[];\n};\n\n/**\n * Watches filesystem paths and emits debounced change events.\n *\n * Uses `fs.watch` only (no polling fallback). Teardown closes all watchers.\n *\n * @category extra\n */\nexport function fromFSWatch(paths: string | string[], opts?: FromFSWatchOptions): Node<FSEvent> {\n\tconst list = Array.isArray(paths) ? paths : [paths];\n\tif (list.length === 0) {\n\t\tthrow new RangeError(\"fromFSWatch expects at least one path\");\n\t}\n\tconst { recursive = true, debounce = 100, include, exclude, ...rest } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = (exclude ?? [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\"]).map(\n\t\tglobToRegExp,\n\t);\n\treturn node<FSEvent>((_data, a) => {\n\t\tconst pending = new Map<string, FSEvent>();\n\t\tconst watchers: ReturnType<typeof watch>[] = [];\n\t\tlet stopped = false;\n\t\tlet terminalEmitted = false;\n\t\tlet generation = 0;\n\t\tconst closeWatchers = () => {\n\t\t\tfor (const watcher of watchers.splice(0)) watcher.close();\n\t\t};\n\t\tconst emitError = (err: unknown) => {\n\t\t\tif (terminalEmitted) return;\n\t\t\tterminalEmitted = true;\n\t\t\tstopped = true;\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t\tpending.clear();\n\t\t\tcloseWatchers();\n\t\t\ta.down([[ERROR, err]]);\n\t\t};\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst flush = (token: number) => {\n\t\t\ttimer = undefined;\n\t\t\tif (stopped || terminalEmitted) return;\n\t\t\tif (pending.size === 0) return;\n\t\t\tconst batchMessages: Message[] = [];\n\t\t\tfor (const evt of pending.values()) batchMessages.push([DATA, evt]);\n\t\t\tpending.clear();\n\t\t\tif (stopped || terminalEmitted || token !== generation) return;\n\t\t\ta.down(batchMessages);\n\t\t};\n\t\ttry {\n\t\t\tfor (const basePath of list) {\n\t\t\t\tconst watcher = watch(\n\t\t\t\t\tbasePath,\n\t\t\t\t\t{ recursive },\n\t\t\t\t\t(eventType: \"rename\" | \"change\", fileName: string | Buffer | null) => {\n\t\t\t\t\t\tif (stopped || terminalEmitted) return;\n\t\t\t\t\t\tif (fileName == null) return;\n\t\t\t\t\t\tconst rel = String(fileName).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst abs = resolvePath(basePath, String(fileName));\n\t\t\t\t\t\tconst normalized = abs.replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst root = resolvePath(basePath).replaceAll(\"\\\\\", \"/\");\n\t\t\t\t\t\tconst relForMatch = rel.startsWith(\"./\") ? rel.slice(2) : rel;\n\t\t\t\t\t\tconst included =\n\t\t\t\t\t\t\tincludePatterns.length === 0 ||\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, includePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, includePatterns);\n\t\t\t\t\t\tif (!included) return;\n\t\t\t\t\t\tconst excluded =\n\t\t\t\t\t\t\tmatchesAnyPattern(normalized, excludePatterns) ||\n\t\t\t\t\t\t\tmatchesAnyPattern(relForMatch, excludePatterns);\n\t\t\t\t\t\tif (excluded) return;\n\t\t\t\t\t\tlet kind: FSEventType = \"change\";\n\t\t\t\t\t\tif (eventType === \"rename\") {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tkind = existsSync(normalized) ? \"create\" : \"delete\";\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tkind = \"rename\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpending.set(normalized, {\n\t\t\t\t\t\t\ttype: kind,\n\t\t\t\t\t\t\tpath: normalized,\n\t\t\t\t\t\t\troot,\n\t\t\t\t\t\t\trelative_path: relForMatch,\n\t\t\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\t\t\tconst token = generation;\n\t\t\t\t\t\ttimer = setTimeout(() => flush(token), debounce);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\twatcher.on(\"error\", (err) => emitError(err));\n\t\t\t\twatchers.push(watcher);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\temitError(err);\n\t\t}\n\t\treturn {\n\t\t\tonDeactivation: () => {\n\t\t\t\tstopped = true;\n\t\t\t\tgeneration += 1;\n\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\ttimer = undefined;\n\t\t\t\tcloseWatchers();\n\t\t\t\tpending.clear();\n\t\t\t},\n\t\t};\n\t}, sourceOpts(rest));\n}\n","/**\n * Git hook source — Node-only reactive source that polls a repository's HEAD\n * and emits structured `GitEvent`s on every new commit.\n *\n * Isolated from `./adapters.ts` so that the universal `extra/index` barrel\n * stays browser-safe. Access via `@graphrefly/graphrefly/extra/node`, which\n * re-exports this module.\n *\n * @module\n */\n\nimport { ERROR, type Node, type NodeOptions, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromTimer, globToRegExp, matchesAnyPattern, switchMap } from \"@graphrefly/pure-ts/extra\";\n\ntype ExtraOpts = Omit<NodeOptions, \"describeKind\">;\n\n/** Git hook type for {@link fromGitHook}. */\nexport type GitHookType = \"post-commit\" | \"post-merge\" | \"post-checkout\" | \"post-rewrite\";\n\n/** Structured git event emitted by {@link fromGitHook}. */\nexport type GitEvent = {\n\thook: GitHookType;\n\tcommit: string;\n\tfiles: string[];\n\tmessage: string;\n\tauthor: string;\n\ttimestamp_ns: number;\n};\n\n/** Options for {@link fromGitHook}. */\nexport type FromGitHookOptions = ExtraOpts & {\n\tpollMs?: number;\n\tinclude?: string[];\n\texclude?: string[];\n\t/**\n\t * Maximum consecutive poll errors before terminating the source. Prevents\n\t * error storms when the repository is unavailable (e.g. deleted, corrupt,\n\t * permissions lost). Default: `1` (terminate on first error — preserves\n\t * pre-switchMap back-compat). Raise it (or set `Infinity`) to keep\n\t * retrying indefinitely (legacy behavior).\n\t */\n\tmaxConsecutiveErrors?: number;\n};\n\n/**\n * Git change detection as a reactive source.\n *\n * @category extra\n */\nexport function fromGitHook(repoPath: string, opts?: FromGitHookOptions): Node<GitEvent> {\n\tconst { pollMs = 5000, include, exclude, maxConsecutiveErrors = 1 } = opts ?? {};\n\tconst includePatterns = include?.map(globToRegExp) ?? [];\n\tconst excludePatterns = exclude?.map(globToRegExp) ?? [];\n\tconst { execFileSync } = require(\"node:child_process\") as typeof import(\"node:child_process\");\n\n\tconst gitQuery = (args: string[]): string =>\n\t\texecFileSync(\"git\", args, { cwd: repoPath, encoding: \"utf-8\" }).trim();\n\n\t// Shared across ticks: the previous HEAD we committed to. Undefined on the\n\t// very first poll (we record the initial HEAD without emitting).\n\tlet lastSeen: string | undefined;\n\t// Circuit breaker: consecutive error count. Resets on any successful poll.\n\tlet consecutiveErrors = 0;\n\n\t// `fromTimer | switchMap(sync-git-diff)` — ticks drive the poll, switchMap\n\t// cancels any in-flight inner on next tick. First tick at t=0 records the\n\t// baseline HEAD silently; subsequent ticks emit `GitEvent` on HEAD change.\n\treturn switchMap(fromTimer(0, { period: pollMs }), () =>\n\t\tnode<GitEvent>((_data, a) => {\n\t\t\ttry {\n\t\t\t\tconst head = gitQuery([\"rev-parse\", \"HEAD\"]);\n\t\t\t\tif (!head) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn { onDeactivation: () => {} };\n\t\t\t\t}\n\t\t\t\tif (lastSeen === undefined) {\n\t\t\t\t\t// First poll: record baseline; stay idle until next tick\n\t\t\t\t\t// disposes this inner.\n\t\t\t\t\tlastSeen = head;\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn { onDeactivation: () => {} };\n\t\t\t\t}\n\t\t\t\tif (head === lastSeen) {\n\t\t\t\t\tconsecutiveErrors = 0;\n\t\t\t\t\treturn { onDeactivation: () => {} };\n\t\t\t\t}\n\t\t\t\tlet files = gitQuery([\"diff\", \"--name-only\", `${lastSeen}..${head}`])\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter(Boolean);\n\t\t\t\tif (includePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => matchesAnyPattern(f, includePatterns));\n\t\t\t\t}\n\t\t\t\tif (excludePatterns.length > 0) {\n\t\t\t\t\tfiles = files.filter((f) => !matchesAnyPattern(f, excludePatterns));\n\t\t\t\t}\n\t\t\t\tconst message = gitQuery([\"log\", \"-1\", \"--format=%s\", head]);\n\t\t\t\tconst author = gitQuery([\"log\", \"-1\", \"--format=%an\", head]);\n\t\t\t\ta.emit({\n\t\t\t\t\thook: \"post-commit\" as GitHookType,\n\t\t\t\t\tcommit: head,\n\t\t\t\t\tfiles,\n\t\t\t\t\tmessage,\n\t\t\t\t\tauthor,\n\t\t\t\t\ttimestamp_ns: wallClockNs(),\n\t\t\t\t});\n\t\t\t\tlastSeen = head;\n\t\t\t\tconsecutiveErrors = 0;\n\t\t\t} catch (err) {\n\t\t\t\tconsecutiveErrors += 1;\n\t\t\t\tif (consecutiveErrors >= maxConsecutiveErrors) {\n\t\t\t\t\ta.down([[ERROR, err]]);\n\t\t\t\t}\n\t\t\t\t// else: transient error — next tick will retry; don't spam ERROR.\n\t\t\t}\n\t\t\treturn { onDeactivation: () => {} };\n\t\t}),\n\t);\n}\n","/**\n * Child-process reactive sources — Node-only.\n *\n * Isolated from `./sources.ts` so bundlers targeting the browser can import\n * browser-safe sources without pulling in `node:child_process`.\n *\n * Access via `@graphrefly/graphrefly/extra/node`, which re-exports this module.\n *\n * @module\n */\n\nimport { type SpawnOptions, spawn } from \"node:child_process\";\nimport { COMPLETE, DATA, ERROR, type Messages, type Node, node } from \"@graphrefly/pure-ts/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * SpawnEvent — discriminated stream emitted by {@link fromSpawn}.\n *\n * @category extra\n */\nexport type SpawnEvent =\n\t| { kind: \"stdout\"; chunk: Buffer }\n\t| { kind: \"stderr\"; chunk: Buffer }\n\t| { kind: \"exit\"; code: number | null; signal: NodeJS.Signals | null };\n\n/** Options for {@link fromSpawn}. Mirrors `child_process.SpawnOptions`. */\nexport interface FromSpawnOptions {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\tshell?: boolean | string;\n\t/**\n\t * Optional caller-owned AbortSignal. When fired, the subprocess is sent\n\t * SIGTERM (per `child_process.spawn` signal semantics). The producer's own\n\t * teardown also sends SIGTERM regardless of caller signal — so `switchMap`\n\t * supersede in `actuatorExecutor` cancels in-flight subprocesses without\n\t * the caller wiring extra signals.\n\t */\n\tsignal?: AbortSignal;\n\t/** Extra args forwarded to spawn — e.g. stdio configuration. */\n\tstdio?: \"pipe\" | readonly (\"pipe\" | \"ignore\" | \"inherit\")[];\n}\n\n// ---------------------------------------------------------------------------\n// fromSpawn\n// ---------------------------------------------------------------------------\n\n/**\n * Spawn `cmd args` as a child process and stream stdout/stderr/exit as a\n * single discriminated `SpawnEvent` stream.\n *\n * Lifecycle:\n * - Stdout/stderr chunks emit as `DATA { kind: \"stdout\"|\"stderr\", chunk }`.\n * - Process exit emits one final `DATA { kind: \"exit\", code, signal }` then\n * `COMPLETE`.\n * - Spawn-error (ENOENT, EPERM, …) emits `ERROR`.\n * - Producer teardown sends `SIGTERM` to the subprocess if it is still alive.\n *\n * **Multicast semantics:** `fromSpawn` returns a node backed by a single\n * `producer` activation — the subprocess is spawned once when the first\n * subscriber connects, and all subsequent subscribers share the same event\n * stream. Unsubscribing the last subscriber tears down the subprocess.\n *\n * @example\n * ```ts\n * import { fromSpawn } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const stream = fromSpawn(\"git\", [\"log\", \"--oneline\"]);\n * stream.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value);\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function fromSpawn(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<SpawnEvent> {\n\treturn node<SpawnEvent>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stdout\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tactions.down([[DATA, { kind: \"stderr\", chunk }]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tactions.down([\n\t\t\t\t\t[DATA, { kind: \"exit\", code: info.code, signal: info.signal }],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tonDeactivation: () => {\n\t\t\t\t\tif (alive) {\n\t\t\t\t\t\talive = false;\n\t\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ name: \"from_spawn\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// runProcess\n// ---------------------------------------------------------------------------\n\n/**\n * Run `cmd args` to completion and emit one DATA with aggregated output.\n *\n * Convenience over {@link fromSpawn} for the \"wait for the process to finish,\n * capture stdout/stderr as strings, get exit code\" case.\n *\n * Aggregation policy: stdout and stderr are concatenated as `Buffer`s and\n * decoded as utf-8 once at exit, so multi-byte sequences split across chunks\n * are handled correctly. Actuators that need byte-exact stdout should use\n * `fromSpawn` directly.\n *\n * @example\n * ```ts\n * import { runProcess } from \"@graphrefly/graphrefly/extra/node\";\n *\n * const result = runProcess(\"git\", [\"rev-parse\", \"HEAD\"]);\n * result.subscribe((msgs) => {\n * for (const [type, value] of msgs) {\n * if (type === DATA) console.log(value.stdout.trim());\n * }\n * });\n * ```\n *\n * @category extra\n */\nexport function runProcess(\n\tcmd: string,\n\targs: readonly string[],\n\topts?: FromSpawnOptions,\n): Node<{\n\tstdout: string;\n\tstderr: string;\n\texitCode: number | null;\n\tsignal: NodeJS.Signals | null;\n}> {\n\ttype Result = {\n\t\tstdout: string;\n\t\tstderr: string;\n\t\texitCode: number | null;\n\t\tsignal: NodeJS.Signals | null;\n\t};\n\treturn node<Result>(\n\t\t(_data, actions) => {\n\t\t\tconst child = spawn(cmd, args as string[], {\n\t\t\t\tcwd: opts?.cwd,\n\t\t\t\tenv: opts?.env,\n\t\t\t\tshell: opts?.shell,\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\tstdio: (opts?.stdio as SpawnOptions[\"stdio\"]) ?? \"pipe\",\n\t\t\t});\n\n\t\t\tlet alive = true;\n\t\t\tconst stdoutChunks: Buffer[] = [];\n\t\t\tconst stderrChunks: Buffer[] = [];\n\t\t\tlet exitInfo: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n\n\t\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstdoutChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\tstderrChunks.push(chunk);\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t});\n\n\t\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\t\t// Capture exit info, but defer terminal emission to \"close\" — by which\n\t\t\t\t// time all stdout/stderr \"data\" events have been delivered.\n\t\t\t\tif (exitInfo == null) exitInfo = { code, signal: signal as NodeJS.Signals | null };\n\t\t\t});\n\n\t\t\tchild.on(\"close\", () => {\n\t\t\t\tif (!alive) return;\n\t\t\t\talive = false;\n\t\t\t\tconst info = exitInfo ?? { code: null, signal: null };\n\t\t\t\tconst stdout = Buffer.concat(stdoutChunks).toString(\"utf8\");\n\t\t\t\tconst stderr = Buffer.concat(stderrChunks).toString(\"utf8\");\n\t\t\t\tactions.down([\n\t\t\t\t\t[\n\t\t\t\t\t\tDATA,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstdout,\n\t\t\t\t\t\t\tstderr,\n\t\t\t\t\t\t\texitCode: info.code,\n\t\t\t\t\t\t\tsignal: info.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t[COMPLETE],\n\t\t\t\t] satisfies Messages);\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tonDeactivation: () => {\n\t\t\t\t\tif (alive) {\n\t\t\t\t\t\talive = false;\n\t\t\t\t\t\tchild.stdout?.removeAllListeners();\n\t\t\t\t\t\tchild.stderr?.removeAllListeners();\n\t\t\t\t\t\tchild.removeAllListeners(\"error\");\n\t\t\t\t\t\tchild.removeAllListeners(\"exit\");\n\t\t\t\t\t\tchild.removeAllListeners(\"close\");\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// already dead — ignore\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ name: \"run_process\" },\n\t);\n}\n"],"mappings":"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","names":["ERROR","node","wallClockNs","globToRegExp","matchesAnyPattern","DATA","ERROR","node"]}
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
memoryWithKG,
|
|
6
6
|
memoryWithTiers,
|
|
7
7
|
memoryWithVectors
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3REMCHSS.js";
|
|
9
9
|
import {
|
|
10
10
|
distill
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-G7H6PN7P.js";
|
|
12
12
|
|
|
13
13
|
// src/presets/ai/agent-memory.ts
|
|
14
14
|
import { DATA, node, placeholderArgs, RESOLVED } from "@graphrefly/pure-ts/core";
|
|
@@ -204,4 +204,4 @@ export {
|
|
|
204
204
|
AgentMemoryGraph,
|
|
205
205
|
agentMemory
|
|
206
206
|
};
|
|
207
|
-
//# sourceMappingURL=chunk-
|
|
207
|
+
//# sourceMappingURL=chunk-23MAWVOJ.js.map
|
|
@@ -3,7 +3,10 @@ import {
|
|
|
3
3
|
cosineSimilarity,
|
|
4
4
|
knowledgeGraph,
|
|
5
5
|
vectorIndex
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-K4ZYJ4EM.js";
|
|
7
|
+
import {
|
|
8
|
+
retry
|
|
9
|
+
} from "./chunk-KUFXLAEY.js";
|
|
7
10
|
import {
|
|
8
11
|
DEFAULT_DECAY_RATE,
|
|
9
12
|
decay
|
|
@@ -13,13 +16,10 @@ import {
|
|
|
13
16
|
} from "./chunk-FMPF42Q4.js";
|
|
14
17
|
import {
|
|
15
18
|
distill
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-G7H6PN7P.js";
|
|
17
20
|
import {
|
|
18
21
|
nodeSignal
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import {
|
|
21
|
-
retry
|
|
22
|
-
} from "./chunk-Z4YXAUDN.js";
|
|
22
|
+
} from "./chunk-N6MNJNHB.js";
|
|
23
23
|
|
|
24
24
|
// src/utils/ai/agents/chat-stream.ts
|
|
25
25
|
import { node as node2, RESOLVED } from "@graphrefly/pure-ts/core";
|
|
@@ -131,9 +131,11 @@ function _oneShotLlmCall(adapter, messages, config) {
|
|
|
131
131
|
invokeResult = adapter.invoke(messages, { ...config.invokeOpts, signal: ac.signal });
|
|
132
132
|
} catch (err) {
|
|
133
133
|
emitOnce(config.onFailure("throw", err));
|
|
134
|
-
return
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
return {
|
|
135
|
+
onDeactivation: () => {
|
|
136
|
+
unlinkParent();
|
|
137
|
+
ac.abort();
|
|
138
|
+
}
|
|
137
139
|
};
|
|
138
140
|
}
|
|
139
141
|
const callNode = fromAny(invokeResult, { signal: ac.signal });
|
|
@@ -162,11 +164,13 @@ function _oneShotLlmCall(adapter, messages, config) {
|
|
|
162
164
|
unsub();
|
|
163
165
|
unsub = null;
|
|
164
166
|
}
|
|
165
|
-
return
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
return {
|
|
168
|
+
onDeactivation: () => {
|
|
169
|
+
unlinkParent();
|
|
170
|
+
ac.abort();
|
|
171
|
+
unsub?.();
|
|
172
|
+
unsub = null;
|
|
173
|
+
}
|
|
170
174
|
};
|
|
171
175
|
},
|
|
172
176
|
{ describeKind: "producer" }
|
|
@@ -390,16 +394,20 @@ var ToolRegistryGraph = class extends Graph2 {
|
|
|
390
394
|
inner = handlerResultToNode(raw, ac.signal);
|
|
391
395
|
} catch (err) {
|
|
392
396
|
actions.down([[ERROR2, err]]);
|
|
393
|
-
return
|
|
394
|
-
|
|
397
|
+
return {
|
|
398
|
+
onDeactivation: () => {
|
|
399
|
+
ac.abort();
|
|
400
|
+
}
|
|
395
401
|
};
|
|
396
402
|
}
|
|
397
403
|
const unsub = inner.subscribe((batch2) => {
|
|
398
404
|
actions.down(batch2);
|
|
399
405
|
});
|
|
400
|
-
return
|
|
401
|
-
|
|
402
|
-
|
|
406
|
+
return {
|
|
407
|
+
onDeactivation: () => {
|
|
408
|
+
ac.abort();
|
|
409
|
+
unsub();
|
|
410
|
+
}
|
|
403
411
|
};
|
|
404
412
|
},
|
|
405
413
|
{
|
|
@@ -999,8 +1007,10 @@ function promptNode(adapter, deps, prompt, opts) {
|
|
|
999
1007
|
} catch (err) {
|
|
1000
1008
|
done = true;
|
|
1001
1009
|
actions.down([[ERROR3, err]]);
|
|
1002
|
-
return
|
|
1003
|
-
|
|
1010
|
+
return {
|
|
1011
|
+
onDeactivation: () => {
|
|
1012
|
+
abortDispose?.();
|
|
1013
|
+
}
|
|
1004
1014
|
};
|
|
1005
1015
|
}
|
|
1006
1016
|
const callNode = fromAny3(invokeResult);
|
|
@@ -1058,11 +1068,13 @@ function promptNode(adapter, deps, prompt, opts) {
|
|
|
1058
1068
|
}
|
|
1059
1069
|
}
|
|
1060
1070
|
});
|
|
1061
|
-
return
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1071
|
+
return {
|
|
1072
|
+
onDeactivation: () => {
|
|
1073
|
+
cancelled = true;
|
|
1074
|
+
sub();
|
|
1075
|
+
abortDispose?.();
|
|
1076
|
+
abortDispose = void 0;
|
|
1077
|
+
}
|
|
1066
1078
|
};
|
|
1067
1079
|
},
|
|
1068
1080
|
{
|
|
@@ -1150,4 +1162,4 @@ export {
|
|
|
1150
1162
|
llmExtractor,
|
|
1151
1163
|
llmConsolidator
|
|
1152
1164
|
};
|
|
1153
|
-
//# sourceMappingURL=chunk-
|
|
1165
|
+
//# sourceMappingURL=chunk-3REMCHSS.js.map
|