webpipe-js 2.0.71 → 2.0.97

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/index.cjs CHANGED
@@ -299,6 +299,32 @@ var Parser = class {
299
299
  skipWhitespaceOnly() {
300
300
  this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r" || ch === "\n");
301
301
  }
302
+ skipStandaloneCommentsBeforeKeywords(keywords) {
303
+ while (true) {
304
+ this.skipWhitespaceOnly();
305
+ const commentStart = this.pos;
306
+ const comment = this.tryParse(() => this.parseStandaloneComment());
307
+ if (!comment) {
308
+ this.pos = commentStart;
309
+ return;
310
+ }
311
+ const afterComment = this.pos;
312
+ if (this.cur() === "\n") this.pos++;
313
+ while (true) {
314
+ this.skipWhitespaceOnly();
315
+ const nestedComment = this.tryParse(() => this.parseStandaloneComment());
316
+ if (!nestedComment) break;
317
+ if (this.cur() === "\n") this.pos++;
318
+ }
319
+ const followedByKeyword = keywords.some((keyword) => this.text.startsWith(keyword, this.pos));
320
+ this.pos = afterComment;
321
+ if (!followedByKeyword) {
322
+ this.pos = commentStart;
323
+ return;
324
+ }
325
+ if (this.cur() === "\n") this.pos++;
326
+ }
327
+ }
302
328
  skipInlineSpaces() {
303
329
  this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r");
304
330
  }
@@ -526,35 +552,10 @@ var Parser = class {
526
552
  parsePipelineStep() {
527
553
  const result = this.tryParse(() => this.parseResultStep());
528
554
  if (result) return result;
529
- const ifStep = this.tryParse(() => this.parseIfStep());
530
- if (ifStep) return ifStep;
531
555
  const dispatchStep = this.tryParse(() => this.parseDispatchStep());
532
556
  if (dispatchStep) return dispatchStep;
533
- const foreachStep = this.tryParse(() => this.parseForeachStep());
534
- if (foreachStep) return foreachStep;
535
557
  return this.parseRegularStep();
536
558
  }
537
- parseForeachStep() {
538
- this.skipWhitespaceOnly();
539
- const start = this.pos;
540
- this.expect("|>");
541
- this.skipInlineSpaces();
542
- this.expect("foreach");
543
- if (this.cur() !== " " && this.cur() !== " ") {
544
- throw new ParseFailure("space after foreach", this.pos);
545
- }
546
- this.skipInlineSpaces();
547
- const selector = this.consumeWhile((c) => c !== "\n" && c !== "#").trim();
548
- if (selector.length === 0) {
549
- throw new ParseFailure("foreach selector", this.pos);
550
- }
551
- this.skipSpaces();
552
- const pipeline = this.parseIfPipeline("end");
553
- this.skipSpaces();
554
- this.expect("end");
555
- const end = this.pos;
556
- return { kind: "Foreach", selector, pipeline, start, end };
557
- }
558
559
  parseRegularStep() {
559
560
  this.skipWhitespaceOnly();
560
561
  const start = this.pos;
@@ -563,7 +564,9 @@ var Parser = class {
563
564
  const nameStart = this.pos;
564
565
  const name = this.parseIdentifier();
565
566
  const nameEnd = this.pos;
566
- const args = this.parseInlineArgs();
567
+ const inlineArgs = this.parseInlineArgs();
568
+ const args = inlineArgs.args;
569
+ const argSpans = inlineArgs.argSpans;
567
570
  this.skipInlineSpaces();
568
571
  let config = "";
569
572
  let configType = "quoted";
@@ -584,7 +587,7 @@ var Parser = class {
584
587
  const parsedJoinTargets = name === "join" ? this.parseJoinTaskNames(config) : void 0;
585
588
  this.skipWhitespaceOnly();
586
589
  const end = this.pos;
587
- return { kind: "Regular", name, nameStart, nameEnd, args, config, configType, hasConfig, configStart, configEnd, condition, parsedJoinTargets, start, end };
590
+ return { kind: "Regular", name, nameStart, nameEnd, args, argSpans, config, configType, hasConfig, configStart, configEnd, condition, parsedJoinTargets, start, end };
588
591
  }
589
592
  /**
590
593
  * Parse optional step condition (tag expression after the config)
@@ -642,58 +645,58 @@ var Parser = class {
642
645
  * Split argument content by commas while respecting nesting depth and strings
643
646
  * Example: `"url", {a:1, b:2}` -> [`"url"`, `{a:1, b:2}`]
644
647
  */
645
- splitBalancedArgs(content) {
648
+ splitBalancedArgs(content, baseOffset) {
646
649
  const args = [];
647
- let current = "";
650
+ const argSpans = [];
651
+ let segmentStart = 0;
648
652
  let depth = 0;
649
653
  let inString = false;
650
654
  let stringChar = "";
651
655
  let escapeNext = false;
656
+ const pushArg = (segmentEnd) => {
657
+ let start = segmentStart;
658
+ let end = segmentEnd;
659
+ while (start < end && /\s/.test(content[start])) start++;
660
+ while (end > start && /\s/.test(content[end - 1])) end--;
661
+ if (start < end) {
662
+ args.push(content.slice(start, end));
663
+ argSpans.push({ start: baseOffset + start, end: baseOffset + end });
664
+ }
665
+ };
652
666
  for (let i = 0; i < content.length; i++) {
653
667
  const ch = content[i];
654
668
  if (escapeNext) {
655
- current += ch;
656
669
  escapeNext = false;
657
670
  continue;
658
671
  }
659
672
  if (ch === "\\" && inString) {
660
- current += ch;
661
673
  escapeNext = true;
662
674
  continue;
663
675
  }
664
- if ((ch === '"' || ch === "`") && !inString) {
676
+ if ((ch === '"' || ch === "'" || ch === "`") && !inString) {
665
677
  inString = true;
666
678
  stringChar = ch;
667
- current += ch;
668
679
  continue;
669
680
  }
670
681
  if (ch === stringChar && inString) {
671
682
  inString = false;
672
683
  stringChar = "";
673
- current += ch;
674
684
  continue;
675
685
  }
676
686
  if (inString) {
677
- current += ch;
678
687
  continue;
679
688
  }
680
689
  if (ch === "(" || ch === "[" || ch === "{") {
681
690
  depth++;
682
- current += ch;
683
691
  } else if (ch === ")" || ch === "]" || ch === "}") {
684
692
  depth--;
685
- current += ch;
686
693
  } else if (ch === "," && depth === 0) {
687
- args.push(current.trim());
688
- current = "";
689
- } else {
690
- current += ch;
694
+ pushArg(i);
695
+ segmentStart = i + 1;
691
696
  }
692
697
  }
693
- if (current.trim().length > 0) {
694
- args.push(current.trim());
695
- }
696
- return args;
698
+ pushArg(content.length);
699
+ return { args, argSpans };
697
700
  }
698
701
  /**
699
702
  * Parse inline arguments: middleware(arg1, arg2) or middleware[arg1, arg2]
@@ -705,7 +708,7 @@ var Parser = class {
705
708
  const ch = this.cur();
706
709
  if (ch !== "(" && ch !== "[") {
707
710
  this.pos = trimmedStart;
708
- return [];
711
+ return { args: [], argSpans: [] };
709
712
  }
710
713
  const openChar = ch;
711
714
  const closeChar = openChar === "(" ? ")" : "]";
@@ -757,9 +760,9 @@ var Parser = class {
757
760
  const argsContent = this.text.slice(contentStart, this.pos);
758
761
  this.pos++;
759
762
  if (argsContent.trim().length === 0) {
760
- return [];
763
+ return { args: [], argSpans: [] };
761
764
  }
762
- return this.splitBalancedArgs(argsContent);
765
+ return this.splitBalancedArgs(argsContent, contentStart);
763
766
  }
764
767
  parseResultStep() {
765
768
  this.skipWhitespaceOnly();
@@ -802,32 +805,6 @@ var Parser = class {
802
805
  const end = this.pos;
803
806
  return { branchType, statusCode, pipeline, start, end };
804
807
  }
805
- parseIfStep() {
806
- this.skipWhitespaceOnly();
807
- const start = this.pos;
808
- this.expect("|>");
809
- this.skipInlineSpaces();
810
- this.expect("if");
811
- this.skipSpaces();
812
- const condition = this.parseIfPipeline("then:");
813
- this.skipSpaces();
814
- this.expect("then:");
815
- this.skipWhitespaceOnly();
816
- const thenBranch = this.parseIfPipeline("else:", "end");
817
- this.skipWhitespaceOnly();
818
- const elseBranch = this.tryParse(() => {
819
- this.expect("else:");
820
- this.skipWhitespaceOnly();
821
- return this.parseIfPipeline("end");
822
- });
823
- this.skipWhitespaceOnly();
824
- this.tryParse(() => {
825
- this.expect("end");
826
- return true;
827
- });
828
- const end = this.pos;
829
- return { kind: "If", condition, thenBranch, elseBranch: elseBranch || void 0, start, end };
830
- }
831
808
  parseDispatchStep() {
832
809
  this.skipWhitespaceOnly();
833
810
  const start = this.pos;
@@ -837,11 +814,13 @@ var Parser = class {
837
814
  this.skipWhitespaceOnly();
838
815
  const branches = [];
839
816
  while (true) {
817
+ this.skipStandaloneCommentsBeforeKeywords(["case", "default:", "end"]);
840
818
  const branch = this.tryParse(() => this.parseDispatchBranch());
841
819
  if (!branch) break;
842
820
  branches.push(branch);
843
821
  this.skipWhitespaceOnly();
844
822
  }
823
+ this.skipStandaloneCommentsBeforeKeywords(["default:", "end"]);
845
824
  const defaultBranch = this.tryParse(() => {
846
825
  this.expect("default:");
847
826
  this.skipWhitespaceOnly();
@@ -1041,18 +1020,6 @@ var Parser = class {
1041
1020
  if (inline && inline.steps.length > 0) {
1042
1021
  return { kind: "Inline", pipeline: inline, start: inline.start, end: inline.end };
1043
1022
  }
1044
- const named = this.tryParse(() => {
1045
- this.skipWhitespaceOnly();
1046
- const start = this.pos;
1047
- this.expect("|>");
1048
- this.skipInlineSpaces();
1049
- this.expect("pipeline:");
1050
- this.skipInlineSpaces();
1051
- const name = this.parseIdentifier();
1052
- const end = this.pos;
1053
- return { kind: "Named", name, start, end };
1054
- });
1055
- if (named) return named;
1056
1023
  throw new Error("pipeline-ref");
1057
1024
  }
1058
1025
  parseVariable() {
@@ -2088,61 +2055,6 @@ function formatPipelineStep(step, indent = " ", isLastStep = false) {
2088
2055
  });
2089
2056
  });
2090
2057
  return lines.join("\n");
2091
- } else if (step.kind === "If") {
2092
- const lines = [`${indent}|> if`];
2093
- const conditionItems = [];
2094
- step.condition.steps.forEach((s) => {
2095
- conditionItems.push({ type: "step", item: s, position: s.start });
2096
- });
2097
- step.condition.comments.forEach((c) => {
2098
- conditionItems.push({ type: "comment", item: c, position: c.start || 0 });
2099
- });
2100
- conditionItems.sort((a, b) => a.position - b.position);
2101
- conditionItems.forEach((entry) => {
2102
- if (entry.type === "step") {
2103
- lines.push(formatPipelineStep(entry.item, indent + " "));
2104
- } else {
2105
- lines.push(`${indent} ${printComment(entry.item)}`);
2106
- }
2107
- });
2108
- lines.push(`${indent} then:`);
2109
- const thenItems = [];
2110
- step.thenBranch.steps.forEach((s) => {
2111
- thenItems.push({ type: "step", item: s, position: s.start });
2112
- });
2113
- step.thenBranch.comments.forEach((c) => {
2114
- thenItems.push({ type: "comment", item: c, position: c.start || 0 });
2115
- });
2116
- thenItems.sort((a, b) => a.position - b.position);
2117
- thenItems.forEach((entry) => {
2118
- if (entry.type === "step") {
2119
- lines.push(formatPipelineStep(entry.item, indent + " "));
2120
- } else {
2121
- lines.push(`${indent} ${printComment(entry.item)}`);
2122
- }
2123
- });
2124
- if (step.elseBranch) {
2125
- lines.push(`${indent} else:`);
2126
- const elseItems = [];
2127
- step.elseBranch.steps.forEach((s) => {
2128
- elseItems.push({ type: "step", item: s, position: s.start });
2129
- });
2130
- step.elseBranch.comments.forEach((c) => {
2131
- elseItems.push({ type: "comment", item: c, position: c.start || 0 });
2132
- });
2133
- elseItems.sort((a, b) => a.position - b.position);
2134
- elseItems.forEach((entry) => {
2135
- if (entry.type === "step") {
2136
- lines.push(formatPipelineStep(entry.item, indent + " "));
2137
- } else {
2138
- lines.push(`${indent} ${printComment(entry.item)}`);
2139
- }
2140
- });
2141
- }
2142
- if (!isLastStep) {
2143
- lines.push(`${indent}end`);
2144
- }
2145
- return lines.join("\n");
2146
2058
  } else if (step.kind === "Dispatch") {
2147
2059
  const lines = [`${indent}|> dispatch`];
2148
2060
  step.branches.forEach((branch) => {
@@ -2158,14 +2070,8 @@ function formatPipelineStep(step, indent = " ", isLastStep = false) {
2158
2070
  });
2159
2071
  }
2160
2072
  return lines.join("\n");
2161
- } else {
2162
- const lines = [`${indent}|> foreach ${step.selector}`];
2163
- step.pipeline.steps.forEach((innerStep) => {
2164
- lines.push(formatPipelineStep(innerStep, indent + " "));
2165
- });
2166
- lines.push(`${indent}end`);
2167
- return lines.join("\n");
2168
2073
  }
2074
+ throw new Error(`Unsupported pipeline step: ${step.kind}`);
2169
2075
  }
2170
2076
  function formatStepConfig(config, configType) {
2171
2077
  switch (configType) {
@@ -2205,35 +2111,31 @@ function formatTagExpr(expr) {
2205
2111
  }
2206
2112
  }
2207
2113
  function formatPipelineRef(ref) {
2208
- if (ref.kind === "Named") {
2209
- return [` |> pipeline: ${ref.name}`];
2210
- } else {
2211
- const lines = [];
2212
- const items = [];
2213
- ref.pipeline.steps.forEach((step) => {
2214
- items.push({ type: "step", item: step, position: step.start });
2215
- });
2216
- ref.pipeline.comments.forEach((comment) => {
2217
- items.push({ type: "comment", item: comment, position: comment.start || 0 });
2218
- });
2219
- items.sort((a, b) => a.position - b.position);
2220
- let lastStepIndex = -1;
2221
- for (let i = items.length - 1; i >= 0; i--) {
2222
- if (items[i].type === "step") {
2223
- lastStepIndex = i;
2224
- break;
2225
- }
2114
+ const lines = [];
2115
+ const items = [];
2116
+ ref.pipeline.steps.forEach((step) => {
2117
+ items.push({ type: "step", item: step, position: step.start });
2118
+ });
2119
+ ref.pipeline.comments.forEach((comment) => {
2120
+ items.push({ type: "comment", item: comment, position: comment.start || 0 });
2121
+ });
2122
+ items.sort((a, b) => a.position - b.position);
2123
+ let lastStepIndex = -1;
2124
+ for (let i = items.length - 1; i >= 0; i--) {
2125
+ if (items[i].type === "step") {
2126
+ lastStepIndex = i;
2127
+ break;
2226
2128
  }
2227
- items.forEach((entry, index) => {
2228
- if (entry.type === "step") {
2229
- const isLastStep = index === lastStepIndex;
2230
- lines.push(formatPipelineStep(entry.item, " ", isLastStep));
2231
- } else {
2232
- lines.push(` ${printComment(entry.item)}`);
2233
- }
2234
- });
2235
- return lines;
2236
2129
  }
2130
+ items.forEach((entry, index) => {
2131
+ if (entry.type === "step") {
2132
+ const isLastStep = index === lastStepIndex;
2133
+ lines.push(formatPipelineStep(entry.item, " ", isLastStep));
2134
+ } else {
2135
+ lines.push(` ${printComment(entry.item)}`);
2136
+ }
2137
+ });
2138
+ return lines;
2237
2139
  }
2238
2140
  function formatWhen(when) {
2239
2141
  switch (when.kind) {
package/dist/index.d.cts CHANGED
@@ -116,11 +116,6 @@ type PipelineRef = {
116
116
  pipeline: Pipeline;
117
117
  start: number;
118
118
  end: number;
119
- } | {
120
- kind: 'Named';
121
- name: string;
122
- start: number;
123
- end: number;
124
119
  };
125
120
  interface Pipeline {
126
121
  steps: PipelineStep[];
@@ -129,6 +124,10 @@ interface Pipeline {
129
124
  end: number;
130
125
  }
131
126
  type ConfigType = 'backtick' | 'quoted' | 'identifier';
127
+ interface SourceSpan {
128
+ start: number;
129
+ end: number;
130
+ }
132
131
  type LetValueFormat = 'quoted' | 'backtick' | 'bare';
133
132
  interface LetVariable {
134
133
  name: string;
@@ -166,6 +165,7 @@ type PipelineStep = {
166
165
  nameStart: number;
167
166
  nameEnd: number;
168
167
  args: string[];
168
+ argSpans: SourceSpan[];
169
169
  config: string;
170
170
  configType: ConfigType;
171
171
  hasConfig: boolean;
@@ -180,25 +180,12 @@ type PipelineStep = {
180
180
  branches: ResultBranch[];
181
181
  start: number;
182
182
  end: number;
183
- } | {
184
- kind: 'If';
185
- condition: Pipeline;
186
- thenBranch: Pipeline;
187
- elseBranch?: Pipeline;
188
- start: number;
189
- end: number;
190
183
  } | {
191
184
  kind: 'Dispatch';
192
185
  branches: DispatchBranch[];
193
186
  default?: Pipeline;
194
187
  start: number;
195
188
  end: number;
196
- } | {
197
- kind: 'Foreach';
198
- selector: string;
199
- pipeline: Pipeline;
200
- start: number;
201
- end: number;
202
189
  };
203
190
  interface DispatchBranch {
204
191
  condition: TagExpr;
@@ -357,4 +344,4 @@ declare function formatTagExpr(expr: TagExpr): string;
357
344
  declare function formatPipelineRef(ref: PipelineRef): string[];
358
345
  declare function formatWhen(when: When): string;
359
346
 
360
- export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type DomAssertType, type GraphQLSchema, type Import, type It, type LetValueFormat, type LetVariable, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type Tag, type TagExpr, type TestLetVariable, type TypeResolver, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getTestLetVariableRanges, getTestLetVariables, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printFeatureFlags, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printTypeResolver, printVariable };
347
+ export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type DomAssertType, type GraphQLSchema, type Import, type It, type LetValueFormat, type LetVariable, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type SourceSpan, type Tag, type TagExpr, type TestLetVariable, type TypeResolver, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getTestLetVariableRanges, getTestLetVariables, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printFeatureFlags, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printTypeResolver, printVariable };
package/dist/index.d.ts CHANGED
@@ -116,11 +116,6 @@ type PipelineRef = {
116
116
  pipeline: Pipeline;
117
117
  start: number;
118
118
  end: number;
119
- } | {
120
- kind: 'Named';
121
- name: string;
122
- start: number;
123
- end: number;
124
119
  };
125
120
  interface Pipeline {
126
121
  steps: PipelineStep[];
@@ -129,6 +124,10 @@ interface Pipeline {
129
124
  end: number;
130
125
  }
131
126
  type ConfigType = 'backtick' | 'quoted' | 'identifier';
127
+ interface SourceSpan {
128
+ start: number;
129
+ end: number;
130
+ }
132
131
  type LetValueFormat = 'quoted' | 'backtick' | 'bare';
133
132
  interface LetVariable {
134
133
  name: string;
@@ -166,6 +165,7 @@ type PipelineStep = {
166
165
  nameStart: number;
167
166
  nameEnd: number;
168
167
  args: string[];
168
+ argSpans: SourceSpan[];
169
169
  config: string;
170
170
  configType: ConfigType;
171
171
  hasConfig: boolean;
@@ -180,25 +180,12 @@ type PipelineStep = {
180
180
  branches: ResultBranch[];
181
181
  start: number;
182
182
  end: number;
183
- } | {
184
- kind: 'If';
185
- condition: Pipeline;
186
- thenBranch: Pipeline;
187
- elseBranch?: Pipeline;
188
- start: number;
189
- end: number;
190
183
  } | {
191
184
  kind: 'Dispatch';
192
185
  branches: DispatchBranch[];
193
186
  default?: Pipeline;
194
187
  start: number;
195
188
  end: number;
196
- } | {
197
- kind: 'Foreach';
198
- selector: string;
199
- pipeline: Pipeline;
200
- start: number;
201
- end: number;
202
189
  };
203
190
  interface DispatchBranch {
204
191
  condition: TagExpr;
@@ -357,4 +344,4 @@ declare function formatTagExpr(expr: TagExpr): string;
357
344
  declare function formatPipelineRef(ref: PipelineRef): string[];
358
345
  declare function formatWhen(when: When): string;
359
346
 
360
- export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type DomAssertType, type GraphQLSchema, type Import, type It, type LetValueFormat, type LetVariable, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type Tag, type TagExpr, type TestLetVariable, type TypeResolver, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getTestLetVariableRanges, getTestLetVariables, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printFeatureFlags, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printTypeResolver, printVariable };
347
+ export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type DomAssertType, type GraphQLSchema, type Import, type It, type LetValueFormat, type LetVariable, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type SourceSpan, type Tag, type TagExpr, type TestLetVariable, type TypeResolver, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getTestLetVariableRanges, getTestLetVariables, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printFeatureFlags, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printTypeResolver, printVariable };
package/dist/index.mjs CHANGED
@@ -245,6 +245,32 @@ var Parser = class {
245
245
  skipWhitespaceOnly() {
246
246
  this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r" || ch === "\n");
247
247
  }
248
+ skipStandaloneCommentsBeforeKeywords(keywords) {
249
+ while (true) {
250
+ this.skipWhitespaceOnly();
251
+ const commentStart = this.pos;
252
+ const comment = this.tryParse(() => this.parseStandaloneComment());
253
+ if (!comment) {
254
+ this.pos = commentStart;
255
+ return;
256
+ }
257
+ const afterComment = this.pos;
258
+ if (this.cur() === "\n") this.pos++;
259
+ while (true) {
260
+ this.skipWhitespaceOnly();
261
+ const nestedComment = this.tryParse(() => this.parseStandaloneComment());
262
+ if (!nestedComment) break;
263
+ if (this.cur() === "\n") this.pos++;
264
+ }
265
+ const followedByKeyword = keywords.some((keyword) => this.text.startsWith(keyword, this.pos));
266
+ this.pos = afterComment;
267
+ if (!followedByKeyword) {
268
+ this.pos = commentStart;
269
+ return;
270
+ }
271
+ if (this.cur() === "\n") this.pos++;
272
+ }
273
+ }
248
274
  skipInlineSpaces() {
249
275
  this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r");
250
276
  }
@@ -472,35 +498,10 @@ var Parser = class {
472
498
  parsePipelineStep() {
473
499
  const result = this.tryParse(() => this.parseResultStep());
474
500
  if (result) return result;
475
- const ifStep = this.tryParse(() => this.parseIfStep());
476
- if (ifStep) return ifStep;
477
501
  const dispatchStep = this.tryParse(() => this.parseDispatchStep());
478
502
  if (dispatchStep) return dispatchStep;
479
- const foreachStep = this.tryParse(() => this.parseForeachStep());
480
- if (foreachStep) return foreachStep;
481
503
  return this.parseRegularStep();
482
504
  }
483
- parseForeachStep() {
484
- this.skipWhitespaceOnly();
485
- const start = this.pos;
486
- this.expect("|>");
487
- this.skipInlineSpaces();
488
- this.expect("foreach");
489
- if (this.cur() !== " " && this.cur() !== " ") {
490
- throw new ParseFailure("space after foreach", this.pos);
491
- }
492
- this.skipInlineSpaces();
493
- const selector = this.consumeWhile((c) => c !== "\n" && c !== "#").trim();
494
- if (selector.length === 0) {
495
- throw new ParseFailure("foreach selector", this.pos);
496
- }
497
- this.skipSpaces();
498
- const pipeline = this.parseIfPipeline("end");
499
- this.skipSpaces();
500
- this.expect("end");
501
- const end = this.pos;
502
- return { kind: "Foreach", selector, pipeline, start, end };
503
- }
504
505
  parseRegularStep() {
505
506
  this.skipWhitespaceOnly();
506
507
  const start = this.pos;
@@ -509,7 +510,9 @@ var Parser = class {
509
510
  const nameStart = this.pos;
510
511
  const name = this.parseIdentifier();
511
512
  const nameEnd = this.pos;
512
- const args = this.parseInlineArgs();
513
+ const inlineArgs = this.parseInlineArgs();
514
+ const args = inlineArgs.args;
515
+ const argSpans = inlineArgs.argSpans;
513
516
  this.skipInlineSpaces();
514
517
  let config = "";
515
518
  let configType = "quoted";
@@ -530,7 +533,7 @@ var Parser = class {
530
533
  const parsedJoinTargets = name === "join" ? this.parseJoinTaskNames(config) : void 0;
531
534
  this.skipWhitespaceOnly();
532
535
  const end = this.pos;
533
- return { kind: "Regular", name, nameStart, nameEnd, args, config, configType, hasConfig, configStart, configEnd, condition, parsedJoinTargets, start, end };
536
+ return { kind: "Regular", name, nameStart, nameEnd, args, argSpans, config, configType, hasConfig, configStart, configEnd, condition, parsedJoinTargets, start, end };
534
537
  }
535
538
  /**
536
539
  * Parse optional step condition (tag expression after the config)
@@ -588,58 +591,58 @@ var Parser = class {
588
591
  * Split argument content by commas while respecting nesting depth and strings
589
592
  * Example: `"url", {a:1, b:2}` -> [`"url"`, `{a:1, b:2}`]
590
593
  */
591
- splitBalancedArgs(content) {
594
+ splitBalancedArgs(content, baseOffset) {
592
595
  const args = [];
593
- let current = "";
596
+ const argSpans = [];
597
+ let segmentStart = 0;
594
598
  let depth = 0;
595
599
  let inString = false;
596
600
  let stringChar = "";
597
601
  let escapeNext = false;
602
+ const pushArg = (segmentEnd) => {
603
+ let start = segmentStart;
604
+ let end = segmentEnd;
605
+ while (start < end && /\s/.test(content[start])) start++;
606
+ while (end > start && /\s/.test(content[end - 1])) end--;
607
+ if (start < end) {
608
+ args.push(content.slice(start, end));
609
+ argSpans.push({ start: baseOffset + start, end: baseOffset + end });
610
+ }
611
+ };
598
612
  for (let i = 0; i < content.length; i++) {
599
613
  const ch = content[i];
600
614
  if (escapeNext) {
601
- current += ch;
602
615
  escapeNext = false;
603
616
  continue;
604
617
  }
605
618
  if (ch === "\\" && inString) {
606
- current += ch;
607
619
  escapeNext = true;
608
620
  continue;
609
621
  }
610
- if ((ch === '"' || ch === "`") && !inString) {
622
+ if ((ch === '"' || ch === "'" || ch === "`") && !inString) {
611
623
  inString = true;
612
624
  stringChar = ch;
613
- current += ch;
614
625
  continue;
615
626
  }
616
627
  if (ch === stringChar && inString) {
617
628
  inString = false;
618
629
  stringChar = "";
619
- current += ch;
620
630
  continue;
621
631
  }
622
632
  if (inString) {
623
- current += ch;
624
633
  continue;
625
634
  }
626
635
  if (ch === "(" || ch === "[" || ch === "{") {
627
636
  depth++;
628
- current += ch;
629
637
  } else if (ch === ")" || ch === "]" || ch === "}") {
630
638
  depth--;
631
- current += ch;
632
639
  } else if (ch === "," && depth === 0) {
633
- args.push(current.trim());
634
- current = "";
635
- } else {
636
- current += ch;
640
+ pushArg(i);
641
+ segmentStart = i + 1;
637
642
  }
638
643
  }
639
- if (current.trim().length > 0) {
640
- args.push(current.trim());
641
- }
642
- return args;
644
+ pushArg(content.length);
645
+ return { args, argSpans };
643
646
  }
644
647
  /**
645
648
  * Parse inline arguments: middleware(arg1, arg2) or middleware[arg1, arg2]
@@ -651,7 +654,7 @@ var Parser = class {
651
654
  const ch = this.cur();
652
655
  if (ch !== "(" && ch !== "[") {
653
656
  this.pos = trimmedStart;
654
- return [];
657
+ return { args: [], argSpans: [] };
655
658
  }
656
659
  const openChar = ch;
657
660
  const closeChar = openChar === "(" ? ")" : "]";
@@ -703,9 +706,9 @@ var Parser = class {
703
706
  const argsContent = this.text.slice(contentStart, this.pos);
704
707
  this.pos++;
705
708
  if (argsContent.trim().length === 0) {
706
- return [];
709
+ return { args: [], argSpans: [] };
707
710
  }
708
- return this.splitBalancedArgs(argsContent);
711
+ return this.splitBalancedArgs(argsContent, contentStart);
709
712
  }
710
713
  parseResultStep() {
711
714
  this.skipWhitespaceOnly();
@@ -748,32 +751,6 @@ var Parser = class {
748
751
  const end = this.pos;
749
752
  return { branchType, statusCode, pipeline, start, end };
750
753
  }
751
- parseIfStep() {
752
- this.skipWhitespaceOnly();
753
- const start = this.pos;
754
- this.expect("|>");
755
- this.skipInlineSpaces();
756
- this.expect("if");
757
- this.skipSpaces();
758
- const condition = this.parseIfPipeline("then:");
759
- this.skipSpaces();
760
- this.expect("then:");
761
- this.skipWhitespaceOnly();
762
- const thenBranch = this.parseIfPipeline("else:", "end");
763
- this.skipWhitespaceOnly();
764
- const elseBranch = this.tryParse(() => {
765
- this.expect("else:");
766
- this.skipWhitespaceOnly();
767
- return this.parseIfPipeline("end");
768
- });
769
- this.skipWhitespaceOnly();
770
- this.tryParse(() => {
771
- this.expect("end");
772
- return true;
773
- });
774
- const end = this.pos;
775
- return { kind: "If", condition, thenBranch, elseBranch: elseBranch || void 0, start, end };
776
- }
777
754
  parseDispatchStep() {
778
755
  this.skipWhitespaceOnly();
779
756
  const start = this.pos;
@@ -783,11 +760,13 @@ var Parser = class {
783
760
  this.skipWhitespaceOnly();
784
761
  const branches = [];
785
762
  while (true) {
763
+ this.skipStandaloneCommentsBeforeKeywords(["case", "default:", "end"]);
786
764
  const branch = this.tryParse(() => this.parseDispatchBranch());
787
765
  if (!branch) break;
788
766
  branches.push(branch);
789
767
  this.skipWhitespaceOnly();
790
768
  }
769
+ this.skipStandaloneCommentsBeforeKeywords(["default:", "end"]);
791
770
  const defaultBranch = this.tryParse(() => {
792
771
  this.expect("default:");
793
772
  this.skipWhitespaceOnly();
@@ -987,18 +966,6 @@ var Parser = class {
987
966
  if (inline && inline.steps.length > 0) {
988
967
  return { kind: "Inline", pipeline: inline, start: inline.start, end: inline.end };
989
968
  }
990
- const named = this.tryParse(() => {
991
- this.skipWhitespaceOnly();
992
- const start = this.pos;
993
- this.expect("|>");
994
- this.skipInlineSpaces();
995
- this.expect("pipeline:");
996
- this.skipInlineSpaces();
997
- const name = this.parseIdentifier();
998
- const end = this.pos;
999
- return { kind: "Named", name, start, end };
1000
- });
1001
- if (named) return named;
1002
969
  throw new Error("pipeline-ref");
1003
970
  }
1004
971
  parseVariable() {
@@ -2034,61 +2001,6 @@ function formatPipelineStep(step, indent = " ", isLastStep = false) {
2034
2001
  });
2035
2002
  });
2036
2003
  return lines.join("\n");
2037
- } else if (step.kind === "If") {
2038
- const lines = [`${indent}|> if`];
2039
- const conditionItems = [];
2040
- step.condition.steps.forEach((s) => {
2041
- conditionItems.push({ type: "step", item: s, position: s.start });
2042
- });
2043
- step.condition.comments.forEach((c) => {
2044
- conditionItems.push({ type: "comment", item: c, position: c.start || 0 });
2045
- });
2046
- conditionItems.sort((a, b) => a.position - b.position);
2047
- conditionItems.forEach((entry) => {
2048
- if (entry.type === "step") {
2049
- lines.push(formatPipelineStep(entry.item, indent + " "));
2050
- } else {
2051
- lines.push(`${indent} ${printComment(entry.item)}`);
2052
- }
2053
- });
2054
- lines.push(`${indent} then:`);
2055
- const thenItems = [];
2056
- step.thenBranch.steps.forEach((s) => {
2057
- thenItems.push({ type: "step", item: s, position: s.start });
2058
- });
2059
- step.thenBranch.comments.forEach((c) => {
2060
- thenItems.push({ type: "comment", item: c, position: c.start || 0 });
2061
- });
2062
- thenItems.sort((a, b) => a.position - b.position);
2063
- thenItems.forEach((entry) => {
2064
- if (entry.type === "step") {
2065
- lines.push(formatPipelineStep(entry.item, indent + " "));
2066
- } else {
2067
- lines.push(`${indent} ${printComment(entry.item)}`);
2068
- }
2069
- });
2070
- if (step.elseBranch) {
2071
- lines.push(`${indent} else:`);
2072
- const elseItems = [];
2073
- step.elseBranch.steps.forEach((s) => {
2074
- elseItems.push({ type: "step", item: s, position: s.start });
2075
- });
2076
- step.elseBranch.comments.forEach((c) => {
2077
- elseItems.push({ type: "comment", item: c, position: c.start || 0 });
2078
- });
2079
- elseItems.sort((a, b) => a.position - b.position);
2080
- elseItems.forEach((entry) => {
2081
- if (entry.type === "step") {
2082
- lines.push(formatPipelineStep(entry.item, indent + " "));
2083
- } else {
2084
- lines.push(`${indent} ${printComment(entry.item)}`);
2085
- }
2086
- });
2087
- }
2088
- if (!isLastStep) {
2089
- lines.push(`${indent}end`);
2090
- }
2091
- return lines.join("\n");
2092
2004
  } else if (step.kind === "Dispatch") {
2093
2005
  const lines = [`${indent}|> dispatch`];
2094
2006
  step.branches.forEach((branch) => {
@@ -2104,14 +2016,8 @@ function formatPipelineStep(step, indent = " ", isLastStep = false) {
2104
2016
  });
2105
2017
  }
2106
2018
  return lines.join("\n");
2107
- } else {
2108
- const lines = [`${indent}|> foreach ${step.selector}`];
2109
- step.pipeline.steps.forEach((innerStep) => {
2110
- lines.push(formatPipelineStep(innerStep, indent + " "));
2111
- });
2112
- lines.push(`${indent}end`);
2113
- return lines.join("\n");
2114
2019
  }
2020
+ throw new Error(`Unsupported pipeline step: ${step.kind}`);
2115
2021
  }
2116
2022
  function formatStepConfig(config, configType) {
2117
2023
  switch (configType) {
@@ -2151,35 +2057,31 @@ function formatTagExpr(expr) {
2151
2057
  }
2152
2058
  }
2153
2059
  function formatPipelineRef(ref) {
2154
- if (ref.kind === "Named") {
2155
- return [` |> pipeline: ${ref.name}`];
2156
- } else {
2157
- const lines = [];
2158
- const items = [];
2159
- ref.pipeline.steps.forEach((step) => {
2160
- items.push({ type: "step", item: step, position: step.start });
2161
- });
2162
- ref.pipeline.comments.forEach((comment) => {
2163
- items.push({ type: "comment", item: comment, position: comment.start || 0 });
2164
- });
2165
- items.sort((a, b) => a.position - b.position);
2166
- let lastStepIndex = -1;
2167
- for (let i = items.length - 1; i >= 0; i--) {
2168
- if (items[i].type === "step") {
2169
- lastStepIndex = i;
2170
- break;
2171
- }
2060
+ const lines = [];
2061
+ const items = [];
2062
+ ref.pipeline.steps.forEach((step) => {
2063
+ items.push({ type: "step", item: step, position: step.start });
2064
+ });
2065
+ ref.pipeline.comments.forEach((comment) => {
2066
+ items.push({ type: "comment", item: comment, position: comment.start || 0 });
2067
+ });
2068
+ items.sort((a, b) => a.position - b.position);
2069
+ let lastStepIndex = -1;
2070
+ for (let i = items.length - 1; i >= 0; i--) {
2071
+ if (items[i].type === "step") {
2072
+ lastStepIndex = i;
2073
+ break;
2172
2074
  }
2173
- items.forEach((entry, index) => {
2174
- if (entry.type === "step") {
2175
- const isLastStep = index === lastStepIndex;
2176
- lines.push(formatPipelineStep(entry.item, " ", isLastStep));
2177
- } else {
2178
- lines.push(` ${printComment(entry.item)}`);
2179
- }
2180
- });
2181
- return lines;
2182
2075
  }
2076
+ items.forEach((entry, index) => {
2077
+ if (entry.type === "step") {
2078
+ const isLastStep = index === lastStepIndex;
2079
+ lines.push(formatPipelineStep(entry.item, " ", isLastStep));
2080
+ } else {
2081
+ lines.push(` ${printComment(entry.item)}`);
2082
+ }
2083
+ });
2084
+ return lines;
2183
2085
  }
2184
2086
  function formatWhen(when) {
2185
2087
  switch (when.kind) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpipe-js",
3
- "version": "2.0.71",
3
+ "version": "2.0.97",
4
4
  "description": "Web Pipe parser",
5
5
  "license": "ISC",
6
6
  "author": "William Cotton",