@launchsecure/launch-kit 0.0.28 → 0.0.30
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/beacon/beacon.mjs +2759 -1246
- package/dist/beacon/beacon.mjs.map +1 -1
- package/dist/beacon/beacon.umd.js +710 -95
- package/dist/beacon/beacon.umd.js.map +1 -1
- package/dist/beacon/types/core.d.ts +14 -0
- package/dist/beacon/types/core.d.ts.map +1 -0
- package/dist/beacon/types/ctx.d.ts +14 -0
- package/dist/beacon/types/ctx.d.ts.map +1 -0
- package/dist/beacon/types/element.d.ts +16 -48
- package/dist/beacon/types/element.d.ts.map +1 -1
- package/dist/beacon/types/index.d.ts +5 -4
- package/dist/beacon/types/index.d.ts.map +1 -1
- package/dist/beacon/types/internal/annotation-cache.d.ts +10 -0
- package/dist/beacon/types/internal/annotation-cache.d.ts.map +1 -0
- package/dist/beacon/types/internal/element-capture.d.ts +19 -0
- package/dist/beacon/types/internal/element-capture.d.ts.map +1 -0
- package/dist/beacon/types/internal/event-buffer.d.ts +16 -0
- package/dist/beacon/types/internal/event-buffer.d.ts.map +1 -0
- package/dist/beacon/types/internal/framework-detect.d.ts +6 -0
- package/dist/beacon/types/internal/framework-detect.d.ts.map +1 -0
- package/dist/beacon/types/internal/markers.d.ts +17 -0
- package/dist/beacon/types/internal/markers.d.ts.map +1 -0
- package/dist/beacon/types/internal/monitor/capture-dom.d.ts +14 -0
- package/dist/beacon/types/internal/monitor/capture-dom.d.ts.map +1 -0
- package/dist/beacon/types/internal/monitor/capture-network.d.ts +12 -0
- package/dist/beacon/types/internal/monitor/capture-network.d.ts.map +1 -0
- package/dist/beacon/types/internal/monitor/overlay.d.ts +16 -0
- package/dist/beacon/types/internal/monitor/overlay.d.ts.map +1 -0
- package/dist/beacon/types/internal/monitor/session.d.ts +41 -0
- package/dist/beacon/types/internal/monitor/session.d.ts.map +1 -0
- package/dist/beacon/types/{monitor → internal/monitor}/transport.d.ts +3 -3
- package/dist/beacon/types/internal/monitor/transport.d.ts.map +1 -0
- package/dist/beacon/types/{monitor/types.d.ts → internal/monitor/wire.d.ts} +69 -27
- package/dist/beacon/types/internal/monitor/wire.d.ts.map +1 -0
- package/dist/beacon/types/{ui → internal}/pick-mode-overlay.d.ts +4 -5
- package/dist/beacon/types/internal/pick-mode-overlay.d.ts.map +1 -0
- package/dist/beacon/types/{capture → internal}/picker.d.ts +0 -1
- package/dist/beacon/types/internal/picker.d.ts.map +1 -0
- package/dist/beacon/types/{ui → internal}/pin-popover.d.ts +1 -1
- package/dist/beacon/types/internal/pin-popover.d.ts.map +1 -0
- package/dist/beacon/types/{capture → internal}/screenshot.d.ts +1 -0
- package/dist/beacon/types/internal/screenshot.d.ts.map +1 -0
- package/dist/beacon/types/internal/selector.d.ts.map +1 -0
- package/dist/beacon/types/plugins/domEle.d.ts +14 -0
- package/dist/beacon/types/plugins/domEle.d.ts.map +1 -0
- package/dist/beacon/types/plugins/domSS.d.ts +8 -0
- package/dist/beacon/types/plugins/domSS.d.ts.map +1 -0
- package/dist/beacon/types/plugins/errors.d.ts +3 -0
- package/dist/beacon/types/plugins/errors.d.ts.map +1 -0
- package/dist/beacon/types/plugins/index.d.ts +8 -0
- package/dist/beacon/types/plugins/index.d.ts.map +1 -0
- package/dist/beacon/types/plugins/liveMonitor.d.ts +14 -0
- package/dist/beacon/types/plugins/liveMonitor.d.ts.map +1 -0
- package/dist/beacon/types/plugins/metadata.d.ts +3 -0
- package/dist/beacon/types/plugins/metadata.d.ts.map +1 -0
- package/dist/beacon/types/registry.d.ts +33 -0
- package/dist/beacon/types/registry.d.ts.map +1 -0
- package/dist/beacon/types/styles.d.ts +8 -0
- package/dist/beacon/types/styles.d.ts.map +1 -0
- package/dist/beacon/types/transport.d.ts +3 -0
- package/dist/beacon/types/transport.d.ts.map +1 -0
- package/dist/beacon/types/types.d.ts +152 -68
- package/dist/beacon/types/types.d.ts.map +1 -1
- package/dist/beacon/types/ui/dialog.d.ts +53 -0
- package/dist/beacon/types/ui/dialog.d.ts.map +1 -0
- package/dist/beacon/types/ui/form.d.ts +7 -0
- package/dist/beacon/types/ui/form.d.ts.map +1 -0
- package/dist/beacon/types/ui/overlay.d.ts +6 -0
- package/dist/beacon/types/ui/overlay.d.ts.map +1 -0
- package/dist/deck-client/assets/{_baseUniq-W2JQDmje.js → _baseUniq-DCt2IMRR.js} +1 -1
- package/dist/deck-client/assets/{arc-DIBWAId9.js → arc-h-ifqmNR.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-CAIRMvJK.js → architectureDiagram-Q4EWVU46-C9dITSPv.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-BeNaNiOi.js → blockDiagram-DXYQGD6D-BHuJT34t.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-B9Ozi62h.js → c4Diagram-AHTNJAMY-CpvMGtDG.js} +1 -1
- package/dist/deck-client/assets/channel-2PZVMiXf.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-D7AZ47dt.js → chunk-4BX2VUAB-B6md1VIm.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-DnVnNPcI.js → chunk-4TB4RGXK-BmEnX8ik.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-UKYs-YNd.js → chunk-55IACEB6-BZPUyZAZ.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-D43b-SKn.js → chunk-EDXVE4YY-BWwNUK-l.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-QzBAoyyW.js → chunk-FMBD7UC4-o7gSppGI.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-Cjif4r6W.js → chunk-OYMX7WX6-C4KoTL5p.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-CqLDirEI.js → chunk-QZHKN3VN-jkf68sDs.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-_FQvmMs4.js → chunk-YZCP3GAM-Cd4yBE7o.js} +1 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-Bt8xBAof.js +1 -0
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-Bt8xBAof.js +1 -0
- package/dist/deck-client/assets/clone-BHQryoDl.js +1 -0
- package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-rfrocesE.js → cose-bilkent-S5V4N54A-DeGFUgAV.js} +1 -1
- package/dist/deck-client/assets/{dagre-KV5264BT-Bv_7DJat.js → dagre-KV5264BT-ekcYJuUV.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-4F1414G5.js → diagram-5BDNPKRD-YHPk4rV2.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-C4-Pszqm.js → diagram-G4DWMVQ6-DM-JCd_B.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-B647TIx9.js → diagram-MMDJMWI5-l5FK1ybk.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-BFAqpezd.js → diagram-TYMM5635-CIN4_1-j.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfBfrJOC.js → erDiagram-SMLLAGMA-MyinSkEl.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-DX9YAYes.js → flowDiagram-DWJPFMVM-Dk8nn42x.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DCuiy7wF.js → ganttDiagram-T4ZO3ILL-BU1ihicu.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-CGp1IXUh.js → gitGraphDiagram-UUTBAWPF-BjsTL13C.js} +1 -1
- package/dist/deck-client/assets/{graph-B7g8aoxv.js → graph-DJmh-xi7.js} +1 -1
- package/dist/deck-client/assets/{index-Dg1r-WSN.js → index-KsShfCV-.js} +3 -3
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-L3fahMkF.js → infoDiagram-42DDH7IO-Dxvy_RB4.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-aS_EjWBZ.js → ishikawaDiagram-UXIWVN3A-DPOaNF1l.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-djTSQZF9.js → journeyDiagram-VCZTEJTY-DMew3K5c.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-CcTHo4CM.js → kanban-definition-6JOO6SKY-csciJFuk.js} +1 -1
- package/dist/deck-client/assets/{layout-mEJiadb7.js → layout-Dg4yyms2.js} +1 -1
- package/dist/deck-client/assets/{linear-XgTKqyRu.js → linear-BA3zU6gq.js} +1 -1
- package/dist/deck-client/assets/{min-Ct9jZdpd.js → min-lz-Ird-p.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-BaFxCGNU.js → mindmap-definition-QFDTVHPH-CCEN8OQV.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-CIbYYjtw.js → pieDiagram-DEJITSTG-DM6n1HY7.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-D9EtCOvh.js → quadrantDiagram-34T5L4WZ-_ULoR66n.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-xeni9eVG.js → requirementDiagram-MS252O5E-BuwJs7Tn.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-LYeknz9h.js → sankeyDiagram-XADWPNL6-BEsuzkW4.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-RDbsKFZf.js → sequenceDiagram-FGHM5R23-CP2H0YWf.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-BH1Zjglk.js → stateDiagram-FHFEXIEX-B5Gw_NNL.js} +1 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-4T4wMDXr.js +1 -0
- package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-IFXxKptt.js → timeline-definition-GMOUNBTQ-DsoYydQa.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D-sLkQs9.js → vennDiagram-DHZGUBPP-Dz8JT_ob.js} +1 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-DGHQ_Ijv.js +162 -0
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-BTjjuDU3.js → wardleyDiagram-NUSXRM2D-DN1LJMB1.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-AYbv92n-.js → xychartDiagram-5P7HB3ND-nb0oSfrQ.js} +1 -1
- package/dist/deck-client/index.html +1 -1
- package/dist/server/beacon-monitor-entry.js +548 -6
- package/dist/server/chart-serve.js +920 -249
- package/dist/server/cli.js +1599 -595
- package/dist/server/course-entry.js +3 -3
- package/dist/server/graph-mcp-entry.js +1361 -394
- package/dist/server/init-entry.js +799 -195
- package/dist/server/orbit-entry.js +135 -7
- package/dist/server/parse-worker-entry.js +918 -247
- package/package.json +3 -2
- package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +4 -4
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/.claude-plugin/plugin.json +1 -10
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/activate-beacon.md +2 -2
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +46 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +34 -0
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/standup.md +52 -38
- package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-array.md +107 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-clear.md +94 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-pulse.md +82 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-scan.md +66 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/blast-radius.md +101 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/brief.md +112 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/course.md +84 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/debug.md +92 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/deploy-check.md +160 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/diagram.md +134 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/orbit.md +87 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/prototype.md +90 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/recall.md +83 -0
- package/scaffolds/ls-marketplace/plugins/{ls/commands → kit/skills}/show-mcp-status.md +8 -8
- package/scaffolds/ls-marketplace/plugins/kit/skills/wireframe.md +70 -0
- package/scaffolds/statusline/statusline-mcp.sh +204 -0
- package/scaffolds/statusline/statusline-wrapper.sh +50 -0
- package/dist/beacon/types/capture/element.d.ts +0 -3
- package/dist/beacon/types/capture/element.d.ts.map +0 -1
- package/dist/beacon/types/capture/events.d.ts +0 -20
- package/dist/beacon/types/capture/events.d.ts.map +0 -1
- package/dist/beacon/types/capture/framework.d.ts +0 -3
- package/dist/beacon/types/capture/framework.d.ts.map +0 -1
- package/dist/beacon/types/capture/metadata.d.ts +0 -3
- package/dist/beacon/types/capture/metadata.d.ts.map +0 -1
- package/dist/beacon/types/capture/overlay.d.ts +0 -7
- package/dist/beacon/types/capture/overlay.d.ts.map +0 -1
- package/dist/beacon/types/capture/picker.d.ts.map +0 -1
- package/dist/beacon/types/capture/screenshot.d.ts.map +0 -1
- package/dist/beacon/types/capture/selector.d.ts.map +0 -1
- package/dist/beacon/types/monitor/dom.d.ts +0 -13
- package/dist/beacon/types/monitor/dom.d.ts.map +0 -1
- package/dist/beacon/types/monitor/index.d.ts +0 -19
- package/dist/beacon/types/monitor/index.d.ts.map +0 -1
- package/dist/beacon/types/monitor/network.d.ts +0 -12
- package/dist/beacon/types/monitor/network.d.ts.map +0 -1
- package/dist/beacon/types/monitor/transport.d.ts.map +0 -1
- package/dist/beacon/types/monitor/types.d.ts.map +0 -1
- package/dist/beacon/types/transport/submit.d.ts +0 -3
- package/dist/beacon/types/transport/submit.d.ts.map +0 -1
- package/dist/beacon/types/ui/button.d.ts +0 -2
- package/dist/beacon/types/ui/button.d.ts.map +0 -1
- package/dist/beacon/types/ui/drawer.d.ts +0 -33
- package/dist/beacon/types/ui/drawer.d.ts.map +0 -1
- package/dist/beacon/types/ui/icons.d.ts +0 -9
- package/dist/beacon/types/ui/icons.d.ts.map +0 -1
- package/dist/beacon/types/ui/monitor-panel.d.ts +0 -19
- package/dist/beacon/types/ui/monitor-panel.d.ts.map +0 -1
- package/dist/beacon/types/ui/pick-mode-overlay.d.ts.map +0 -1
- package/dist/beacon/types/ui/pin-popover.d.ts.map +0 -1
- package/dist/deck-client/assets/channel-CRdozqbp.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-lIZMp57W.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-lIZMp57W.js +0 -1
- package/dist/deck-client/assets/clone-BtWeSTyJ.js +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BrV78NDR.js +0 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-C010F8l4.js +0 -162
- package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-array.md +0 -92
- package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-clear.md +0 -68
- package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-pulse.md +0 -80
- package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-scan.md +0 -62
- /package/dist/beacon/types/{capture → internal}/selector.d.ts +0 -0
package/dist/server/cli.js
CHANGED
|
@@ -553,8 +553,8 @@ var require_claude_bridge = __commonJS({
|
|
|
553
553
|
"../claude-code-web/src/claude-bridge.js"(exports2, module2) {
|
|
554
554
|
"use strict";
|
|
555
555
|
var { spawn: spawn4 } = require("node-pty");
|
|
556
|
-
var
|
|
557
|
-
var
|
|
556
|
+
var path13 = require("path");
|
|
557
|
+
var fs11 = require("fs");
|
|
558
558
|
var ClaudeBridge = class {
|
|
559
559
|
constructor() {
|
|
560
560
|
this.sessions = /* @__PURE__ */ new Map();
|
|
@@ -565,14 +565,14 @@ var require_claude_bridge = __commonJS({
|
|
|
565
565
|
"/home/ec2-user/.claude/local/claude",
|
|
566
566
|
"claude",
|
|
567
567
|
"claude-code",
|
|
568
|
-
|
|
569
|
-
|
|
568
|
+
path13.join(process.env.HOME || "/", ".claude", "local", "claude"),
|
|
569
|
+
path13.join(process.env.HOME || "/", ".local", "bin", "claude"),
|
|
570
570
|
"/usr/local/bin/claude",
|
|
571
571
|
"/usr/bin/claude"
|
|
572
572
|
];
|
|
573
573
|
for (const cmd of possibleCommands) {
|
|
574
574
|
try {
|
|
575
|
-
if (
|
|
575
|
+
if (fs11.existsSync(cmd) || this.commandExists(cmd)) {
|
|
576
576
|
console.log(`Found Claude command at: ${cmd}`);
|
|
577
577
|
return cmd;
|
|
578
578
|
}
|
|
@@ -797,8 +797,8 @@ var require_codex_bridge = __commonJS({
|
|
|
797
797
|
"../claude-code-web/src/codex-bridge.js"(exports2, module2) {
|
|
798
798
|
"use strict";
|
|
799
799
|
var { spawn: spawn4 } = require("node-pty");
|
|
800
|
-
var
|
|
801
|
-
var
|
|
800
|
+
var path13 = require("path");
|
|
801
|
+
var fs11 = require("fs");
|
|
802
802
|
var CodexBridge = class {
|
|
803
803
|
constructor() {
|
|
804
804
|
this.sessions = /* @__PURE__ */ new Map();
|
|
@@ -806,16 +806,16 @@ var require_codex_bridge = __commonJS({
|
|
|
806
806
|
}
|
|
807
807
|
findCodexCommand() {
|
|
808
808
|
const possibleCommands = [
|
|
809
|
-
|
|
809
|
+
path13.join(process.env.HOME || "/", ".codex", "local", "codex"),
|
|
810
810
|
"codex",
|
|
811
811
|
"codex-code",
|
|
812
|
-
|
|
812
|
+
path13.join(process.env.HOME || "/", ".local", "bin", "codex"),
|
|
813
813
|
"/usr/local/bin/codex",
|
|
814
814
|
"/usr/bin/codex"
|
|
815
815
|
];
|
|
816
816
|
for (const cmd of possibleCommands) {
|
|
817
817
|
try {
|
|
818
|
-
if (
|
|
818
|
+
if (fs11.existsSync(cmd) || this.commandExists(cmd)) {
|
|
819
819
|
console.log(`Found Codex command at: ${cmd}`);
|
|
820
820
|
return cmd;
|
|
821
821
|
}
|
|
@@ -990,8 +990,8 @@ var require_agent_bridge = __commonJS({
|
|
|
990
990
|
"../claude-code-web/src/agent-bridge.js"(exports2, module2) {
|
|
991
991
|
"use strict";
|
|
992
992
|
var { spawn: spawn4 } = require("node-pty");
|
|
993
|
-
var
|
|
994
|
-
var
|
|
993
|
+
var path13 = require("path");
|
|
994
|
+
var fs11 = require("fs");
|
|
995
995
|
var AgentBridge = class {
|
|
996
996
|
constructor() {
|
|
997
997
|
this.sessions = /* @__PURE__ */ new Map();
|
|
@@ -999,15 +999,15 @@ var require_agent_bridge = __commonJS({
|
|
|
999
999
|
}
|
|
1000
1000
|
findAgentCommand() {
|
|
1001
1001
|
const possibleCommands = [
|
|
1002
|
-
|
|
1002
|
+
path13.join(process.env.HOME || "/", ".cursor", "local", "cursor-agent"),
|
|
1003
1003
|
"cursor-agent",
|
|
1004
|
-
|
|
1004
|
+
path13.join(process.env.HOME || "/", ".local", "bin", "cursor-agent"),
|
|
1005
1005
|
"/usr/local/bin/cursor-agent",
|
|
1006
1006
|
"/usr/bin/cursor-agent"
|
|
1007
1007
|
];
|
|
1008
1008
|
for (const cmd of possibleCommands) {
|
|
1009
1009
|
try {
|
|
1010
|
-
if (
|
|
1010
|
+
if (fs11.existsSync(cmd) || this.commandExists(cmd)) {
|
|
1011
1011
|
console.log(`Found Agent command at: ${cmd}`);
|
|
1012
1012
|
return cmd;
|
|
1013
1013
|
}
|
|
@@ -1331,25 +1331,25 @@ var require_script_bridge = __commonJS({
|
|
|
1331
1331
|
var require_session_store = __commonJS({
|
|
1332
1332
|
"../claude-code-web/src/utils/session-store.js"(exports2, module2) {
|
|
1333
1333
|
"use strict";
|
|
1334
|
-
var
|
|
1335
|
-
var
|
|
1334
|
+
var fs11 = require("fs").promises;
|
|
1335
|
+
var path13 = require("path");
|
|
1336
1336
|
var os4 = require("os");
|
|
1337
1337
|
var SessionStore = class {
|
|
1338
1338
|
constructor(options = {}) {
|
|
1339
|
-
this.storageDir = options.storageDir ||
|
|
1340
|
-
this.sessionsFile =
|
|
1339
|
+
this.storageDir = options.storageDir || path13.join(os4.homedir(), ".claude-code-web");
|
|
1340
|
+
this.sessionsFile = path13.join(this.storageDir, "sessions.json");
|
|
1341
1341
|
this.initializeStorage();
|
|
1342
1342
|
}
|
|
1343
1343
|
async initializeStorage() {
|
|
1344
1344
|
try {
|
|
1345
|
-
await
|
|
1345
|
+
await fs11.mkdir(this.storageDir, { recursive: true });
|
|
1346
1346
|
} catch (error) {
|
|
1347
1347
|
console.error("Failed to create storage directory:", error);
|
|
1348
1348
|
}
|
|
1349
1349
|
}
|
|
1350
1350
|
async saveSessions(sessions) {
|
|
1351
1351
|
try {
|
|
1352
|
-
await
|
|
1352
|
+
await fs11.mkdir(this.storageDir, { recursive: true });
|
|
1353
1353
|
const sessionsArray = Array.from(sessions.entries()).map(([id, session]) => ({
|
|
1354
1354
|
id,
|
|
1355
1355
|
name: session.name || "Unnamed Session",
|
|
@@ -1380,9 +1380,9 @@ var require_session_store = __commonJS({
|
|
|
1380
1380
|
sessions: sessionsArray
|
|
1381
1381
|
};
|
|
1382
1382
|
const tempFile = `${this.sessionsFile}.tmp`;
|
|
1383
|
-
await
|
|
1384
|
-
await
|
|
1385
|
-
await
|
|
1383
|
+
await fs11.writeFile(tempFile, JSON.stringify(data, null, 2));
|
|
1384
|
+
await fs11.mkdir(this.storageDir, { recursive: true });
|
|
1385
|
+
await fs11.rename(tempFile, this.sessionsFile);
|
|
1386
1386
|
return true;
|
|
1387
1387
|
} catch (error) {
|
|
1388
1388
|
console.error("Failed to save sessions:", error.message);
|
|
@@ -1391,8 +1391,8 @@ var require_session_store = __commonJS({
|
|
|
1391
1391
|
}
|
|
1392
1392
|
async loadSessions() {
|
|
1393
1393
|
try {
|
|
1394
|
-
await
|
|
1395
|
-
const data = await
|
|
1394
|
+
await fs11.access(this.sessionsFile);
|
|
1395
|
+
const data = await fs11.readFile(this.sessionsFile, "utf8");
|
|
1396
1396
|
if (!data || !data.trim()) {
|
|
1397
1397
|
console.log("Sessions file is empty, starting fresh");
|
|
1398
1398
|
return /* @__PURE__ */ new Map();
|
|
@@ -1403,7 +1403,7 @@ var require_session_store = __commonJS({
|
|
|
1403
1403
|
} catch (parseError) {
|
|
1404
1404
|
console.error("Sessions file is corrupted, starting fresh:", parseError.message);
|
|
1405
1405
|
try {
|
|
1406
|
-
await
|
|
1406
|
+
await fs11.rename(this.sessionsFile, `${this.sessionsFile}.corrupted.${Date.now()}`);
|
|
1407
1407
|
} catch (renameError) {
|
|
1408
1408
|
}
|
|
1409
1409
|
return /* @__PURE__ */ new Map();
|
|
@@ -1447,7 +1447,7 @@ var require_session_store = __commonJS({
|
|
|
1447
1447
|
}
|
|
1448
1448
|
async clearOldSessions() {
|
|
1449
1449
|
try {
|
|
1450
|
-
await
|
|
1450
|
+
await fs11.unlink(this.sessionsFile);
|
|
1451
1451
|
console.log("Cleared old sessions");
|
|
1452
1452
|
return true;
|
|
1453
1453
|
} catch (error) {
|
|
@@ -1459,9 +1459,9 @@ var require_session_store = __commonJS({
|
|
|
1459
1459
|
}
|
|
1460
1460
|
async getSessionMetadata() {
|
|
1461
1461
|
try {
|
|
1462
|
-
await
|
|
1463
|
-
const stats = await
|
|
1464
|
-
const data = await
|
|
1462
|
+
await fs11.access(this.sessionsFile);
|
|
1463
|
+
const stats = await fs11.stat(this.sessionsFile);
|
|
1464
|
+
const data = await fs11.readFile(this.sessionsFile, "utf8");
|
|
1465
1465
|
const parsed = JSON.parse(data);
|
|
1466
1466
|
return {
|
|
1467
1467
|
exists: true,
|
|
@@ -1486,13 +1486,13 @@ var require_session_store = __commonJS({
|
|
|
1486
1486
|
var require_usage_reader = __commonJS({
|
|
1487
1487
|
"../claude-code-web/src/usage-reader.js"(exports2, module2) {
|
|
1488
1488
|
"use strict";
|
|
1489
|
-
var
|
|
1490
|
-
var
|
|
1489
|
+
var fs11 = require("fs").promises;
|
|
1490
|
+
var path13 = require("path");
|
|
1491
1491
|
var readline = require("readline");
|
|
1492
1492
|
var { createReadStream } = require("fs");
|
|
1493
1493
|
var UsageReader = class {
|
|
1494
1494
|
constructor(sessionDurationHours = 5) {
|
|
1495
|
-
this.claudeProjectsPath =
|
|
1495
|
+
this.claudeProjectsPath = path13.join(process.env.HOME, ".claude", "projects");
|
|
1496
1496
|
this.cache = null;
|
|
1497
1497
|
this.cacheTime = null;
|
|
1498
1498
|
this.cacheTimeout = 5e3;
|
|
@@ -1692,14 +1692,14 @@ var require_usage_reader = __commonJS({
|
|
|
1692
1692
|
try {
|
|
1693
1693
|
const cwd = process.cwd();
|
|
1694
1694
|
const projectDirName = cwd.replace(/\//g, "-");
|
|
1695
|
-
let projectPath =
|
|
1695
|
+
let projectPath = path13.join(this.claudeProjectsPath, projectDirName);
|
|
1696
1696
|
try {
|
|
1697
|
-
await
|
|
1697
|
+
await fs11.access(projectPath);
|
|
1698
1698
|
} catch (err2) {
|
|
1699
1699
|
console.log(`Project directory not found: ${projectPath}`);
|
|
1700
1700
|
return null;
|
|
1701
1701
|
}
|
|
1702
|
-
const files = await
|
|
1702
|
+
const files = await fs11.readdir(projectPath);
|
|
1703
1703
|
const jsonlFiles = files.filter((f) => f.endsWith(".jsonl"));
|
|
1704
1704
|
if (jsonlFiles.length === 0) {
|
|
1705
1705
|
return null;
|
|
@@ -1707,8 +1707,8 @@ var require_usage_reader = __commonJS({
|
|
|
1707
1707
|
let mostRecentFile = null;
|
|
1708
1708
|
let mostRecentTime = 0;
|
|
1709
1709
|
for (const file of jsonlFiles) {
|
|
1710
|
-
const filePath =
|
|
1711
|
-
const stat = await
|
|
1710
|
+
const filePath = path13.join(projectPath, file);
|
|
1711
|
+
const stat = await fs11.stat(filePath);
|
|
1712
1712
|
if (stat.mtime.getTime() > mostRecentTime) {
|
|
1713
1713
|
mostRecentTime = stat.mtime.getTime();
|
|
1714
1714
|
mostRecentFile = filePath;
|
|
@@ -1723,17 +1723,17 @@ var require_usage_reader = __commonJS({
|
|
|
1723
1723
|
async findJsonlFiles(onlyRecent = false) {
|
|
1724
1724
|
const files = [];
|
|
1725
1725
|
try {
|
|
1726
|
-
const projectDirs = await
|
|
1726
|
+
const projectDirs = await fs11.readdir(this.claudeProjectsPath);
|
|
1727
1727
|
for (const projectDir of projectDirs) {
|
|
1728
|
-
const projectPath =
|
|
1729
|
-
const stat = await
|
|
1728
|
+
const projectPath = path13.join(this.claudeProjectsPath, projectDir);
|
|
1729
|
+
const stat = await fs11.stat(projectPath);
|
|
1730
1730
|
if (stat.isDirectory()) {
|
|
1731
|
-
const projectFiles = await
|
|
1731
|
+
const projectFiles = await fs11.readdir(projectPath);
|
|
1732
1732
|
const jsonlFiles = projectFiles.filter((f) => f.endsWith(".jsonl"));
|
|
1733
1733
|
for (const jsonlFile of jsonlFiles) {
|
|
1734
|
-
const filePath =
|
|
1734
|
+
const filePath = path13.join(projectPath, jsonlFile);
|
|
1735
1735
|
if (onlyRecent) {
|
|
1736
|
-
const fileStat = await
|
|
1736
|
+
const fileStat = await fs11.stat(filePath);
|
|
1737
1737
|
const hoursSinceModified = (Date.now() - fileStat.mtime.getTime()) / (1e3 * 60 * 60);
|
|
1738
1738
|
if (hoursSinceModified <= 24) {
|
|
1739
1739
|
files.push(filePath);
|
|
@@ -1752,7 +1752,7 @@ var require_usage_reader = __commonJS({
|
|
|
1752
1752
|
async readJsonlFile(filePath, cutoffTime) {
|
|
1753
1753
|
const entries = [];
|
|
1754
1754
|
const fileProcessedEntries = /* @__PURE__ */ new Set();
|
|
1755
|
-
return new Promise((
|
|
1755
|
+
return new Promise((resolve6) => {
|
|
1756
1756
|
const rl = readline.createInterface({
|
|
1757
1757
|
input: createReadStream(filePath),
|
|
1758
1758
|
crlfDelay: Infinity
|
|
@@ -1810,11 +1810,11 @@ var require_usage_reader = __commonJS({
|
|
|
1810
1810
|
}
|
|
1811
1811
|
});
|
|
1812
1812
|
rl.on("close", () => {
|
|
1813
|
-
|
|
1813
|
+
resolve6(entries);
|
|
1814
1814
|
});
|
|
1815
1815
|
rl.on("error", (error) => {
|
|
1816
1816
|
console.error("Error reading file:", filePath, error);
|
|
1817
|
-
|
|
1817
|
+
resolve6(entries);
|
|
1818
1818
|
});
|
|
1819
1819
|
});
|
|
1820
1820
|
}
|
|
@@ -1894,9 +1894,9 @@ var require_usage_reader = __commonJS({
|
|
|
1894
1894
|
if (!sessionId) {
|
|
1895
1895
|
return null;
|
|
1896
1896
|
}
|
|
1897
|
-
const sessionFile =
|
|
1897
|
+
const sessionFile = path13.join(this.claudeProjectsPath, path13.basename(process.cwd()).replace(/[^a-zA-Z0-9-]/g, "-"), `${sessionId}.jsonl`);
|
|
1898
1898
|
try {
|
|
1899
|
-
await
|
|
1899
|
+
await fs11.access(sessionFile);
|
|
1900
1900
|
} catch (err2) {
|
|
1901
1901
|
return null;
|
|
1902
1902
|
}
|
|
@@ -2552,7 +2552,7 @@ var require_usage_analytics = __commonJS({
|
|
|
2552
2552
|
var require_src = __commonJS({
|
|
2553
2553
|
"../claude-code-web/src/index.js"(exports2, module2) {
|
|
2554
2554
|
"use strict";
|
|
2555
|
-
var
|
|
2555
|
+
var path13 = require("path");
|
|
2556
2556
|
var WebSocket2 = require("ws");
|
|
2557
2557
|
var { v4: uuidv4 } = (init_esm_node(), __toCommonJS(esm_node_exports));
|
|
2558
2558
|
var ClaudeBridge = require_claude_bridge();
|
|
@@ -2562,7 +2562,7 @@ var require_src = __commonJS({
|
|
|
2562
2562
|
var SessionStore = require_session_store();
|
|
2563
2563
|
var UsageReader = require_usage_reader();
|
|
2564
2564
|
var UsageAnalytics = require_usage_analytics();
|
|
2565
|
-
var
|
|
2565
|
+
var fs11 = require("fs");
|
|
2566
2566
|
function stripAnsi2(str) {
|
|
2567
2567
|
return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").replace(/\x1b\][^\x07]*\x07/g, "").replace(/\x1b[()][AB012]/g, "").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "").replace(/\r\n?/g, "\n").trim();
|
|
2568
2568
|
}
|
|
@@ -2637,8 +2637,8 @@ var require_src = __commonJS({
|
|
|
2637
2637
|
// ── Path validation ──────────────────────────────────────────────────
|
|
2638
2638
|
isPathWithinBase(targetPath) {
|
|
2639
2639
|
try {
|
|
2640
|
-
const resolvedTarget =
|
|
2641
|
-
const resolvedBase =
|
|
2640
|
+
const resolvedTarget = path13.resolve(targetPath);
|
|
2641
|
+
const resolvedBase = path13.resolve(this.baseFolder);
|
|
2642
2642
|
return resolvedTarget.startsWith(resolvedBase);
|
|
2643
2643
|
} catch (error) {
|
|
2644
2644
|
return false;
|
|
@@ -2648,7 +2648,7 @@ var require_src = __commonJS({
|
|
|
2648
2648
|
if (!targetPath) {
|
|
2649
2649
|
return { valid: false, error: "Path is required" };
|
|
2650
2650
|
}
|
|
2651
|
-
const resolvedPath =
|
|
2651
|
+
const resolvedPath = path13.resolve(targetPath);
|
|
2652
2652
|
if (!this.isPathWithinBase(resolvedPath)) {
|
|
2653
2653
|
return {
|
|
2654
2654
|
valid: false,
|
|
@@ -2820,14 +2820,14 @@ var require_src = __commonJS({
|
|
|
2820
2820
|
return true;
|
|
2821
2821
|
}
|
|
2822
2822
|
try {
|
|
2823
|
-
const items =
|
|
2823
|
+
const items = fs11.readdirSync(validation.path, { withFileTypes: true });
|
|
2824
2824
|
const showHidden = url.searchParams.get("showHidden") === "true";
|
|
2825
2825
|
const folders = items.filter((item) => item.isDirectory()).filter((item) => !item.name.startsWith(".") || showHidden).map((item) => ({
|
|
2826
2826
|
name: item.name,
|
|
2827
|
-
path:
|
|
2827
|
+
path: path13.join(validation.path, item.name),
|
|
2828
2828
|
isDirectory: true
|
|
2829
2829
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
2830
|
-
const parentDir =
|
|
2830
|
+
const parentDir = path13.dirname(validation.path);
|
|
2831
2831
|
const canGoUp = this.isPathWithinBase(parentDir) && parentDir !== validation.path;
|
|
2832
2832
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2833
2833
|
res.end(JSON.stringify({
|
|
@@ -2855,7 +2855,7 @@ var require_src = __commonJS({
|
|
|
2855
2855
|
res.end(JSON.stringify({ error: validation.error }));
|
|
2856
2856
|
return;
|
|
2857
2857
|
}
|
|
2858
|
-
if (!
|
|
2858
|
+
if (!fs11.existsSync(validation.path) || !fs11.statSync(validation.path).isDirectory()) {
|
|
2859
2859
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2860
2860
|
res.end(JSON.stringify({ error: "Not a valid directory" }));
|
|
2861
2861
|
return;
|
|
@@ -2882,7 +2882,7 @@ var require_src = __commonJS({
|
|
|
2882
2882
|
res.end(JSON.stringify({ error: validation.error }));
|
|
2883
2883
|
return;
|
|
2884
2884
|
}
|
|
2885
|
-
if (!
|
|
2885
|
+
if (!fs11.existsSync(validation.path) || !fs11.statSync(validation.path).isDirectory()) {
|
|
2886
2886
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2887
2887
|
res.end(JSON.stringify({ error: "Invalid directory path" }));
|
|
2888
2888
|
return;
|
|
@@ -2909,7 +2909,7 @@ var require_src = __commonJS({
|
|
|
2909
2909
|
return;
|
|
2910
2910
|
}
|
|
2911
2911
|
const basePath = parentPath || this.baseFolder;
|
|
2912
|
-
const fullPath =
|
|
2912
|
+
const fullPath = path13.join(basePath, folderName);
|
|
2913
2913
|
const parentValidation = this.validatePath(basePath);
|
|
2914
2914
|
const fullValidation = this.validatePath(fullPath);
|
|
2915
2915
|
if (!parentValidation.valid || !fullValidation.valid) {
|
|
@@ -2917,12 +2917,12 @@ var require_src = __commonJS({
|
|
|
2917
2917
|
res.end(JSON.stringify({ message: "Cannot create folder outside the allowed area" }));
|
|
2918
2918
|
return;
|
|
2919
2919
|
}
|
|
2920
|
-
if (
|
|
2920
|
+
if (fs11.existsSync(fullValidation.path)) {
|
|
2921
2921
|
res.writeHead(409, { "Content-Type": "application/json" });
|
|
2922
2922
|
res.end(JSON.stringify({ message: "Folder already exists" }));
|
|
2923
2923
|
return;
|
|
2924
2924
|
}
|
|
2925
|
-
|
|
2925
|
+
fs11.mkdirSync(fullValidation.path, { recursive: true });
|
|
2926
2926
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2927
2927
|
res.end(JSON.stringify({ success: true, path: fullValidation.path }));
|
|
2928
2928
|
} catch (e) {
|
|
@@ -2946,10 +2946,10 @@ var require_src = __commonJS({
|
|
|
2946
2946
|
const url = new URL(req.url || "/", `http://localhost`);
|
|
2947
2947
|
let filePath = url.pathname.replace(/^\/terminal\/?/, "");
|
|
2948
2948
|
if (!filePath || filePath === "") filePath = "index.html";
|
|
2949
|
-
const fullPath =
|
|
2949
|
+
const fullPath = path13.join(__dirname, "public", filePath);
|
|
2950
2950
|
try {
|
|
2951
|
-
if (!
|
|
2952
|
-
const ext =
|
|
2951
|
+
if (!fs11.existsSync(fullPath)) return false;
|
|
2952
|
+
const ext = path13.extname(fullPath);
|
|
2953
2953
|
const mimeTypes = {
|
|
2954
2954
|
".html": "text/html",
|
|
2955
2955
|
".js": "application/javascript",
|
|
@@ -2960,7 +2960,7 @@ var require_src = __commonJS({
|
|
|
2960
2960
|
".ico": "image/x-icon"
|
|
2961
2961
|
};
|
|
2962
2962
|
const mime = mimeTypes[ext] || "application/octet-stream";
|
|
2963
|
-
const content =
|
|
2963
|
+
const content = fs11.readFileSync(fullPath);
|
|
2964
2964
|
res.writeHead(200, { "Content-Type": mime });
|
|
2965
2965
|
res.end(content);
|
|
2966
2966
|
return true;
|
|
@@ -3623,7 +3623,7 @@ var require_src = __commonJS({
|
|
|
3623
3623
|
if (session.active) throw new Error(`Agent already running in session ${sessionId}`);
|
|
3624
3624
|
const { command, args = [], env = {} } = options;
|
|
3625
3625
|
if (!command) throw new Error("startScriptInSession requires a command");
|
|
3626
|
-
return new Promise((
|
|
3626
|
+
return new Promise((resolve6, reject) => {
|
|
3627
3627
|
this.scriptBridge.startSession(sessionId, {
|
|
3628
3628
|
command,
|
|
3629
3629
|
args,
|
|
@@ -3645,7 +3645,7 @@ var require_src = __commonJS({
|
|
|
3645
3645
|
session.lastActivity = /* @__PURE__ */ new Date();
|
|
3646
3646
|
this.broadcastToSession(sessionId, { type: "script_stopped", sessionId });
|
|
3647
3647
|
if (exitCode === 0) {
|
|
3648
|
-
|
|
3648
|
+
resolve6({ code: exitCode, signal });
|
|
3649
3649
|
} else {
|
|
3650
3650
|
reject(new Error(`Script exited with code ${exitCode}`));
|
|
3651
3651
|
}
|
|
@@ -4553,14 +4553,14 @@ var require_util = __commonJS({
|
|
|
4553
4553
|
}
|
|
4554
4554
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
4555
4555
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
4556
|
-
let
|
|
4556
|
+
let path13 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
4557
4557
|
if (origin[origin.length - 1] === "/") {
|
|
4558
4558
|
origin = origin.slice(0, origin.length - 1);
|
|
4559
4559
|
}
|
|
4560
|
-
if (
|
|
4561
|
-
|
|
4560
|
+
if (path13 && path13[0] !== "/") {
|
|
4561
|
+
path13 = `/${path13}`;
|
|
4562
4562
|
}
|
|
4563
|
-
return new URL(`${origin}${
|
|
4563
|
+
return new URL(`${origin}${path13}`);
|
|
4564
4564
|
}
|
|
4565
4565
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
4566
4566
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -5011,39 +5011,39 @@ var require_diagnostics = __commonJS({
|
|
|
5011
5011
|
});
|
|
5012
5012
|
diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => {
|
|
5013
5013
|
const {
|
|
5014
|
-
request: { method, path:
|
|
5014
|
+
request: { method, path: path13, origin }
|
|
5015
5015
|
} = evt;
|
|
5016
|
-
debuglog("sending request to %s %s/%s", method, origin,
|
|
5016
|
+
debuglog("sending request to %s %s/%s", method, origin, path13);
|
|
5017
5017
|
});
|
|
5018
5018
|
diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => {
|
|
5019
5019
|
const {
|
|
5020
|
-
request: { method, path:
|
|
5020
|
+
request: { method, path: path13, origin },
|
|
5021
5021
|
response: { statusCode }
|
|
5022
5022
|
} = evt;
|
|
5023
5023
|
debuglog(
|
|
5024
5024
|
"received response to %s %s/%s - HTTP %d",
|
|
5025
5025
|
method,
|
|
5026
5026
|
origin,
|
|
5027
|
-
|
|
5027
|
+
path13,
|
|
5028
5028
|
statusCode
|
|
5029
5029
|
);
|
|
5030
5030
|
});
|
|
5031
5031
|
diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => {
|
|
5032
5032
|
const {
|
|
5033
|
-
request: { method, path:
|
|
5033
|
+
request: { method, path: path13, origin }
|
|
5034
5034
|
} = evt;
|
|
5035
|
-
debuglog("trailers received from %s %s/%s", method, origin,
|
|
5035
|
+
debuglog("trailers received from %s %s/%s", method, origin, path13);
|
|
5036
5036
|
});
|
|
5037
5037
|
diagnosticsChannel.channel("undici:request:error").subscribe((evt) => {
|
|
5038
5038
|
const {
|
|
5039
|
-
request: { method, path:
|
|
5039
|
+
request: { method, path: path13, origin },
|
|
5040
5040
|
error
|
|
5041
5041
|
} = evt;
|
|
5042
5042
|
debuglog(
|
|
5043
5043
|
"request to %s %s/%s errored - %s",
|
|
5044
5044
|
method,
|
|
5045
5045
|
origin,
|
|
5046
|
-
|
|
5046
|
+
path13,
|
|
5047
5047
|
error.message
|
|
5048
5048
|
);
|
|
5049
5049
|
});
|
|
@@ -5092,9 +5092,9 @@ var require_diagnostics = __commonJS({
|
|
|
5092
5092
|
});
|
|
5093
5093
|
diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => {
|
|
5094
5094
|
const {
|
|
5095
|
-
request: { method, path:
|
|
5095
|
+
request: { method, path: path13, origin }
|
|
5096
5096
|
} = evt;
|
|
5097
|
-
debuglog("sending request to %s %s/%s", method, origin,
|
|
5097
|
+
debuglog("sending request to %s %s/%s", method, origin, path13);
|
|
5098
5098
|
});
|
|
5099
5099
|
}
|
|
5100
5100
|
diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => {
|
|
@@ -5157,7 +5157,7 @@ var require_request = __commonJS({
|
|
|
5157
5157
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
5158
5158
|
var Request = class {
|
|
5159
5159
|
constructor(origin, {
|
|
5160
|
-
path:
|
|
5160
|
+
path: path13,
|
|
5161
5161
|
method,
|
|
5162
5162
|
body,
|
|
5163
5163
|
headers,
|
|
@@ -5172,11 +5172,11 @@ var require_request = __commonJS({
|
|
|
5172
5172
|
expectContinue,
|
|
5173
5173
|
servername
|
|
5174
5174
|
}, handler2) {
|
|
5175
|
-
if (typeof
|
|
5175
|
+
if (typeof path13 !== "string") {
|
|
5176
5176
|
throw new InvalidArgumentError("path must be a string");
|
|
5177
|
-
} else if (
|
|
5177
|
+
} else if (path13[0] !== "/" && !(path13.startsWith("http://") || path13.startsWith("https://")) && method !== "CONNECT") {
|
|
5178
5178
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
5179
|
-
} else if (invalidPathRegex.test(
|
|
5179
|
+
} else if (invalidPathRegex.test(path13)) {
|
|
5180
5180
|
throw new InvalidArgumentError("invalid request path");
|
|
5181
5181
|
}
|
|
5182
5182
|
if (typeof method !== "string") {
|
|
@@ -5242,7 +5242,7 @@ var require_request = __commonJS({
|
|
|
5242
5242
|
this.completed = false;
|
|
5243
5243
|
this.aborted = false;
|
|
5244
5244
|
this.upgrade = upgrade || null;
|
|
5245
|
-
this.path = query ? buildURL(
|
|
5245
|
+
this.path = query ? buildURL(path13, query) : path13;
|
|
5246
5246
|
this.origin = origin;
|
|
5247
5247
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
5248
5248
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -5567,9 +5567,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
5567
5567
|
}
|
|
5568
5568
|
close(callback) {
|
|
5569
5569
|
if (callback === void 0) {
|
|
5570
|
-
return new Promise((
|
|
5570
|
+
return new Promise((resolve6, reject) => {
|
|
5571
5571
|
this.close((err2, data) => {
|
|
5572
|
-
return err2 ? reject(err2) :
|
|
5572
|
+
return err2 ? reject(err2) : resolve6(data);
|
|
5573
5573
|
});
|
|
5574
5574
|
});
|
|
5575
5575
|
}
|
|
@@ -5607,12 +5607,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
5607
5607
|
err2 = null;
|
|
5608
5608
|
}
|
|
5609
5609
|
if (callback === void 0) {
|
|
5610
|
-
return new Promise((
|
|
5610
|
+
return new Promise((resolve6, reject) => {
|
|
5611
5611
|
this.destroy(err2, (err3, data) => {
|
|
5612
5612
|
return err3 ? (
|
|
5613
5613
|
/* istanbul ignore next: should never error */
|
|
5614
5614
|
reject(err3)
|
|
5615
|
-
) :
|
|
5615
|
+
) : resolve6(data);
|
|
5616
5616
|
});
|
|
5617
5617
|
});
|
|
5618
5618
|
}
|
|
@@ -7879,8 +7879,8 @@ var require_util2 = __commonJS({
|
|
|
7879
7879
|
function createDeferredPromise() {
|
|
7880
7880
|
let res;
|
|
7881
7881
|
let rej;
|
|
7882
|
-
const promise = new Promise((
|
|
7883
|
-
res =
|
|
7882
|
+
const promise = new Promise((resolve6, reject) => {
|
|
7883
|
+
res = resolve6;
|
|
7884
7884
|
rej = reject;
|
|
7885
7885
|
});
|
|
7886
7886
|
return { promise, resolve: res, reject: rej };
|
|
@@ -9768,7 +9768,7 @@ var require_client_h1 = __commonJS({
|
|
|
9768
9768
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
9769
9769
|
}
|
|
9770
9770
|
function writeH1(client, request) {
|
|
9771
|
-
const { method, path:
|
|
9771
|
+
const { method, path: path13, host, upgrade, blocking, reset } = request;
|
|
9772
9772
|
let { body, headers, contentLength } = request;
|
|
9773
9773
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
9774
9774
|
if (util.isFormDataLike(body)) {
|
|
@@ -9834,7 +9834,7 @@ var require_client_h1 = __commonJS({
|
|
|
9834
9834
|
if (blocking) {
|
|
9835
9835
|
socket[kBlocking] = true;
|
|
9836
9836
|
}
|
|
9837
|
-
let header = `${method} ${
|
|
9837
|
+
let header = `${method} ${path13} HTTP/1.1\r
|
|
9838
9838
|
`;
|
|
9839
9839
|
if (typeof host === "string") {
|
|
9840
9840
|
header += `host: ${host}\r
|
|
@@ -10021,12 +10021,12 @@ upgrade: ${upgrade}\r
|
|
|
10021
10021
|
cb();
|
|
10022
10022
|
}
|
|
10023
10023
|
}
|
|
10024
|
-
const waitForDrain = () => new Promise((
|
|
10024
|
+
const waitForDrain = () => new Promise((resolve6, reject) => {
|
|
10025
10025
|
assert(callback === null);
|
|
10026
10026
|
if (socket[kError]) {
|
|
10027
10027
|
reject(socket[kError]);
|
|
10028
10028
|
} else {
|
|
10029
|
-
callback =
|
|
10029
|
+
callback = resolve6;
|
|
10030
10030
|
}
|
|
10031
10031
|
});
|
|
10032
10032
|
socket.on("close", onDrain).on("drain", onDrain);
|
|
@@ -10360,7 +10360,7 @@ var require_client_h2 = __commonJS({
|
|
|
10360
10360
|
}
|
|
10361
10361
|
function writeH2(client, request) {
|
|
10362
10362
|
const session = client[kHTTP2Session];
|
|
10363
|
-
const { method, path:
|
|
10363
|
+
const { method, path: path13, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
10364
10364
|
let { body } = request;
|
|
10365
10365
|
if (upgrade) {
|
|
10366
10366
|
util.errorRequest(client, request, new Error("Upgrade not supported for H2"));
|
|
@@ -10427,7 +10427,7 @@ var require_client_h2 = __commonJS({
|
|
|
10427
10427
|
});
|
|
10428
10428
|
return true;
|
|
10429
10429
|
}
|
|
10430
|
-
headers[HTTP2_HEADER_PATH] =
|
|
10430
|
+
headers[HTTP2_HEADER_PATH] = path13;
|
|
10431
10431
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
10432
10432
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
10433
10433
|
if (body && typeof body.read === "function") {
|
|
@@ -10663,12 +10663,12 @@ var require_client_h2 = __commonJS({
|
|
|
10663
10663
|
cb();
|
|
10664
10664
|
}
|
|
10665
10665
|
}
|
|
10666
|
-
const waitForDrain = () => new Promise((
|
|
10666
|
+
const waitForDrain = () => new Promise((resolve6, reject) => {
|
|
10667
10667
|
assert(callback === null);
|
|
10668
10668
|
if (socket[kError]) {
|
|
10669
10669
|
reject(socket[kError]);
|
|
10670
10670
|
} else {
|
|
10671
|
-
callback =
|
|
10671
|
+
callback = resolve6;
|
|
10672
10672
|
}
|
|
10673
10673
|
});
|
|
10674
10674
|
h2stream.on("close", onDrain).on("drain", onDrain);
|
|
@@ -10780,9 +10780,9 @@ var require_redirect_handler = __commonJS({
|
|
|
10780
10780
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
10781
10781
|
}
|
|
10782
10782
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
10783
|
-
const
|
|
10783
|
+
const path13 = search ? `${pathname}${search}` : pathname;
|
|
10784
10784
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
10785
|
-
this.opts.path =
|
|
10785
|
+
this.opts.path = path13;
|
|
10786
10786
|
this.opts.origin = origin;
|
|
10787
10787
|
this.opts.maxRedirections = 0;
|
|
10788
10788
|
this.opts.query = null;
|
|
@@ -11146,16 +11146,16 @@ var require_client = __commonJS({
|
|
|
11146
11146
|
return this[kNeedDrain] < 2;
|
|
11147
11147
|
}
|
|
11148
11148
|
async [kClose]() {
|
|
11149
|
-
return new Promise((
|
|
11149
|
+
return new Promise((resolve6) => {
|
|
11150
11150
|
if (this[kSize]) {
|
|
11151
|
-
this[kClosedResolve] =
|
|
11151
|
+
this[kClosedResolve] = resolve6;
|
|
11152
11152
|
} else {
|
|
11153
|
-
|
|
11153
|
+
resolve6(null);
|
|
11154
11154
|
}
|
|
11155
11155
|
});
|
|
11156
11156
|
}
|
|
11157
11157
|
async [kDestroy](err2) {
|
|
11158
|
-
return new Promise((
|
|
11158
|
+
return new Promise((resolve6) => {
|
|
11159
11159
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
11160
11160
|
for (let i = 0; i < requests.length; i++) {
|
|
11161
11161
|
const request = requests[i];
|
|
@@ -11166,7 +11166,7 @@ var require_client = __commonJS({
|
|
|
11166
11166
|
this[kClosedResolve]();
|
|
11167
11167
|
this[kClosedResolve] = null;
|
|
11168
11168
|
}
|
|
11169
|
-
|
|
11169
|
+
resolve6(null);
|
|
11170
11170
|
};
|
|
11171
11171
|
if (this[kHTTPContext]) {
|
|
11172
11172
|
this[kHTTPContext].destroy(err2, callback);
|
|
@@ -11217,7 +11217,7 @@ var require_client = __commonJS({
|
|
|
11217
11217
|
});
|
|
11218
11218
|
}
|
|
11219
11219
|
try {
|
|
11220
|
-
const socket = await new Promise((
|
|
11220
|
+
const socket = await new Promise((resolve6, reject) => {
|
|
11221
11221
|
client[kConnector]({
|
|
11222
11222
|
host,
|
|
11223
11223
|
hostname,
|
|
@@ -11229,7 +11229,7 @@ var require_client = __commonJS({
|
|
|
11229
11229
|
if (err2) {
|
|
11230
11230
|
reject(err2);
|
|
11231
11231
|
} else {
|
|
11232
|
-
|
|
11232
|
+
resolve6(socket2);
|
|
11233
11233
|
}
|
|
11234
11234
|
});
|
|
11235
11235
|
});
|
|
@@ -11565,8 +11565,8 @@ var require_pool_base = __commonJS({
|
|
|
11565
11565
|
if (this[kQueue].isEmpty()) {
|
|
11566
11566
|
await Promise.all(this[kClients].map((c) => c.close()));
|
|
11567
11567
|
} else {
|
|
11568
|
-
await new Promise((
|
|
11569
|
-
this[kClosedResolve] =
|
|
11568
|
+
await new Promise((resolve6) => {
|
|
11569
|
+
this[kClosedResolve] = resolve6;
|
|
11570
11570
|
});
|
|
11571
11571
|
}
|
|
11572
11572
|
}
|
|
@@ -12017,10 +12017,10 @@ var require_proxy_agent = __commonJS({
|
|
|
12017
12017
|
};
|
|
12018
12018
|
const {
|
|
12019
12019
|
origin,
|
|
12020
|
-
path:
|
|
12020
|
+
path: path13 = "/",
|
|
12021
12021
|
headers = {}
|
|
12022
12022
|
} = opts;
|
|
12023
|
-
opts.path = origin +
|
|
12023
|
+
opts.path = origin + path13;
|
|
12024
12024
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
12025
12025
|
const { host } = new URL3(origin);
|
|
12026
12026
|
headers.host = host;
|
|
@@ -12781,7 +12781,7 @@ var require_readable = __commonJS({
|
|
|
12781
12781
|
if (this._readableState.closeEmitted) {
|
|
12782
12782
|
return null;
|
|
12783
12783
|
}
|
|
12784
|
-
return await new Promise((
|
|
12784
|
+
return await new Promise((resolve6, reject) => {
|
|
12785
12785
|
if (this[kContentLength] > limit) {
|
|
12786
12786
|
this.destroy(new AbortError());
|
|
12787
12787
|
}
|
|
@@ -12794,7 +12794,7 @@ var require_readable = __commonJS({
|
|
|
12794
12794
|
if (signal?.aborted) {
|
|
12795
12795
|
reject(signal.reason ?? new AbortError());
|
|
12796
12796
|
} else {
|
|
12797
|
-
|
|
12797
|
+
resolve6(null);
|
|
12798
12798
|
}
|
|
12799
12799
|
}).on("error", noop).on("data", function(chunk) {
|
|
12800
12800
|
limit -= chunk.length;
|
|
@@ -12813,7 +12813,7 @@ var require_readable = __commonJS({
|
|
|
12813
12813
|
}
|
|
12814
12814
|
async function consume(stream, type) {
|
|
12815
12815
|
assert(!stream[kConsume]);
|
|
12816
|
-
return new Promise((
|
|
12816
|
+
return new Promise((resolve6, reject) => {
|
|
12817
12817
|
if (isUnusable(stream)) {
|
|
12818
12818
|
const rState = stream._readableState;
|
|
12819
12819
|
if (rState.destroyed && rState.closeEmitted === false) {
|
|
@@ -12830,7 +12830,7 @@ var require_readable = __commonJS({
|
|
|
12830
12830
|
stream[kConsume] = {
|
|
12831
12831
|
type,
|
|
12832
12832
|
stream,
|
|
12833
|
-
resolve:
|
|
12833
|
+
resolve: resolve6,
|
|
12834
12834
|
reject,
|
|
12835
12835
|
length: 0,
|
|
12836
12836
|
body: []
|
|
@@ -12900,18 +12900,18 @@ var require_readable = __commonJS({
|
|
|
12900
12900
|
return buffer;
|
|
12901
12901
|
}
|
|
12902
12902
|
function consumeEnd(consume2) {
|
|
12903
|
-
const { type, body, resolve:
|
|
12903
|
+
const { type, body, resolve: resolve6, stream, length } = consume2;
|
|
12904
12904
|
try {
|
|
12905
12905
|
if (type === "text") {
|
|
12906
|
-
|
|
12906
|
+
resolve6(chunksDecode(body, length));
|
|
12907
12907
|
} else if (type === "json") {
|
|
12908
|
-
|
|
12908
|
+
resolve6(JSON.parse(chunksDecode(body, length)));
|
|
12909
12909
|
} else if (type === "arrayBuffer") {
|
|
12910
|
-
|
|
12910
|
+
resolve6(chunksConcat(body, length).buffer);
|
|
12911
12911
|
} else if (type === "blob") {
|
|
12912
|
-
|
|
12912
|
+
resolve6(new Blob(body, { type: stream[kContentType] }));
|
|
12913
12913
|
} else if (type === "bytes") {
|
|
12914
|
-
|
|
12914
|
+
resolve6(chunksConcat(body, length));
|
|
12915
12915
|
}
|
|
12916
12916
|
consumeFinish(consume2);
|
|
12917
12917
|
} catch (err2) {
|
|
@@ -13168,9 +13168,9 @@ var require_api_request = __commonJS({
|
|
|
13168
13168
|
};
|
|
13169
13169
|
function request(opts, callback) {
|
|
13170
13170
|
if (callback === void 0) {
|
|
13171
|
-
return new Promise((
|
|
13171
|
+
return new Promise((resolve6, reject) => {
|
|
13172
13172
|
request.call(this, opts, (err2, data) => {
|
|
13173
|
-
return err2 ? reject(err2) :
|
|
13173
|
+
return err2 ? reject(err2) : resolve6(data);
|
|
13174
13174
|
});
|
|
13175
13175
|
});
|
|
13176
13176
|
}
|
|
@@ -13393,9 +13393,9 @@ var require_api_stream = __commonJS({
|
|
|
13393
13393
|
};
|
|
13394
13394
|
function stream(opts, factory, callback) {
|
|
13395
13395
|
if (callback === void 0) {
|
|
13396
|
-
return new Promise((
|
|
13396
|
+
return new Promise((resolve6, reject) => {
|
|
13397
13397
|
stream.call(this, opts, factory, (err2, data) => {
|
|
13398
|
-
return err2 ? reject(err2) :
|
|
13398
|
+
return err2 ? reject(err2) : resolve6(data);
|
|
13399
13399
|
});
|
|
13400
13400
|
});
|
|
13401
13401
|
}
|
|
@@ -13680,9 +13680,9 @@ var require_api_upgrade = __commonJS({
|
|
|
13680
13680
|
};
|
|
13681
13681
|
function upgrade(opts, callback) {
|
|
13682
13682
|
if (callback === void 0) {
|
|
13683
|
-
return new Promise((
|
|
13683
|
+
return new Promise((resolve6, reject) => {
|
|
13684
13684
|
upgrade.call(this, opts, (err2, data) => {
|
|
13685
|
-
return err2 ? reject(err2) :
|
|
13685
|
+
return err2 ? reject(err2) : resolve6(data);
|
|
13686
13686
|
});
|
|
13687
13687
|
});
|
|
13688
13688
|
}
|
|
@@ -13774,9 +13774,9 @@ var require_api_connect = __commonJS({
|
|
|
13774
13774
|
};
|
|
13775
13775
|
function connect(opts, callback) {
|
|
13776
13776
|
if (callback === void 0) {
|
|
13777
|
-
return new Promise((
|
|
13777
|
+
return new Promise((resolve6, reject) => {
|
|
13778
13778
|
connect.call(this, opts, (err2, data) => {
|
|
13779
|
-
return err2 ? reject(err2) :
|
|
13779
|
+
return err2 ? reject(err2) : resolve6(data);
|
|
13780
13780
|
});
|
|
13781
13781
|
});
|
|
13782
13782
|
}
|
|
@@ -13941,20 +13941,20 @@ var require_mock_utils = __commonJS({
|
|
|
13941
13941
|
}
|
|
13942
13942
|
return true;
|
|
13943
13943
|
}
|
|
13944
|
-
function safeUrl(
|
|
13945
|
-
if (typeof
|
|
13946
|
-
return
|
|
13944
|
+
function safeUrl(path13) {
|
|
13945
|
+
if (typeof path13 !== "string") {
|
|
13946
|
+
return path13;
|
|
13947
13947
|
}
|
|
13948
|
-
const pathSegments =
|
|
13948
|
+
const pathSegments = path13.split("?");
|
|
13949
13949
|
if (pathSegments.length !== 2) {
|
|
13950
|
-
return
|
|
13950
|
+
return path13;
|
|
13951
13951
|
}
|
|
13952
13952
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
13953
13953
|
qp.sort();
|
|
13954
13954
|
return [...pathSegments, qp.toString()].join("?");
|
|
13955
13955
|
}
|
|
13956
|
-
function matchKey(mockDispatch2, { path:
|
|
13957
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
13956
|
+
function matchKey(mockDispatch2, { path: path13, method, body, headers }) {
|
|
13957
|
+
const pathMatch = matchValue(mockDispatch2.path, path13);
|
|
13958
13958
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
13959
13959
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
13960
13960
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -13976,7 +13976,7 @@ var require_mock_utils = __commonJS({
|
|
|
13976
13976
|
function getMockDispatch(mockDispatches, key) {
|
|
13977
13977
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
13978
13978
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
13979
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
13979
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path13 }) => matchValue(safeUrl(path13), resolvedPath));
|
|
13980
13980
|
if (matchedMockDispatches.length === 0) {
|
|
13981
13981
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
13982
13982
|
}
|
|
@@ -14014,9 +14014,9 @@ var require_mock_utils = __commonJS({
|
|
|
14014
14014
|
}
|
|
14015
14015
|
}
|
|
14016
14016
|
function buildKey(opts) {
|
|
14017
|
-
const { path:
|
|
14017
|
+
const { path: path13, method, body, headers, query } = opts;
|
|
14018
14018
|
return {
|
|
14019
|
-
path:
|
|
14019
|
+
path: path13,
|
|
14020
14020
|
method,
|
|
14021
14021
|
body,
|
|
14022
14022
|
headers,
|
|
@@ -14479,10 +14479,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
14479
14479
|
}
|
|
14480
14480
|
format(pendingInterceptors) {
|
|
14481
14481
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
14482
|
-
({ method, path:
|
|
14482
|
+
({ method, path: path13, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
14483
14483
|
Method: method,
|
|
14484
14484
|
Origin: origin,
|
|
14485
|
-
Path:
|
|
14485
|
+
Path: path13,
|
|
14486
14486
|
"Status code": statusCode,
|
|
14487
14487
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
14488
14488
|
Invocations: timesInvoked,
|
|
@@ -17638,7 +17638,7 @@ var require_fetch = __commonJS({
|
|
|
17638
17638
|
function dispatch({ body }) {
|
|
17639
17639
|
const url = requestCurrentURL(request);
|
|
17640
17640
|
const agent = fetchParams.controller.dispatcher;
|
|
17641
|
-
return new Promise((
|
|
17641
|
+
return new Promise((resolve6, reject) => agent.dispatch(
|
|
17642
17642
|
{
|
|
17643
17643
|
path: url.pathname + url.search,
|
|
17644
17644
|
origin: url.origin,
|
|
@@ -17714,7 +17714,7 @@ var require_fetch = __commonJS({
|
|
|
17714
17714
|
}
|
|
17715
17715
|
}
|
|
17716
17716
|
const onError = this.onError.bind(this);
|
|
17717
|
-
|
|
17717
|
+
resolve6({
|
|
17718
17718
|
status,
|
|
17719
17719
|
statusText,
|
|
17720
17720
|
headersList,
|
|
@@ -17760,7 +17760,7 @@ var require_fetch = __commonJS({
|
|
|
17760
17760
|
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
17761
17761
|
headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true);
|
|
17762
17762
|
}
|
|
17763
|
-
|
|
17763
|
+
resolve6({
|
|
17764
17764
|
status,
|
|
17765
17765
|
statusText: STATUS_CODES[status],
|
|
17766
17766
|
headersList,
|
|
@@ -19363,9 +19363,9 @@ var require_util6 = __commonJS({
|
|
|
19363
19363
|
}
|
|
19364
19364
|
}
|
|
19365
19365
|
}
|
|
19366
|
-
function validateCookiePath(
|
|
19367
|
-
for (let i = 0; i <
|
|
19368
|
-
const code =
|
|
19366
|
+
function validateCookiePath(path13) {
|
|
19367
|
+
for (let i = 0; i < path13.length; ++i) {
|
|
19368
|
+
const code = path13.charCodeAt(i);
|
|
19369
19369
|
if (code < 32 || // exclude CTLs (0-31)
|
|
19370
19370
|
code === 127 || // DEL
|
|
19371
19371
|
code === 59) {
|
|
@@ -21436,8 +21436,8 @@ var require_util8 = __commonJS({
|
|
|
21436
21436
|
return true;
|
|
21437
21437
|
}
|
|
21438
21438
|
function delay(ms) {
|
|
21439
|
-
return new Promise((
|
|
21440
|
-
setTimeout(
|
|
21439
|
+
return new Promise((resolve6) => {
|
|
21440
|
+
setTimeout(resolve6, ms).unref();
|
|
21441
21441
|
});
|
|
21442
21442
|
}
|
|
21443
21443
|
module2.exports = {
|
|
@@ -22042,11 +22042,11 @@ var require_undici = __commonJS({
|
|
|
22042
22042
|
if (typeof opts.path !== "string") {
|
|
22043
22043
|
throw new InvalidArgumentError("invalid opts.path");
|
|
22044
22044
|
}
|
|
22045
|
-
let
|
|
22045
|
+
let path13 = opts.path;
|
|
22046
22046
|
if (!opts.path.startsWith("/")) {
|
|
22047
|
-
|
|
22047
|
+
path13 = `/${path13}`;
|
|
22048
22048
|
}
|
|
22049
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
22049
|
+
url = new URL(util.parseOrigin(url).origin + path13);
|
|
22050
22050
|
} else {
|
|
22051
22051
|
if (!opts) {
|
|
22052
22052
|
opts = typeof url === "object" ? url : {};
|
|
@@ -22628,7 +22628,7 @@ function resolveWorkerPath() {
|
|
|
22628
22628
|
);
|
|
22629
22629
|
}
|
|
22630
22630
|
function runParseInWorker(req) {
|
|
22631
|
-
return new Promise((
|
|
22631
|
+
return new Promise((resolve6, reject) => {
|
|
22632
22632
|
let workerPath;
|
|
22633
22633
|
try {
|
|
22634
22634
|
workerPath = resolveWorkerPath();
|
|
@@ -22647,7 +22647,7 @@ function runParseInWorker(req) {
|
|
|
22647
22647
|
};
|
|
22648
22648
|
worker.on("message", (reply) => {
|
|
22649
22649
|
if (reply.ok) {
|
|
22650
|
-
finish(() =>
|
|
22650
|
+
finish(() => resolve6({ results: reply.results, failedFiles: reply.failedFiles }));
|
|
22651
22651
|
} else {
|
|
22652
22652
|
const err2 = new Error(reply.error.message);
|
|
22653
22653
|
err2.name = reply.error.name;
|
|
@@ -22727,9 +22727,9 @@ function buildEffectsIndex(layerOutputs) {
|
|
|
22727
22727
|
return idx;
|
|
22728
22728
|
}
|
|
22729
22729
|
function writeEffectsIndex(rootDir, idx) {
|
|
22730
|
-
const
|
|
22731
|
-
atomicWriteFileSync(
|
|
22732
|
-
return
|
|
22730
|
+
const path13 = (0, import_node_path11.join)(rootDir, LAUNCHSECURE_DIR, "graphs", "effects-index.json");
|
|
22731
|
+
atomicWriteFileSync(path13, JSON.stringify(idx, null, 2) + "\n");
|
|
22732
|
+
return path13;
|
|
22733
22733
|
}
|
|
22734
22734
|
var import_node_path11;
|
|
22735
22735
|
var init_effects_index = __esm({
|
|
@@ -22891,7 +22891,7 @@ var init_freshness = __esm({
|
|
|
22891
22891
|
function getAvailableLayers(rootDir) {
|
|
22892
22892
|
const dir = (0, import_node_path13.join)(rootDir, GRAPHS_DIR2);
|
|
22893
22893
|
if (!(0, import_node_fs11.existsSync)(dir)) return [];
|
|
22894
|
-
return (0, import_node_fs11.readdirSync)(dir).filter((f) => f.endsWith(".json") && !NON_LAYER_GRAPH_FILES.has(f)).map((f) => f.replace(".json", ""));
|
|
22894
|
+
return (0, import_node_fs11.readdirSync)(dir).filter((f) => f.endsWith(".json") && !f.startsWith(".") && !NON_LAYER_GRAPH_FILES.has(f)).map((f) => f.replace(".json", ""));
|
|
22895
22895
|
}
|
|
22896
22896
|
function graphsDir(rootDir) {
|
|
22897
22897
|
return (0, import_node_path13.join)(rootDir, GRAPHS_DIR2);
|
|
@@ -23040,10 +23040,10 @@ async function generateGraph(rootDir, layer) {
|
|
|
23040
23040
|
return results;
|
|
23041
23041
|
}
|
|
23042
23042
|
function readEffectsIndex(rootDir) {
|
|
23043
|
-
const
|
|
23044
|
-
if (!(0, import_node_fs11.existsSync)(
|
|
23043
|
+
const path13 = (0, import_node_path13.join)(rootDir, GRAPHS_DIR2, "effects-index.json");
|
|
23044
|
+
if (!(0, import_node_fs11.existsSync)(path13)) return null;
|
|
23045
23045
|
try {
|
|
23046
|
-
return JSON.parse((0, import_node_fs11.readFileSync)(
|
|
23046
|
+
return JSON.parse((0, import_node_fs11.readFileSync)(path13, "utf-8"));
|
|
23047
23047
|
} catch {
|
|
23048
23048
|
return null;
|
|
23049
23049
|
}
|
|
@@ -24089,6 +24089,8 @@ function extractDeep(absPath) {
|
|
|
24089
24089
|
false
|
|
24090
24090
|
);
|
|
24091
24091
|
const hasEffects = Object.keys(fileEffects).length > 0;
|
|
24092
|
+
const uiLabels = collectUiLabels(root);
|
|
24093
|
+
const notes = collectNotes(root);
|
|
24092
24094
|
return {
|
|
24093
24095
|
elements,
|
|
24094
24096
|
stateVars,
|
|
@@ -24096,10 +24098,77 @@ function extractDeep(absPath) {
|
|
|
24096
24098
|
variables,
|
|
24097
24099
|
responses,
|
|
24098
24100
|
params,
|
|
24099
|
-
...hasEffects ? { effects: fileEffects } : {}
|
|
24101
|
+
...hasEffects ? { effects: fileEffects } : {},
|
|
24102
|
+
...uiLabels.length > 0 ? { ui_labels: uiLabels } : {},
|
|
24103
|
+
...notes.length > 0 ? { notes } : {}
|
|
24100
24104
|
};
|
|
24101
24105
|
}
|
|
24102
|
-
|
|
24106
|
+
function collectNotes(root) {
|
|
24107
|
+
const out = [];
|
|
24108
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24109
|
+
function visit(node) {
|
|
24110
|
+
if (out.length >= NOTES_MAX) return;
|
|
24111
|
+
if (node.type === "comment") {
|
|
24112
|
+
const text = node.text;
|
|
24113
|
+
const startRow = node.startPosition.row;
|
|
24114
|
+
NOTE_REGEX.lastIndex = 0;
|
|
24115
|
+
let m;
|
|
24116
|
+
while ((m = NOTE_REGEX.exec(text)) !== null) {
|
|
24117
|
+
const kind = m[1];
|
|
24118
|
+
const author = m[2];
|
|
24119
|
+
const body = m[3];
|
|
24120
|
+
if (!kind || !body) continue;
|
|
24121
|
+
const newlinesBefore = (text.slice(0, m.index).match(/\n/g) ?? []).length;
|
|
24122
|
+
const line = startRow + 1 + newlinesBefore;
|
|
24123
|
+
const key = `${line}:${kind}`;
|
|
24124
|
+
if (seen.has(key)) continue;
|
|
24125
|
+
seen.add(key);
|
|
24126
|
+
const note = {
|
|
24127
|
+
kind,
|
|
24128
|
+
text: body.length <= 200 ? body : body.slice(0, 200) + "...",
|
|
24129
|
+
line
|
|
24130
|
+
};
|
|
24131
|
+
if (author) note.author = author;
|
|
24132
|
+
out.push(note);
|
|
24133
|
+
if (out.length >= NOTES_MAX) return;
|
|
24134
|
+
}
|
|
24135
|
+
}
|
|
24136
|
+
for (const child of node.namedChildren) {
|
|
24137
|
+
visit(child);
|
|
24138
|
+
if (out.length >= NOTES_MAX) return;
|
|
24139
|
+
}
|
|
24140
|
+
}
|
|
24141
|
+
visit(root);
|
|
24142
|
+
return out;
|
|
24143
|
+
}
|
|
24144
|
+
function collectUiLabels(root) {
|
|
24145
|
+
const out = [];
|
|
24146
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24147
|
+
function visit(node) {
|
|
24148
|
+
if (out.length >= UI_LABELS_MAX) return;
|
|
24149
|
+
if (node.type === "pair") {
|
|
24150
|
+
const key = node.childForFieldName("key");
|
|
24151
|
+
const val = node.childForFieldName("value");
|
|
24152
|
+
if (key && val) {
|
|
24153
|
+
const keyText = key.type === "property_identifier" ? key.text : stringLiteralValue(key) ?? key.text;
|
|
24154
|
+
if (UI_LABEL_KEYS.has(keyText)) {
|
|
24155
|
+
const strVal = stringLiteralValue(val);
|
|
24156
|
+
if (strVal && strVal.length > 0 && strVal.length <= 200 && !seen.has(strVal)) {
|
|
24157
|
+
seen.add(strVal);
|
|
24158
|
+
out.push(strVal);
|
|
24159
|
+
}
|
|
24160
|
+
}
|
|
24161
|
+
}
|
|
24162
|
+
}
|
|
24163
|
+
for (const child of node.namedChildren) {
|
|
24164
|
+
visit(child);
|
|
24165
|
+
if (out.length >= UI_LABELS_MAX) return;
|
|
24166
|
+
}
|
|
24167
|
+
}
|
|
24168
|
+
visit(root);
|
|
24169
|
+
return out;
|
|
24170
|
+
}
|
|
24171
|
+
var import_node_fs15, import_node_path17, tsxLanguage, parserInstance, TreeSitterCtor, initPromise, initialized, queriesDir, queryCache, MAX_PARSEABLE_BYTES, MAX_CONSECUTIVE_PARSE_FAILURES, consecutiveParseFailures, ParseCascadeError, PRISMA_MUTATION_METHODS_BUILTIN, SUPABASE_MUTATION_METHODS_BUILTIN, DB_IDENTIFIERS_FALLBACK, extraDbIdentifiers, extraMutationMethods, INLINE_AUTH_IMPORTS, EXEMPT_NAME_PATTERNS, PROTECT_NAME_PATTERNS, TRUST_AS_PROTECT_KEYS, TIMER_FNS, DOM_METHOD_NAMES, CLASSLIST_METHODS, STORAGE_OBJECTS, HISTORY_METHODS, LOCATION_METHODS, ASSIGN_DOM_PROPS, UI_LABEL_KEYS, UI_LABELS_MAX, NOTE_REGEX, NOTES_MAX;
|
|
24103
24172
|
var init_ts_extractor = __esm({
|
|
24104
24173
|
"src/server/graph/core/ts-extractor.ts"() {
|
|
24105
24174
|
"use strict";
|
|
@@ -24218,6 +24287,27 @@ var init_ts_extractor = __esm({
|
|
|
24218
24287
|
"selected",
|
|
24219
24288
|
"disabled"
|
|
24220
24289
|
]);
|
|
24290
|
+
UI_LABEL_KEYS = /* @__PURE__ */ new Set([
|
|
24291
|
+
"label",
|
|
24292
|
+
"title",
|
|
24293
|
+
"name",
|
|
24294
|
+
"text",
|
|
24295
|
+
"description",
|
|
24296
|
+
"placeholder",
|
|
24297
|
+
"tooltip",
|
|
24298
|
+
"heading",
|
|
24299
|
+
"subheading",
|
|
24300
|
+
"sheetTitle",
|
|
24301
|
+
"sheetDescription",
|
|
24302
|
+
"caption",
|
|
24303
|
+
"cta",
|
|
24304
|
+
"buttonText",
|
|
24305
|
+
"emptyText",
|
|
24306
|
+
"subtitle"
|
|
24307
|
+
]);
|
|
24308
|
+
UI_LABELS_MAX = 200;
|
|
24309
|
+
NOTE_REGEX = /^\s*(?:\/\/|\/\*+|\*)\s*([A-Z][A-Z0-9_]{1,15})(?:\(([^)]+)\))?:\s*(\S.*?)\s*(?:\*\/)?$/gm;
|
|
24310
|
+
NOTES_MAX = 100;
|
|
24221
24311
|
}
|
|
24222
24312
|
});
|
|
24223
24313
|
|
|
@@ -24229,7 +24319,7 @@ __export(watcher_exports, {
|
|
|
24229
24319
|
function isIgnoredPath(rel) {
|
|
24230
24320
|
if (rel.startsWith(GRAPHS_RELATIVE)) return true;
|
|
24231
24321
|
if (rel.endsWith(".lock") || rel.endsWith(".log")) return true;
|
|
24232
|
-
for (const part of rel.split(
|
|
24322
|
+
for (const part of rel.split(import_node_path32.sep)) {
|
|
24233
24323
|
if (IGNORE_SEGMENTS.has(part)) return true;
|
|
24234
24324
|
}
|
|
24235
24325
|
return false;
|
|
@@ -24271,7 +24361,7 @@ function startGraphWatcher(rootDir, opts = {}) {
|
|
|
24271
24361
|
regenerating = false;
|
|
24272
24362
|
}
|
|
24273
24363
|
}
|
|
24274
|
-
const watcher = (0,
|
|
24364
|
+
const watcher = (0, import_node_fs27.watch)(rootDir, { recursive: true }, (event, filename) => {
|
|
24275
24365
|
if (!filename) return;
|
|
24276
24366
|
const rel = filename.toString();
|
|
24277
24367
|
if (process.env.LAUNCH_CHART_WATCH_TRACE === "1") {
|
|
@@ -24304,12 +24394,12 @@ function startGraphWatcher(rootDir, opts = {}) {
|
|
|
24304
24394
|
freshness: () => getFreshnessTracker(rootDir).get()
|
|
24305
24395
|
};
|
|
24306
24396
|
}
|
|
24307
|
-
var
|
|
24397
|
+
var import_node_fs27, import_node_path32, IGNORE_SEGMENTS, TRIGGER_EXTENSIONS, GRAPHS_RELATIVE;
|
|
24308
24398
|
var init_watcher = __esm({
|
|
24309
24399
|
"src/server/graph/core/watcher.ts"() {
|
|
24310
24400
|
"use strict";
|
|
24311
|
-
|
|
24312
|
-
|
|
24401
|
+
import_node_fs27 = require("node:fs");
|
|
24402
|
+
import_node_path32 = require("node:path");
|
|
24313
24403
|
init_launch_kit_paths();
|
|
24314
24404
|
init_graph();
|
|
24315
24405
|
init_freshness();
|
|
@@ -24338,7 +24428,7 @@ var init_watcher = __esm({
|
|
|
24338
24428
|
".prisma",
|
|
24339
24429
|
".sql"
|
|
24340
24430
|
]);
|
|
24341
|
-
GRAPHS_RELATIVE = (0,
|
|
24431
|
+
GRAPHS_RELATIVE = (0, import_node_path32.join)(LAUNCHSECURE_DIR, "graphs");
|
|
24342
24432
|
}
|
|
24343
24433
|
});
|
|
24344
24434
|
|
|
@@ -24463,6 +24553,18 @@ function initLaunchPodTerminalBridge(httpServer, projectDir) {
|
|
|
24463
24553
|
var import_fs = __toESM(require("fs"));
|
|
24464
24554
|
var import_path2 = __toESM(require("path"));
|
|
24465
24555
|
var MANAGED_SERVERS = ["launch-pod", "launch-chart"];
|
|
24556
|
+
function mergeMcpEntry(existing, ours) {
|
|
24557
|
+
if (!existing || typeof existing !== "object") return ours;
|
|
24558
|
+
const prev = existing;
|
|
24559
|
+
const merged = { ...prev, ...ours };
|
|
24560
|
+
if (prev.headers || ours.headers) {
|
|
24561
|
+
merged.headers = { ...prev.headers ?? {}, ...ours.headers ?? {} };
|
|
24562
|
+
}
|
|
24563
|
+
if (prev.env || ours.env) {
|
|
24564
|
+
merged.env = { ...prev.env ?? {}, ...ours.env ?? {} };
|
|
24565
|
+
}
|
|
24566
|
+
return merged;
|
|
24567
|
+
}
|
|
24466
24568
|
var writtenPaths = [];
|
|
24467
24569
|
function writeMcpConfigs(opts) {
|
|
24468
24570
|
const { projectDir, token, serverUrl } = opts;
|
|
@@ -24524,17 +24626,17 @@ function writeClaudeConfig(projectDir, mcpUrl, token) {
|
|
|
24524
24626
|
}
|
|
24525
24627
|
}
|
|
24526
24628
|
const servers = existing.mcpServers ?? {};
|
|
24527
|
-
servers["launch-pod"] = {
|
|
24629
|
+
servers["launch-pod"] = mergeMcpEntry(servers["launch-pod"], {
|
|
24528
24630
|
type: "http",
|
|
24529
24631
|
url: mcpUrl,
|
|
24530
24632
|
headers: {
|
|
24531
24633
|
Authorization: `Bearer ${token}`
|
|
24532
24634
|
}
|
|
24533
|
-
};
|
|
24534
|
-
servers["launch-chart"] = {
|
|
24635
|
+
});
|
|
24636
|
+
servers["launch-chart"] = mergeMcpEntry(servers["launch-chart"], {
|
|
24535
24637
|
command: "launch-chart",
|
|
24536
24638
|
args: []
|
|
24537
|
-
};
|
|
24639
|
+
});
|
|
24538
24640
|
existing.mcpServers = servers;
|
|
24539
24641
|
import_fs.default.writeFileSync(filePath, JSON.stringify(existing, null, 2) + "\n", { mode: 384 });
|
|
24540
24642
|
writtenPaths.push(filePath);
|
|
@@ -26003,7 +26105,7 @@ var PostImplLaunchExecutor = class {
|
|
|
26003
26105
|
return 3001;
|
|
26004
26106
|
}
|
|
26005
26107
|
startDevServer(port, databaseUrl) {
|
|
26006
|
-
return new Promise((
|
|
26108
|
+
return new Promise((resolve6) => {
|
|
26007
26109
|
const env = { ...process.env, PORT: String(port), ...databaseUrl ? { DATABASE_URL: databaseUrl } : {} };
|
|
26008
26110
|
this.devProcess = (0, import_child_process3.spawn)("npm", ["run", "dev"], {
|
|
26009
26111
|
cwd: this.workingDir,
|
|
@@ -26015,7 +26117,7 @@ var PostImplLaunchExecutor = class {
|
|
|
26015
26117
|
const timeout = setTimeout(() => {
|
|
26016
26118
|
if (!resolved) {
|
|
26017
26119
|
resolved = true;
|
|
26018
|
-
this.healthCheck(port).then(
|
|
26120
|
+
this.healthCheck(port).then(resolve6);
|
|
26019
26121
|
}
|
|
26020
26122
|
}, 15e3);
|
|
26021
26123
|
const onData = (data) => {
|
|
@@ -26024,7 +26126,7 @@ var PostImplLaunchExecutor = class {
|
|
|
26024
26126
|
if (!resolved) {
|
|
26025
26127
|
resolved = true;
|
|
26026
26128
|
clearTimeout(timeout);
|
|
26027
|
-
|
|
26129
|
+
resolve6(true);
|
|
26028
26130
|
}
|
|
26029
26131
|
}
|
|
26030
26132
|
};
|
|
@@ -26035,7 +26137,7 @@ var PostImplLaunchExecutor = class {
|
|
|
26035
26137
|
if (!resolved) {
|
|
26036
26138
|
resolved = true;
|
|
26037
26139
|
clearTimeout(timeout);
|
|
26038
|
-
|
|
26140
|
+
resolve6(false);
|
|
26039
26141
|
}
|
|
26040
26142
|
});
|
|
26041
26143
|
this.devProcess.unref();
|
|
@@ -27072,8 +27174,7 @@ function buildAnalyzerMcpConfig() {
|
|
|
27072
27174
|
"launch-chart": {
|
|
27073
27175
|
command: process.execPath,
|
|
27074
27176
|
// current node binary, guaranteed-resolvable
|
|
27075
|
-
args: [graphEntry]
|
|
27076
|
-
env: { LAUNCH_CHART_AUTOSERVE: "1" }
|
|
27177
|
+
args: [graphEntry]
|
|
27077
27178
|
}
|
|
27078
27179
|
}
|
|
27079
27180
|
});
|
|
@@ -27381,7 +27482,7 @@ var ProjectMcpClient = class {
|
|
|
27381
27482
|
this.initialized = true;
|
|
27382
27483
|
}
|
|
27383
27484
|
send(body) {
|
|
27384
|
-
return new Promise((
|
|
27485
|
+
return new Promise((resolve6, reject) => {
|
|
27385
27486
|
const headers = {
|
|
27386
27487
|
...this.headers,
|
|
27387
27488
|
"Content-Length": String(Buffer.byteLength(body))
|
|
@@ -27406,7 +27507,7 @@ var ProjectMcpClient = class {
|
|
|
27406
27507
|
return;
|
|
27407
27508
|
}
|
|
27408
27509
|
const sid = res.headers["mcp-session-id"];
|
|
27409
|
-
|
|
27510
|
+
resolve6({ body: text, sessionId: typeof sid === "string" ? sid : void 0 });
|
|
27410
27511
|
});
|
|
27411
27512
|
}
|
|
27412
27513
|
);
|
|
@@ -27762,19 +27863,19 @@ var import_node_path3 = require("node:path");
|
|
|
27762
27863
|
init_launch_kit_paths();
|
|
27763
27864
|
var MAX_DEDUPE_SET = 1e3;
|
|
27764
27865
|
var MAX_PINGS = 200;
|
|
27765
|
-
function readJson(
|
|
27766
|
-
if (!(0, import_node_fs2.existsSync)(
|
|
27866
|
+
function readJson(path13, fallback) {
|
|
27867
|
+
if (!(0, import_node_fs2.existsSync)(path13)) return fallback;
|
|
27767
27868
|
try {
|
|
27768
|
-
return JSON.parse((0, import_node_fs2.readFileSync)(
|
|
27869
|
+
return JSON.parse((0, import_node_fs2.readFileSync)(path13, "utf-8"));
|
|
27769
27870
|
} catch {
|
|
27770
27871
|
return fallback;
|
|
27771
27872
|
}
|
|
27772
27873
|
}
|
|
27773
|
-
function writeJsonAtomic(
|
|
27774
|
-
(0, import_node_fs2.mkdirSync)((0, import_node_path3.dirname)(
|
|
27775
|
-
const tmp = `${
|
|
27874
|
+
function writeJsonAtomic(path13, value) {
|
|
27875
|
+
(0, import_node_fs2.mkdirSync)((0, import_node_path3.dirname)(path13), { recursive: true });
|
|
27876
|
+
const tmp = `${path13}.tmp.${process.pid}.${Date.now()}`;
|
|
27776
27877
|
(0, import_node_fs2.writeFileSync)(tmp, JSON.stringify(value, null, 2), "utf-8");
|
|
27777
|
-
(0, import_node_fs2.renameSync)(tmp,
|
|
27878
|
+
(0, import_node_fs2.renameSync)(tmp, path13);
|
|
27778
27879
|
}
|
|
27779
27880
|
var RadarState = class {
|
|
27780
27881
|
constructor(projectRoot) {
|
|
@@ -27907,9 +28008,9 @@ var RadarState = class {
|
|
|
27907
28008
|
});
|
|
27908
28009
|
}
|
|
27909
28010
|
/** Persist the local path of a successfully-prefetched screenshot. */
|
|
27910
|
-
setScreenshotLocalPath(id,
|
|
28011
|
+
setScreenshotLocalPath(id, path13) {
|
|
27911
28012
|
return this.mutate(id, (p) => {
|
|
27912
|
-
p.context.screenshotLocalPath =
|
|
28013
|
+
p.context.screenshotLocalPath = path13;
|
|
27913
28014
|
});
|
|
27914
28015
|
}
|
|
27915
28016
|
/**
|
|
@@ -28333,16 +28434,16 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28333
28434
|
const tun = this.tunnel;
|
|
28334
28435
|
this.tunnel = null;
|
|
28335
28436
|
if (!tun) return;
|
|
28336
|
-
return new Promise((
|
|
28437
|
+
return new Promise((resolve6) => {
|
|
28337
28438
|
tun.once("exit", () => {
|
|
28338
28439
|
this.emit("stopped");
|
|
28339
|
-
|
|
28440
|
+
resolve6();
|
|
28340
28441
|
});
|
|
28341
28442
|
try {
|
|
28342
28443
|
tun.stop();
|
|
28343
28444
|
} catch {
|
|
28344
28445
|
}
|
|
28345
|
-
setTimeout(() =>
|
|
28446
|
+
setTimeout(() => resolve6(), 6e3);
|
|
28346
28447
|
});
|
|
28347
28448
|
}
|
|
28348
28449
|
spawnOnce() {
|
|
@@ -28996,10 +29097,10 @@ function streamTranscript(opts) {
|
|
|
28996
29097
|
}
|
|
28997
29098
|
|
|
28998
29099
|
// src/server/graph-mcp.ts
|
|
28999
|
-
var
|
|
29000
|
-
var
|
|
29100
|
+
var import_node_fs28 = require("node:fs");
|
|
29101
|
+
var import_node_path33 = require("node:path");
|
|
29001
29102
|
var import_node_child_process3 = require("node:child_process");
|
|
29002
|
-
var
|
|
29103
|
+
var import_node_os6 = require("node:os");
|
|
29003
29104
|
init_launch_kit_paths();
|
|
29004
29105
|
init_graph();
|
|
29005
29106
|
|
|
@@ -29742,6 +29843,7 @@ function generate(rootDir) {
|
|
|
29742
29843
|
responses: deep.responses,
|
|
29743
29844
|
params: deep.params,
|
|
29744
29845
|
...deep.effects ? { effects: deep.effects } : {},
|
|
29846
|
+
...deep.notes ? { notes: deep.notes } : {},
|
|
29745
29847
|
_dbCalls: dbCalls
|
|
29746
29848
|
// temp: used for cross-ref building below
|
|
29747
29849
|
});
|
|
@@ -29762,6 +29864,8 @@ function generate(rootDir) {
|
|
|
29762
29864
|
conditions: deep.conditions,
|
|
29763
29865
|
variables: deep.variables,
|
|
29764
29866
|
...deep.effects ? { effects: deep.effects } : {},
|
|
29867
|
+
...deep.ui_labels ? { ui_labels: deep.ui_labels } : {},
|
|
29868
|
+
...deep.notes ? { notes: deep.notes } : {},
|
|
29765
29869
|
...authWrappers.length > 0 ? { auth: authWrappers } : {},
|
|
29766
29870
|
...dbCalls.length > 0 ? { _dbCalls: dbCalls } : {}
|
|
29767
29871
|
});
|
|
@@ -30363,6 +30467,7 @@ var prismaSchemaParser = {
|
|
|
30363
30467
|
// src/server/graph/parsers/db/sql-migrations.ts
|
|
30364
30468
|
var import_node_fs18 = require("node:fs");
|
|
30365
30469
|
var import_node_path19 = require("node:path");
|
|
30470
|
+
var import_pgsql_parser = require("pgsql-parser");
|
|
30366
30471
|
init_config();
|
|
30367
30472
|
var PG_TO_PRISMA = {
|
|
30368
30473
|
"TEXT": "String",
|
|
@@ -30394,243 +30499,6 @@ function pgTypeToPrisma(pgType) {
|
|
|
30394
30499
|
const upper = pgType.toUpperCase().trim();
|
|
30395
30500
|
return PG_TO_PRISMA[upper] ?? upper;
|
|
30396
30501
|
}
|
|
30397
|
-
var ID = `(?:"[\\w$]+"|[\\w$]+)`;
|
|
30398
|
-
var QID = `(?:${ID}\\.)?${ID}`;
|
|
30399
|
-
function bareName(captured) {
|
|
30400
|
-
const parts = captured.split(".");
|
|
30401
|
-
const last = parts[parts.length - 1];
|
|
30402
|
-
return last.replace(/^"(.*)"$/, "$1").trim();
|
|
30403
|
-
}
|
|
30404
|
-
function parseCreateTable(sql, state) {
|
|
30405
|
-
const re = new RegExp(
|
|
30406
|
-
`CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s*\\(([\\s\\S]*?)\\);`,
|
|
30407
|
-
"gi"
|
|
30408
|
-
);
|
|
30409
|
-
let m;
|
|
30410
|
-
while ((m = re.exec(sql)) !== null) {
|
|
30411
|
-
const tableName = bareName(m[1]);
|
|
30412
|
-
const body = m[2];
|
|
30413
|
-
const columns = /* @__PURE__ */ new Map();
|
|
30414
|
-
let primaryCol = null;
|
|
30415
|
-
const inlineFks = [];
|
|
30416
|
-
const lines = splitTopLevelCommas(body);
|
|
30417
|
-
for (const raw of lines) {
|
|
30418
|
-
const trimmed = raw.trim().replace(/,\s*$/, "");
|
|
30419
|
-
if (!trimmed || trimmed.startsWith("--")) continue;
|
|
30420
|
-
const namedPk = trimmed.match(new RegExp(`^CONSTRAINT\\s+${ID}\\s+PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
30421
|
-
if (namedPk) {
|
|
30422
|
-
primaryCol = bareName(namedPk[1]);
|
|
30423
|
-
continue;
|
|
30424
|
-
}
|
|
30425
|
-
const tablePk = trimmed.match(new RegExp(`^PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
30426
|
-
if (tablePk) {
|
|
30427
|
-
primaryCol = bareName(tablePk[1]);
|
|
30428
|
-
continue;
|
|
30429
|
-
}
|
|
30430
|
-
if (/^UNIQUE\s*\(/i.test(trimmed)) continue;
|
|
30431
|
-
const namedFk = trimmed.match(new RegExp(
|
|
30432
|
-
`^CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
30433
|
-
"i"
|
|
30434
|
-
));
|
|
30435
|
-
if (namedFk) {
|
|
30436
|
-
inlineFks.push({
|
|
30437
|
-
constraintName: bareName(namedFk[1]),
|
|
30438
|
-
sourceTable: tableName,
|
|
30439
|
-
sourceColumn: bareName(namedFk[2]),
|
|
30440
|
-
targetTable: bareName(namedFk[3]),
|
|
30441
|
-
targetColumn: bareName(namedFk[4]),
|
|
30442
|
-
onDelete: namedFk[5] ?? null
|
|
30443
|
-
});
|
|
30444
|
-
continue;
|
|
30445
|
-
}
|
|
30446
|
-
const bareFk = trimmed.match(new RegExp(
|
|
30447
|
-
`^FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
30448
|
-
"i"
|
|
30449
|
-
));
|
|
30450
|
-
if (bareFk) {
|
|
30451
|
-
inlineFks.push({
|
|
30452
|
-
constraintName: `${tableName}_${bareName(bareFk[1])}_fkey`,
|
|
30453
|
-
sourceTable: tableName,
|
|
30454
|
-
sourceColumn: bareName(bareFk[1]),
|
|
30455
|
-
targetTable: bareName(bareFk[2]),
|
|
30456
|
-
targetColumn: bareName(bareFk[3]),
|
|
30457
|
-
onDelete: bareFk[4] ?? null
|
|
30458
|
-
});
|
|
30459
|
-
continue;
|
|
30460
|
-
}
|
|
30461
|
-
if (/^CONSTRAINT\s/i.test(trimmed)) continue;
|
|
30462
|
-
const colMatch = trimmed.match(new RegExp(`^(${ID})\\s+(.+)`, "i"));
|
|
30463
|
-
if (!colMatch) continue;
|
|
30464
|
-
const colName = bareName(colMatch[1]);
|
|
30465
|
-
let rest = colMatch[2];
|
|
30466
|
-
const inlineRefMatch = rest.match(new RegExp(
|
|
30467
|
-
`\\bREFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
30468
|
-
"i"
|
|
30469
|
-
));
|
|
30470
|
-
if (inlineRefMatch) {
|
|
30471
|
-
inlineFks.push({
|
|
30472
|
-
constraintName: `${tableName}_${colName}_fkey`,
|
|
30473
|
-
sourceTable: tableName,
|
|
30474
|
-
sourceColumn: colName,
|
|
30475
|
-
targetTable: bareName(inlineRefMatch[1]),
|
|
30476
|
-
targetColumn: bareName(inlineRefMatch[2]),
|
|
30477
|
-
onDelete: inlineRefMatch[3] ?? null
|
|
30478
|
-
});
|
|
30479
|
-
rest = rest.replace(inlineRefMatch[0], "").trim();
|
|
30480
|
-
}
|
|
30481
|
-
const isNotNull = /\bNOT\s+NULL\b/i.test(rest);
|
|
30482
|
-
const isPrimaryKey = /\bPRIMARY\s+KEY\b/i.test(rest);
|
|
30483
|
-
const isUnique = /\bUNIQUE\b/i.test(rest);
|
|
30484
|
-
const defaultMatch = rest.match(/\bDEFAULT\s+(.+?)(?:\s*,?\s*$)/i);
|
|
30485
|
-
const defaultVal = defaultMatch ? defaultMatch[1].trim() : null;
|
|
30486
|
-
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bPRIMARY\s+KEY\b/gi, "").replace(/\bUNIQUE\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
30487
|
-
columns.set(colName, {
|
|
30488
|
-
name: colName,
|
|
30489
|
-
type: colType,
|
|
30490
|
-
nullable: !isNotNull && !isPrimaryKey,
|
|
30491
|
-
primary: isPrimaryKey,
|
|
30492
|
-
unique: isUnique,
|
|
30493
|
-
default: defaultVal
|
|
30494
|
-
});
|
|
30495
|
-
if (isPrimaryKey) primaryCol = colName;
|
|
30496
|
-
}
|
|
30497
|
-
if (primaryCol && columns.has(primaryCol)) {
|
|
30498
|
-
columns.get(primaryCol).primary = true;
|
|
30499
|
-
}
|
|
30500
|
-
state.tables.set(tableName, { name: tableName, columns });
|
|
30501
|
-
state.fks.push(...inlineFks);
|
|
30502
|
-
}
|
|
30503
|
-
}
|
|
30504
|
-
function splitTopLevelCommas(body) {
|
|
30505
|
-
const out = [];
|
|
30506
|
-
let depth = 0;
|
|
30507
|
-
let buf = "";
|
|
30508
|
-
let inString = null;
|
|
30509
|
-
for (const ch of body) {
|
|
30510
|
-
if (inString) {
|
|
30511
|
-
buf += ch;
|
|
30512
|
-
if (ch === inString) inString = null;
|
|
30513
|
-
continue;
|
|
30514
|
-
}
|
|
30515
|
-
if (ch === "'" || ch === '"') {
|
|
30516
|
-
inString = ch;
|
|
30517
|
-
buf += ch;
|
|
30518
|
-
continue;
|
|
30519
|
-
}
|
|
30520
|
-
if (ch === "(") depth++;
|
|
30521
|
-
else if (ch === ")") depth--;
|
|
30522
|
-
if (ch === "," && depth === 0) {
|
|
30523
|
-
out.push(buf);
|
|
30524
|
-
buf = "";
|
|
30525
|
-
continue;
|
|
30526
|
-
}
|
|
30527
|
-
buf += ch;
|
|
30528
|
-
}
|
|
30529
|
-
if (buf.trim()) out.push(buf);
|
|
30530
|
-
return out;
|
|
30531
|
-
}
|
|
30532
|
-
function parseCreateEnum(sql, state) {
|
|
30533
|
-
const re = new RegExp(
|
|
30534
|
-
`CREATE\\s+TYPE\\s+(${QID})\\s+AS\\s+ENUM\\s*\\(([^)]+)\\)`,
|
|
30535
|
-
"gi"
|
|
30536
|
-
);
|
|
30537
|
-
let m;
|
|
30538
|
-
while ((m = re.exec(sql)) !== null) {
|
|
30539
|
-
const enumName = bareName(m[1]);
|
|
30540
|
-
const valuesStr = m[2];
|
|
30541
|
-
const values = new Set(
|
|
30542
|
-
valuesStr.split(",").map((v) => v.trim().replace(/^'(.*)'$/, "$1")).filter(Boolean)
|
|
30543
|
-
);
|
|
30544
|
-
state.enums.set(enumName, { name: enumName, values });
|
|
30545
|
-
}
|
|
30546
|
-
}
|
|
30547
|
-
function parseAlterTable(sql, state) {
|
|
30548
|
-
const addColRe = new RegExp(
|
|
30549
|
-
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+COLUMN\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s+(.+?);`,
|
|
30550
|
-
"gi"
|
|
30551
|
-
);
|
|
30552
|
-
let m;
|
|
30553
|
-
while ((m = addColRe.exec(sql)) !== null) {
|
|
30554
|
-
const tableName = bareName(m[1]);
|
|
30555
|
-
const colName = bareName(m[2]);
|
|
30556
|
-
let rest = m[3];
|
|
30557
|
-
const table = state.tables.get(tableName);
|
|
30558
|
-
if (!table) continue;
|
|
30559
|
-
const isNotNull = /\bNOT\s+NULL\b/i.test(rest);
|
|
30560
|
-
const defaultMatch = rest.match(/\bDEFAULT\s+(.+?)$/i);
|
|
30561
|
-
const defaultVal = defaultMatch ? defaultMatch[1].trim() : null;
|
|
30562
|
-
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim();
|
|
30563
|
-
table.columns.set(colName, {
|
|
30564
|
-
name: colName,
|
|
30565
|
-
type: colType,
|
|
30566
|
-
nullable: !isNotNull,
|
|
30567
|
-
primary: false,
|
|
30568
|
-
unique: false,
|
|
30569
|
-
default: defaultVal
|
|
30570
|
-
});
|
|
30571
|
-
}
|
|
30572
|
-
const dropColRe = new RegExp(
|
|
30573
|
-
`ALTER\\s+TABLE\\s+(${QID})\\s+DROP\\s+COLUMN\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
30574
|
-
"gi"
|
|
30575
|
-
);
|
|
30576
|
-
while ((m = dropColRe.exec(sql)) !== null) {
|
|
30577
|
-
const table = state.tables.get(bareName(m[1]));
|
|
30578
|
-
if (table) table.columns.delete(bareName(m[2]));
|
|
30579
|
-
}
|
|
30580
|
-
const fkRe = new RegExp(
|
|
30581
|
-
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
30582
|
-
"gi"
|
|
30583
|
-
);
|
|
30584
|
-
while ((m = fkRe.exec(sql)) !== null) {
|
|
30585
|
-
state.fks.push({
|
|
30586
|
-
constraintName: bareName(m[2]),
|
|
30587
|
-
sourceTable: bareName(m[1]),
|
|
30588
|
-
sourceColumn: bareName(m[3]),
|
|
30589
|
-
targetTable: bareName(m[4]),
|
|
30590
|
-
targetColumn: bareName(m[5]),
|
|
30591
|
-
onDelete: m[6] ?? null
|
|
30592
|
-
});
|
|
30593
|
-
}
|
|
30594
|
-
}
|
|
30595
|
-
function parseAlterEnum(sql, state) {
|
|
30596
|
-
const re = new RegExp(
|
|
30597
|
-
`ALTER\\s+TYPE\\s+(${QID})\\s+ADD\\s+VALUE\\s+'([^']+)'`,
|
|
30598
|
-
"gi"
|
|
30599
|
-
);
|
|
30600
|
-
let m;
|
|
30601
|
-
while ((m = re.exec(sql)) !== null) {
|
|
30602
|
-
const en = state.enums.get(bareName(m[1]));
|
|
30603
|
-
if (en) en.values.add(m[2]);
|
|
30604
|
-
}
|
|
30605
|
-
}
|
|
30606
|
-
function parseDropTable(sql, state) {
|
|
30607
|
-
const re = new RegExp(
|
|
30608
|
-
`DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
30609
|
-
"gi"
|
|
30610
|
-
);
|
|
30611
|
-
let m;
|
|
30612
|
-
while ((m = re.exec(sql)) !== null) {
|
|
30613
|
-
const dropped = bareName(m[1]);
|
|
30614
|
-
state.tables.delete(dropped);
|
|
30615
|
-
state.fks = state.fks.filter((fk) => fk.sourceTable !== dropped && fk.targetTable !== dropped);
|
|
30616
|
-
}
|
|
30617
|
-
}
|
|
30618
|
-
function parseUniqueIndex(sql, state) {
|
|
30619
|
-
const re = new RegExp(
|
|
30620
|
-
`CREATE\\s+UNIQUE\\s+INDEX\\s+(?:(?:IF\\s+NOT\\s+EXISTS\\s+)?(?:${ID}\\s+)?)?ON\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)`,
|
|
30621
|
-
"gi"
|
|
30622
|
-
);
|
|
30623
|
-
let m;
|
|
30624
|
-
while ((m = re.exec(sql)) !== null) {
|
|
30625
|
-
const tableName = bareName(m[1]);
|
|
30626
|
-
const colName = bareName(m[2]);
|
|
30627
|
-
const table = state.tables.get(tableName);
|
|
30628
|
-
const col = table?.columns.get(colName);
|
|
30629
|
-
if (col) col.unique = true;
|
|
30630
|
-
if (!state.uniqueIndexes.has(tableName)) state.uniqueIndexes.set(tableName, /* @__PURE__ */ new Set());
|
|
30631
|
-
state.uniqueIndexes.get(tableName).add(colName);
|
|
30632
|
-
}
|
|
30633
|
-
}
|
|
30634
30502
|
function discoverMigrationFiles(migrationsDir) {
|
|
30635
30503
|
if (!(0, import_node_fs18.existsSync)(migrationsDir)) return [];
|
|
30636
30504
|
const out = [];
|
|
@@ -30645,25 +30513,614 @@ function discoverMigrationFiles(migrationsDir) {
|
|
|
30645
30513
|
}
|
|
30646
30514
|
return out;
|
|
30647
30515
|
}
|
|
30648
|
-
|
|
30516
|
+
var postgresDialect = {
|
|
30517
|
+
parse(sql) {
|
|
30518
|
+
return (0, import_pgsql_parser.parseSync)(sql);
|
|
30519
|
+
},
|
|
30520
|
+
applyAll(ast, state, filepath) {
|
|
30521
|
+
const stmts = ast.stmts ?? [];
|
|
30522
|
+
extractTablesFromStmts(stmts, state);
|
|
30523
|
+
extractEnumsFromStmts(stmts, state);
|
|
30524
|
+
extractIndexesFromStmts(stmts, state, filepath);
|
|
30525
|
+
extractPoliciesFromStmts(stmts, state, filepath);
|
|
30526
|
+
extractExtensionsFromStmts(stmts, state, filepath);
|
|
30527
|
+
extractTriggersFromStmts(stmts, state, filepath);
|
|
30528
|
+
extractFunctionsFromStmts(stmts, state, filepath);
|
|
30529
|
+
extractViewsFromStmts(stmts, state, filepath);
|
|
30530
|
+
applyDropIndexes(stmts, state);
|
|
30531
|
+
applyDropPolicies(stmts, state);
|
|
30532
|
+
applyDropsForSchemaObjects(stmts, state);
|
|
30533
|
+
applyAstAlterEnums(stmts, state);
|
|
30534
|
+
applyAstAlterations(stmts, state);
|
|
30535
|
+
},
|
|
30536
|
+
extractMigrationInfo(ast, name, filepath) {
|
|
30537
|
+
const stmts = ast.stmts ?? [];
|
|
30538
|
+
return extractMigrationInfoFromStmts(stmts, name, filepath);
|
|
30539
|
+
}
|
|
30540
|
+
};
|
|
30541
|
+
function parseMigrations(migrationsDir, dialect = postgresDialect) {
|
|
30649
30542
|
const state = {
|
|
30650
30543
|
tables: /* @__PURE__ */ new Map(),
|
|
30651
30544
|
enums: /* @__PURE__ */ new Map(),
|
|
30652
30545
|
fks: [],
|
|
30653
|
-
uniqueIndexes: /* @__PURE__ */ new Map()
|
|
30546
|
+
uniqueIndexes: /* @__PURE__ */ new Map(),
|
|
30547
|
+
indexes: [],
|
|
30548
|
+
policies: [],
|
|
30549
|
+
extensions: [],
|
|
30550
|
+
triggers: [],
|
|
30551
|
+
functions: [],
|
|
30552
|
+
views: []
|
|
30654
30553
|
};
|
|
30655
30554
|
if (!migrationsDir) return state;
|
|
30656
30555
|
for (const sqlPath of discoverMigrationFiles(migrationsDir)) {
|
|
30657
30556
|
const sql = (0, import_node_fs18.readFileSync)(sqlPath, "utf-8");
|
|
30658
|
-
|
|
30659
|
-
|
|
30660
|
-
|
|
30661
|
-
|
|
30662
|
-
|
|
30663
|
-
|
|
30557
|
+
let ast;
|
|
30558
|
+
try {
|
|
30559
|
+
ast = dialect.parse(sql);
|
|
30560
|
+
} catch {
|
|
30561
|
+
continue;
|
|
30562
|
+
}
|
|
30563
|
+
dialect.applyAll(ast, state, sqlPath);
|
|
30664
30564
|
}
|
|
30665
30565
|
return state;
|
|
30666
30566
|
}
|
|
30567
|
+
function extractIndexesFromStmts(stmts, state, filepath) {
|
|
30568
|
+
for (const wrap of stmts) {
|
|
30569
|
+
const stmt = wrap.stmt ?? {};
|
|
30570
|
+
const ix = stmt.IndexStmt;
|
|
30571
|
+
if (!ix) continue;
|
|
30572
|
+
const name = ix.idxname ?? "";
|
|
30573
|
+
if (!name) continue;
|
|
30574
|
+
const table = ix.relation?.relname ?? "";
|
|
30575
|
+
const unique = !!ix.unique;
|
|
30576
|
+
const method = String(ix.accessMethod ?? "btree").toLowerCase();
|
|
30577
|
+
const params = ix.indexParams ?? [];
|
|
30578
|
+
const columns = [];
|
|
30579
|
+
let hasExpressions = false;
|
|
30580
|
+
for (const p of params) {
|
|
30581
|
+
const elem = p.IndexElem;
|
|
30582
|
+
if (!elem) continue;
|
|
30583
|
+
if (elem.name) columns.push(elem.name);
|
|
30584
|
+
else if (elem.expr) hasExpressions = true;
|
|
30585
|
+
}
|
|
30586
|
+
const hasPredicate = !!ix.whereClause;
|
|
30587
|
+
const existing = state.indexes.findIndex((i) => i.name === name);
|
|
30588
|
+
const next = { name, table, unique, method, columns, hasExpressions, hasPredicate, filepath };
|
|
30589
|
+
if (existing >= 0) state.indexes[existing] = next;
|
|
30590
|
+
else state.indexes.push(next);
|
|
30591
|
+
if (unique && columns.length === 1 && !hasPredicate && !hasExpressions) {
|
|
30592
|
+
const t = state.tables.get(table);
|
|
30593
|
+
const col = t?.columns.get(columns[0]);
|
|
30594
|
+
if (col) col.unique = true;
|
|
30595
|
+
if (!state.uniqueIndexes.has(table)) state.uniqueIndexes.set(table, /* @__PURE__ */ new Set());
|
|
30596
|
+
state.uniqueIndexes.get(table).add(columns[0]);
|
|
30597
|
+
}
|
|
30598
|
+
}
|
|
30599
|
+
}
|
|
30600
|
+
function applyDropIndexes(stmts, state) {
|
|
30601
|
+
for (const wrap of stmts) {
|
|
30602
|
+
const drop = wrap.stmt?.DropStmt;
|
|
30603
|
+
if (!drop || drop.removeType !== "OBJECT_INDEX") continue;
|
|
30604
|
+
const objects = drop.objects ?? [];
|
|
30605
|
+
const droppedNames = /* @__PURE__ */ new Set();
|
|
30606
|
+
for (const obj of objects) {
|
|
30607
|
+
const items = obj.List?.items ?? [];
|
|
30608
|
+
const last = items[items.length - 1]?.String?.sval;
|
|
30609
|
+
if (last) droppedNames.add(last);
|
|
30610
|
+
}
|
|
30611
|
+
if (droppedNames.size > 0) {
|
|
30612
|
+
state.indexes = state.indexes.filter((i) => !droppedNames.has(i.name));
|
|
30613
|
+
}
|
|
30614
|
+
}
|
|
30615
|
+
}
|
|
30616
|
+
function formatPgTypeName(typeName) {
|
|
30617
|
+
const names = (typeName?.names ?? []).map((n) => n.String?.sval ?? "").filter(Boolean);
|
|
30618
|
+
const base = (names[names.length - 1] ?? "").toLowerCase();
|
|
30619
|
+
const PG_INTERNAL_MAP = {
|
|
30620
|
+
int4: "INTEGER",
|
|
30621
|
+
int8: "BIGINT",
|
|
30622
|
+
int2: "SMALLINT",
|
|
30623
|
+
float8: "DOUBLE PRECISION",
|
|
30624
|
+
float4: "REAL",
|
|
30625
|
+
bool: "BOOLEAN",
|
|
30626
|
+
bpchar: "CHAR",
|
|
30627
|
+
timestamptz: "TIMESTAMPTZ",
|
|
30628
|
+
timestamp: "TIMESTAMP",
|
|
30629
|
+
numeric: "NUMERIC",
|
|
30630
|
+
text: "TEXT",
|
|
30631
|
+
varchar: "VARCHAR",
|
|
30632
|
+
jsonb: "JSONB",
|
|
30633
|
+
json: "JSON",
|
|
30634
|
+
uuid: "UUID",
|
|
30635
|
+
date: "DATE",
|
|
30636
|
+
bytea: "BYTEA"
|
|
30637
|
+
};
|
|
30638
|
+
return PG_INTERNAL_MAP[base] ?? base.toUpperCase();
|
|
30639
|
+
}
|
|
30640
|
+
function applyAstAlterations(stmts, state) {
|
|
30641
|
+
for (const wrap of stmts) {
|
|
30642
|
+
const stmt = wrap.stmt ?? {};
|
|
30643
|
+
const kind = Object.keys(stmt)[0];
|
|
30644
|
+
if (!kind) continue;
|
|
30645
|
+
if (kind === "AlterTableStmt") {
|
|
30646
|
+
const body = stmt.AlterTableStmt;
|
|
30647
|
+
const tableName = body.relation?.relname ?? "";
|
|
30648
|
+
const table = state.tables.get(tableName);
|
|
30649
|
+
if (!table) continue;
|
|
30650
|
+
const cmds = body.cmds ?? [];
|
|
30651
|
+
for (const c of cmds) {
|
|
30652
|
+
const cmd = c.AlterTableCmd;
|
|
30653
|
+
if (!cmd) continue;
|
|
30654
|
+
const subtype = cmd.subtype ?? "";
|
|
30655
|
+
const colName = cmd.name ?? "";
|
|
30656
|
+
const col = colName ? table.columns.get(colName) : void 0;
|
|
30657
|
+
switch (subtype) {
|
|
30658
|
+
case "AT_AlterColumnType": {
|
|
30659
|
+
if (!col) break;
|
|
30660
|
+
const typeName = cmd.def?.ColumnDef?.typeName ?? cmd.def?.typeName;
|
|
30661
|
+
if (typeName) col.type = formatPgTypeNameWithMods(typeName);
|
|
30662
|
+
break;
|
|
30663
|
+
}
|
|
30664
|
+
case "AT_SetNotNull":
|
|
30665
|
+
if (col) col.nullable = false;
|
|
30666
|
+
break;
|
|
30667
|
+
case "AT_DropNotNull":
|
|
30668
|
+
if (col) col.nullable = true;
|
|
30669
|
+
break;
|
|
30670
|
+
case "AT_AddColumn": {
|
|
30671
|
+
const cd = cmd.def?.ColumnDef;
|
|
30672
|
+
if (!cd) break;
|
|
30673
|
+
const newColName = cd.colname ?? "";
|
|
30674
|
+
if (!newColName) break;
|
|
30675
|
+
if (table.columns.has(newColName)) break;
|
|
30676
|
+
let nullable = true;
|
|
30677
|
+
let primary = false;
|
|
30678
|
+
let unique = false;
|
|
30679
|
+
let defaultVal = null;
|
|
30680
|
+
for (const c2 of cd.constraints ?? []) {
|
|
30681
|
+
const ct = c2.Constraint;
|
|
30682
|
+
if (!ct) continue;
|
|
30683
|
+
if (ct.contype === "CONSTR_NOTNULL") nullable = false;
|
|
30684
|
+
else if (ct.contype === "CONSTR_PRIMARY") {
|
|
30685
|
+
primary = true;
|
|
30686
|
+
nullable = false;
|
|
30687
|
+
} else if (ct.contype === "CONSTR_UNIQUE") unique = true;
|
|
30688
|
+
else if (ct.contype === "CONSTR_DEFAULT") defaultVal = "<expr>";
|
|
30689
|
+
}
|
|
30690
|
+
table.columns.set(newColName, {
|
|
30691
|
+
name: newColName,
|
|
30692
|
+
type: formatPgTypeNameWithMods(cd.typeName),
|
|
30693
|
+
nullable,
|
|
30694
|
+
primary,
|
|
30695
|
+
unique,
|
|
30696
|
+
default: defaultVal
|
|
30697
|
+
});
|
|
30698
|
+
break;
|
|
30699
|
+
}
|
|
30700
|
+
case "AT_DropColumn":
|
|
30701
|
+
if (colName) table.columns.delete(colName);
|
|
30702
|
+
break;
|
|
30703
|
+
case "AT_AddConstraint": {
|
|
30704
|
+
const ct = cmd.def?.Constraint;
|
|
30705
|
+
if (!ct) break;
|
|
30706
|
+
if (ct.contype !== "CONSTR_FOREIGN") break;
|
|
30707
|
+
const fkCols = (ct.fk_attrs ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30708
|
+
const pkCols = (ct.pk_attrs ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30709
|
+
const pkTable = ct.pktable?.relname ?? "";
|
|
30710
|
+
if (fkCols.length && pkCols.length && pkTable) {
|
|
30711
|
+
state.fks.push({
|
|
30712
|
+
constraintName: ct.conname || `${tableName}_${fkCols[0]}_fkey`,
|
|
30713
|
+
sourceTable: tableName,
|
|
30714
|
+
sourceColumn: fkCols[0],
|
|
30715
|
+
targetTable: pkTable,
|
|
30716
|
+
targetColumn: pkCols[0],
|
|
30717
|
+
onDelete: mapFkAction(ct.fk_del_action)
|
|
30718
|
+
});
|
|
30719
|
+
}
|
|
30720
|
+
break;
|
|
30721
|
+
}
|
|
30722
|
+
}
|
|
30723
|
+
}
|
|
30724
|
+
} else if (kind === "RenameStmt") {
|
|
30725
|
+
const body = stmt.RenameStmt;
|
|
30726
|
+
const renameType = body.renameType ?? "";
|
|
30727
|
+
const newName = body.newname ?? "";
|
|
30728
|
+
if (renameType === "OBJECT_COLUMN") {
|
|
30729
|
+
const tableName = body.relation?.relname ?? "";
|
|
30730
|
+
const oldName = body.subname ?? "";
|
|
30731
|
+
const table = state.tables.get(tableName);
|
|
30732
|
+
if (!table || !oldName || !newName) continue;
|
|
30733
|
+
const col = table.columns.get(oldName);
|
|
30734
|
+
if (col) {
|
|
30735
|
+
col.name = newName;
|
|
30736
|
+
table.columns.delete(oldName);
|
|
30737
|
+
table.columns.set(newName, col);
|
|
30738
|
+
}
|
|
30739
|
+
} else if (renameType === "OBJECT_TABLE") {
|
|
30740
|
+
const oldName = body.relation?.relname ?? "";
|
|
30741
|
+
if (!oldName || !newName) continue;
|
|
30742
|
+
const t = state.tables.get(oldName);
|
|
30743
|
+
if (!t) continue;
|
|
30744
|
+
state.tables.delete(oldName);
|
|
30745
|
+
t.name = newName;
|
|
30746
|
+
state.tables.set(newName, t);
|
|
30747
|
+
for (const fk of state.fks) {
|
|
30748
|
+
if (fk.sourceTable === oldName) fk.sourceTable = newName;
|
|
30749
|
+
if (fk.targetTable === oldName) fk.targetTable = newName;
|
|
30750
|
+
}
|
|
30751
|
+
}
|
|
30752
|
+
}
|
|
30753
|
+
}
|
|
30754
|
+
}
|
|
30755
|
+
function extractPoliciesFromStmts(stmts, state, filepath) {
|
|
30756
|
+
for (const wrap of stmts) {
|
|
30757
|
+
const body = wrap.stmt?.CreatePolicyStmt;
|
|
30758
|
+
if (!body) continue;
|
|
30759
|
+
const name = body.policy_name ?? "";
|
|
30760
|
+
if (!name) continue;
|
|
30761
|
+
const table = body.table?.relname ?? "";
|
|
30762
|
+
const cmdRaw = String(body.cmd_name ?? "all").toUpperCase();
|
|
30763
|
+
const command = ["SELECT", "INSERT", "UPDATE", "DELETE", "ALL"].includes(cmdRaw) ? cmdRaw : "ALL";
|
|
30764
|
+
const permissive = body.permissive === true;
|
|
30765
|
+
const roles = (body.roles ?? []).map((r) => {
|
|
30766
|
+
const rs = r.RoleSpec;
|
|
30767
|
+
if (!rs) return "";
|
|
30768
|
+
if (rs.roletype === "ROLESPEC_PUBLIC") return "public";
|
|
30769
|
+
if (rs.roletype === "ROLESPEC_CURRENT_USER") return "current_user";
|
|
30770
|
+
if (rs.roletype === "ROLESPEC_CSTRING" && rs.rolename) return rs.rolename;
|
|
30771
|
+
return "";
|
|
30772
|
+
}).filter(Boolean);
|
|
30773
|
+
const hasUsing = !!body.qual;
|
|
30774
|
+
const hasWithCheck = !!body.with_check;
|
|
30775
|
+
const existing = state.policies.findIndex((p) => p.table === table && p.name === name);
|
|
30776
|
+
const next = { name, table, command, permissive, roles, hasUsing, hasWithCheck, filepath };
|
|
30777
|
+
if (existing >= 0) state.policies[existing] = next;
|
|
30778
|
+
else state.policies.push(next);
|
|
30779
|
+
}
|
|
30780
|
+
}
|
|
30781
|
+
function applyDropPolicies(stmts, state) {
|
|
30782
|
+
for (const wrap of stmts) {
|
|
30783
|
+
const drop = wrap.stmt?.DropStmt;
|
|
30784
|
+
if (!drop || drop.removeType !== "OBJECT_POLICY") continue;
|
|
30785
|
+
const objects = drop.objects ?? [];
|
|
30786
|
+
for (const obj of objects) {
|
|
30787
|
+
const items = obj.List?.items ?? [];
|
|
30788
|
+
if (items.length < 2) continue;
|
|
30789
|
+
const table = items[0]?.String?.sval ?? "";
|
|
30790
|
+
const policyName = items[items.length - 1]?.String?.sval ?? "";
|
|
30791
|
+
if (!table || !policyName) continue;
|
|
30792
|
+
state.policies = state.policies.filter((p) => !(p.table === table && p.name === policyName));
|
|
30793
|
+
}
|
|
30794
|
+
}
|
|
30795
|
+
}
|
|
30796
|
+
function mapFkAction(action) {
|
|
30797
|
+
if (!action) return null;
|
|
30798
|
+
const m = {
|
|
30799
|
+
r: "RESTRICT",
|
|
30800
|
+
c: "CASCADE",
|
|
30801
|
+
s: "SET NULL",
|
|
30802
|
+
d: "SET DEFAULT",
|
|
30803
|
+
a: "NO ACTION",
|
|
30804
|
+
// pgsql-parser may also emit FKCONSTR_ACTION_* enum strings:
|
|
30805
|
+
FKCONSTR_ACTION_RESTRICT: "RESTRICT",
|
|
30806
|
+
FKCONSTR_ACTION_CASCADE: "CASCADE",
|
|
30807
|
+
FKCONSTR_ACTION_SETNULL: "SET NULL",
|
|
30808
|
+
FKCONSTR_ACTION_SETDEFAULT: "SET DEFAULT",
|
|
30809
|
+
FKCONSTR_ACTION_NOACTION: "NO ACTION"
|
|
30810
|
+
};
|
|
30811
|
+
return m[action] ?? null;
|
|
30812
|
+
}
|
|
30813
|
+
function formatPgTypeNameWithMods(typeName) {
|
|
30814
|
+
const base = formatPgTypeName(typeName);
|
|
30815
|
+
if (base === "String" || base === "unknown") return base;
|
|
30816
|
+
const typmods = [];
|
|
30817
|
+
for (const m of typeName?.typmods ?? []) {
|
|
30818
|
+
const v = m.A_Const?.ival?.ival;
|
|
30819
|
+
if (typeof v === "number") typmods.push(v);
|
|
30820
|
+
}
|
|
30821
|
+
return typmods.length ? `${base}(${typmods.join(",")})` : base;
|
|
30822
|
+
}
|
|
30823
|
+
function extractTablesFromStmts(stmts, state) {
|
|
30824
|
+
for (const wrap of stmts) {
|
|
30825
|
+
const body = wrap.stmt?.CreateStmt;
|
|
30826
|
+
if (!body) continue;
|
|
30827
|
+
const tableName = body.relation?.relname ?? "";
|
|
30828
|
+
if (!tableName) continue;
|
|
30829
|
+
const columns = /* @__PURE__ */ new Map();
|
|
30830
|
+
const fks = [];
|
|
30831
|
+
let primaryCol = null;
|
|
30832
|
+
for (const elt of body.tableElts ?? []) {
|
|
30833
|
+
if (elt.ColumnDef) {
|
|
30834
|
+
const cd = elt.ColumnDef;
|
|
30835
|
+
const colName = cd.colname ?? "";
|
|
30836
|
+
if (!colName) continue;
|
|
30837
|
+
const colType = formatPgTypeNameWithMods(cd.typeName);
|
|
30838
|
+
let nullable = true;
|
|
30839
|
+
let primary = false;
|
|
30840
|
+
let unique = false;
|
|
30841
|
+
let defaultVal = null;
|
|
30842
|
+
for (const c of cd.constraints ?? []) {
|
|
30843
|
+
const ct = c.Constraint;
|
|
30844
|
+
if (!ct) continue;
|
|
30845
|
+
switch (ct.contype) {
|
|
30846
|
+
case "CONSTR_NOTNULL":
|
|
30847
|
+
nullable = false;
|
|
30848
|
+
break;
|
|
30849
|
+
case "CONSTR_PRIMARY":
|
|
30850
|
+
primary = true;
|
|
30851
|
+
nullable = false;
|
|
30852
|
+
primaryCol = colName;
|
|
30853
|
+
break;
|
|
30854
|
+
case "CONSTR_UNIQUE":
|
|
30855
|
+
unique = true;
|
|
30856
|
+
break;
|
|
30857
|
+
case "CONSTR_DEFAULT":
|
|
30858
|
+
defaultVal = "<expr>";
|
|
30859
|
+
break;
|
|
30860
|
+
case "CONSTR_FOREIGN": {
|
|
30861
|
+
const pkTable = ct.pktable?.relname ?? "";
|
|
30862
|
+
const pkCols = (ct.pk_attrs ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30863
|
+
if (pkTable && pkCols.length) {
|
|
30864
|
+
fks.push({
|
|
30865
|
+
constraintName: ct.conname || `${tableName}_${colName}_fkey`,
|
|
30866
|
+
sourceTable: tableName,
|
|
30867
|
+
sourceColumn: colName,
|
|
30868
|
+
targetTable: pkTable,
|
|
30869
|
+
targetColumn: pkCols[0],
|
|
30870
|
+
onDelete: mapFkAction(ct.fk_del_action)
|
|
30871
|
+
});
|
|
30872
|
+
}
|
|
30873
|
+
break;
|
|
30874
|
+
}
|
|
30875
|
+
}
|
|
30876
|
+
}
|
|
30877
|
+
columns.set(colName, {
|
|
30878
|
+
name: colName,
|
|
30879
|
+
type: colType,
|
|
30880
|
+
nullable,
|
|
30881
|
+
primary,
|
|
30882
|
+
unique,
|
|
30883
|
+
default: defaultVal
|
|
30884
|
+
});
|
|
30885
|
+
} else if (elt.Constraint) {
|
|
30886
|
+
const ct = elt.Constraint;
|
|
30887
|
+
switch (ct.contype) {
|
|
30888
|
+
case "CONSTR_PRIMARY": {
|
|
30889
|
+
const keys = (ct.keys ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30890
|
+
if (keys.length) primaryCol = keys[0];
|
|
30891
|
+
break;
|
|
30892
|
+
}
|
|
30893
|
+
case "CONSTR_FOREIGN": {
|
|
30894
|
+
const fkCols = (ct.fk_attrs ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30895
|
+
const pkCols = (ct.pk_attrs ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30896
|
+
const pkTable = ct.pktable?.relname ?? "";
|
|
30897
|
+
if (fkCols.length && pkCols.length && pkTable) {
|
|
30898
|
+
fks.push({
|
|
30899
|
+
constraintName: ct.conname || `${tableName}_${fkCols[0]}_fkey`,
|
|
30900
|
+
sourceTable: tableName,
|
|
30901
|
+
sourceColumn: fkCols[0],
|
|
30902
|
+
targetTable: pkTable,
|
|
30903
|
+
targetColumn: pkCols[0],
|
|
30904
|
+
onDelete: mapFkAction(ct.fk_del_action)
|
|
30905
|
+
});
|
|
30906
|
+
}
|
|
30907
|
+
break;
|
|
30908
|
+
}
|
|
30909
|
+
}
|
|
30910
|
+
}
|
|
30911
|
+
}
|
|
30912
|
+
if (primaryCol && columns.has(primaryCol)) {
|
|
30913
|
+
columns.get(primaryCol).primary = true;
|
|
30914
|
+
columns.get(primaryCol).nullable = false;
|
|
30915
|
+
}
|
|
30916
|
+
state.tables.set(tableName, { name: tableName, columns });
|
|
30917
|
+
state.fks.push(...fks);
|
|
30918
|
+
}
|
|
30919
|
+
}
|
|
30920
|
+
function extractEnumsFromStmts(stmts, state) {
|
|
30921
|
+
for (const wrap of stmts) {
|
|
30922
|
+
const body = wrap.stmt?.CreateEnumStmt;
|
|
30923
|
+
if (!body) continue;
|
|
30924
|
+
const names = (body.typeName ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30925
|
+
const enumName = names[names.length - 1] ?? "";
|
|
30926
|
+
if (!enumName) continue;
|
|
30927
|
+
const vals = new Set(
|
|
30928
|
+
(body.vals ?? []).map((s) => s.String?.sval ?? "").filter(Boolean)
|
|
30929
|
+
);
|
|
30930
|
+
state.enums.set(enumName, { name: enumName, values: vals });
|
|
30931
|
+
}
|
|
30932
|
+
}
|
|
30933
|
+
function applyAstAlterEnums(stmts, state) {
|
|
30934
|
+
for (const wrap of stmts) {
|
|
30935
|
+
const body = wrap.stmt?.AlterEnumStmt;
|
|
30936
|
+
if (!body) continue;
|
|
30937
|
+
const names = (body.typeName ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
30938
|
+
const enumName = names[names.length - 1] ?? "";
|
|
30939
|
+
const en = state.enums.get(enumName);
|
|
30940
|
+
if (!en) continue;
|
|
30941
|
+
if (body.newVal) en.values.add(String(body.newVal));
|
|
30942
|
+
}
|
|
30943
|
+
}
|
|
30944
|
+
function extractExtensionsFromStmts(stmts, state, filepath) {
|
|
30945
|
+
for (const wrap of stmts) {
|
|
30946
|
+
const body = wrap.stmt?.CreateExtensionStmt;
|
|
30947
|
+
if (!body) continue;
|
|
30948
|
+
const name = body.extname ?? "";
|
|
30949
|
+
if (!name) continue;
|
|
30950
|
+
let schema = null;
|
|
30951
|
+
let version2 = null;
|
|
30952
|
+
for (const opt of body.options ?? []) {
|
|
30953
|
+
const de = opt.DefElem;
|
|
30954
|
+
if (!de) continue;
|
|
30955
|
+
if (de.defname === "schema" && de.arg?.String?.sval) schema = de.arg.String.sval;
|
|
30956
|
+
else if (de.defname === "new_version" && de.arg?.String?.sval) version2 = de.arg.String.sval;
|
|
30957
|
+
}
|
|
30958
|
+
const next = { name, schema, version: version2, filepath };
|
|
30959
|
+
const existing = state.extensions.findIndex((e) => e.name === name);
|
|
30960
|
+
if (existing >= 0) state.extensions[existing] = next;
|
|
30961
|
+
else state.extensions.push(next);
|
|
30962
|
+
}
|
|
30963
|
+
}
|
|
30964
|
+
function extractTriggersFromStmts(stmts, state, filepath) {
|
|
30965
|
+
for (const wrap of stmts) {
|
|
30966
|
+
const body = wrap.stmt?.CreateTrigStmt;
|
|
30967
|
+
if (!body) continue;
|
|
30968
|
+
const name = body.trigname ?? "";
|
|
30969
|
+
if (!name) continue;
|
|
30970
|
+
const table = body.relation?.relname ?? "";
|
|
30971
|
+
const timingVal = body.timing ?? 0;
|
|
30972
|
+
const eventsVal = body.events ?? 0;
|
|
30973
|
+
const timing = timingVal & 2 ? "BEFORE" : timingVal & 64 ? "INSTEAD OF" : "AFTER";
|
|
30974
|
+
const events = [];
|
|
30975
|
+
if (eventsVal & 4) events.push("INSERT");
|
|
30976
|
+
if (eventsVal & 8) events.push("DELETE");
|
|
30977
|
+
if (eventsVal & 16) events.push("UPDATE");
|
|
30978
|
+
if (eventsVal & 32) events.push("TRUNCATE");
|
|
30979
|
+
const funcname = body.funcname ?? [];
|
|
30980
|
+
const funcCall = funcname[funcname.length - 1]?.String?.sval ?? "";
|
|
30981
|
+
const forEach = body.row ? "ROW" : "STATEMENT";
|
|
30982
|
+
const hasWhen = !!body.whenClause;
|
|
30983
|
+
const next = { name, table, timing, events, function: funcCall, hasWhen, forEach, filepath };
|
|
30984
|
+
const existing = state.triggers.findIndex((t) => t.table === table && t.name === name);
|
|
30985
|
+
if (existing >= 0) state.triggers[existing] = next;
|
|
30986
|
+
else state.triggers.push(next);
|
|
30987
|
+
}
|
|
30988
|
+
}
|
|
30989
|
+
function functionIdFor(name, schema) {
|
|
30990
|
+
return schema ? `${schema}.${name}` : name;
|
|
30991
|
+
}
|
|
30992
|
+
function extractFunctionsFromStmts(stmts, state, filepath) {
|
|
30993
|
+
for (const wrap of stmts) {
|
|
30994
|
+
const body = wrap.stmt?.CreateFunctionStmt;
|
|
30995
|
+
if (!body) continue;
|
|
30996
|
+
const fn = body.funcname ?? [];
|
|
30997
|
+
if (fn.length === 0) continue;
|
|
30998
|
+
const name = fn[fn.length - 1]?.String?.sval ?? "";
|
|
30999
|
+
if (!name) continue;
|
|
31000
|
+
const schema = fn.length > 1 ? fn[fn.length - 2]?.String?.sval ?? null : null;
|
|
31001
|
+
let language = "sql";
|
|
31002
|
+
for (const opt of body.options ?? []) {
|
|
31003
|
+
const de = opt.DefElem;
|
|
31004
|
+
if (de?.defname === "language" && de.arg?.String?.sval) language = de.arg.String.sval;
|
|
31005
|
+
}
|
|
31006
|
+
const returnType = body.returnType ? formatPgTypeName(body.returnType) : "";
|
|
31007
|
+
const isProcedure = !!body.is_procedure;
|
|
31008
|
+
const next = { name, schema, language, returnType, isProcedure, filepath };
|
|
31009
|
+
const id = functionIdFor(name, schema);
|
|
31010
|
+
const existing = state.functions.findIndex((f) => functionIdFor(f.name, f.schema) === id);
|
|
31011
|
+
if (existing >= 0) state.functions[existing] = next;
|
|
31012
|
+
else state.functions.push(next);
|
|
31013
|
+
}
|
|
31014
|
+
}
|
|
31015
|
+
function extractViewsFromStmts(stmts, state, filepath) {
|
|
31016
|
+
for (const wrap of stmts) {
|
|
31017
|
+
const stmt = wrap.stmt ?? {};
|
|
31018
|
+
const view = stmt.ViewStmt;
|
|
31019
|
+
if (view) {
|
|
31020
|
+
const name = view.view?.relname ?? "";
|
|
31021
|
+
if (!name) continue;
|
|
31022
|
+
const schema = view.view?.schemaname ?? null;
|
|
31023
|
+
const next = {
|
|
31024
|
+
name,
|
|
31025
|
+
schema,
|
|
31026
|
+
isMaterialized: false,
|
|
31027
|
+
withCheckOption: String(view.withCheckOption ?? "NO_CHECK_OPTION"),
|
|
31028
|
+
filepath
|
|
31029
|
+
};
|
|
31030
|
+
const id = functionIdFor(name, schema);
|
|
31031
|
+
const existing = state.views.findIndex((v) => functionIdFor(v.name, v.schema) === id);
|
|
31032
|
+
if (existing >= 0) state.views[existing] = next;
|
|
31033
|
+
else state.views.push(next);
|
|
31034
|
+
}
|
|
31035
|
+
const ctas = stmt.CreateTableAsStmt;
|
|
31036
|
+
if (ctas && ctas.objtype === "OBJECT_MATVIEW") {
|
|
31037
|
+
const name = ctas.into?.rel?.relname ?? "";
|
|
31038
|
+
if (!name) continue;
|
|
31039
|
+
const schema = ctas.into?.rel?.schemaname ?? null;
|
|
31040
|
+
const next = {
|
|
31041
|
+
name,
|
|
31042
|
+
schema,
|
|
31043
|
+
isMaterialized: true,
|
|
31044
|
+
withCheckOption: "N/A",
|
|
31045
|
+
filepath
|
|
31046
|
+
};
|
|
31047
|
+
const id = functionIdFor(name, schema);
|
|
31048
|
+
const existing = state.views.findIndex((v) => functionIdFor(v.name, v.schema) === id);
|
|
31049
|
+
if (existing >= 0) state.views[existing] = next;
|
|
31050
|
+
else state.views.push(next);
|
|
31051
|
+
}
|
|
31052
|
+
}
|
|
31053
|
+
}
|
|
31054
|
+
function applyDropsForSchemaObjects(stmts, state) {
|
|
31055
|
+
for (const wrap of stmts) {
|
|
31056
|
+
const drop = wrap.stmt?.DropStmt;
|
|
31057
|
+
if (!drop) continue;
|
|
31058
|
+
const removeType = drop.removeType ?? "";
|
|
31059
|
+
const objects = drop.objects ?? [];
|
|
31060
|
+
if (removeType === "OBJECT_TABLE") {
|
|
31061
|
+
const droppedTables = /* @__PURE__ */ new Set();
|
|
31062
|
+
for (const obj of objects) {
|
|
31063
|
+
const items = obj.List?.items ?? [];
|
|
31064
|
+
const last = items[items.length - 1]?.String?.sval;
|
|
31065
|
+
if (last) droppedTables.add(last);
|
|
31066
|
+
}
|
|
31067
|
+
if (droppedTables.size > 0) {
|
|
31068
|
+
for (const t of droppedTables) state.tables.delete(t);
|
|
31069
|
+
state.fks = state.fks.filter((fk) => !droppedTables.has(fk.sourceTable) && !droppedTables.has(fk.targetTable));
|
|
31070
|
+
}
|
|
31071
|
+
} else if (removeType === "OBJECT_TYPE") {
|
|
31072
|
+
const droppedEnums = /* @__PURE__ */ new Set();
|
|
31073
|
+
for (const obj of objects) {
|
|
31074
|
+
const tn = obj.TypeName;
|
|
31075
|
+
if (!tn) continue;
|
|
31076
|
+
const names = (tn.names ?? []).map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
31077
|
+
const last = names[names.length - 1];
|
|
31078
|
+
if (last) droppedEnums.add(last);
|
|
31079
|
+
}
|
|
31080
|
+
for (const e of droppedEnums) state.enums.delete(e);
|
|
31081
|
+
} else if (removeType === "OBJECT_EXTENSION") {
|
|
31082
|
+
const names = /* @__PURE__ */ new Set();
|
|
31083
|
+
for (const obj of objects) {
|
|
31084
|
+
const sval = obj.String?.sval;
|
|
31085
|
+
if (sval) names.add(sval);
|
|
31086
|
+
}
|
|
31087
|
+
if (names.size > 0) state.extensions = state.extensions.filter((e) => !names.has(e.name));
|
|
31088
|
+
} else if (removeType === "OBJECT_TRIGGER") {
|
|
31089
|
+
for (const obj of objects) {
|
|
31090
|
+
const items = obj.List?.items ?? [];
|
|
31091
|
+
if (items.length < 2) continue;
|
|
31092
|
+
const table = items[0]?.String?.sval ?? "";
|
|
31093
|
+
const trigName = items[items.length - 1]?.String?.sval ?? "";
|
|
31094
|
+
if (!table || !trigName) continue;
|
|
31095
|
+
state.triggers = state.triggers.filter((t) => !(t.table === table && t.name === trigName));
|
|
31096
|
+
}
|
|
31097
|
+
} else if (removeType === "OBJECT_FUNCTION" || removeType === "OBJECT_PROCEDURE") {
|
|
31098
|
+
for (const obj of objects) {
|
|
31099
|
+
const items = obj.ObjectWithArgs?.objname?.items ?? obj.ObjectWithArgs?.objname ?? obj.List?.items ?? [];
|
|
31100
|
+
if (!items.length) continue;
|
|
31101
|
+
const segs = items.map((s) => s.String?.sval ?? "").filter(Boolean);
|
|
31102
|
+
if (!segs.length) continue;
|
|
31103
|
+
const name = segs[segs.length - 1];
|
|
31104
|
+
const schema = segs.length > 1 ? segs[segs.length - 2] : null;
|
|
31105
|
+
const id = functionIdFor(name, schema);
|
|
31106
|
+
state.functions = state.functions.filter((f) => functionIdFor(f.name, f.schema) !== id);
|
|
31107
|
+
}
|
|
31108
|
+
} else if (removeType === "OBJECT_VIEW" || removeType === "OBJECT_MATVIEW") {
|
|
31109
|
+
for (const obj of objects) {
|
|
31110
|
+
const items = obj.List?.items ?? [];
|
|
31111
|
+
if (!items.length) continue;
|
|
31112
|
+
const name = items[items.length - 1]?.String?.sval ?? "";
|
|
31113
|
+
const schema = items.length > 1 ? items[items.length - 2]?.String?.sval ?? null : null;
|
|
31114
|
+
if (!name) continue;
|
|
31115
|
+
const id = functionIdFor(name, schema);
|
|
31116
|
+
state.views = state.views.filter((v) => functionIdFor(v.name, v.schema) !== id);
|
|
31117
|
+
}
|
|
31118
|
+
}
|
|
31119
|
+
}
|
|
31120
|
+
}
|
|
31121
|
+
function indexIsPrismaUncoverable(idx) {
|
|
31122
|
+
return idx.hasPredicate || idx.hasExpressions || idx.method !== "btree";
|
|
31123
|
+
}
|
|
30667
31124
|
function loadPrismaState(schemaPath) {
|
|
30668
31125
|
if (!schemaPath || !(0, import_node_fs18.existsSync)(schemaPath)) return null;
|
|
30669
31126
|
const content = (0, import_node_fs18.readFileSync)(schemaPath, "utf-8");
|
|
@@ -30830,6 +31287,96 @@ function verify(sqlState, prisma) {
|
|
|
30830
31287
|
}
|
|
30831
31288
|
return { contradictions, flaggedEdges };
|
|
30832
31289
|
}
|
|
31290
|
+
function deriveMigrationName(sqlPath) {
|
|
31291
|
+
const segments = sqlPath.split(/[\\/]/);
|
|
31292
|
+
const last = segments[segments.length - 1];
|
|
31293
|
+
if (last === "migration.sql" && segments.length >= 2) {
|
|
31294
|
+
return segments[segments.length - 2];
|
|
31295
|
+
}
|
|
31296
|
+
return last.replace(/\.sql$/, "");
|
|
31297
|
+
}
|
|
31298
|
+
function extractMigrationInfoFromStmts(stmts, name, filepath) {
|
|
31299
|
+
let isDestructive = false;
|
|
31300
|
+
let hasOrphanCheck = false;
|
|
31301
|
+
let hasSidecarBackup = false;
|
|
31302
|
+
let hasPreFlightNotice = false;
|
|
31303
|
+
let containsBackfill = false;
|
|
31304
|
+
let containsDropColumn = false;
|
|
31305
|
+
let containsDropTable = false;
|
|
31306
|
+
for (const wrap of stmts) {
|
|
31307
|
+
const stmt = wrap.stmt ?? {};
|
|
31308
|
+
const kind = Object.keys(stmt)[0];
|
|
31309
|
+
if (!kind) continue;
|
|
31310
|
+
const body = stmt[kind] ?? {};
|
|
31311
|
+
switch (kind) {
|
|
31312
|
+
case "AlterTableStmt": {
|
|
31313
|
+
const cmds = body.cmds ?? [];
|
|
31314
|
+
for (const c of cmds) {
|
|
31315
|
+
const subtype = c.AlterTableCmd?.subtype;
|
|
31316
|
+
if (subtype === "AT_DropColumn") {
|
|
31317
|
+
containsDropColumn = true;
|
|
31318
|
+
isDestructive = true;
|
|
31319
|
+
} else if (subtype === "AT_AlterColumnType" || subtype === "AT_DropNotNull" || subtype === "AT_DropConstraint") {
|
|
31320
|
+
isDestructive = true;
|
|
31321
|
+
}
|
|
31322
|
+
}
|
|
31323
|
+
break;
|
|
31324
|
+
}
|
|
31325
|
+
case "DropStmt": {
|
|
31326
|
+
const removeType = body.removeType ?? "";
|
|
31327
|
+
if (removeType === "OBJECT_TABLE") {
|
|
31328
|
+
containsDropTable = true;
|
|
31329
|
+
isDestructive = true;
|
|
31330
|
+
} else if (removeType === "OBJECT_TYPE" || removeType === "OBJECT_COLUMN" || removeType === "OBJECT_INDEX" || removeType === "OBJECT_POLICY") {
|
|
31331
|
+
isDestructive = true;
|
|
31332
|
+
}
|
|
31333
|
+
break;
|
|
31334
|
+
}
|
|
31335
|
+
case "CreateStmt": {
|
|
31336
|
+
const relname = body.relation?.relname ?? "";
|
|
31337
|
+
if (relname.startsWith("_backup_")) hasSidecarBackup = true;
|
|
31338
|
+
break;
|
|
31339
|
+
}
|
|
31340
|
+
case "CreateTableAsStmt": {
|
|
31341
|
+
const relname = body.into?.rel?.relname ?? "";
|
|
31342
|
+
if (relname.startsWith("_backup_")) hasSidecarBackup = true;
|
|
31343
|
+
break;
|
|
31344
|
+
}
|
|
31345
|
+
case "UpdateStmt":
|
|
31346
|
+
case "InsertStmt":
|
|
31347
|
+
case "DeleteStmt": {
|
|
31348
|
+
containsBackfill = true;
|
|
31349
|
+
break;
|
|
31350
|
+
}
|
|
31351
|
+
case "DoStmt": {
|
|
31352
|
+
const args = body.args ?? [];
|
|
31353
|
+
for (const arg of args) {
|
|
31354
|
+
const def = arg.DefElem;
|
|
31355
|
+
if (!def || def.defname !== "as") continue;
|
|
31356
|
+
const code = def.arg?.String?.sval ?? "";
|
|
31357
|
+
if (/\bRAISE\s+EXCEPTION\b/i.test(code)) hasOrphanCheck = true;
|
|
31358
|
+
if (/\bRAISE\s+NOTICE\b/i.test(code)) hasPreFlightNotice = true;
|
|
31359
|
+
}
|
|
31360
|
+
break;
|
|
31361
|
+
}
|
|
31362
|
+
}
|
|
31363
|
+
}
|
|
31364
|
+
const tsMatch = name.match(/^(\d{8,14})/);
|
|
31365
|
+
const timestamp = tsMatch ? tsMatch[1] : null;
|
|
31366
|
+
return {
|
|
31367
|
+
name,
|
|
31368
|
+
filepath,
|
|
31369
|
+
timestamp,
|
|
31370
|
+
isDestructive,
|
|
31371
|
+
hasOrphanCheck,
|
|
31372
|
+
hasSidecarBackup,
|
|
31373
|
+
hasPreFlightNotice,
|
|
31374
|
+
containsBackfill,
|
|
31375
|
+
containsDropColumn,
|
|
31376
|
+
containsDropTable,
|
|
31377
|
+
statementCount: stmts.length
|
|
31378
|
+
};
|
|
31379
|
+
}
|
|
30833
31380
|
function migrationsDirFor(rootDir) {
|
|
30834
31381
|
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
30835
31382
|
if (!paths) return null;
|
|
@@ -30884,6 +31431,132 @@ function generate3(rootDir) {
|
|
|
30884
31431
|
values: [...sqlEnum.values]
|
|
30885
31432
|
});
|
|
30886
31433
|
}
|
|
31434
|
+
let indexNodeCount = 0;
|
|
31435
|
+
for (const idx of sqlState.indexes) {
|
|
31436
|
+
if (!indexIsPrismaUncoverable(idx)) continue;
|
|
31437
|
+
nodes.push({
|
|
31438
|
+
id: `index:${idx.name}`,
|
|
31439
|
+
type: "index",
|
|
31440
|
+
name: idx.name,
|
|
31441
|
+
source: "sql",
|
|
31442
|
+
table: idx.table,
|
|
31443
|
+
unique: idx.unique,
|
|
31444
|
+
method: idx.method,
|
|
31445
|
+
columns: idx.columns,
|
|
31446
|
+
has_expressions: idx.hasExpressions,
|
|
31447
|
+
has_predicate: idx.hasPredicate,
|
|
31448
|
+
filepath: idx.filepath
|
|
31449
|
+
});
|
|
31450
|
+
indexNodeCount++;
|
|
31451
|
+
}
|
|
31452
|
+
let extensionNodeCount = 0;
|
|
31453
|
+
for (const ext of sqlState.extensions) {
|
|
31454
|
+
nodes.push({
|
|
31455
|
+
id: `extension:${ext.name}`,
|
|
31456
|
+
type: "extension",
|
|
31457
|
+
name: ext.name,
|
|
31458
|
+
source: "sql",
|
|
31459
|
+
schema: ext.schema,
|
|
31460
|
+
version: ext.version,
|
|
31461
|
+
filepath: ext.filepath
|
|
31462
|
+
});
|
|
31463
|
+
extensionNodeCount++;
|
|
31464
|
+
}
|
|
31465
|
+
let triggerNodeCount = 0;
|
|
31466
|
+
for (const trg of sqlState.triggers) {
|
|
31467
|
+
nodes.push({
|
|
31468
|
+
id: `trigger:${trg.table}:${trg.name}`,
|
|
31469
|
+
type: "trigger",
|
|
31470
|
+
name: trg.name,
|
|
31471
|
+
source: "sql",
|
|
31472
|
+
table: trg.table,
|
|
31473
|
+
timing: trg.timing,
|
|
31474
|
+
events: trg.events,
|
|
31475
|
+
function: trg.function,
|
|
31476
|
+
has_when: trg.hasWhen,
|
|
31477
|
+
for_each: trg.forEach,
|
|
31478
|
+
filepath: trg.filepath
|
|
31479
|
+
});
|
|
31480
|
+
triggerNodeCount++;
|
|
31481
|
+
}
|
|
31482
|
+
let functionNodeCount = 0;
|
|
31483
|
+
for (const fn of sqlState.functions) {
|
|
31484
|
+
const qualified = fn.schema ? `${fn.schema}.${fn.name}` : fn.name;
|
|
31485
|
+
nodes.push({
|
|
31486
|
+
id: `function:${qualified}`,
|
|
31487
|
+
type: "function",
|
|
31488
|
+
name: fn.name,
|
|
31489
|
+
source: "sql",
|
|
31490
|
+
schema: fn.schema,
|
|
31491
|
+
language: fn.language,
|
|
31492
|
+
return_type: fn.returnType,
|
|
31493
|
+
is_procedure: fn.isProcedure,
|
|
31494
|
+
filepath: fn.filepath
|
|
31495
|
+
});
|
|
31496
|
+
functionNodeCount++;
|
|
31497
|
+
}
|
|
31498
|
+
let viewNodeCount = 0;
|
|
31499
|
+
for (const vw of sqlState.views) {
|
|
31500
|
+
const qualified = vw.schema ? `${vw.schema}.${vw.name}` : vw.name;
|
|
31501
|
+
nodes.push({
|
|
31502
|
+
id: `${vw.isMaterialized ? "matview" : "view"}:${qualified}`,
|
|
31503
|
+
type: vw.isMaterialized ? "materialized_view" : "view",
|
|
31504
|
+
name: vw.name,
|
|
31505
|
+
source: "sql",
|
|
31506
|
+
schema: vw.schema,
|
|
31507
|
+
is_materialized: vw.isMaterialized,
|
|
31508
|
+
with_check_option: vw.withCheckOption,
|
|
31509
|
+
filepath: vw.filepath
|
|
31510
|
+
});
|
|
31511
|
+
viewNodeCount++;
|
|
31512
|
+
}
|
|
31513
|
+
let policyNodeCount = 0;
|
|
31514
|
+
for (const pol of sqlState.policies) {
|
|
31515
|
+
nodes.push({
|
|
31516
|
+
id: `policy:${pol.table}:${pol.name}`,
|
|
31517
|
+
type: "policy",
|
|
31518
|
+
name: pol.name,
|
|
31519
|
+
source: "sql",
|
|
31520
|
+
table: pol.table,
|
|
31521
|
+
command: pol.command,
|
|
31522
|
+
permissive: pol.permissive,
|
|
31523
|
+
roles: pol.roles,
|
|
31524
|
+
has_using: pol.hasUsing,
|
|
31525
|
+
has_with_check: pol.hasWithCheck,
|
|
31526
|
+
filepath: pol.filepath
|
|
31527
|
+
});
|
|
31528
|
+
policyNodeCount++;
|
|
31529
|
+
}
|
|
31530
|
+
const migrationFiles = migrationsDir ? discoverMigrationFiles(migrationsDir) : [];
|
|
31531
|
+
let migrationNodeCount = 0;
|
|
31532
|
+
for (const sqlPath of migrationFiles) {
|
|
31533
|
+
const sql = (0, import_node_fs18.readFileSync)(sqlPath, "utf-8");
|
|
31534
|
+
const name = deriveMigrationName(sqlPath);
|
|
31535
|
+
let ast;
|
|
31536
|
+
try {
|
|
31537
|
+
ast = postgresDialect.parse(sql);
|
|
31538
|
+
} catch {
|
|
31539
|
+
ast = { stmts: [] };
|
|
31540
|
+
}
|
|
31541
|
+
const info = postgresDialect.extractMigrationInfo(ast, name, sqlPath);
|
|
31542
|
+
nodes.push({
|
|
31543
|
+
id: `migration:${name}`,
|
|
31544
|
+
type: "migration",
|
|
31545
|
+
name,
|
|
31546
|
+
source: "sql",
|
|
31547
|
+
filepath: info.filepath,
|
|
31548
|
+
timestamp: info.timestamp,
|
|
31549
|
+
is_destructive: info.isDestructive,
|
|
31550
|
+
has_orphan_check: info.hasOrphanCheck,
|
|
31551
|
+
has_sidecar_backup: info.hasSidecarBackup,
|
|
31552
|
+
has_pre_flight_notice: info.hasPreFlightNotice,
|
|
31553
|
+
contains_backfill: info.containsBackfill,
|
|
31554
|
+
contains_drop_column: info.containsDropColumn,
|
|
31555
|
+
contains_drop_table: info.containsDropTable,
|
|
31556
|
+
statement_count: info.statementCount
|
|
31557
|
+
});
|
|
31558
|
+
migrationNodeCount++;
|
|
31559
|
+
}
|
|
30887
31560
|
const sqlOnlyTables = new Set(nodes.filter((n) => n.type === "table").map((n) => n.id));
|
|
30888
31561
|
const edges = sqlState.fks.filter((fk) => sqlOnlyTables.has(fk.sourceTable)).map((fk) => ({
|
|
30889
31562
|
source: fk.sourceTable,
|
|
@@ -30902,6 +31575,13 @@ function generate3(rootDir) {
|
|
|
30902
31575
|
sql_tables: sqlState.tables.size,
|
|
30903
31576
|
sql_enums: sqlState.enums.size,
|
|
30904
31577
|
sql_fks: sqlState.fks.length,
|
|
31578
|
+
sql_index_nodes: indexNodeCount,
|
|
31579
|
+
sql_policy_nodes: policyNodeCount,
|
|
31580
|
+
sql_extension_nodes: extensionNodeCount,
|
|
31581
|
+
sql_trigger_nodes: triggerNodeCount,
|
|
31582
|
+
sql_function_nodes: functionNodeCount,
|
|
31583
|
+
sql_view_nodes: viewNodeCount,
|
|
31584
|
+
sql_migration_nodes: migrationNodeCount,
|
|
30905
31585
|
additive_nodes: nodes.length,
|
|
30906
31586
|
contradictions_found: contradictions.length,
|
|
30907
31587
|
flagged_edges_found: flaggedEdges.length
|
|
@@ -30926,12 +31606,12 @@ init_launch_kit_paths();
|
|
|
30926
31606
|
function loadApiRoutesFromOutput(apiOutput) {
|
|
30927
31607
|
const routes = [];
|
|
30928
31608
|
for (const n of apiOutput.nodes) {
|
|
30929
|
-
const
|
|
30930
|
-
if (!
|
|
31609
|
+
const path13 = n.path;
|
|
31610
|
+
if (!path13 || typeof path13 !== "string") continue;
|
|
30931
31611
|
routes.push({
|
|
30932
|
-
path:
|
|
31612
|
+
path: path13,
|
|
30933
31613
|
nodeId: n.id,
|
|
30934
|
-
segments:
|
|
31614
|
+
segments: path13.split("/").filter(Boolean)
|
|
30935
31615
|
});
|
|
30936
31616
|
}
|
|
30937
31617
|
return routes;
|
|
@@ -31023,16 +31703,16 @@ function resolveFetchCall(call, apiPathMap, apiRoutes) {
|
|
|
31023
31703
|
if (call.isConcat) {
|
|
31024
31704
|
return { kind: "dynamic", normalizedUrl: raw };
|
|
31025
31705
|
}
|
|
31026
|
-
const { path:
|
|
31027
|
-
if (!
|
|
31028
|
-
return { kind: "unresolved", normalizedUrl:
|
|
31706
|
+
const { path: path13, hadInterpolation } = normalizeFetchUrl(raw);
|
|
31707
|
+
if (!path13.startsWith("/")) {
|
|
31708
|
+
return { kind: "unresolved", normalizedUrl: path13 };
|
|
31029
31709
|
}
|
|
31030
|
-
const segs =
|
|
31710
|
+
const segs = path13.split("/").filter(Boolean);
|
|
31031
31711
|
if (hadInterpolation && segs.length > 0 && segs[0].startsWith(":")) {
|
|
31032
|
-
return { kind: "dynamic", normalizedUrl:
|
|
31712
|
+
return { kind: "dynamic", normalizedUrl: path13 };
|
|
31033
31713
|
}
|
|
31034
|
-
const exact = apiPathMap.get(
|
|
31035
|
-
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl:
|
|
31714
|
+
const exact = apiPathMap.get(path13);
|
|
31715
|
+
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path13 };
|
|
31036
31716
|
let bestScore = -1;
|
|
31037
31717
|
let bestId = null;
|
|
31038
31718
|
for (const r of apiRoutes) {
|
|
@@ -31043,21 +31723,21 @@ function resolveFetchCall(call, apiPathMap, apiRoutes) {
|
|
|
31043
31723
|
}
|
|
31044
31724
|
}
|
|
31045
31725
|
if (bestId && bestScore > 0) {
|
|
31046
|
-
return { kind: "resolved", nodeId: bestId, normalizedUrl:
|
|
31726
|
+
return { kind: "resolved", nodeId: bestId, normalizedUrl: path13 };
|
|
31047
31727
|
}
|
|
31048
|
-
return { kind: "unresolved", normalizedUrl:
|
|
31728
|
+
return { kind: "unresolved", normalizedUrl: path13 };
|
|
31049
31729
|
}
|
|
31050
31730
|
function resolveUrlPath(urlPath, apiPathMap, apiRoutes) {
|
|
31051
|
-
const { path:
|
|
31052
|
-
if (!
|
|
31053
|
-
return { kind: "unresolved", normalizedUrl:
|
|
31731
|
+
const { path: path13, hadInterpolation } = normalizeFetchUrl(urlPath);
|
|
31732
|
+
if (!path13.startsWith("/")) {
|
|
31733
|
+
return { kind: "unresolved", normalizedUrl: path13 };
|
|
31054
31734
|
}
|
|
31055
|
-
const segs =
|
|
31735
|
+
const segs = path13.split("/").filter(Boolean);
|
|
31056
31736
|
if (hadInterpolation && segs.length > 0 && segs[0].startsWith(":")) {
|
|
31057
|
-
return { kind: "dynamic", normalizedUrl:
|
|
31737
|
+
return { kind: "dynamic", normalizedUrl: path13 };
|
|
31058
31738
|
}
|
|
31059
|
-
const exact = apiPathMap.get(
|
|
31060
|
-
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl:
|
|
31739
|
+
const exact = apiPathMap.get(path13);
|
|
31740
|
+
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path13 };
|
|
31061
31741
|
let bestScore = -1;
|
|
31062
31742
|
let bestId = null;
|
|
31063
31743
|
for (const r of apiRoutes) {
|
|
@@ -31068,9 +31748,9 @@ function resolveUrlPath(urlPath, apiPathMap, apiRoutes) {
|
|
|
31068
31748
|
}
|
|
31069
31749
|
}
|
|
31070
31750
|
if (bestId && bestScore > 0) {
|
|
31071
|
-
return { kind: "resolved", nodeId: bestId, normalizedUrl:
|
|
31751
|
+
return { kind: "resolved", nodeId: bestId, normalizedUrl: path13 };
|
|
31072
31752
|
}
|
|
31073
|
-
return { kind: "unresolved", normalizedUrl:
|
|
31753
|
+
return { kind: "unresolved", normalizedUrl: path13 };
|
|
31074
31754
|
}
|
|
31075
31755
|
|
|
31076
31756
|
// src/server/graph/parsers/crosslayer/fetch-resolver.ts
|
|
@@ -32048,9 +32728,9 @@ function collectTargets(apiOutput, uiOutput) {
|
|
|
32048
32728
|
const out = [];
|
|
32049
32729
|
for (const n of apiOutput?.nodes ?? []) {
|
|
32050
32730
|
if (n.type !== "endpoint") continue;
|
|
32051
|
-
const
|
|
32052
|
-
if (typeof
|
|
32053
|
-
out.push({ id: n.id, route:
|
|
32731
|
+
const path13 = n.path;
|
|
32732
|
+
if (typeof path13 !== "string" || !path13) continue;
|
|
32733
|
+
out.push({ id: n.id, route: path13, layer: "api" });
|
|
32054
32734
|
}
|
|
32055
32735
|
for (const n of uiOutput?.nodes ?? []) {
|
|
32056
32736
|
if (n.type !== "page") continue;
|
|
@@ -33042,15 +33722,75 @@ function runAudit(rootDir, layer, check) {
|
|
|
33042
33722
|
}
|
|
33043
33723
|
|
|
33044
33724
|
// src/server/graph/core/projects.ts
|
|
33725
|
+
var import_node_path31 = require("node:path");
|
|
33726
|
+
|
|
33727
|
+
// src/server/lib/worktree.ts
|
|
33728
|
+
var import_node_path30 = require("node:path");
|
|
33729
|
+
|
|
33730
|
+
// src/server/orbit/registry.ts
|
|
33731
|
+
var import_node_fs26 = require("node:fs");
|
|
33732
|
+
var import_node_os5 = require("node:os");
|
|
33045
33733
|
var import_node_path29 = require("node:path");
|
|
33734
|
+
init_launch_kit_paths();
|
|
33735
|
+
var REGISTRY_DIR = (0, import_node_path29.join)((0, import_node_os5.homedir)(), LAUNCHSECURE_DIR, "orbit");
|
|
33736
|
+
var REGISTRY_PATH = (0, import_node_path29.join)(REGISTRY_DIR, "state.json");
|
|
33737
|
+
var LOCK_PATH = (0, import_node_path29.join)(REGISTRY_DIR, "state.json.lock");
|
|
33738
|
+
function emptyRegistry() {
|
|
33739
|
+
return { version: 1, worktrees: {} };
|
|
33740
|
+
}
|
|
33741
|
+
function readRegistry() {
|
|
33742
|
+
if (!(0, import_node_fs26.existsSync)(REGISTRY_PATH)) return emptyRegistry();
|
|
33743
|
+
try {
|
|
33744
|
+
const parsed = JSON.parse((0, import_node_fs26.readFileSync)(REGISTRY_PATH, "utf-8"));
|
|
33745
|
+
if (parsed?.version === 1 && parsed.worktrees && typeof parsed.worktrees === "object") {
|
|
33746
|
+
return parsed;
|
|
33747
|
+
}
|
|
33748
|
+
} catch {
|
|
33749
|
+
}
|
|
33750
|
+
return emptyRegistry();
|
|
33751
|
+
}
|
|
33752
|
+
function listWorktrees() {
|
|
33753
|
+
return Object.values(readRegistry().worktrees);
|
|
33754
|
+
}
|
|
33755
|
+
|
|
33756
|
+
// src/server/lib/worktree.ts
|
|
33757
|
+
var WORKTREE_PARAM_DESCRIPTION = "Optional orbit worktree slug (from `launch-orbit create`). Resolves to the worktree's path via the orbit registry (~/.launchsecure/orbit/state.json). Lets you query a worktree's state from a Claude Code session pinned to the main repo. Superseded by `project_root`.";
|
|
33758
|
+
var PROJECT_ROOT_PARAM_DESCRIPTION = "Optional explicit project root. Accepts an absolute path or a path relative to the monorepo root. Escape hatch when `worktree` doesn't fit. Takes precedence over all other root args.";
|
|
33759
|
+
function resolveWorktreeRoot(slug, monorepoRoot) {
|
|
33760
|
+
const local = listWorktrees().filter((w) => w.projectRoot === monorepoRoot);
|
|
33761
|
+
const match = local.find((w) => w.slug === slug);
|
|
33762
|
+
if (match) return match.path;
|
|
33763
|
+
if (local.length === 0) {
|
|
33764
|
+
throw new Error(
|
|
33765
|
+
`worktree="${slug}" requested but no worktrees are registered for this project. Run \`launch-orbit create <branch>\` first, or use \`project_root\` to point at an arbitrary path.`
|
|
33766
|
+
);
|
|
33767
|
+
}
|
|
33768
|
+
const available = local.map((w) => `"${w.slug}" (${w.branch})`).join(", ");
|
|
33769
|
+
throw new Error(`Unknown worktree "${slug}". Available: ${available}.`);
|
|
33770
|
+
}
|
|
33771
|
+
function resolveWorktreeOrProjectRoot(args, monorepoRoot) {
|
|
33772
|
+
const projectRoot = typeof args.project_root === "string" ? args.project_root.trim() : "";
|
|
33773
|
+
if (projectRoot) {
|
|
33774
|
+
return (0, import_node_path30.isAbsolute)(projectRoot) ? projectRoot : (0, import_node_path30.resolve)(monorepoRoot, projectRoot);
|
|
33775
|
+
}
|
|
33776
|
+
const worktree = typeof args.worktree === "string" ? args.worktree.trim() : "";
|
|
33777
|
+
if (worktree) {
|
|
33778
|
+
return resolveWorktreeRoot(worktree, monorepoRoot);
|
|
33779
|
+
}
|
|
33780
|
+
return null;
|
|
33781
|
+
}
|
|
33782
|
+
|
|
33783
|
+
// src/server/graph/core/projects.ts
|
|
33046
33784
|
init_config();
|
|
33785
|
+
var WORKTREE_PARAM_DESCRIPTION2 = WORKTREE_PARAM_DESCRIPTION;
|
|
33786
|
+
var PROJECT_ROOT_PARAM_DESCRIPTION2 = PROJECT_ROOT_PARAM_DESCRIPTION;
|
|
33047
33787
|
function listProjects(monorepoRoot) {
|
|
33048
33788
|
const cfg = loadConfig(monorepoRoot);
|
|
33049
33789
|
const entries = cfg.projects ?? [];
|
|
33050
33790
|
return entries.map((p) => ({
|
|
33051
33791
|
name: p.name,
|
|
33052
33792
|
root: p.root,
|
|
33053
|
-
absoluteRoot: (0,
|
|
33793
|
+
absoluteRoot: (0, import_node_path31.resolve)(monorepoRoot, p.root)
|
|
33054
33794
|
}));
|
|
33055
33795
|
}
|
|
33056
33796
|
function resolveProject(name, projects) {
|
|
@@ -33073,6 +33813,12 @@ function resolveProjectRoot(project, monorepoRoot) {
|
|
|
33073
33813
|
return resolveProject(raw, projects).absoluteRoot;
|
|
33074
33814
|
}
|
|
33075
33815
|
var PROJECT_PARAM_DESCRIPTION = "Optional sub-project name (or root path) from .launchchart.json projects[]. Defaults to the monorepo root. Run detect_project_stack to list configured projects.";
|
|
33816
|
+
function resolveRequestRoot(args, monorepoRoot) {
|
|
33817
|
+
const fromArgs = resolveWorktreeOrProjectRoot(args, monorepoRoot);
|
|
33818
|
+
if (fromArgs) return fromArgs;
|
|
33819
|
+
const project = typeof args.project === "string" ? args.project : void 0;
|
|
33820
|
+
return resolveProjectRoot(project, monorepoRoot);
|
|
33821
|
+
}
|
|
33076
33822
|
|
|
33077
33823
|
// src/server/graph-mcp.ts
|
|
33078
33824
|
init_freshness();
|
|
@@ -33094,13 +33840,21 @@ var TOOLS = [
|
|
|
33094
33840
|
project: {
|
|
33095
33841
|
type: "string",
|
|
33096
33842
|
description: PROJECT_PARAM_DESCRIPTION + " Special: omit to regenerate ALL configured projects."
|
|
33843
|
+
},
|
|
33844
|
+
worktree: {
|
|
33845
|
+
type: "string",
|
|
33846
|
+
description: WORKTREE_PARAM_DESCRIPTION2
|
|
33847
|
+
},
|
|
33848
|
+
project_root: {
|
|
33849
|
+
type: "string",
|
|
33850
|
+
description: PROJECT_ROOT_PARAM_DESCRIPTION2
|
|
33097
33851
|
}
|
|
33098
33852
|
}
|
|
33099
33853
|
}
|
|
33100
33854
|
},
|
|
33101
33855
|
{
|
|
33102
33856
|
name: "read_graph",
|
|
33103
|
-
description: 'Query the structural project graph \u2014 use INSTEAD of Glob and Grep for locating files, understanding structure, and navigating the codebase. Faster and more accurate than file-system search because it returns typed nodes with metadata and relationships. \n\nUSE THIS FOR: "where is X", "what files are in module Y", "what pages exist under /admin", "what components does Z render", "what tables relate to User", "list all hooks in auth module", "which endpoints touch the User table", "what auth strategy does this endpoint use". \n\nDO NOT USE FOR: understanding what\'s INSIDE a component (use inspect_node for elements, conditions, state, variables, responses), reading actual source code (use Read). \n\nQUERY PARAMS (at least one required for node data \u2014 unfiltered calls return summary only to stay in context):\n- search: substring match on node id, name, or
|
|
33857
|
+
description: 'Query the structural project graph \u2014 use INSTEAD of Glob and Grep for locating files, understanding structure, and navigating the codebase. Faster and more accurate than file-system search because it returns typed nodes with metadata and relationships. \n\nUSE THIS FOR: "where is X", "what files are in module Y", "what pages exist under /admin", "what components does Z render", "what tables relate to User", "list all hooks in auth module", "which endpoints touch the User table", "what auth strategy does this endpoint use". \n\nDO NOT USE FOR: understanding what\'s INSIDE a component (use inspect_node for elements, conditions, state, variables, responses), reading actual source code (use Read). \n\nQUERY PARAMS (at least one required for node data \u2014 unfiltered calls return summary only to stay in context):\n- search: substring match on node id, name, route, JSX element text/string-prop literals, ui_labels (strings from `const X = [{label:\'\u2026\'}]` data arrays), and notes (tagged comments). Lets queries like search:"Briefs" find a page where "Briefs" is a tab label inside an array, or search:"FIXME" find every file with a FIXME comment. For exhaustive note listings use list_notes.\n- type: filter by node type (ui layer: page, layout, component, ui, hook, context, config, util; api layer: endpoint; db layer: table, enum, migration). Migration nodes carry safety attributes \u2014 is_destructive, has_orphan_check, has_sidecar_backup, has_pre_flight_notice, contains_backfill, contains_drop_column, contains_drop_table, statement_count, timestamp \u2014 queryable via tag_key filters or by inspecting returned node fields.\n- include_findings: db layer only. When true, response includes `contradictions` and `flagged_edges` arrays surfacing SQL\u2194ORM schema drift detected by the SQL migrations parser. Use this to audit "schema vs migrations" disagreement (missing columns, type mismatches, nullability drift, FKs declared in SQL but not ORM).\n- module: filter by module tag (computed from directory structure, e.g. "auth", "admin", "settings")\n- node_id: return this node + its neighborhood (incoming+outgoing edges within `hops`)\n- hops: neighborhood radius when node_id is set (default 1)\n- minimal: return only id/type/name/module/route per node (skip heavy fields like columns, exports)\n- include_edges: return the actual edge list. Default: TRUE for neighborhood queries (node_id), FALSE for filter queries (search/type/module). Filter responses always include `edge_count`; only pass include_edges:true when you actually need to inspect individual edges (e.g. "which components render X"). This default cuts typical filter responses in half.\n\nBATCH MODE: pass `queries` (array of query objects) to run multiple independent queries in a single call. Each query object uses the same params (layer/search/type/module/node_id/hops/minimal). Returns { batch: true, count, results: [{index, query, result}, ...] }. Use this when you need multiple graph views up-front (e.g. scoping a feature across ui+api+db layers) to save round-trips. When batch mode is used, top-level params are ignored.\n\nReturns: filtered nodes + edges between them. If no filter given, returns per-layer counts and type breakdown only.\n\nWIRE FORMAT (compact): responses that include nodes/edges use short keys and edge-by-index refs to cut payload ~40-60%. Every such response carries a `_schema` legend. Quick reference:\n nodes[]: { i: id, t: type, n: name, m: module, r: route, mt: methods, x: exports, c: columns }\n edges[]: { s: source_node_index, d: target_node_index, t: type, l: label }\nedges.s / edges.d are 0-based indices into THIS response\'s nodes array. If a referenced node is not in the response (boundary case), s/d may instead contain the full node id string \u2014 always check the type.\n\nPAGINATION (filter queries):\n- Use `offset` and `limit` to paginate through large result sets.\n- Response includes: `total` (matched), `returned` (in this page), `has_more`, `next_offset`.\n- If `has_more: true`, call again with `offset: next_offset` to get the next page.\n\nBUDGET GUARDS:\n- Neighborhood queries stop expanding when the projected response exceeds budget. The response then contains `budget_exceeded: true` plus `hops_traversed < hops_requested`. When this happens, drill into a specific neighbor with another node_id call rather than retrying with larger hops \u2014 it will just truncate again.\n- Batch mode caps total response size. Once the budget is hit, later queries return `{skipped: true, reason: "batch_budget_exhausted"}` and you must re-run them individually.\n\nMONOREPOS: pass `project: "<name>"` to query a sub-project graph (defined in .launchchart.json projects[]). Omitting `project` targets the monorepo root. In batch mode the top-level `project` is inherited by sub-queries that do not set their own. Run detect_project_stack to list configured projects.',
|
|
33104
33858
|
inputSchema: {
|
|
33105
33859
|
type: "object",
|
|
33106
33860
|
properties: {
|
|
@@ -33110,7 +33864,7 @@ var TOOLS = [
|
|
|
33110
33864
|
},
|
|
33111
33865
|
search: {
|
|
33112
33866
|
type: "string",
|
|
33113
|
-
description: "Case-insensitive substring match against node id, name,
|
|
33867
|
+
description: "Case-insensitive substring match against node id, name, route, JSX element text/string-prop literals, and ui_labels (strings from `const X = [{label:'\u2026'}]` data arrays)."
|
|
33114
33868
|
},
|
|
33115
33869
|
type: {
|
|
33116
33870
|
type: "string",
|
|
@@ -33144,6 +33898,10 @@ var TOOLS = [
|
|
|
33144
33898
|
type: "boolean",
|
|
33145
33899
|
description: "Include the edge list in the response. Default TRUE for neighborhood queries (node_id), FALSE for filter queries. Filter responses always include edge_count. Only set true on filter queries when you actually need edge data."
|
|
33146
33900
|
},
|
|
33901
|
+
include_findings: {
|
|
33902
|
+
type: "boolean",
|
|
33903
|
+
description: "DB layer only. When true, response includes `contradictions[]` and `flagged_edges[]` arrays from the SQL migrations parser \u2014 SQL\u2194ORM schema drift findings (missing columns/tables, type mismatches, nullability drift, FKs in SQL but no ORM @relation). Default false."
|
|
33904
|
+
},
|
|
33147
33905
|
offset: {
|
|
33148
33906
|
type: "number",
|
|
33149
33907
|
description: "Skip first N matched nodes (pagination). Default 0. Use next_offset from a previous response to get the next page."
|
|
@@ -33154,7 +33912,7 @@ var TOOLS = [
|
|
|
33154
33912
|
},
|
|
33155
33913
|
queries: {
|
|
33156
33914
|
type: "array",
|
|
33157
|
-
description: "Batch mode \u2014 array of query objects to run in a single call. Each uses the same param schema (including `project`).
|
|
33915
|
+
description: "Batch mode \u2014 array of query objects to run in a single call. Each uses the same param schema (including `project` / `worktree` / `project_root`). Top-level root args are inherited by sub-queries that don't specify their own. Subject to an aggregate size budget \u2014 later queries may return a skipped stub.",
|
|
33158
33916
|
items: {
|
|
33159
33917
|
type: "object",
|
|
33160
33918
|
properties: {
|
|
@@ -33166,13 +33924,24 @@ var TOOLS = [
|
|
|
33166
33924
|
hops: { type: "number" },
|
|
33167
33925
|
minimal: { type: "boolean" },
|
|
33168
33926
|
include_edges: { type: "boolean" },
|
|
33169
|
-
|
|
33927
|
+
include_findings: { type: "boolean" },
|
|
33928
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
33929
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
33930
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33170
33931
|
}
|
|
33171
33932
|
}
|
|
33172
33933
|
},
|
|
33173
33934
|
project: {
|
|
33174
33935
|
type: "string",
|
|
33175
33936
|
description: PROJECT_PARAM_DESCRIPTION
|
|
33937
|
+
},
|
|
33938
|
+
worktree: {
|
|
33939
|
+
type: "string",
|
|
33940
|
+
description: WORKTREE_PARAM_DESCRIPTION2
|
|
33941
|
+
},
|
|
33942
|
+
project_root: {
|
|
33943
|
+
type: "string",
|
|
33944
|
+
description: PROJECT_ROOT_PARAM_DESCRIPTION2
|
|
33176
33945
|
}
|
|
33177
33946
|
}
|
|
33178
33947
|
}
|
|
@@ -33220,7 +33989,9 @@ Returns: { pattern, filter, files_searched, total_matches, matches: [{file, line
|
|
|
33220
33989
|
context: { type: "number", description: "Context lines around each match. Default 2." },
|
|
33221
33990
|
max_matches: { type: "number", description: "Max matches to return total. Default 50." },
|
|
33222
33991
|
max_files: { type: "number", description: "Max files to search. Default 50." },
|
|
33223
|
-
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION }
|
|
33992
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
33993
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
33994
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33224
33995
|
},
|
|
33225
33996
|
required: ["layer", "pattern"]
|
|
33226
33997
|
}
|
|
@@ -33262,7 +34033,9 @@ Returns deep fields only \u2014 not structural metadata (use read_graph for that
|
|
|
33262
34033
|
type: "boolean",
|
|
33263
34034
|
description: "Case-insensitive filter matching. Default true."
|
|
33264
34035
|
},
|
|
33265
|
-
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION }
|
|
34036
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
34037
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
34038
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33266
34039
|
},
|
|
33267
34040
|
required: ["layer"]
|
|
33268
34041
|
}
|
|
@@ -33313,7 +34086,9 @@ Use this when the user asks "is the chart running", "show me the project graph U
|
|
|
33313
34086
|
type: "string",
|
|
33314
34087
|
description: 'Optional specific key to look up within the chosen kind (e.g. "moon-shadow-blur"). When omitted, returns the full {key:nodes} map for the kind.'
|
|
33315
34088
|
},
|
|
33316
|
-
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION }
|
|
34089
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
34090
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
34091
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33317
34092
|
}
|
|
33318
34093
|
}
|
|
33319
34094
|
},
|
|
@@ -33343,7 +34118,9 @@ Use this when the user asks "is the chart running", "show me the project graph U
|
|
|
33343
34118
|
type: "string",
|
|
33344
34119
|
description: 'Tag value (e.g. "auth", "alice", "true").'
|
|
33345
34120
|
},
|
|
33346
|
-
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION }
|
|
34121
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
34122
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
34123
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33347
34124
|
},
|
|
33348
34125
|
required: ["node_id", "key", "value"]
|
|
33349
34126
|
}
|
|
@@ -33362,7 +34139,9 @@ Use this when the user asks "is the chart running", "show me the project graph U
|
|
|
33362
34139
|
type: "string",
|
|
33363
34140
|
description: "Tag key to remove."
|
|
33364
34141
|
},
|
|
33365
|
-
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION }
|
|
34142
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
34143
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
34144
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33366
34145
|
},
|
|
33367
34146
|
required: ["node_id", "key"]
|
|
33368
34147
|
}
|
|
@@ -33381,7 +34160,9 @@ Use this when the user asks "is the chart running", "show me the project graph U
|
|
|
33381
34160
|
type: "string",
|
|
33382
34161
|
description: "Specific check to run (e.g. 'schema_drift', 'unprotected_routes'). Omit to run all checks for the layer."
|
|
33383
34162
|
},
|
|
33384
|
-
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION }
|
|
34163
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
34164
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
34165
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33385
34166
|
},
|
|
33386
34167
|
required: ["layer"]
|
|
33387
34168
|
}
|
|
@@ -33417,10 +34198,56 @@ Example: blast_points(node_id: "server/auth/middleware.ts", hops: 2) \u2192 retu
|
|
|
33417
34198
|
enum: ["reverse", "both"],
|
|
33418
34199
|
description: "'reverse' (default) = only what depends on this node. 'both' = full neighborhood."
|
|
33419
34200
|
},
|
|
33420
|
-
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION }
|
|
34201
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
34202
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
34203
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
33421
34204
|
},
|
|
33422
34205
|
required: ["node_id"]
|
|
33423
34206
|
}
|
|
34207
|
+
},
|
|
34208
|
+
{
|
|
34209
|
+
name: "list_notes",
|
|
34210
|
+
description: 'List tagged comments across the project graph \u2014 TODO, FIXME, HACK, NOTE, SECURITY, etc. Any `// KIND: body` or `/* KIND: body */` comment where KIND is an all-caps identifier (2\u201316 chars) is captured automatically; team conventions like `// CLAUDE:` are discovered without configuration.\n\nKinds are categorized at read time:\n actionable: TODO, FIXME, HACK, XXX, REFACTOR, OPTIMIZE, REVIEW\n warning: SECURITY, WARNING, IMPORTANT, CAUTION, DANGER, DEPRECATED\n doc: NOTE, TIP, SEE, NB, INFO, EXAMPLE\n custom: anything else (team-specific conventions)\n\nDefault category filter is `actionable,warning` \u2014 the "what should I act on" view. Pass category:"all" for everything including doc + custom.\n\nReturns: { total, returned, has_more, items: [{file, line, kind, category, text, author?, module?}] }.',
|
|
34211
|
+
inputSchema: {
|
|
34212
|
+
type: "object",
|
|
34213
|
+
properties: {
|
|
34214
|
+
layer: {
|
|
34215
|
+
type: "string",
|
|
34216
|
+
description: "Restrict to one layer ('ui', 'api', 'db'). Default: scan all layers that have notes."
|
|
34217
|
+
},
|
|
34218
|
+
kind: {
|
|
34219
|
+
type: "string",
|
|
34220
|
+
description: 'Exact kind match, case-insensitive (e.g. "TODO", "FIXME", "SECURITY").'
|
|
34221
|
+
},
|
|
34222
|
+
category: {
|
|
34223
|
+
type: "string",
|
|
34224
|
+
description: "'actionable' | 'warning' | 'doc' | 'custom' | 'all'. Comma-separated list also accepted. Default: 'actionable,warning'."
|
|
34225
|
+
},
|
|
34226
|
+
module: {
|
|
34227
|
+
type: "string",
|
|
34228
|
+
description: 'Restrict to nodes carrying this module tag (e.g. "auth", "work-items").'
|
|
34229
|
+
},
|
|
34230
|
+
pattern: {
|
|
34231
|
+
type: "string",
|
|
34232
|
+
description: 'Regex applied to note body text (case-insensitive). Use to grep within bodies, e.g. "race condition".'
|
|
34233
|
+
},
|
|
34234
|
+
author: {
|
|
34235
|
+
type: "string",
|
|
34236
|
+
description: "Match author from `// TODO(alice): \u2026` syntax, case-insensitive."
|
|
34237
|
+
},
|
|
34238
|
+
limit: {
|
|
34239
|
+
type: "number",
|
|
34240
|
+
description: "Max items returned. Default 100. Pair with offset for pagination."
|
|
34241
|
+
},
|
|
34242
|
+
offset: {
|
|
34243
|
+
type: "number",
|
|
34244
|
+
description: "Skip first N items. Default 0."
|
|
34245
|
+
},
|
|
34246
|
+
project: { type: "string", description: PROJECT_PARAM_DESCRIPTION },
|
|
34247
|
+
worktree: { type: "string", description: WORKTREE_PARAM_DESCRIPTION2 },
|
|
34248
|
+
project_root: { type: "string", description: PROJECT_ROOT_PARAM_DESCRIPTION2 }
|
|
34249
|
+
}
|
|
34250
|
+
}
|
|
33424
34251
|
}
|
|
33425
34252
|
];
|
|
33426
34253
|
function matchesSearch(node, query) {
|
|
@@ -33429,14 +34256,44 @@ function matchesSearch(node, query) {
|
|
|
33429
34256
|
if (node.name.toLowerCase().includes(q)) return true;
|
|
33430
34257
|
const route = node.route;
|
|
33431
34258
|
if (route && route.toLowerCase().includes(q)) return true;
|
|
34259
|
+
const elements = node.elements;
|
|
34260
|
+
if (elements) {
|
|
34261
|
+
for (const el of elements) {
|
|
34262
|
+
if (el.text && el.text.toLowerCase().includes(q)) return true;
|
|
34263
|
+
if (el.props) {
|
|
34264
|
+
for (const v of Object.values(el.props)) {
|
|
34265
|
+
if (typeof v !== "string") continue;
|
|
34266
|
+
if (v.includes("=>") || v.startsWith("(") || v.startsWith("{")) continue;
|
|
34267
|
+
if (v.toLowerCase().includes(q)) return true;
|
|
34268
|
+
}
|
|
34269
|
+
}
|
|
34270
|
+
}
|
|
34271
|
+
}
|
|
34272
|
+
const uiLabels = node.ui_labels;
|
|
34273
|
+
if (uiLabels) {
|
|
34274
|
+
for (const lbl of uiLabels) {
|
|
34275
|
+
if (typeof lbl === "string" && lbl.toLowerCase().includes(q)) return true;
|
|
34276
|
+
}
|
|
34277
|
+
}
|
|
34278
|
+
const notes = node.notes;
|
|
34279
|
+
if (notes) {
|
|
34280
|
+
for (const n of notes) {
|
|
34281
|
+
if (n.kind && n.kind.toLowerCase().includes(q)) return true;
|
|
34282
|
+
if (n.text && n.text.toLowerCase().includes(q)) return true;
|
|
34283
|
+
}
|
|
34284
|
+
}
|
|
33432
34285
|
return false;
|
|
33433
34286
|
}
|
|
34287
|
+
var MINIMAL_STRIP_FIELDS = /* @__PURE__ */ new Set(["columns"]);
|
|
33434
34288
|
function toMinimal(nodes) {
|
|
33435
34289
|
return nodes.map((n) => {
|
|
33436
34290
|
const out = { id: n.id, type: n.type, name: n.name };
|
|
33437
|
-
|
|
33438
|
-
|
|
33439
|
-
|
|
34291
|
+
for (const [k, v] of Object.entries(n)) {
|
|
34292
|
+
if (k === "id" || k === "type" || k === "name") continue;
|
|
34293
|
+
if (MINIMAL_STRIP_FIELDS.has(k)) continue;
|
|
34294
|
+
if (DEEP_FIELDS.has(k)) continue;
|
|
34295
|
+
if (v != null) out[k] = v;
|
|
34296
|
+
}
|
|
33440
34297
|
return out;
|
|
33441
34298
|
});
|
|
33442
34299
|
}
|
|
@@ -33487,8 +34344,34 @@ var DEEP_FIELDS = /* @__PURE__ */ new Set([
|
|
|
33487
34344
|
"variables",
|
|
33488
34345
|
"responses",
|
|
33489
34346
|
"params",
|
|
33490
|
-
"effects"
|
|
34347
|
+
"effects",
|
|
34348
|
+
"ui_labels",
|
|
34349
|
+
"notes"
|
|
33491
34350
|
]);
|
|
34351
|
+
var NOTE_KIND_CATEGORY = {
|
|
34352
|
+
TODO: "actionable",
|
|
34353
|
+
FIXME: "actionable",
|
|
34354
|
+
HACK: "actionable",
|
|
34355
|
+
XXX: "actionable",
|
|
34356
|
+
REFACTOR: "actionable",
|
|
34357
|
+
OPTIMIZE: "actionable",
|
|
34358
|
+
REVIEW: "actionable",
|
|
34359
|
+
SECURITY: "warning",
|
|
34360
|
+
WARNING: "warning",
|
|
34361
|
+
IMPORTANT: "warning",
|
|
34362
|
+
CAUTION: "warning",
|
|
34363
|
+
DANGER: "warning",
|
|
34364
|
+
DEPRECATED: "warning",
|
|
34365
|
+
NOTE: "doc",
|
|
34366
|
+
TIP: "doc",
|
|
34367
|
+
SEE: "doc",
|
|
34368
|
+
NB: "doc",
|
|
34369
|
+
INFO: "doc",
|
|
34370
|
+
EXAMPLE: "doc"
|
|
34371
|
+
};
|
|
34372
|
+
function categorizeNoteKind(kind) {
|
|
34373
|
+
return NOTE_KIND_CATEGORY[kind] ?? "custom";
|
|
34374
|
+
}
|
|
33492
34375
|
var EST_CHARS_PER_NODE_FULL = {
|
|
33493
34376
|
ui: 300,
|
|
33494
34377
|
api: 300,
|
|
@@ -33764,7 +34647,7 @@ function withFreshnessMeta(result, args) {
|
|
|
33764
34647
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return result;
|
|
33765
34648
|
let rootDir;
|
|
33766
34649
|
try {
|
|
33767
|
-
rootDir =
|
|
34650
|
+
rootDir = resolveRequestRoot(args, process.cwd());
|
|
33768
34651
|
} catch {
|
|
33769
34652
|
return result;
|
|
33770
34653
|
}
|
|
@@ -33779,7 +34662,7 @@ function withFreshnessMeta(result, args) {
|
|
|
33779
34662
|
}
|
|
33780
34663
|
function resolveOrErr(args) {
|
|
33781
34664
|
try {
|
|
33782
|
-
return { rootDir:
|
|
34665
|
+
return { rootDir: resolveRequestRoot(args, process.cwd()) };
|
|
33783
34666
|
} catch (e) {
|
|
33784
34667
|
return err(e.message);
|
|
33785
34668
|
}
|
|
@@ -33788,6 +34671,8 @@ async function handleGenerateGraph(args) {
|
|
|
33788
34671
|
const monorepoRoot = process.cwd();
|
|
33789
34672
|
const layer = args.layer;
|
|
33790
34673
|
const projectArg = typeof args.project === "string" ? args.project.trim() : "";
|
|
34674
|
+
const worktreeArg = typeof args.worktree === "string" ? args.worktree.trim() : "";
|
|
34675
|
+
const projectRootArg = typeof args.project_root === "string" ? args.project_root.trim() : "";
|
|
33791
34676
|
function formatProjectResult(results2, relativeRoot) {
|
|
33792
34677
|
return results2.map((r) => {
|
|
33793
34678
|
const warnings = r.output.warnings.length;
|
|
@@ -33795,25 +34680,27 @@ async function handleGenerateGraph(args) {
|
|
|
33795
34680
|
}).join("\n") + `
|
|
33796
34681
|
\u2192 ${relativeRoot}/.launchsecure/graphs/`;
|
|
33797
34682
|
}
|
|
33798
|
-
if (projectArg) {
|
|
34683
|
+
if (projectArg || worktreeArg || projectRootArg) {
|
|
33799
34684
|
let rootDir;
|
|
33800
34685
|
try {
|
|
33801
|
-
rootDir =
|
|
34686
|
+
rootDir = resolveRequestRoot(args, monorepoRoot);
|
|
33802
34687
|
} catch (e) {
|
|
33803
34688
|
return err(e.message);
|
|
33804
34689
|
}
|
|
33805
34690
|
const results2 = await generateGraph(rootDir, layer);
|
|
34691
|
+
const label = worktreeArg ? `worktree "${worktreeArg}"` : projectArg ? `project "${projectArg}"` : `root "${projectRootArg}"`;
|
|
34692
|
+
const queryHint = worktreeArg ? `read_graph (with worktree="${worktreeArg}")` : projectArg ? `read_graph (with project="${projectArg}")` : `read_graph (with project_root="${projectRootArg}")`;
|
|
33806
34693
|
if (results2.length === 0) {
|
|
33807
34694
|
return err(
|
|
33808
|
-
layer ? `No parser detected for the "${layer}" layer in
|
|
34695
|
+
layer ? `No parser detected for the "${layer}" layer in ${label}.` : `No parsers detected for ${label}. Check that the root has the expected structure.`
|
|
33809
34696
|
);
|
|
33810
34697
|
}
|
|
33811
34698
|
return ok(
|
|
33812
|
-
`Graph generated successfully for
|
|
34699
|
+
`Graph generated successfully for ${label}.
|
|
33813
34700
|
|
|
33814
|
-
${formatProjectResult(results2,
|
|
34701
|
+
${formatProjectResult(results2, rootDir)}
|
|
33815
34702
|
|
|
33816
|
-
Use
|
|
34703
|
+
Use ${queryHint} to query.`
|
|
33817
34704
|
);
|
|
33818
34705
|
}
|
|
33819
34706
|
const projects = listProjects(monorepoRoot);
|
|
@@ -33876,6 +34763,7 @@ function runReadGraphQueryRaw(rootDir, args) {
|
|
|
33876
34763
|
const layerIsDb = args.layer === "db";
|
|
33877
34764
|
const minimal = args.minimal ?? layerIsDb;
|
|
33878
34765
|
const includeEdges = args.include_edges;
|
|
34766
|
+
const includeFindings = args.include_findings === true;
|
|
33879
34767
|
const offset = args.offset ?? 0;
|
|
33880
34768
|
const limit = args.limit;
|
|
33881
34769
|
const hasFilter = !!(search || type || module_ || nodeId || tagKey && tagValue);
|
|
@@ -33925,14 +34813,23 @@ function runReadGraphQueryRaw(rootDir, args) {
|
|
|
33925
34813
|
result2.budget_exceeded = true;
|
|
33926
34814
|
result2.hint = `Neighborhood truncated at hop ${nb.stoppedAtHop} (projected size exceeded budget). To explore further, call read_graph with node_id set to a specific neighbor from the returned nodes, or rerun with hops=${Math.max(1, nb.stoppedAtHop)} to confirm the partial view is what you wanted.`;
|
|
33927
34815
|
}
|
|
34816
|
+
if (includeFindings && layer === "db") {
|
|
34817
|
+
result2.contradictions = graph.contradictions ?? [];
|
|
34818
|
+
result2.flagged_edges = graph.flagged_edges ?? [];
|
|
34819
|
+
}
|
|
33928
34820
|
return result2;
|
|
33929
34821
|
}
|
|
33930
34822
|
if (!hasFilter) {
|
|
33931
|
-
|
|
34823
|
+
const summaryResult = {
|
|
33932
34824
|
hint: "No filter specified \u2014 returning summary only. Use search/type/module/node_id to retrieve nodes.",
|
|
33933
34825
|
layer,
|
|
33934
34826
|
summary: layerSummary(graph)
|
|
33935
34827
|
};
|
|
34828
|
+
if (includeFindings && layer === "db") {
|
|
34829
|
+
summaryResult.contradictions = graph.contradictions ?? [];
|
|
34830
|
+
summaryResult.flagged_edges = graph.flagged_edges ?? [];
|
|
34831
|
+
}
|
|
34832
|
+
return summaryResult;
|
|
33936
34833
|
}
|
|
33937
34834
|
const matched = graph.nodes.filter((n) => {
|
|
33938
34835
|
if (search && !matchesSearch(n, search)) return false;
|
|
@@ -33983,6 +34880,10 @@ function runReadGraphQueryRaw(rootDir, args) {
|
|
|
33983
34880
|
} else if (returnedEdges.length > 0) {
|
|
33984
34881
|
result.edges_hint = `${returnedEdges.length} edges between matched nodes omitted. Pass include_edges:true to retrieve them (only do this when you actually need edge data).`;
|
|
33985
34882
|
}
|
|
34883
|
+
if (includeFindings && layer === "db") {
|
|
34884
|
+
result.contradictions = graph.contradictions ?? [];
|
|
34885
|
+
result.flagged_edges = graph.flagged_edges ?? [];
|
|
34886
|
+
}
|
|
33986
34887
|
return result;
|
|
33987
34888
|
}
|
|
33988
34889
|
function runReadGraphQuery(rootDir, args) {
|
|
@@ -33997,6 +34898,8 @@ function handleReadGraph(args) {
|
|
|
33997
34898
|
return err("queries array is empty. Provide at least one query object.");
|
|
33998
34899
|
}
|
|
33999
34900
|
const inheritedProject = typeof args.project === "string" ? args.project : void 0;
|
|
34901
|
+
const inheritedWorktree = typeof args.worktree === "string" ? args.worktree : void 0;
|
|
34902
|
+
const inheritedProjectRoot = typeof args.project_root === "string" ? args.project_root : void 0;
|
|
34000
34903
|
const results = [];
|
|
34001
34904
|
let cumulativeChars = 0;
|
|
34002
34905
|
let budgetHit = false;
|
|
@@ -34014,15 +34917,18 @@ function handleReadGraph(args) {
|
|
|
34014
34917
|
});
|
|
34015
34918
|
continue;
|
|
34016
34919
|
}
|
|
34017
|
-
const
|
|
34920
|
+
const qInherited = { ...q };
|
|
34921
|
+
if (inheritedProject && !qInherited.project) qInherited.project = inheritedProject;
|
|
34922
|
+
if (inheritedWorktree && !qInherited.worktree) qInherited.worktree = inheritedWorktree;
|
|
34923
|
+
if (inheritedProjectRoot && !qInherited.project_root) qInherited.project_root = inheritedProjectRoot;
|
|
34018
34924
|
let perQueryRoot;
|
|
34019
34925
|
try {
|
|
34020
|
-
perQueryRoot =
|
|
34926
|
+
perQueryRoot = resolveRequestRoot(qInherited, monorepoRoot);
|
|
34021
34927
|
} catch (e) {
|
|
34022
34928
|
results.push({ index: i, query: q, result: { error: e.message } });
|
|
34023
34929
|
continue;
|
|
34024
34930
|
}
|
|
34025
|
-
const r = runReadGraphQuery(perQueryRoot,
|
|
34931
|
+
const r = runReadGraphQuery(perQueryRoot, qInherited);
|
|
34026
34932
|
const entry = { index: i, query: q, result: r };
|
|
34027
34933
|
const entrySize = JSON.stringify(entry, null, 2).length;
|
|
34028
34934
|
if (cumulativeChars + entrySize > BATCH_BUDGET_CHARS && results.length > 0) {
|
|
@@ -34055,12 +34961,12 @@ function handleReadGraph(args) {
|
|
|
34055
34961
|
return okJson(result);
|
|
34056
34962
|
}
|
|
34057
34963
|
function nodeToFilePath(rootDir, layer, nodeId) {
|
|
34058
|
-
if (layer === "ui" || layer === "api") return (0,
|
|
34059
|
-
if (layer === "db") return (0,
|
|
34060
|
-
const withSrc = (0,
|
|
34061
|
-
if ((0,
|
|
34062
|
-
const direct = (0,
|
|
34063
|
-
if ((0,
|
|
34964
|
+
if (layer === "ui" || layer === "api") return (0, import_node_path33.join)(rootDir, "src", nodeId);
|
|
34965
|
+
if (layer === "db") return (0, import_node_path33.join)(rootDir, "prisma", "schema.prisma");
|
|
34966
|
+
const withSrc = (0, import_node_path33.join)(rootDir, "src", nodeId);
|
|
34967
|
+
if ((0, import_node_fs28.existsSync)(withSrc)) return withSrc;
|
|
34968
|
+
const direct = (0, import_node_path33.join)(rootDir, nodeId);
|
|
34969
|
+
if ((0, import_node_fs28.existsSync)(direct)) return direct;
|
|
34064
34970
|
return null;
|
|
34065
34971
|
}
|
|
34066
34972
|
function handleInspectNode(args) {
|
|
@@ -34090,7 +34996,7 @@ function handleInspectNode(args) {
|
|
|
34090
34996
|
} else {
|
|
34091
34997
|
matched = graph.nodes;
|
|
34092
34998
|
}
|
|
34093
|
-
const allDeepFields = ["elements", "stateVars", "conditions", "variables", "responses", "params", "effects"];
|
|
34999
|
+
const allDeepFields = ["elements", "stateVars", "conditions", "variables", "responses", "params", "effects", "ui_labels", "notes"];
|
|
34094
35000
|
const requestedFields = fields ?? allDeepFields;
|
|
34095
35001
|
let filterRegex = null;
|
|
34096
35002
|
if (filter) {
|
|
@@ -34145,6 +35051,101 @@ function handleInspectNode(args) {
|
|
|
34145
35051
|
nodes: results
|
|
34146
35052
|
});
|
|
34147
35053
|
}
|
|
35054
|
+
function handleListNotes(args) {
|
|
35055
|
+
const __resolved = resolveOrErr(args);
|
|
35056
|
+
if ("content" in __resolved) return __resolved;
|
|
35057
|
+
const { rootDir } = __resolved;
|
|
35058
|
+
const layerArg = args.layer;
|
|
35059
|
+
const kindArg = args.kind?.toUpperCase();
|
|
35060
|
+
const categoryArg = args.category ?? "actionable,warning";
|
|
35061
|
+
const moduleArg = args.module;
|
|
35062
|
+
const patternArg = args.pattern;
|
|
35063
|
+
const authorArg = args.author?.toLowerCase();
|
|
35064
|
+
const limit = args.limit ?? 100;
|
|
35065
|
+
const offset = args.offset ?? 0;
|
|
35066
|
+
let patternRegex = null;
|
|
35067
|
+
if (patternArg) {
|
|
35068
|
+
try {
|
|
35069
|
+
patternRegex = new RegExp(patternArg, "i");
|
|
35070
|
+
} catch {
|
|
35071
|
+
return err(`Invalid regex pattern: "${patternArg}"`);
|
|
35072
|
+
}
|
|
35073
|
+
}
|
|
35074
|
+
const wantedCategories = (() => {
|
|
35075
|
+
const trimmed = categoryArg.trim().toLowerCase();
|
|
35076
|
+
if (trimmed === "all") return "all";
|
|
35077
|
+
const out = /* @__PURE__ */ new Set();
|
|
35078
|
+
for (const part of trimmed.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
35079
|
+
if (part === "actionable" || part === "warning" || part === "doc" || part === "custom") {
|
|
35080
|
+
out.add(part);
|
|
35081
|
+
}
|
|
35082
|
+
}
|
|
35083
|
+
if (out.size === 0) {
|
|
35084
|
+
out.add("actionable");
|
|
35085
|
+
out.add("warning");
|
|
35086
|
+
}
|
|
35087
|
+
return out;
|
|
35088
|
+
})();
|
|
35089
|
+
const layers = layerArg ? [layerArg] : getAvailableLayers(rootDir);
|
|
35090
|
+
const items = [];
|
|
35091
|
+
for (const layer of layers) {
|
|
35092
|
+
const graph = readGraph(rootDir, layer);
|
|
35093
|
+
if (!graph) continue;
|
|
35094
|
+
for (const node of graph.nodes) {
|
|
35095
|
+
const nodeNotes = node.notes;
|
|
35096
|
+
if (!nodeNotes || nodeNotes.length === 0) continue;
|
|
35097
|
+
const tags = node.tags;
|
|
35098
|
+
const nodeModule = tags?.module;
|
|
35099
|
+
if (moduleArg && nodeModule !== moduleArg) continue;
|
|
35100
|
+
for (const n of nodeNotes) {
|
|
35101
|
+
if (!n.kind || !n.text || typeof n.line !== "number") continue;
|
|
35102
|
+
const category = categorizeNoteKind(n.kind);
|
|
35103
|
+
if (wantedCategories !== "all" && !wantedCategories.has(category)) continue;
|
|
35104
|
+
if (kindArg && n.kind.toUpperCase() !== kindArg) continue;
|
|
35105
|
+
if (authorArg && (!n.author || n.author.toLowerCase() !== authorArg)) continue;
|
|
35106
|
+
if (patternRegex && !patternRegex.test(n.text)) continue;
|
|
35107
|
+
const item = {
|
|
35108
|
+
file: node.id,
|
|
35109
|
+
line: n.line,
|
|
35110
|
+
kind: n.kind,
|
|
35111
|
+
category,
|
|
35112
|
+
text: n.text
|
|
35113
|
+
};
|
|
35114
|
+
if (n.author) item.author = n.author;
|
|
35115
|
+
if (nodeModule) item.module = nodeModule;
|
|
35116
|
+
items.push(item);
|
|
35117
|
+
}
|
|
35118
|
+
}
|
|
35119
|
+
}
|
|
35120
|
+
const catOrder = { actionable: 0, warning: 1, doc: 2, custom: 3 };
|
|
35121
|
+
items.sort((a, b) => {
|
|
35122
|
+
const c = catOrder[a.category] - catOrder[b.category];
|
|
35123
|
+
if (c !== 0) return c;
|
|
35124
|
+
const k = a.kind.localeCompare(b.kind);
|
|
35125
|
+
if (k !== 0) return k;
|
|
35126
|
+
const f = a.file.localeCompare(b.file);
|
|
35127
|
+
if (f !== 0) return f;
|
|
35128
|
+
return a.line - b.line;
|
|
35129
|
+
});
|
|
35130
|
+
const total = items.length;
|
|
35131
|
+
const paged = items.slice(offset, offset + limit);
|
|
35132
|
+
const hasMore = offset + paged.length < total;
|
|
35133
|
+
return okJson({
|
|
35134
|
+
total,
|
|
35135
|
+
returned: paged.length,
|
|
35136
|
+
has_more: hasMore,
|
|
35137
|
+
...hasMore ? { next_offset: offset + paged.length } : {},
|
|
35138
|
+
filter: {
|
|
35139
|
+
layer: layerArg ?? "all",
|
|
35140
|
+
kind: kindArg ?? null,
|
|
35141
|
+
category: categoryArg,
|
|
35142
|
+
module: moduleArg ?? null,
|
|
35143
|
+
pattern: patternArg ?? null,
|
|
35144
|
+
author: authorArg ?? null
|
|
35145
|
+
},
|
|
35146
|
+
items: paged
|
|
35147
|
+
});
|
|
35148
|
+
}
|
|
34148
35149
|
function handleGrepNodes(args) {
|
|
34149
35150
|
const __resolved = resolveOrErr(args);
|
|
34150
35151
|
if ("content" in __resolved) return __resolved;
|
|
@@ -34207,11 +35208,11 @@ function handleGrepNodes(args) {
|
|
|
34207
35208
|
let filesSearched = 0;
|
|
34208
35209
|
let truncated = false;
|
|
34209
35210
|
for (const [filePath, nodeId] of filePaths) {
|
|
34210
|
-
if (!(0,
|
|
35211
|
+
if (!(0, import_node_fs28.existsSync)(filePath)) continue;
|
|
34211
35212
|
filesSearched++;
|
|
34212
35213
|
let content;
|
|
34213
35214
|
try {
|
|
34214
|
-
content = (0,
|
|
35215
|
+
content = (0, import_node_fs28.readFileSync)(filePath, "utf-8");
|
|
34215
35216
|
} catch {
|
|
34216
35217
|
continue;
|
|
34217
35218
|
}
|
|
@@ -34333,16 +35334,15 @@ function handleStartChartServer(args) {
|
|
|
34333
35334
|
});
|
|
34334
35335
|
}
|
|
34335
35336
|
const entryPath = process.argv[1];
|
|
34336
|
-
const logDir = (0,
|
|
34337
|
-
(0,
|
|
34338
|
-
const logPath = (0,
|
|
34339
|
-
const out = (0,
|
|
34340
|
-
const err2 = (0,
|
|
35337
|
+
const logDir = (0, import_node_path33.join)((0, import_node_os6.homedir)(), LAUNCHSECURE_DIR);
|
|
35338
|
+
(0, import_node_fs28.mkdirSync)(logDir, { recursive: true });
|
|
35339
|
+
const logPath = (0, import_node_path33.join)(logDir, "launch-chart.log");
|
|
35340
|
+
const out = (0, import_node_fs28.openSync)(logPath, "a");
|
|
35341
|
+
const err2 = (0, import_node_fs28.openSync)(logPath, "a");
|
|
34341
35342
|
const portArgs = args.port ? ["--port", String(args.port)] : [];
|
|
34342
35343
|
const child = (0, import_node_child_process3.spawn)(process.execPath, [entryPath, "serve", ...portArgs], {
|
|
34343
35344
|
detached: true,
|
|
34344
|
-
stdio: ["ignore", out, err2]
|
|
34345
|
-
env: { ...process.env, LAUNCH_CHART_AUTOSERVE: "" }
|
|
35345
|
+
stdio: ["ignore", out, err2]
|
|
34346
35346
|
});
|
|
34347
35347
|
child.unref();
|
|
34348
35348
|
return okJson({
|
|
@@ -34467,20 +35467,20 @@ function handleDetectProjectStack() {
|
|
|
34467
35467
|
if (ref.type === "references_api") stats.references_api++;
|
|
34468
35468
|
}
|
|
34469
35469
|
}
|
|
34470
|
-
const srcDir = (0,
|
|
34471
|
-
if ((0,
|
|
35470
|
+
const srcDir = (0, import_node_path33.join)(rootDir, "src");
|
|
35471
|
+
if ((0, import_node_fs28.existsSync)(srcDir)) {
|
|
34472
35472
|
const scanDir = (dir) => {
|
|
34473
|
-
if (!(0,
|
|
34474
|
-
for (const entry of (0,
|
|
35473
|
+
if (!(0, import_node_fs28.existsSync)(dir)) return;
|
|
35474
|
+
for (const entry of (0, import_node_fs28.readdirSync)(dir, { withFileTypes: true })) {
|
|
34475
35475
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
34476
|
-
const full = (0,
|
|
35476
|
+
const full = (0, import_node_path33.join)(dir, entry.name);
|
|
34477
35477
|
if (entry.isDirectory()) {
|
|
34478
35478
|
scanDir(full);
|
|
34479
35479
|
continue;
|
|
34480
35480
|
}
|
|
34481
|
-
if (![".ts", ".tsx"].includes((0,
|
|
35481
|
+
if (![".ts", ".tsx"].includes((0, import_node_path33.extname)(entry.name))) continue;
|
|
34482
35482
|
try {
|
|
34483
|
-
const content = (0,
|
|
35483
|
+
const content = (0, import_node_fs28.readFileSync)(full, "utf-8");
|
|
34484
35484
|
const matches = content.match(/@api\s+(GET|POST|PUT|DELETE|PATCH)\s+\/\S+/g);
|
|
34485
35485
|
if (matches) stats.annotations += matches.length;
|
|
34486
35486
|
} catch {
|
|
@@ -34499,7 +35499,7 @@ function handleDetectProjectStack() {
|
|
|
34499
35499
|
name: p.name,
|
|
34500
35500
|
root: p.root,
|
|
34501
35501
|
absolute_root: p.absoluteRoot,
|
|
34502
|
-
has_graph: (0,
|
|
35502
|
+
has_graph: (0, import_node_fs28.existsSync)((0, import_node_path33.join)(p.absoluteRoot, LAUNCHSECURE_DIR, "graphs"))
|
|
34503
35503
|
}));
|
|
34504
35504
|
return okJson({
|
|
34505
35505
|
languages,
|
|
@@ -34613,6 +35613,10 @@ async function handleMessage(msg) {
|
|
|
34613
35613
|
respond(id ?? null, withFreshnessMeta(handleBlastPoints(args), args));
|
|
34614
35614
|
return;
|
|
34615
35615
|
}
|
|
35616
|
+
if (toolName === "list_notes") {
|
|
35617
|
+
respond(id ?? null, withFreshnessMeta(handleListNotes(args), args));
|
|
35618
|
+
return;
|
|
35619
|
+
}
|
|
34616
35620
|
respondError(id ?? null, -32601, `Unknown tool: ${toolName}`);
|
|
34617
35621
|
return;
|
|
34618
35622
|
}
|
|
@@ -34677,6 +35681,53 @@ function startGraphMcpServer() {
|
|
|
34677
35681
|
|
|
34678
35682
|
// src/server/cli.ts
|
|
34679
35683
|
init_launch_kit_paths();
|
|
35684
|
+
|
|
35685
|
+
// src/server/cred-shape.ts
|
|
35686
|
+
var fs9 = __toESM(require("node:fs"));
|
|
35687
|
+
var path11 = __toESM(require("node:path"));
|
|
35688
|
+
var CONFIG_FILENAME = ".launch-secure.cred.config";
|
|
35689
|
+
function inferCourseName(serverUrl) {
|
|
35690
|
+
try {
|
|
35691
|
+
const host = new URL(serverUrl).hostname.toLowerCase();
|
|
35692
|
+
if (host === "localhost" || host === "127.0.0.1" || host.endsWith(".local")) return "local";
|
|
35693
|
+
if (host.includes("staging")) return "staging";
|
|
35694
|
+
if (host.endsWith(".vercel.app")) return "prod";
|
|
35695
|
+
return host.split(".")[0] || "default";
|
|
35696
|
+
} catch {
|
|
35697
|
+
return "default";
|
|
35698
|
+
}
|
|
35699
|
+
}
|
|
35700
|
+
function toNested(cred) {
|
|
35701
|
+
if (cred.profiles && cred.active && cred.profiles[cred.active]) {
|
|
35702
|
+
return { active: cred.active, profiles: cred.profiles };
|
|
35703
|
+
}
|
|
35704
|
+
if (!cred.pat || !cred.orgSlug || !cred.projectSlug || !cred.serverUrl) {
|
|
35705
|
+
return null;
|
|
35706
|
+
}
|
|
35707
|
+
const name = inferCourseName(cred.serverUrl);
|
|
35708
|
+
return {
|
|
35709
|
+
active: name,
|
|
35710
|
+
profiles: {
|
|
35711
|
+
[name]: {
|
|
35712
|
+
pat: cred.pat,
|
|
35713
|
+
orgSlug: cred.orgSlug,
|
|
35714
|
+
projectSlug: cred.projectSlug,
|
|
35715
|
+
serverUrl: cred.serverUrl
|
|
35716
|
+
}
|
|
35717
|
+
}
|
|
35718
|
+
};
|
|
35719
|
+
}
|
|
35720
|
+
function readCredFile(repoRoot) {
|
|
35721
|
+
const p = path11.join(repoRoot, CONFIG_FILENAME);
|
|
35722
|
+
if (!fs9.existsSync(p)) return null;
|
|
35723
|
+
try {
|
|
35724
|
+
return JSON.parse(fs9.readFileSync(p, "utf-8"));
|
|
35725
|
+
} catch (err2) {
|
|
35726
|
+
throw new Error(`could not parse ${CONFIG_FILENAME}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
35727
|
+
}
|
|
35728
|
+
}
|
|
35729
|
+
|
|
35730
|
+
// src/server/cli.ts
|
|
34680
35731
|
var DEFAULT_CAPABILITIES = {
|
|
34681
35732
|
workspace_setup: true,
|
|
34682
35733
|
terminal: true
|
|
@@ -34740,7 +35791,7 @@ function parseArgs() {
|
|
|
34740
35791
|
return { port, token, serverUrl: LAUNCHSECURE_URL, subcommand };
|
|
34741
35792
|
}
|
|
34742
35793
|
function tryListen(server, port, maxRetries = 10) {
|
|
34743
|
-
return new Promise((
|
|
35794
|
+
return new Promise((resolve6, reject) => {
|
|
34744
35795
|
let attempts = 0;
|
|
34745
35796
|
function attempt(p) {
|
|
34746
35797
|
server.once("error", (err2) => {
|
|
@@ -34751,7 +35802,7 @@ function tryListen(server, port, maxRetries = 10) {
|
|
|
34751
35802
|
reject(err2);
|
|
34752
35803
|
}
|
|
34753
35804
|
});
|
|
34754
|
-
server.listen(p, "127.0.0.1", () =>
|
|
35805
|
+
server.listen(p, "127.0.0.1", () => resolve6(p));
|
|
34755
35806
|
}
|
|
34756
35807
|
attempt(port);
|
|
34757
35808
|
});
|
|
@@ -34772,7 +35823,7 @@ function saveCredentials(creds) {
|
|
|
34772
35823
|
});
|
|
34773
35824
|
}
|
|
34774
35825
|
function verifyToken(serverUrl, token) {
|
|
34775
|
-
return new Promise((
|
|
35826
|
+
return new Promise((resolve6) => {
|
|
34776
35827
|
const url = new URL("/api/mcp/verify", serverUrl);
|
|
34777
35828
|
const body = JSON.stringify({ token });
|
|
34778
35829
|
const mod = url.protocol === "https:" ? import_https.default : import_http.default;
|
|
@@ -34787,30 +35838,30 @@ function verifyToken(serverUrl, token) {
|
|
|
34787
35838
|
res.on("data", (chunk) => data += chunk);
|
|
34788
35839
|
res.on("end", () => {
|
|
34789
35840
|
try {
|
|
34790
|
-
|
|
35841
|
+
resolve6(JSON.parse(data));
|
|
34791
35842
|
} catch {
|
|
34792
|
-
|
|
35843
|
+
resolve6({ valid: false, error: "Invalid response from server" });
|
|
34793
35844
|
}
|
|
34794
35845
|
});
|
|
34795
35846
|
});
|
|
34796
35847
|
req.on("error", (err2) => {
|
|
34797
|
-
|
|
35848
|
+
resolve6({ valid: false, error: `Cannot reach server: ${err2.message}` });
|
|
34798
35849
|
});
|
|
34799
35850
|
req.setTimeout(1e4, () => {
|
|
34800
35851
|
req.destroy();
|
|
34801
|
-
|
|
35852
|
+
resolve6({ valid: false, error: "Connection timed out" });
|
|
34802
35853
|
});
|
|
34803
35854
|
req.write(body);
|
|
34804
35855
|
req.end();
|
|
34805
35856
|
});
|
|
34806
35857
|
}
|
|
34807
35858
|
function httpRequest2(reqUrl, options, body, timeout = 3e4) {
|
|
34808
|
-
return new Promise((
|
|
35859
|
+
return new Promise((resolve6, reject) => {
|
|
34809
35860
|
const mod = reqUrl.protocol === "https:" ? import_https.default : import_http.default;
|
|
34810
35861
|
const r = mod.request(reqUrl, options, (resp) => {
|
|
34811
35862
|
let data = "";
|
|
34812
35863
|
resp.on("data", (chunk) => data += chunk);
|
|
34813
|
-
resp.on("end", () =>
|
|
35864
|
+
resp.on("end", () => resolve6({ status: resp.statusCode || 0, headers: resp.headers, body: data }));
|
|
34814
35865
|
});
|
|
34815
35866
|
r.on("error", reject);
|
|
34816
35867
|
r.setTimeout(timeout, () => {
|
|
@@ -35290,7 +36341,7 @@ if (parsedArgs.subcommand === "graph:generate" || parsedArgs.subcommand === "gra
|
|
|
35290
36341
|
const result = (0, import_child_process4.spawnSync)(
|
|
35291
36342
|
process.execPath,
|
|
35292
36343
|
[chartEntry, chartSubcommand, ...process.argv.slice(3)],
|
|
35293
|
-
{ stdio: "inherit"
|
|
36344
|
+
{ stdio: "inherit" }
|
|
35294
36345
|
);
|
|
35295
36346
|
process.exit(result.status ?? 1);
|
|
35296
36347
|
}
|
|
@@ -35300,75 +36351,28 @@ if (parsedArgs.subcommand === "mcp:graph") {
|
|
|
35300
36351
|
var __isMcpMode = parsedArgs.subcommand === "mcp:graph";
|
|
35301
36352
|
var __isRadarMode = parsedArgs.subcommand === "radar";
|
|
35302
36353
|
var radar = null;
|
|
35303
|
-
var CRED_CONFIG_FILENAME = ".launch-secure.cred.config";
|
|
35304
|
-
var LEGACY_CRED_CONFIG_FILENAME = ".launch-secure.config";
|
|
35305
|
-
function migrateLegacyCredConfig(repoRoot) {
|
|
35306
|
-
const legacy = import_path9.default.join(repoRoot, LEGACY_CRED_CONFIG_FILENAME);
|
|
35307
|
-
const dest = import_path9.default.join(repoRoot, CRED_CONFIG_FILENAME);
|
|
35308
|
-
if (!import_fs8.default.existsSync(legacy) || import_fs8.default.existsSync(dest)) return;
|
|
35309
|
-
let parsed;
|
|
35310
|
-
try {
|
|
35311
|
-
parsed = JSON.parse(import_fs8.default.readFileSync(legacy, "utf-8"));
|
|
35312
|
-
} catch {
|
|
35313
|
-
return;
|
|
35314
|
-
}
|
|
35315
|
-
const pat = parsed?.pat;
|
|
35316
|
-
if (typeof pat !== "string" || !pat.startsWith("ls_pat_")) return;
|
|
35317
|
-
import_fs8.default.renameSync(legacy, dest);
|
|
35318
|
-
console.warn(`[launchpod] migrated legacy ${LEGACY_CRED_CONFIG_FILENAME} \u2192 ${CRED_CONFIG_FILENAME} (the old name is now reserved for file-backed-config)`);
|
|
35319
|
-
}
|
|
35320
36354
|
function readLaunchSecureMcpConfig() {
|
|
35321
|
-
|
|
35322
|
-
const
|
|
35323
|
-
if (
|
|
35324
|
-
|
|
35325
|
-
try {
|
|
35326
|
-
parsed = JSON.parse(import_fs8.default.readFileSync(configPath, "utf-8"));
|
|
35327
|
-
} catch (err2) {
|
|
35328
|
-
throw new Error(`Could not parse ${configPath}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
35329
|
-
}
|
|
35330
|
-
const block = parsed.profiles && parsed.active ? parsed.profiles[parsed.active] : parsed;
|
|
35331
|
-
if (!block) {
|
|
35332
|
-
throw new Error(`${CRED_CONFIG_FILENAME} active course "${parsed.active}" not found in profiles.`);
|
|
35333
|
-
}
|
|
35334
|
-
const { pat: pat2, orgSlug: orgSlug2, projectSlug: projectSlug2, serverUrl } = block;
|
|
35335
|
-
if (!pat2 || !pat2.startsWith("ls_pat_")) {
|
|
35336
|
-
throw new Error(`${CRED_CONFIG_FILENAME} "pat" is missing or not a LaunchSecure PAT (ls_pat_...).`);
|
|
35337
|
-
}
|
|
35338
|
-
if (!orgSlug2 || !projectSlug2 || !serverUrl) {
|
|
35339
|
-
throw new Error(`${CRED_CONFIG_FILENAME} is missing required fields (orgSlug, projectSlug, serverUrl).`);
|
|
35340
|
-
}
|
|
35341
|
-
return { pat: pat2, orgSlug: orgSlug2, projectSlug: projectSlug2, serverUrl, source: CRED_CONFIG_FILENAME };
|
|
36355
|
+
const fix = `Run \`npx @launchsecure/launch-kit@latest refresh\` to re-sync this project (or \`init\` if you haven't bootstrapped yet).`;
|
|
36356
|
+
const cred = readCredFile(REPO_ROOT);
|
|
36357
|
+
if (!cred) {
|
|
36358
|
+
throw new Error(`${CONFIG_FILENAME} not found in ${REPO_ROOT}. ${fix}`);
|
|
35342
36359
|
}
|
|
35343
|
-
const
|
|
35344
|
-
if (!
|
|
35345
|
-
throw new Error(
|
|
35346
|
-
`Neither ${CRED_CONFIG_FILENAME} nor .mcp.json found in ${REPO_ROOT}. Run \`npx launch-kit init --token=... --org=... --project=...\` to bootstrap.`
|
|
35347
|
-
);
|
|
36360
|
+
const nested = toNested(cred);
|
|
36361
|
+
if (!nested) {
|
|
36362
|
+
throw new Error(`${CONFIG_FILENAME} is malformed or missing required fields (pat/orgSlug/projectSlug/serverUrl). ${fix}`);
|
|
35348
36363
|
}
|
|
35349
|
-
const
|
|
35350
|
-
|
|
35351
|
-
|
|
35352
|
-
const entry = raw.mcpServers?.[entryName];
|
|
35353
|
-
if (!entry?.url) {
|
|
35354
|
-
throw new Error(`No "${entryName}" entry with url found in .mcp.json (set LAUNCHPOD_MCP_NAME=<name> to pick a different one, or migrate to ${CRED_CONFIG_FILENAME} via \`launch-kit init\`)`);
|
|
36364
|
+
const profile = nested.profiles[nested.active];
|
|
36365
|
+
if (!profile) {
|
|
36366
|
+
throw new Error(`${CONFIG_FILENAME} active course "${nested.active}" not found in profiles. ${fix}`);
|
|
35355
36367
|
}
|
|
35356
|
-
const
|
|
35357
|
-
|
|
35358
|
-
|
|
35359
|
-
throw new Error(
|
|
35360
|
-
`.mcp.json launch-secure Authorization header is not a PAT (ls_pat_...). Migrate to ${CRED_CONFIG_FILENAME} via \`launch-kit init\`, or update the header.`
|
|
35361
|
-
);
|
|
36368
|
+
const { pat, orgSlug, projectSlug, serverUrl } = profile;
|
|
36369
|
+
if (!pat || !pat.startsWith("ls_pat_")) {
|
|
36370
|
+
throw new Error(`${CONFIG_FILENAME} "pat" is missing or not a LaunchSecure PAT (ls_pat_...). ${fix}`);
|
|
35362
36371
|
}
|
|
35363
|
-
|
|
35364
|
-
|
|
35365
|
-
if (!orgSlug || !projectSlug) {
|
|
35366
|
-
throw new Error(
|
|
35367
|
-
"Missing X-Org-Slug / X-Project-Slug headers in .mcp.json launch-secure entry."
|
|
35368
|
-
);
|
|
36372
|
+
if (!orgSlug || !projectSlug || !serverUrl) {
|
|
36373
|
+
throw new Error(`${CONFIG_FILENAME} is missing required fields (orgSlug, projectSlug, serverUrl). ${fix}`);
|
|
35369
36374
|
}
|
|
35370
|
-
|
|
35371
|
-
return { pat, orgSlug, projectSlug, serverUrl: `${url.protocol}//${url.host}`, source: `.mcp.json[${entryName}]` };
|
|
36375
|
+
return { pat, orgSlug, projectSlug, serverUrl, source: `${CONFIG_FILENAME}[${nested.active}]` };
|
|
35372
36376
|
}
|
|
35373
36377
|
if (!__isMcpMode) {
|
|
35374
36378
|
let gracefulShutdown = function() {
|