@stackables/bridge 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { parseBridgeChevrotain, parseBridgeChevrotain as parseBridge } from "./parser/index.js";
1
+ export { parseBridgeChevrotain, parseBridgeChevrotain as parseBridge, parseBridgeDiagnostics } from "./parser/index.js";
2
+ export type { BridgeDiagnostic, BridgeParseResult } from "./parser/index.js";
2
3
  export { bridgeTransform, getBridgeTraces, useBridgeTracing } from "./bridge-transform.js";
3
4
  export type { BridgeOptions, InstructionSource } from "./bridge-transform.js";
4
5
  export { builtinTools, std, createHttpCall } from "./tools/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,IAAI,WAAW,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACxH,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
package/build/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { parseBridgeChevrotain, parseBridgeChevrotain as parseBridge } from "./parser/index.js";
1
+ export { parseBridgeChevrotain, parseBridgeChevrotain as parseBridge, parseBridgeDiagnostics } from "./parser/index.js";
2
2
  export { bridgeTransform, getBridgeTraces, useBridgeTracing } from "./bridge-transform.js";
3
3
  export { builtinTools, std, createHttpCall } from "./tools/index.js";
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Re-exports the public parse function as well as the lexer for direct access.
5
5
  */
6
- export { parseBridgeChevrotain } from "./parser.js";
6
+ export { parseBridgeChevrotain, parseBridgeDiagnostics } from "./parser.js";
7
+ export type { BridgeDiagnostic, BridgeParseResult } from "./parser.js";
7
8
  export { BridgeLexer, allTokens } from "./lexer.js";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC5E,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
@@ -3,5 +3,5 @@
3
3
  *
4
4
  * Re-exports the public parse function as well as the lexer for direct access.
5
5
  */
6
- export { parseBridgeChevrotain } from "./parser.js";
6
+ export { parseBridgeChevrotain, parseBridgeDiagnostics } from "./parser.js";
7
7
  export { BridgeLexer, allTokens } from "./lexer.js";
@@ -1,3 +1,29 @@
1
1
  import type { Instruction } from "../types.js";
2
2
  export declare function parseBridgeChevrotain(text: string): Instruction[];
3
+ export type BridgeDiagnostic = {
4
+ message: string;
5
+ severity: "error" | "warning";
6
+ range: {
7
+ start: {
8
+ line: number;
9
+ character: number;
10
+ };
11
+ end: {
12
+ line: number;
13
+ character: number;
14
+ };
15
+ };
16
+ };
17
+ export type BridgeParseResult = {
18
+ instructions: Instruction[];
19
+ diagnostics: BridgeDiagnostic[];
20
+ /** 1-based start line for each top-level instruction */
21
+ startLines: Map<Instruction, number>;
22
+ };
23
+ /**
24
+ * Parse a Bridge DSL text and return both the AST and all diagnostics.
25
+ * Uses Chevrotain's error recovery — always returns a (possibly partial) AST
26
+ * even when the file has errors. Designed for LSP/IDE use.
27
+ */
28
+ export declare function parseBridgeDiagnostics(text: string): BridgeParseResult;
3
29
  //# sourceMappingURL=parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser/parser.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAKV,WAAW,EAMZ,MAAM,aAAa,CAAC;AA0oBrB,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAEjE"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser/parser.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAKV,WAAW,EAMZ,MAAM,aAAa,CAAC;AA6oBrB,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAEjE;AAID,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,KAAK,EAAE;QACL,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3C,GAAG,EAAI;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KAC5C,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,wDAAwD;IACxD,UAAU,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAqDtE"}
@@ -24,9 +24,9 @@ function assertNotReserved(name, lineNum, label) {
24
24
  // Grammar (CstParser)
25
25
  // ═══════════════════════════════════════════════════════════════════════════
26
26
  class BridgeParser extends CstParser {
27
- constructor() {
27
+ constructor(opts = {}) {
28
28
  super(allTokens, {
29
- recoveryEnabled: false,
29
+ recoveryEnabled: opts.recovery ?? false,
30
30
  maxLookahead: 4,
31
31
  });
32
32
  this.performSelfAnalysis();
@@ -607,8 +607,11 @@ class BridgeParser extends CstParser {
607
607
  this.CONSUME(RCurly);
608
608
  });
609
609
  }
610
- // Singleton parser instance (Chevrotain best practice)
610
+ // Singleton parser instances (Chevrotain best practice)
611
+ // Strict instance: throws on first error (used by parseBridgeChevrotain)
611
612
  const parserInstance = new BridgeParser();
613
+ // Lenient instance: error recovery enabled (used by parseBridgeDiagnostics)
614
+ const diagParserInstance = new BridgeParser({ recovery: true });
612
615
  const BRIDGE_VERSION = "1.4";
613
616
  // ═══════════════════════════════════════════════════════════════════════════
614
617
  // Public API
@@ -616,6 +619,62 @@ const BRIDGE_VERSION = "1.4";
616
619
  export function parseBridgeChevrotain(text) {
617
620
  return internalParse(text);
618
621
  }
622
+ /**
623
+ * Parse a Bridge DSL text and return both the AST and all diagnostics.
624
+ * Uses Chevrotain's error recovery — always returns a (possibly partial) AST
625
+ * even when the file has errors. Designed for LSP/IDE use.
626
+ */
627
+ export function parseBridgeDiagnostics(text) {
628
+ const diagnostics = [];
629
+ // 1. Lex
630
+ const lexResult = BridgeLexer.tokenize(text);
631
+ for (const e of lexResult.errors) {
632
+ diagnostics.push({
633
+ message: e.message,
634
+ severity: "error",
635
+ range: {
636
+ start: { line: (e.line ?? 1) - 1, character: (e.column ?? 1) - 1 },
637
+ end: { line: (e.line ?? 1) - 1, character: (e.column ?? 1) - 1 + e.length },
638
+ },
639
+ });
640
+ }
641
+ // 2. Parse with Chevrotain error recovery (builds partial CST past errors)
642
+ diagParserInstance.input = lexResult.tokens;
643
+ const cst = diagParserInstance.program();
644
+ for (const e of diagParserInstance.errors) {
645
+ const t = e.token;
646
+ diagnostics.push({
647
+ message: e.message,
648
+ severity: "error",
649
+ range: {
650
+ start: { line: (t.startLine ?? 1) - 1, character: (t.startColumn ?? 1) - 1 },
651
+ end: { line: (t.endLine ?? t.startLine ?? 1) - 1, character: t.endColumn ?? t.startColumn ?? 1 },
652
+ },
653
+ });
654
+ }
655
+ // 3. Visit → AST (semantic errors thrown as "Line N: ..." messages)
656
+ let instructions = [];
657
+ let startLines = new Map();
658
+ try {
659
+ const result = toBridgeAst(cst, []);
660
+ instructions = result.instructions;
661
+ startLines = result.startLines;
662
+ }
663
+ catch (err) {
664
+ const msg = String(err?.message ?? err);
665
+ const m = msg.match(/^Line (\d+):/);
666
+ const errorLine = m ? parseInt(m[1]) - 1 : 0;
667
+ diagnostics.push({
668
+ message: msg.replace(/^Line \d+:\s*/, ""),
669
+ severity: "error",
670
+ range: {
671
+ start: { line: errorLine, character: 0 },
672
+ end: { line: errorLine, character: 999 },
673
+ },
674
+ });
675
+ }
676
+ return { instructions, diagnostics, startLines };
677
+ }
619
678
  function internalParse(text, previousInstructions) {
620
679
  // 1. Lex
621
680
  const lexResult = BridgeLexer.tokenize(text);
@@ -631,7 +690,7 @@ function internalParse(text, previousInstructions) {
631
690
  throw new Error(e.message);
632
691
  }
633
692
  // 3. Visit → AST
634
- return toBridgeAst(cst, previousInstructions);
693
+ return toBridgeAst(cst, previousInstructions).instructions;
635
694
  }
636
695
  // ═══════════════════════════════════════════════════════════════════════════
637
696
  // CST → AST transformation (imperative visitor)
@@ -826,6 +885,7 @@ function extractJsonValueStripped(node) {
826
885
  // ═══════════════════════════════════════════════════════════════════════════
827
886
  function toBridgeAst(cst, previousInstructions) {
828
887
  const instructions = [];
888
+ const startLines = new Map();
829
889
  // If called from passthrough expansion, seed with prior context
830
890
  const contextInstructions = previousInstructions
831
891
  ? [...previousInstructions]
@@ -851,22 +911,37 @@ function toBridgeAst(cst, previousInstructions) {
851
911
  tagged.push({ offset: findFirstToken(n)?.startOffset ?? 0, kind: "bridge", node: n });
852
912
  tagged.sort((a, b) => a.offset - b.offset);
853
913
  for (const item of tagged) {
914
+ const startLine = findFirstToken(item.node)?.startLine ?? 1;
854
915
  switch (item.kind) {
855
- case "const":
856
- instructions.push(buildConstDef(item.node));
916
+ case "const": {
917
+ const inst = buildConstDef(item.node);
918
+ instructions.push(inst);
919
+ startLines.set(inst, startLine);
857
920
  break;
858
- case "tool":
859
- instructions.push(buildToolDef(item.node, [...contextInstructions, ...instructions]));
921
+ }
922
+ case "tool": {
923
+ const inst = buildToolDef(item.node, [...contextInstructions, ...instructions]);
924
+ instructions.push(inst);
925
+ startLines.set(inst, startLine);
860
926
  break;
861
- case "define":
862
- instructions.push(buildDefineDef(item.node));
927
+ }
928
+ case "define": {
929
+ const inst = buildDefineDef(item.node);
930
+ instructions.push(inst);
931
+ startLines.set(inst, startLine);
863
932
  break;
864
- case "bridge":
865
- instructions.push(...buildBridge(item.node, [...contextInstructions, ...instructions]));
933
+ }
934
+ case "bridge": {
935
+ const newInsts = buildBridge(item.node, [...contextInstructions, ...instructions]);
936
+ for (const bi of newInsts) {
937
+ instructions.push(bi);
938
+ startLines.set(bi, startLine);
939
+ }
866
940
  break;
941
+ }
867
942
  }
868
943
  }
869
- return instructions;
944
+ return { instructions, startLines };
870
945
  }
871
946
  // ── Const ───────────────────────────────────────────────────────────────
872
947
  function buildConstDef(node) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackables/bridge",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Declarative dataflow for GraphQL",
5
5
  "main": "./build/index.js",
6
6
  "type": "module",