@savvy-web/silk 2.1.1 → 2.1.2

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.
@@ -1214,7 +1214,7 @@ var YamlToken = class extends effect.Schema.Class("YamlToken")({
1214
1214
  *
1215
1215
  * @public
1216
1216
  */
1217
- function createScanner$1(text) {
1217
+ function createScanner$2(text) {
1218
1218
  let pos = 0;
1219
1219
  let line = 0;
1220
1220
  let col = 0;
@@ -2165,7 +2165,7 @@ function createScanner$1(text) {
2165
2165
  * @public
2166
2166
  */
2167
2167
  function lex(text) {
2168
- return effect.Stream.unfold(createScanner$1(text), (scanner) => {
2168
+ return effect.Stream.unfold(createScanner$2(text), (scanner) => {
2169
2169
  const kind = scanner.scan();
2170
2170
  if (kind === null) return effect.Option.none();
2171
2171
  const token = new YamlToken({
@@ -6309,7 +6309,7 @@ function parseDocument(text, options) {
6309
6309
  *
6310
6310
  * @public
6311
6311
  */
6312
- function parse$2(text, options) {
6312
+ function parse$3(text, options) {
6313
6313
  const uniqueKeys = options?.uniqueKeys ?? true;
6314
6314
  return parseDocument(text, options).pipe(effect.Effect.flatMap((doc) => {
6315
6315
  if (uniqueKeys) {
@@ -6331,7 +6331,7 @@ function parse$2(text, options) {
6331
6331
  *
6332
6332
  * @public
6333
6333
  */
6334
- const workspaceManifestFromYaml = (content) => parse$2(content).pipe(effect.Effect.mapError((e) => new CatalogAssemblyError({
6334
+ const workspaceManifestFromYaml = (content) => parse$3(content).pipe(effect.Effect.mapError((e) => new CatalogAssemblyError({
6335
6335
  source: "manifest",
6336
6336
  reason: `invalid yaml: ${String(e)}`
6337
6337
  })), effect.Effect.map((parsed) => {
@@ -6650,7 +6650,7 @@ var CatalogSet = class CatalogSet extends effect.Schema.Class("CatalogSet")({ en
6650
6650
  *
6651
6651
  * @internal
6652
6652
  */
6653
- const lockfileCatalogsFromText = (text) => parse$2(text).pipe(effect.Effect.map((parsed) => CatalogSet.fromLockfileCatalogs(parsed?.catalogs)), effect.Effect.orElseSucceed(() => CatalogSet.empty()));
6653
+ const lockfileCatalogsFromText = (text) => parse$3(text).pipe(effect.Effect.map((parsed) => CatalogSet.fromLockfileCatalogs(parsed?.catalogs)), effect.Effect.orElseSucceed(() => CatalogSet.empty()));
6654
6654
  /**
6655
6655
  * Read the working tree's catalog state at `root`.
6656
6656
  *
@@ -8440,6 +8440,1285 @@ effect.Schema.Class("WorkspaceInfo")({
8440
8440
  patterns: effect.Schema.Array(effect.Schema.String)
8441
8441
  });
8442
8442
  //#endregion
8443
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/errors.js
8444
+ /**
8445
+ * JSONC error types using Effect's Data.TaggedError pattern.
8446
+ *
8447
+ * @packageDocumentation
8448
+ */
8449
+ /**
8450
+ * Error codes representing specific JSONC parse failures.
8451
+ *
8452
+ * @remarks
8453
+ * Each code maps to a distinct syntactic error the parser can encounter,
8454
+ * from invalid symbols and number formats to missing delimiters and
8455
+ * unexpected end-of-input conditions.
8456
+ *
8457
+ * @see {@link JsoncParseErrorDetail} — carries one of these codes alongside
8458
+ * position information
8459
+ *
8460
+ * @public
8461
+ */
8462
+ const JsoncParseErrorCode = effect.Schema.Literal("InvalidSymbol", "InvalidNumberFormat", "PropertyNameExpected", "ValueExpected", "ColonExpected", "CommaExpected", "CloseBraceExpected", "CloseBracketExpected", "EndOfFileExpected", "InvalidCommentToken", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter");
8463
+ /**
8464
+ * Detail for a single parse error, including the error code, a human-readable
8465
+ * message, and the exact position within the source document.
8466
+ *
8467
+ * @remarks
8468
+ * - `code` — a {@link (JsoncParseErrorCode:type)} identifying the error kind.
8469
+ * - `message` — a descriptive message suitable for display.
8470
+ * - `offset` — zero-based character offset where the error occurred.
8471
+ * - `length` — character length of the problematic span.
8472
+ * - `startLine` — zero-based line number of the error.
8473
+ * - `startCharacter` — zero-based column within `startLine`.
8474
+ *
8475
+ * @see {@link JsoncParseError} — aggregates an array of these details
8476
+ *
8477
+ * @example
8478
+ * ```ts
8479
+ * import { JsoncParseErrorDetail } from "jsonc-effect";
8480
+ *
8481
+ * const detail = new JsoncParseErrorDetail({
8482
+ * code: "ValueExpected",
8483
+ * message: "Value expected",
8484
+ * offset: 5,
8485
+ * length: 1,
8486
+ * startLine: 0,
8487
+ * startCharacter: 5,
8488
+ * });
8489
+ *
8490
+ * console.log(detail.code); // "ValueExpected"
8491
+ * console.log(detail.offset); // 5
8492
+ * ```
8493
+ *
8494
+ * @public
8495
+ */
8496
+ var JsoncParseErrorDetail = class extends effect.Schema.Class("JsoncParseErrorDetail")({
8497
+ code: JsoncParseErrorCode,
8498
+ message: effect.Schema.String,
8499
+ offset: effect.Schema.Number,
8500
+ length: effect.Schema.Number,
8501
+ startLine: effect.Schema.Number,
8502
+ startCharacter: effect.Schema.Number
8503
+ }) {};
8504
+ /**
8505
+ * Base class for {@link JsoncParseError}; not intended to be constructed or
8506
+ * caught directly — use `JsoncParseError` instead.
8507
+ *
8508
+ * @privateRemarks
8509
+ * The `*Base` pattern is required because `Data.TaggedError` produces complex
8510
+ * type signatures involving intersection types and branded generics that
8511
+ * api-extractor cannot roll up into a single `.d.ts` bundle. Exporting the
8512
+ * base separately lets the public `JsoncParseError` class extend it with
8513
+ * concrete fields, giving api-extractor a simple class declaration to work
8514
+ * with. It is tagged `@public` (rather than `@internal`) because it appears
8515
+ * in `JsoncParseError`'s heritage clause in the public `.d.ts`, and API
8516
+ * Extractor requires release tags to be compatible across a signature.
8517
+ *
8518
+ * @public
8519
+ */
8520
+ const JsoncParseErrorBase = effect.Data.TaggedError("JsoncParseError");
8521
+ /**
8522
+ * Error raised when JSONC parsing encounters one or more syntax errors.
8523
+ *
8524
+ * @remarks
8525
+ * Contains the full source `text`, the `options` used for parsing, and an
8526
+ * `errors` array of {@link JsoncParseErrorDetail} instances with precise
8527
+ * position information for each problem found.
8528
+ *
8529
+ * @see {@link parse} — may fail with this error
8530
+ * @see {@link parseTree} — may fail with this error
8531
+ *
8532
+ * @example Catching with `Effect.catchTag`
8533
+ * ```ts
8534
+ * import { Effect } from "effect";
8535
+ * import { parse } from "jsonc-effect";
8536
+ *
8537
+ * const program = parse("{ invalid }").pipe(
8538
+ * Effect.catchTag("JsoncParseError", (e) => {
8539
+ * console.error(e.errors); // Array of JsoncParseErrorDetail
8540
+ * return Effect.succeed({});
8541
+ * }),
8542
+ * );
8543
+ * ```
8544
+ *
8545
+ * @example Inspecting error details
8546
+ * ```ts
8547
+ * import { Effect } from "effect";
8548
+ * import { parse } from "jsonc-effect";
8549
+ *
8550
+ * const program = parse("{ invalid }").pipe(
8551
+ * Effect.catchTag("JsoncParseError", (e) => {
8552
+ * for (const detail of e.errors) {
8553
+ * console.error(
8554
+ * `[${detail.code}] ${detail.message} at line ${detail.startLine}:${detail.startCharacter}`,
8555
+ * );
8556
+ * }
8557
+ * return Effect.succeed({});
8558
+ * }),
8559
+ * );
8560
+ * ```
8561
+ *
8562
+ * @public
8563
+ */
8564
+ var JsoncParseError = class extends JsoncParseErrorBase {
8565
+ get message() {
8566
+ const count = this.errors.length;
8567
+ return `JSONC parse failed with ${count} error${count !== 1 ? "s" : ""}: ${this.errors.map((e) => e.message).join("; ")}`;
8568
+ }
8569
+ };
8570
+ effect.Data.TaggedError("JsoncNodeNotFoundError");
8571
+ /**
8572
+ * Base class for {@link JsoncModificationError}; not intended to be
8573
+ * constructed or caught directly — use `JsoncModificationError` instead.
8574
+ *
8575
+ * @privateRemarks
8576
+ * Uses the same `*Base` pattern as {@link JsoncParseErrorBase} to work
8577
+ * around api-extractor's inability to roll up the complex type produced
8578
+ * by `Data.TaggedError` into a single `.d.ts` declaration. Tagged `@public`
8579
+ * for the same heritage-clause-compatibility reason as `JsoncParseErrorBase`.
8580
+ *
8581
+ * @public
8582
+ */
8583
+ const JsoncModificationErrorBase = effect.Data.TaggedError("JsoncModificationError");
8584
+ /**
8585
+ * Error raised when {@link modify} produces invalid edits or encounters
8586
+ * an unsupported modification scenario.
8587
+ *
8588
+ * @remarks
8589
+ * Contains the `path` where modification was attempted and a `reason`
8590
+ * string explaining why it failed.
8591
+ *
8592
+ * @see {@link modify} — may fail with this error
8593
+ *
8594
+ * @example
8595
+ * ```ts
8596
+ * import { Effect } from "effect";
8597
+ * import { modify } from "jsonc-effect";
8598
+ *
8599
+ * const program = modify("{}", ["deep", "path"], 42).pipe(
8600
+ * Effect.catchTag("JsoncModificationError", (e) => {
8601
+ * console.error(`Failed at [${e.path.join(", ")}]: ${e.reason}`);
8602
+ * return Effect.succeed([]);
8603
+ * }),
8604
+ * );
8605
+ * ```
8606
+ *
8607
+ * @public
8608
+ */
8609
+ var JsoncModificationError = class extends JsoncModificationErrorBase {
8610
+ get message() {
8611
+ return `Modification failed at path [${this.path.join(", ")}]: ${this.reason}`;
8612
+ }
8613
+ };
8614
+ //#endregion
8615
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/scanner.js
8616
+ const isWhitespace = (ch) => ch === 32 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch === 65279;
8617
+ const isLineBreak$1 = (ch) => ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
8618
+ const isDigit$1 = (ch) => ch >= 48 && ch <= 57;
8619
+ /**
8620
+ * Create a stateful {@link JsoncScanner} for the given JSONC string.
8621
+ *
8622
+ * @param text - JSONC string to tokenize
8623
+ * @param ignoreTrivia - If `true`, the scanner automatically skips whitespace,
8624
+ * line-break, and comment tokens so that only structural tokens are returned
8625
+ * (default: `false`).
8626
+ * @returns A stateful {@link JsoncScanner} positioned before the first token.
8627
+ *
8628
+ * @remarks
8629
+ * When `ignoreTrivia` is `true` the scanner is suitable for building parsers
8630
+ * that only care about structural tokens (`OpenBrace`, `String`, `Number`,
8631
+ * etc.). Set it to `false` (the default) when you need to preserve comments
8632
+ * or whitespace — for example in a formatter or a comment-stripping pass.
8633
+ *
8634
+ * @see {@link JsoncScanner} — the interface returned by this factory
8635
+ * @see {@link parse} — higher-level API that uses a scanner internally
8636
+ *
8637
+ * @example
8638
+ * Tokenizing a JSONC string and printing each token:
8639
+ * ```ts
8640
+ * import type { JsoncSyntaxKind } from "jsonc-effect";
8641
+ * import { createScanner } from "jsonc-effect";
8642
+ *
8643
+ * const scanner = createScanner('{ "name": "jsonc" }', true);
8644
+ * let kind: JsoncSyntaxKind;
8645
+ * do {
8646
+ * kind = scanner.scan();
8647
+ * console.log(kind, scanner.getTokenValue());
8648
+ * } while (kind !== "EOF");
8649
+ * ```
8650
+ *
8651
+ * @privateRemarks
8652
+ * Ported from Microsoft's jsonc-parser (MIT), adapted to use string literal
8653
+ * token types instead of numeric enums.
8654
+ *
8655
+ * @public
8656
+ */
8657
+ const createScanner$1 = (text, ignoreTrivia = false) => {
8658
+ const len = text.length;
8659
+ let pos = 0;
8660
+ let tokenOffset = 0;
8661
+ let token = "Unknown";
8662
+ let tokenValue = "";
8663
+ let tokenError = "None";
8664
+ let lineNumber = 0;
8665
+ let lineStartOffset = 0;
8666
+ let tokenStartLine = 0;
8667
+ let tokenStartCharacter = 0;
8668
+ const scanHexDigits = (count) => {
8669
+ let value = 0;
8670
+ for (let i = 0; i < count; i++) {
8671
+ if (pos >= len) return -1;
8672
+ const ch = text.charCodeAt(pos);
8673
+ if (ch >= 48 && ch <= 57) value = value * 16 + (ch - 48);
8674
+ else if (ch >= 65 && ch <= 70) value = value * 16 + (ch - 65 + 10);
8675
+ else if (ch >= 97 && ch <= 102) value = value * 16 + (ch - 97 + 10);
8676
+ else return -1;
8677
+ pos++;
8678
+ }
8679
+ return value;
8680
+ };
8681
+ const scanString = () => {
8682
+ let result = "";
8683
+ pos++;
8684
+ let start = pos;
8685
+ while (pos < len) {
8686
+ const ch = text.charCodeAt(pos);
8687
+ if (ch === 34) {
8688
+ result += text.substring(start, pos);
8689
+ pos++;
8690
+ return result;
8691
+ }
8692
+ if (ch === 92) {
8693
+ result += text.substring(start, pos);
8694
+ pos++;
8695
+ if (pos >= len) {
8696
+ tokenError = "UnexpectedEndOfString";
8697
+ return result;
8698
+ }
8699
+ const escaped = text.charCodeAt(pos);
8700
+ pos++;
8701
+ switch (escaped) {
8702
+ case 34:
8703
+ result += "\"";
8704
+ break;
8705
+ case 92:
8706
+ result += "\\";
8707
+ break;
8708
+ case 47:
8709
+ result += "/";
8710
+ break;
8711
+ case 98:
8712
+ result += "\b";
8713
+ break;
8714
+ case 102:
8715
+ result += "\f";
8716
+ break;
8717
+ case 110:
8718
+ result += "\n";
8719
+ break;
8720
+ case 114:
8721
+ result += "\r";
8722
+ break;
8723
+ case 116:
8724
+ result += " ";
8725
+ break;
8726
+ case 117: {
8727
+ const value = scanHexDigits(4);
8728
+ if (value >= 0) result += String.fromCharCode(value);
8729
+ else tokenError = "InvalidUnicode";
8730
+ break;
8731
+ }
8732
+ default:
8733
+ tokenError = "InvalidEscapeCharacter";
8734
+ break;
8735
+ }
8736
+ start = pos;
8737
+ } else if (isLineBreak$1(ch)) {
8738
+ tokenError = "UnexpectedEndOfString";
8739
+ return result + text.substring(start, pos);
8740
+ } else pos++;
8741
+ }
8742
+ tokenError = "UnexpectedEndOfString";
8743
+ return result + text.substring(start, pos);
8744
+ };
8745
+ const scanNumber = () => {
8746
+ const start = pos;
8747
+ if (text.charCodeAt(pos) === 45) pos++;
8748
+ if (text.charCodeAt(pos) === 48) pos++;
8749
+ else {
8750
+ if (!isDigit$1(text.charCodeAt(pos))) {
8751
+ tokenError = "UnexpectedEndOfNumber";
8752
+ return text.substring(start, pos);
8753
+ }
8754
+ pos++;
8755
+ while (pos < len && isDigit$1(text.charCodeAt(pos))) pos++;
8756
+ }
8757
+ if (pos < len && text.charCodeAt(pos) === 46) {
8758
+ pos++;
8759
+ if (!isDigit$1(text.charCodeAt(pos))) {
8760
+ tokenError = "UnexpectedEndOfNumber";
8761
+ return text.substring(start, pos);
8762
+ }
8763
+ pos++;
8764
+ while (pos < len && isDigit$1(text.charCodeAt(pos))) pos++;
8765
+ }
8766
+ if (pos < len && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
8767
+ pos++;
8768
+ if (pos < len && (text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45)) pos++;
8769
+ if (!isDigit$1(text.charCodeAt(pos))) {
8770
+ tokenError = "UnexpectedEndOfNumber";
8771
+ return text.substring(start, pos);
8772
+ }
8773
+ pos++;
8774
+ while (pos < len && isDigit$1(text.charCodeAt(pos))) pos++;
8775
+ }
8776
+ return text.substring(start, pos);
8777
+ };
8778
+ const scan = () => {
8779
+ tokenValue = "";
8780
+ tokenError = "None";
8781
+ if (pos >= len) {
8782
+ tokenOffset = len;
8783
+ tokenStartLine = lineNumber;
8784
+ tokenStartCharacter = pos - lineStartOffset;
8785
+ token = "EOF";
8786
+ return token;
8787
+ }
8788
+ let ch = text.charCodeAt(pos);
8789
+ if (isWhitespace(ch)) {
8790
+ tokenOffset = pos;
8791
+ tokenStartLine = lineNumber;
8792
+ tokenStartCharacter = pos - lineStartOffset;
8793
+ do {
8794
+ pos++;
8795
+ ch = pos < len ? text.charCodeAt(pos) : 0;
8796
+ } while (isWhitespace(ch));
8797
+ tokenValue = text.substring(tokenOffset, pos);
8798
+ if (ignoreTrivia) return scan();
8799
+ token = "Trivia";
8800
+ return token;
8801
+ }
8802
+ if (isLineBreak$1(ch)) {
8803
+ tokenOffset = pos;
8804
+ tokenStartLine = lineNumber;
8805
+ tokenStartCharacter = pos - lineStartOffset;
8806
+ pos++;
8807
+ if (ch === 13 && pos < len && text.charCodeAt(pos) === 10) pos++;
8808
+ lineNumber++;
8809
+ lineStartOffset = pos;
8810
+ tokenValue = text.substring(tokenOffset, pos);
8811
+ if (ignoreTrivia) return scan();
8812
+ token = "LineBreak";
8813
+ return token;
8814
+ }
8815
+ tokenOffset = pos;
8816
+ tokenStartLine = lineNumber;
8817
+ tokenStartCharacter = pos - lineStartOffset;
8818
+ switch (ch) {
8819
+ case 123:
8820
+ pos++;
8821
+ tokenValue = "{";
8822
+ token = "OpenBrace";
8823
+ return token;
8824
+ case 125:
8825
+ pos++;
8826
+ tokenValue = "}";
8827
+ token = "CloseBrace";
8828
+ return token;
8829
+ case 91:
8830
+ pos++;
8831
+ tokenValue = "[";
8832
+ token = "OpenBracket";
8833
+ return token;
8834
+ case 93:
8835
+ pos++;
8836
+ tokenValue = "]";
8837
+ token = "CloseBracket";
8838
+ return token;
8839
+ case 58:
8840
+ pos++;
8841
+ tokenValue = ":";
8842
+ token = "Colon";
8843
+ return token;
8844
+ case 44:
8845
+ pos++;
8846
+ tokenValue = ",";
8847
+ token = "Comma";
8848
+ return token;
8849
+ case 34:
8850
+ tokenValue = scanString();
8851
+ token = "String";
8852
+ return token;
8853
+ case 47: {
8854
+ const nextCh = pos + 1 < len ? text.charCodeAt(pos + 1) : 0;
8855
+ if (nextCh === 47) {
8856
+ pos += 2;
8857
+ while (pos < len && !isLineBreak$1(text.charCodeAt(pos))) pos++;
8858
+ tokenValue = text.substring(tokenOffset, pos);
8859
+ if (ignoreTrivia) return scan();
8860
+ token = "LineComment";
8861
+ return token;
8862
+ }
8863
+ if (nextCh === 42) {
8864
+ pos += 2;
8865
+ const safeLen = len - 1;
8866
+ let commentClosed = false;
8867
+ while (pos < safeLen) {
8868
+ const cch = text.charCodeAt(pos);
8869
+ if (isLineBreak$1(cch)) {
8870
+ if (cch === 13 && pos + 1 < len && text.charCodeAt(pos + 1) === 10) pos++;
8871
+ pos++;
8872
+ lineNumber++;
8873
+ lineStartOffset = pos;
8874
+ } else if (cch === 42 && text.charCodeAt(pos + 1) === 47) {
8875
+ pos += 2;
8876
+ commentClosed = true;
8877
+ break;
8878
+ } else pos++;
8879
+ }
8880
+ if (!commentClosed) {
8881
+ pos = len;
8882
+ tokenError = "UnexpectedEndOfComment";
8883
+ }
8884
+ tokenValue = text.substring(tokenOffset, pos);
8885
+ if (ignoreTrivia) return scan();
8886
+ token = "BlockComment";
8887
+ return token;
8888
+ }
8889
+ pos++;
8890
+ tokenValue = text.substring(tokenOffset, pos);
8891
+ token = "Unknown";
8892
+ tokenError = "InvalidCharacter";
8893
+ return token;
8894
+ }
8895
+ case 45:
8896
+ if (pos + 1 < len && isDigit$1(text.charCodeAt(pos + 1))) {
8897
+ tokenValue = scanNumber();
8898
+ token = "Number";
8899
+ return token;
8900
+ }
8901
+ pos++;
8902
+ tokenValue = "-";
8903
+ token = "Unknown";
8904
+ tokenError = "InvalidSymbol";
8905
+ return token;
8906
+ default:
8907
+ if (isDigit$1(ch)) {
8908
+ tokenValue = scanNumber();
8909
+ token = "Number";
8910
+ return token;
8911
+ }
8912
+ if (ch >= 97 && ch <= 122) {
8913
+ const start = pos;
8914
+ pos++;
8915
+ while (pos < len) {
8916
+ const kch = text.charCodeAt(pos);
8917
+ if (kch >= 97 && kch <= 122) pos++;
8918
+ else break;
8919
+ }
8920
+ tokenValue = text.substring(start, pos);
8921
+ switch (tokenValue) {
8922
+ case "true":
8923
+ token = "True";
8924
+ return token;
8925
+ case "false":
8926
+ token = "False";
8927
+ return token;
8928
+ case "null":
8929
+ token = "Null";
8930
+ return token;
8931
+ default:
8932
+ token = "Unknown";
8933
+ tokenError = "InvalidSymbol";
8934
+ return token;
8935
+ }
8936
+ }
8937
+ pos++;
8938
+ tokenValue = text.substring(tokenOffset, pos);
8939
+ token = "Unknown";
8940
+ tokenError = "InvalidCharacter";
8941
+ return token;
8942
+ }
8943
+ };
8944
+ return {
8945
+ scan,
8946
+ getToken: () => token,
8947
+ getTokenValue: () => tokenValue,
8948
+ getTokenOffset: () => tokenOffset,
8949
+ getTokenLength: () => pos - tokenOffset,
8950
+ getTokenStartLine: () => tokenStartLine,
8951
+ getTokenStartCharacter: () => tokenStartCharacter,
8952
+ getTokenError: () => tokenError,
8953
+ getPosition: () => pos,
8954
+ setPosition: (newPos) => {
8955
+ pos = newPos;
8956
+ tokenValue = "";
8957
+ token = "Unknown";
8958
+ tokenError = "None";
8959
+ }
8960
+ };
8961
+ };
8962
+ //#endregion
8963
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/parse.js
8964
+ /**
8965
+ * JSONC Parser — converts token stream into JavaScript values or AST nodes.
8966
+ *
8967
+ * Pure Effect implementation using recursive descent parsing.
8968
+ * Reference: Microsoft's jsonc-parser parser design (MIT).
8969
+ *
8970
+ * @packageDocumentation
8971
+ */
8972
+ /**
8973
+ * Parse a JSONC string into a JavaScript value.
8974
+ *
8975
+ * @param text - JSONC string to parse
8976
+ * @param options - Optional {@link JsoncParseOptions} controlling comment and
8977
+ * trailing-comma handling.
8978
+ * @returns `Effect<unknown, JsoncParseError>` — succeeds with the parsed value
8979
+ * or fails with a {@link JsoncParseError} containing every error encountered.
8980
+ *
8981
+ * @remarks
8982
+ * The return type is `unknown` (not `any`) so consumers are forced to narrow
8983
+ * the result, which is safer in Effect pipelines. By default
8984
+ * `allowTrailingComma` is `true`, matching common JSONC conventions used in
8985
+ * VS Code settings and `tsconfig.json`.
8986
+ *
8987
+ * @see {@link parseTree} — parse into an AST instead of a plain value
8988
+ * @see {@link JsoncParseOptions} — available parse options
8989
+ * @see {@link JsoncParseError} — the tagged error type on the failure channel
8990
+ *
8991
+ * @example
8992
+ * Basic parsing:
8993
+ * ```ts
8994
+ * import { Effect } from "effect";
8995
+ * import { parse } from "jsonc-effect";
8996
+ *
8997
+ * const value = Effect.runSync(parse('{ "key": 42 }'));
8998
+ * console.log(value); // { key: 42 }
8999
+ * ```
9000
+ *
9001
+ * @example
9002
+ * Parsing with options:
9003
+ * ```ts
9004
+ * import { Effect } from "effect";
9005
+ * import { parse } from "jsonc-effect";
9006
+ *
9007
+ * const value = Effect.runSync(
9008
+ * parse('{ "key": 42 }', { disallowComments: true }),
9009
+ * );
9010
+ * ```
9011
+ *
9012
+ * @example
9013
+ * Error handling with `catchTag`:
9014
+ * ```ts
9015
+ * import { Effect } from "effect";
9016
+ * import { parse } from "jsonc-effect";
9017
+ *
9018
+ * const program = parse("{ bad }").pipe(
9019
+ * Effect.catchTag("JsoncParseError", (err) =>
9020
+ * Effect.succeed({ fallback: true, errors: err.errors }),
9021
+ * ),
9022
+ * );
9023
+ *
9024
+ * const result = Effect.runSync(program);
9025
+ * console.log(result);
9026
+ * ```
9027
+ *
9028
+ * @example
9029
+ * Using `Effect.gen`:
9030
+ * ```ts
9031
+ * import { Effect } from "effect";
9032
+ * import { parse } from "jsonc-effect";
9033
+ *
9034
+ * const program = Effect.gen(function* () {
9035
+ * const config = yield* parse('{ "port": 3000 }');
9036
+ * return config;
9037
+ * });
9038
+ *
9039
+ * const result = Effect.runSync(program);
9040
+ * console.log(result); // { port: 3000 }
9041
+ * ```
9042
+ *
9043
+ * @privateRemarks
9044
+ * Uses {@link createScanner} internally with a recursive descent parser.
9045
+ * The scanner is created with `ignoreTrivia = false` so the parser can
9046
+ * report comment-related errors when `disallowComments` is set.
9047
+ *
9048
+ * @public
9049
+ */
9050
+ const parse$2 = (text, options) => effect.Effect.sync(() => parseInternal(text, options ?? {}, false)).pipe(effect.Effect.flatMap(({ value, errors }) => {
9051
+ if (errors.length > 0) return effect.Effect.fail(new JsoncParseError({
9052
+ errors,
9053
+ text,
9054
+ ...options !== void 0 ? { options } : {}
9055
+ }));
9056
+ return effect.Effect.succeed(value);
9057
+ }));
9058
+ function parseInternal(text, options, buildTree) {
9059
+ const scanner = createScanner$1(text, false);
9060
+ const errors = [];
9061
+ const disallowComments = options.disallowComments ?? false;
9062
+ const allowTrailingComma = options.allowTrailingComma ?? true;
9063
+ const allowEmptyContent = options.allowEmptyContent ?? false;
9064
+ let currentToken = "Unknown";
9065
+ function token() {
9066
+ return currentToken;
9067
+ }
9068
+ function scanNext() {
9069
+ for (;;) {
9070
+ currentToken = scanner.scan();
9071
+ switch (scanner.getTokenError()) {
9072
+ case "InvalidUnicode":
9073
+ handleError("InvalidUnicode");
9074
+ break;
9075
+ case "InvalidEscapeCharacter":
9076
+ handleError("InvalidEscapeCharacter");
9077
+ break;
9078
+ case "UnexpectedEndOfNumber":
9079
+ handleError("InvalidNumberFormat");
9080
+ break;
9081
+ case "UnexpectedEndOfComment":
9082
+ handleError("UnexpectedEndOfComment");
9083
+ break;
9084
+ case "UnexpectedEndOfString":
9085
+ handleError("UnexpectedEndOfString");
9086
+ break;
9087
+ case "InvalidCharacter":
9088
+ handleError("InvalidCharacter");
9089
+ break;
9090
+ }
9091
+ switch (currentToken) {
9092
+ case "LineComment":
9093
+ case "BlockComment":
9094
+ if (disallowComments) handleError("InvalidCommentToken");
9095
+ break;
9096
+ case "Trivia":
9097
+ case "LineBreak": break;
9098
+ default: return currentToken;
9099
+ }
9100
+ }
9101
+ }
9102
+ function tokenEnd() {
9103
+ return scanner.getTokenOffset() + scanner.getTokenLength();
9104
+ }
9105
+ function handleError(code, skipUntilAfter = [], skipUntil = []) {
9106
+ errors.push(new JsoncParseErrorDetail({
9107
+ code,
9108
+ message: formatError(code, scanner.getTokenOffset()),
9109
+ offset: scanner.getTokenOffset(),
9110
+ length: scanner.getTokenLength(),
9111
+ startLine: scanner.getTokenStartLine(),
9112
+ startCharacter: scanner.getTokenStartCharacter()
9113
+ }));
9114
+ if (skipUntilAfter.length > 0 || skipUntil.length > 0) {
9115
+ let t = token();
9116
+ while (t !== "EOF") {
9117
+ if (skipUntilAfter.includes(t)) {
9118
+ scanNext();
9119
+ break;
9120
+ }
9121
+ if (skipUntil.includes(t)) break;
9122
+ t = scanNext();
9123
+ }
9124
+ }
9125
+ }
9126
+ function parseValue() {
9127
+ switch (token()) {
9128
+ case "OpenBracket": return parseArray();
9129
+ case "OpenBrace": return parseObject();
9130
+ case "String": return parseString();
9131
+ case "Number": return parseNumber();
9132
+ case "True":
9133
+ scanNext();
9134
+ return true;
9135
+ case "False":
9136
+ scanNext();
9137
+ return false;
9138
+ case "Null":
9139
+ scanNext();
9140
+ return null;
9141
+ default: return;
9142
+ }
9143
+ }
9144
+ function parseString() {
9145
+ const value = scanner.getTokenValue();
9146
+ scanNext();
9147
+ return value;
9148
+ }
9149
+ function parseNumber() {
9150
+ const value = Number.parseFloat(scanner.getTokenValue());
9151
+ scanNext();
9152
+ return value;
9153
+ }
9154
+ function parseArray() {
9155
+ scanNext();
9156
+ const arr = [];
9157
+ let needsComma = false;
9158
+ while (token() !== "CloseBracket" && token() !== "EOF") {
9159
+ if (token() === "Comma") {
9160
+ if (!needsComma) handleError("ValueExpected");
9161
+ scanNext();
9162
+ if (token() === "CloseBracket" && allowTrailingComma) break;
9163
+ } else if (needsComma) handleError("CommaExpected");
9164
+ const value = parseValue();
9165
+ if (value === void 0) handleError("ValueExpected", [], ["CloseBracket", "Comma"]);
9166
+ else arr.push(value);
9167
+ needsComma = true;
9168
+ }
9169
+ if (token() !== "CloseBracket") handleError("CloseBracketExpected");
9170
+ else scanNext();
9171
+ return arr;
9172
+ }
9173
+ function parseObject() {
9174
+ scanNext();
9175
+ const obj = {};
9176
+ let needsComma = false;
9177
+ while (token() !== "CloseBrace" && token() !== "EOF") {
9178
+ if (token() === "Comma") {
9179
+ if (!needsComma) handleError("PropertyNameExpected");
9180
+ scanNext();
9181
+ if (token() === "CloseBrace" && allowTrailingComma) break;
9182
+ } else if (needsComma) handleError("CommaExpected");
9183
+ if (token() !== "String") {
9184
+ handleError("PropertyNameExpected", [], ["CloseBrace", "Comma"]);
9185
+ continue;
9186
+ }
9187
+ const key = scanner.getTokenValue();
9188
+ scanNext();
9189
+ if (token() !== "Colon") {
9190
+ handleError("ColonExpected", [], ["CloseBrace", "Comma"]);
9191
+ continue;
9192
+ }
9193
+ scanNext();
9194
+ const value = parseValue();
9195
+ if (value === void 0) handleError("ValueExpected", [], ["CloseBrace", "Comma"]);
9196
+ else obj[key] = value;
9197
+ needsComma = true;
9198
+ }
9199
+ if (token() !== "CloseBrace") handleError("CloseBraceExpected");
9200
+ else scanNext();
9201
+ return obj;
9202
+ }
9203
+ function parseValueTree() {
9204
+ switch (token()) {
9205
+ case "OpenBracket": return parseArrayTree();
9206
+ case "OpenBrace": return parseObjectTree();
9207
+ case "String": {
9208
+ const node = {
9209
+ type: "string",
9210
+ offset: scanner.getTokenOffset(),
9211
+ length: 0,
9212
+ value: scanner.getTokenValue()
9213
+ };
9214
+ const end = tokenEnd();
9215
+ scanNext();
9216
+ node.length = end - node.offset;
9217
+ return node;
9218
+ }
9219
+ case "Number": {
9220
+ const node = {
9221
+ type: "number",
9222
+ offset: scanner.getTokenOffset(),
9223
+ length: 0,
9224
+ value: Number.parseFloat(scanner.getTokenValue())
9225
+ };
9226
+ const end = tokenEnd();
9227
+ scanNext();
9228
+ node.length = end - node.offset;
9229
+ return node;
9230
+ }
9231
+ case "True": {
9232
+ const node = {
9233
+ type: "boolean",
9234
+ offset: scanner.getTokenOffset(),
9235
+ length: 0,
9236
+ value: true
9237
+ };
9238
+ const end = tokenEnd();
9239
+ scanNext();
9240
+ node.length = end - node.offset;
9241
+ return node;
9242
+ }
9243
+ case "False": {
9244
+ const node = {
9245
+ type: "boolean",
9246
+ offset: scanner.getTokenOffset(),
9247
+ length: 0,
9248
+ value: false
9249
+ };
9250
+ const end = tokenEnd();
9251
+ scanNext();
9252
+ node.length = end - node.offset;
9253
+ return node;
9254
+ }
9255
+ case "Null": {
9256
+ const node = {
9257
+ type: "null",
9258
+ offset: scanner.getTokenOffset(),
9259
+ length: 0,
9260
+ value: null
9261
+ };
9262
+ const end = tokenEnd();
9263
+ scanNext();
9264
+ node.length = end - node.offset;
9265
+ return node;
9266
+ }
9267
+ default: return;
9268
+ }
9269
+ }
9270
+ function parseArrayTree() {
9271
+ const node = {
9272
+ type: "array",
9273
+ offset: scanner.getTokenOffset(),
9274
+ length: 0,
9275
+ children: []
9276
+ };
9277
+ scanNext();
9278
+ let needsComma = false;
9279
+ while (token() !== "CloseBracket" && token() !== "EOF") {
9280
+ if (token() === "Comma") {
9281
+ if (!needsComma) handleError("ValueExpected");
9282
+ scanNext();
9283
+ if (token() === "CloseBracket" && allowTrailingComma) break;
9284
+ } else if (needsComma) handleError("CommaExpected");
9285
+ const child = parseValueTree();
9286
+ if (child) node.children.push(child);
9287
+ else handleError("ValueExpected", [], ["CloseBracket", "Comma"]);
9288
+ needsComma = true;
9289
+ }
9290
+ let end;
9291
+ if (token() !== "CloseBracket") {
9292
+ handleError("CloseBracketExpected");
9293
+ end = scanner.getTokenOffset();
9294
+ } else {
9295
+ end = tokenEnd();
9296
+ scanNext();
9297
+ }
9298
+ node.length = end - node.offset;
9299
+ return node;
9300
+ }
9301
+ function parseObjectTree() {
9302
+ const node = {
9303
+ type: "object",
9304
+ offset: scanner.getTokenOffset(),
9305
+ length: 0,
9306
+ children: []
9307
+ };
9308
+ scanNext();
9309
+ let needsComma = false;
9310
+ while (token() !== "CloseBrace" && token() !== "EOF") {
9311
+ if (token() === "Comma") {
9312
+ if (!needsComma) handleError("PropertyNameExpected");
9313
+ scanNext();
9314
+ if (token() === "CloseBrace" && allowTrailingComma) break;
9315
+ } else if (needsComma) handleError("CommaExpected");
9316
+ if (token() !== "String") {
9317
+ handleError("PropertyNameExpected", [], ["CloseBrace", "Comma"]);
9318
+ continue;
9319
+ }
9320
+ const property = {
9321
+ type: "property",
9322
+ offset: scanner.getTokenOffset(),
9323
+ length: 0,
9324
+ children: []
9325
+ };
9326
+ const keyNode = {
9327
+ type: "string",
9328
+ offset: scanner.getTokenOffset(),
9329
+ length: 0,
9330
+ value: scanner.getTokenValue()
9331
+ };
9332
+ const keyEnd = tokenEnd();
9333
+ scanNext();
9334
+ keyNode.length = keyEnd - keyNode.offset;
9335
+ property.children.push(keyNode);
9336
+ if (token() !== "Colon") {
9337
+ handleError("ColonExpected", [], ["CloseBrace", "Comma"]);
9338
+ property.length = scanner.getTokenOffset() - property.offset;
9339
+ node.children.push(property);
9340
+ continue;
9341
+ }
9342
+ property.colonOffset = scanner.getTokenOffset();
9343
+ scanNext();
9344
+ const valueNode = parseValueTree();
9345
+ if (valueNode) {
9346
+ property.children.push(valueNode);
9347
+ property.length = valueNode.offset + valueNode.length - property.offset;
9348
+ } else {
9349
+ handleError("ValueExpected", [], ["CloseBrace", "Comma"]);
9350
+ property.length = scanner.getTokenOffset() - property.offset;
9351
+ }
9352
+ node.children.push(property);
9353
+ needsComma = true;
9354
+ }
9355
+ let end;
9356
+ if (token() !== "CloseBrace") {
9357
+ handleError("CloseBraceExpected");
9358
+ end = scanner.getTokenOffset();
9359
+ } else {
9360
+ end = tokenEnd();
9361
+ scanNext();
9362
+ }
9363
+ node.length = end - node.offset;
9364
+ return node;
9365
+ }
9366
+ scanNext();
9367
+ if (buildTree) {
9368
+ const root = parseValueTree();
9369
+ if (token() !== "EOF") handleError("EndOfFileExpected");
9370
+ if (!root && !allowEmptyContent) handleError("ValueExpected");
9371
+ return {
9372
+ value: void 0,
9373
+ root,
9374
+ errors
9375
+ };
9376
+ }
9377
+ const value = parseValue();
9378
+ if (token() !== "EOF") handleError("EndOfFileExpected");
9379
+ if (value === void 0 && !allowEmptyContent) handleError("ValueExpected");
9380
+ return {
9381
+ value,
9382
+ root: void 0,
9383
+ errors
9384
+ };
9385
+ }
9386
+ function formatError(code, offset) {
9387
+ switch (code) {
9388
+ case "InvalidSymbol": return `Invalid symbol at offset ${offset}`;
9389
+ case "InvalidNumberFormat": return `Invalid number format at offset ${offset}`;
9390
+ case "PropertyNameExpected": return `Property name expected at offset ${offset}`;
9391
+ case "ValueExpected": return `Value expected at offset ${offset}`;
9392
+ case "ColonExpected": return `Colon expected at offset ${offset}`;
9393
+ case "CommaExpected": return `Comma expected at offset ${offset}`;
9394
+ case "CloseBraceExpected": return `Close brace expected at offset ${offset}`;
9395
+ case "CloseBracketExpected": return `Close bracket expected at offset ${offset}`;
9396
+ case "EndOfFileExpected": return `End of file expected at offset ${offset}`;
9397
+ case "InvalidCommentToken": return `Comments not allowed at offset ${offset}`;
9398
+ case "UnexpectedEndOfComment": return `Unexpected end of comment at offset ${offset}`;
9399
+ case "UnexpectedEndOfString": return `Unexpected end of string at offset ${offset}`;
9400
+ case "UnexpectedEndOfNumber": return `Unexpected end of number at offset ${offset}`;
9401
+ case "InvalidUnicode": return `Invalid unicode escape at offset ${offset}`;
9402
+ case "InvalidEscapeCharacter": return `Invalid escape character at offset ${offset}`;
9403
+ case "InvalidCharacter": return `Invalid character at offset ${offset}`;
9404
+ default: return `Parse error at offset ${offset}`;
9405
+ }
9406
+ }
9407
+ //#endregion
9408
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/format.js
9409
+ /**
9410
+ * Apply an array of text edits to JSONC source text.
9411
+ *
9412
+ * This is a {@link https://effect.website/docs/function-dual | Function.dual}
9413
+ * that supports both data-first and data-last (pipeline) usage.
9414
+ *
9415
+ * @param text - The original JSONC source text.
9416
+ * @param edits - A read-only array of {@link JsoncEdit} objects, typically
9417
+ * produced by {@link format} or {@link modify}.
9418
+ * @returns An `Effect` that succeeds with the edited string.
9419
+ *
9420
+ * @remarks
9421
+ * Edits are sorted in reverse offset order before application so that
9422
+ * earlier edits do not shift the offsets of later ones. The original `edits`
9423
+ * array is not mutated.
9424
+ *
9425
+ * @see {@link format} to compute formatting edits.
9426
+ * @see {@link modify} to compute structural edits (insert, replace, remove).
9427
+ *
9428
+ * @example Data-first usage
9429
+ * ```ts
9430
+ * import { Effect } from "effect";
9431
+ * import { format, applyEdits } from "jsonc-effect";
9432
+ *
9433
+ * const input = '{"a":1}';
9434
+ * const edits = Effect.runSync(format(input));
9435
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9436
+ * ```
9437
+ *
9438
+ * @example Pipeline with modify
9439
+ * ```ts
9440
+ * import { Effect, pipe } from "effect";
9441
+ * import { modify, applyEdits } from "jsonc-effect";
9442
+ *
9443
+ * const input = '{ "a": 1 }';
9444
+ * const result = pipe(
9445
+ * input,
9446
+ * modify(["a"], 42),
9447
+ * Effect.flatMap((edits) => applyEdits(input, edits)),
9448
+ * Effect.runSync,
9449
+ * );
9450
+ * ```
9451
+ *
9452
+ * @public
9453
+ */
9454
+ const applyEdits$1 = effect.Function.dual(2, (text, edits) => effect.Effect.sync(() => {
9455
+ const sorted = [...edits].sort((a, b) => b.offset - a.offset);
9456
+ let result = text;
9457
+ for (const edit of sorted) result = result.substring(0, edit.offset) + edit.content + result.substring(edit.offset + edit.length);
9458
+ return result;
9459
+ }));
9460
+ /**
9461
+ * Compute edits to insert, replace, or remove a value at a JSON path.
9462
+ *
9463
+ * This is a {@link https://effect.website/docs/function-dual | Function.dual}
9464
+ * that supports both data-first and data-last (pipeline) usage.
9465
+ *
9466
+ * @param text - The JSONC source text to modify.
9467
+ * @param path - A {@link (JsoncPath:type)} (array of string keys and numeric indices)
9468
+ * identifying the target location in the JSON structure.
9469
+ * @param value - The value to set. Pass `undefined` to remove the
9470
+ * property or array element at the given path.
9471
+ * @param options - Optional object with `formattingOptions` controlling
9472
+ * indent size, tabs vs. spaces, and EOL style for generated text.
9473
+ * @returns An `Effect` that succeeds with a read-only array of
9474
+ * {@link JsoncEdit} objects, or fails with a
9475
+ * {@link JsoncModificationError} if the path cannot be navigated.
9476
+ *
9477
+ * @remarks
9478
+ * Setting `value` to `undefined` removes the targeted property or element,
9479
+ * including its surrounding comma. When inserting a new property into an
9480
+ * object, it is appended after the last existing property.
9481
+ *
9482
+ * @see {@link applyEdits} to apply the returned edits to the source text.
9483
+ * @see {@link JsoncModificationError} for the error type on navigation failure.
9484
+ *
9485
+ * @example Update an existing property
9486
+ * ```ts
9487
+ * import { Effect } from "effect";
9488
+ * import { modify, applyEdits } from "jsonc-effect";
9489
+ *
9490
+ * const input = '{ "a": 1 }';
9491
+ * const edits = Effect.runSync(modify(input, ["a"], 2));
9492
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9493
+ * ```
9494
+ *
9495
+ * @example Insert a new property
9496
+ * ```ts
9497
+ * import { Effect } from "effect";
9498
+ * import { modify, applyEdits } from "jsonc-effect";
9499
+ *
9500
+ * const input = '{ "a": 1 }';
9501
+ * const edits = Effect.runSync(modify(input, ["b"], "hello"));
9502
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9503
+ * ```
9504
+ *
9505
+ * @example Remove a property
9506
+ * ```ts
9507
+ * import { Effect } from "effect";
9508
+ * import { modify, applyEdits } from "jsonc-effect";
9509
+ *
9510
+ * const input = '{ "a": 1, "b": 2 }';
9511
+ * const edits = Effect.runSync(modify(input, ["a"], undefined));
9512
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9513
+ * ```
9514
+ *
9515
+ * @example Pipeline (data-last) usage
9516
+ * ```ts
9517
+ * import { Effect, pipe } from "effect";
9518
+ * import { modify, applyEdits } from "jsonc-effect";
9519
+ *
9520
+ * const input = '{ "a": 1 }';
9521
+ * const result = pipe(
9522
+ * input,
9523
+ * modify(["a"], 42),
9524
+ * Effect.flatMap((edits) => applyEdits(input, edits)),
9525
+ * Effect.runSync,
9526
+ * );
9527
+ * ```
9528
+ *
9529
+ * @privateRemarks
9530
+ * Uses its own scanner-based navigation to locate the target path rather
9531
+ * than building a full AST via `parseTree`. This keeps the implementation
9532
+ * lightweight and avoids an intermediate allocation.
9533
+ *
9534
+ * @public
9535
+ */
9536
+ const modify = effect.Function.dual((args) => typeof args[0] === "string" && Array.isArray(args[1]), (text, path, value, options) => effect.Effect.try({
9537
+ try: () => modifyImpl(text, path, value, options?.formattingOptions),
9538
+ catch: (e) => new JsoncModificationError({
9539
+ path,
9540
+ reason: String(e)
9541
+ })
9542
+ }));
9543
+ function modifyImpl(text, path, value, formattingOptions) {
9544
+ const opts = {
9545
+ tabSize: formattingOptions?.tabSize ?? 2,
9546
+ insertSpaces: formattingOptions?.insertSpaces ?? true,
9547
+ eol: formattingOptions?.eol ?? "\n"
9548
+ };
9549
+ const indentUnit = opts.insertSpaces ? " ".repeat(opts.tabSize) : " ";
9550
+ if (path.length === 0) {
9551
+ const content = value === void 0 ? "" : JSON.stringify(value, null, opts.tabSize);
9552
+ return [{
9553
+ offset: 0,
9554
+ length: text.length,
9555
+ content
9556
+ }];
9557
+ }
9558
+ const scanner = createScanner$1(text, true);
9559
+ let currentToken = scanner.scan();
9560
+ function tokenEnd() {
9561
+ return scanner.getTokenOffset() + scanner.getTokenLength();
9562
+ }
9563
+ function skipValue() {
9564
+ switch (currentToken) {
9565
+ case "OpenBrace": {
9566
+ let end = tokenEnd();
9567
+ currentToken = scanner.scan();
9568
+ let first = true;
9569
+ while (currentToken !== "CloseBrace" && currentToken !== "EOF") {
9570
+ if (!first && currentToken === "Comma") currentToken = scanner.scan();
9571
+ if (currentToken === "String") {
9572
+ currentToken = scanner.scan();
9573
+ if (currentToken === "Colon") {
9574
+ currentToken = scanner.scan();
9575
+ end = skipValue();
9576
+ }
9577
+ } else {
9578
+ end = tokenEnd();
9579
+ currentToken = scanner.scan();
9580
+ }
9581
+ first = false;
9582
+ }
9583
+ if (currentToken === "CloseBrace") {
9584
+ end = tokenEnd();
9585
+ currentToken = scanner.scan();
9586
+ }
9587
+ return end;
9588
+ }
9589
+ case "OpenBracket": {
9590
+ let end = tokenEnd();
9591
+ currentToken = scanner.scan();
9592
+ let first = true;
9593
+ while (currentToken !== "CloseBracket" && currentToken !== "EOF") {
9594
+ if (!first && currentToken === "Comma") currentToken = scanner.scan();
9595
+ end = skipValue();
9596
+ first = false;
9597
+ }
9598
+ if (currentToken === "CloseBracket") {
9599
+ end = tokenEnd();
9600
+ currentToken = scanner.scan();
9601
+ }
9602
+ return end;
9603
+ }
9604
+ default: {
9605
+ const end = tokenEnd();
9606
+ currentToken = scanner.scan();
9607
+ return end;
9608
+ }
9609
+ }
9610
+ }
9611
+ let depth = 0;
9612
+ for (const segment of path) {
9613
+ depth++;
9614
+ if (typeof segment === "string") {
9615
+ if (currentToken !== "OpenBrace") throw new Error(`Expected object at depth ${depth}`);
9616
+ currentToken = scanner.scan();
9617
+ let found = false;
9618
+ let lastValueEnd = scanner.getTokenOffset();
9619
+ let isFirst = true;
9620
+ while (currentToken !== "CloseBrace" && currentToken !== "EOF") {
9621
+ if (!isFirst && currentToken === "Comma") currentToken = scanner.scan();
9622
+ if (currentToken === "String") {
9623
+ const key = scanner.getTokenValue();
9624
+ currentToken = scanner.scan();
9625
+ if (currentToken === "Colon") currentToken = scanner.scan();
9626
+ if (key === segment) {
9627
+ found = true;
9628
+ if (depth === path.length) {
9629
+ const valueStart = scanner.getTokenOffset();
9630
+ const prevEnd = valueStart;
9631
+ const valueEnd = skipValue();
9632
+ if (value === void 0) {
9633
+ let removeStart = valueStart;
9634
+ let removeEnd = valueEnd;
9635
+ const keyStart = text.substring(0, valueStart).lastIndexOf(`"${segment}"`);
9636
+ if (keyStart >= 0) removeStart = keyStart;
9637
+ const commaPosBefore = text.substring(0, removeStart).trimEnd().lastIndexOf(",");
9638
+ if (commaPosBefore >= 0) removeStart = commaPosBefore;
9639
+ else {
9640
+ const trimmedAfter = text.substring(removeEnd).match(/^(\s*,)/);
9641
+ if (trimmedAfter) removeEnd += trimmedAfter[1].length;
9642
+ }
9643
+ return [{
9644
+ offset: removeStart,
9645
+ length: removeEnd - removeStart,
9646
+ content: ""
9647
+ }];
9648
+ }
9649
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9650
+ return [{
9651
+ offset: prevEnd,
9652
+ length: valueEnd - prevEnd,
9653
+ content: serialized
9654
+ }];
9655
+ }
9656
+ break;
9657
+ }
9658
+ lastValueEnd = skipValue();
9659
+ } else {
9660
+ currentToken = scanner.scan();
9661
+ lastValueEnd = scanner.getTokenOffset();
9662
+ }
9663
+ isFirst = false;
9664
+ }
9665
+ if (!found && depth === path.length && value !== void 0) {
9666
+ const indent = indentUnit.repeat(depth);
9667
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9668
+ const insertText = isFirst ? `${opts.eol}${indent}"${segment}": ${serialized}${opts.eol}${indentUnit.repeat(depth - 1)}` : `,${opts.eol}${indent}"${segment}": ${serialized}`;
9669
+ return [{
9670
+ offset: lastValueEnd,
9671
+ length: 0,
9672
+ content: insertText
9673
+ }];
9674
+ }
9675
+ } else {
9676
+ if (currentToken !== "OpenBracket") throw new Error(`Expected array at depth ${depth}`);
9677
+ currentToken = scanner.scan();
9678
+ let idx = 0;
9679
+ let lastEnd = scanner.getTokenOffset();
9680
+ while (currentToken !== "CloseBracket" && currentToken !== "EOF") {
9681
+ if (idx > 0 && currentToken === "Comma") currentToken = scanner.scan();
9682
+ if (idx === segment) {
9683
+ if (depth === path.length) {
9684
+ const valueStart = scanner.getTokenOffset();
9685
+ const valueEnd = skipValue();
9686
+ if (value === void 0) {
9687
+ let removeEnd = valueEnd;
9688
+ if (text.substring(removeEnd).trimStart().startsWith(",")) removeEnd = text.indexOf(",", removeEnd) + 1;
9689
+ return [{
9690
+ offset: valueStart,
9691
+ length: removeEnd - valueStart,
9692
+ content: ""
9693
+ }];
9694
+ }
9695
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9696
+ return [{
9697
+ offset: valueStart,
9698
+ length: valueEnd - valueStart,
9699
+ content: serialized
9700
+ }];
9701
+ }
9702
+ break;
9703
+ }
9704
+ lastEnd = skipValue();
9705
+ idx++;
9706
+ }
9707
+ if (idx <= segment && depth === path.length && value !== void 0) {
9708
+ const indent = indentUnit.repeat(depth);
9709
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9710
+ const insertText = idx === 0 ? `${opts.eol}${indent}${serialized}${opts.eol}${indentUnit.repeat(depth - 1)}` : `,${opts.eol}${indent}${serialized}`;
9711
+ return [{
9712
+ offset: lastEnd,
9713
+ length: 0,
9714
+ content: insertText
9715
+ }];
9716
+ }
9717
+ }
9718
+ }
9719
+ return [];
9720
+ }
9721
+ //#endregion
8443
9722
  //#region ../../node_modules/.pnpm/workspaces-effect@2.0.2_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/schemas/WorkspaceStateSnapshot.js
8444
9723
  const DepRecord = effect.Schema.optionalWith(effect.Schema.Record({
8445
9724
  key: effect.Schema.String,
@@ -8726,7 +10005,7 @@ const packageSnapshotFromJson = (text, relativePath) => {
8726
10005
  *
8727
10006
  * @internal
8728
10007
  */
8729
- const lockfileCatalogsAtRef = (text) => effect.Option.isNone(text) ? effect.Effect.succeed(CatalogSet.empty()) : parse$2(text.value).pipe(effect.Effect.map((parsed) => CatalogSet.fromLockfileCatalogs(parsed?.catalogs)), effect.Effect.orElseSucceed(() => CatalogSet.empty()));
10008
+ const lockfileCatalogsAtRef = (text) => effect.Option.isNone(text) ? effect.Effect.succeed(CatalogSet.empty()) : parse$3(text.value).pipe(effect.Effect.map((parsed) => CatalogSet.fromLockfileCatalogs(parsed?.catalogs)), effect.Effect.orElseSucceed(() => CatalogSet.empty()));
8730
10009
  /**
8731
10010
  * Live layer for the {@link PointInTimeWorkspace} service.
8732
10011
  *
@@ -38236,23 +39515,46 @@ function parseJsonPath(path) {
38236
39515
  * @internal
38237
39516
  */
38238
39517
  function jsonPathGet(obj, path) {
39518
+ return walkJsonPath(obj, path).map((entry) => entry.node);
39519
+ }
39520
+ /**
39521
+ * Shared breadth-first traversal behind {@link jsonPathGet} and
39522
+ * {@link jsonPathResolve}: each segment fans out the current set of matched
39523
+ * entries, carrying both the node and the concrete path taken to reach it.
39524
+ * The two public functions differ only in which half of the entry they keep.
39525
+ */
39526
+ function walkJsonPath(obj, path) {
38239
39527
  const segments = parseJsonPath(path);
38240
- let current = [obj];
39528
+ let current = [{
39529
+ node: obj,
39530
+ path: []
39531
+ }];
38241
39532
  for (const segment of segments) {
38242
39533
  const next = [];
38243
- for (const node of current) {
39534
+ for (const { node, path: nodePath } of current) {
38244
39535
  if (node === null || node === void 0 || typeof node !== "object") continue;
38245
39536
  switch (segment.type) {
38246
39537
  case "property": {
38247
39538
  const value = node[segment.key];
38248
- if (value !== void 0) next.push(value);
39539
+ if (value !== void 0) next.push({
39540
+ node: value,
39541
+ path: [...nodePath, segment.key]
39542
+ });
38249
39543
  break;
38250
39544
  }
38251
39545
  case "index":
38252
- if (Array.isArray(node) && segment.index < node.length) next.push(node[segment.index]);
39546
+ if (Array.isArray(node) && segment.index < node.length) next.push({
39547
+ node: node[segment.index],
39548
+ path: [...nodePath, segment.index]
39549
+ });
38253
39550
  break;
38254
39551
  case "wildcard":
38255
- if (Array.isArray(node)) next.push(...node);
39552
+ if (Array.isArray(node)) node.forEach((element, index) => {
39553
+ next.push({
39554
+ node: element,
39555
+ path: [...nodePath, index]
39556
+ });
39557
+ });
38256
39558
  break;
38257
39559
  }
38258
39560
  }
@@ -38261,81 +39563,37 @@ function jsonPathGet(obj, path) {
38261
39563
  return current;
38262
39564
  }
38263
39565
  /**
38264
- * Mutate all matching locations in an object in-place.
39566
+ * Resolve a JSONPath expression to the concrete paths of every existing match.
38265
39567
  *
38266
39568
  * @remarks
38267
- * Walks to the parent(s) of the final segment, then sets the value
38268
- * at each matching location. Only updates existing keys/indices;
38269
- * does not create new properties or extend arrays. Returns the count
38270
- * of locations actually updated.
39569
+ * Uses the same breadth-first expansion as {@link jsonPathGet}, but instead of
39570
+ * collecting the matched *values* it records the concrete `(string | number)[]`
39571
+ * path taken to reach each one. Wildcards and indices are materialized into the
39572
+ * numeric array index actually traversed, so the returned paths are directly
39573
+ * consumable by structural editors such as `jsonc-effect`'s `modify`, which
39574
+ * require a fully concrete path (no wildcards).
39575
+ *
39576
+ * Only existing locations are returned; nothing is created. A path with no
39577
+ * matches yields an empty array, and the empty path (`"$."`) yields a single
39578
+ * empty concrete path (the document root).
38271
39579
  *
38272
- * @param obj - The object to modify in-place
39580
+ * @param obj - The object to query
38273
39581
  * @param path - JSONPath string (e.g., `"$.packages[*].version"`)
38274
- * @param value - The value to set at each matching location
38275
- * @returns The number of locations updated (0 if no matches or empty path)
39582
+ * @returns Array of concrete paths, each an array of string keys / numeric indices
38276
39583
  *
38277
39584
  * @example
38278
39585
  * ```typescript
38279
- * import { jsonPathSet } from "../utils/jsonpath.js";
39586
+ * import { jsonPathResolve } from "../utils/jsonpath.js";
38280
39587
  *
38281
- * const obj = { version: "1.0.0" };
38282
- * const count = jsonPathSet(obj, "$.version", "2.0.0");
38283
- * // count === 1, obj.version === "2.0.0"
39588
+ * const obj = { packages: [{ version: "1.0.0" }, { version: "2.0.0" }] };
39589
+ * const paths = jsonPathResolve(obj, "$.packages[*].version");
39590
+ * // [["packages", 0, "version"], ["packages", 1, "version"]]
38284
39591
  * ```
38285
39592
  *
38286
39593
  * @internal
38287
39594
  */
38288
- function jsonPathSet(obj, path, value) {
38289
- const segments = parseJsonPath(path);
38290
- if (segments.length === 0) return 0;
38291
- const lastSegment = segments[segments.length - 1];
38292
- const parentSegments = segments.slice(0, -1);
38293
- let parents = [obj];
38294
- for (const segment of parentSegments) {
38295
- const next = [];
38296
- for (const node of parents) {
38297
- if (node === null || node === void 0 || typeof node !== "object") continue;
38298
- switch (segment.type) {
38299
- case "property": {
38300
- const child = node[segment.key];
38301
- if (child !== void 0) next.push(child);
38302
- break;
38303
- }
38304
- case "index":
38305
- if (Array.isArray(node) && segment.index < node.length) next.push(node[segment.index]);
38306
- break;
38307
- case "wildcard":
38308
- if (Array.isArray(node)) next.push(...node);
38309
- break;
38310
- }
38311
- }
38312
- parents = next;
38313
- }
38314
- let count = 0;
38315
- for (const parent of parents) {
38316
- if (parent === null || parent === void 0 || typeof parent !== "object") continue;
38317
- switch (lastSegment.type) {
38318
- case "property":
38319
- if (lastSegment.key in parent) {
38320
- parent[lastSegment.key] = value;
38321
- count++;
38322
- }
38323
- break;
38324
- case "index":
38325
- if (Array.isArray(parent) && lastSegment.index < parent.length) {
38326
- parent[lastSegment.index] = value;
38327
- count++;
38328
- }
38329
- break;
38330
- case "wildcard":
38331
- if (Array.isArray(parent)) for (let i = 0; i < parent.length; i++) {
38332
- parent[i] = value;
38333
- count++;
38334
- }
38335
- break;
38336
- }
38337
- }
38338
- return count;
39595
+ function jsonPathResolve(obj, path) {
39596
+ return walkJsonPath(obj, path).map((entry) => entry.path);
38339
39597
  }
38340
39598
  //#endregion
38341
39599
  //#region ../silk-effects/dist/dev/pkg/changesets/utils/version-files.js
@@ -38526,31 +39784,39 @@ var VersionFiles = class VersionFiles {
38526
39784
  return content.match(/^(\s+)"/m)?.[1] ?? " ";
38527
39785
  }
38528
39786
  /**
38529
- * Update JSON file at specified JSONPath locations.
39787
+ * Update a JSON (or JSONC) file at specified JSONPath locations,
39788
+ * preserving the original formatting byte-for-byte.
38530
39789
  *
38531
39790
  * @remarks
38532
- * Reads the file, detects its indentation style and trailing newline
38533
- * preference, applies all JSONPath updates via {@link jsonPathSet},
38534
- * and writes the result back preserving the original formatting.
38535
- * Returns `undefined` if no JSONPath locations matched (no write occurs).
39791
+ * The write is performed with `jsonc-effect`'s format-preserving
39792
+ * `modify`/`applyEdits` rather than a `JSON.parse`/`JSON.stringify`
39793
+ * round-trip (which always explodes inline arrays one-element-per-line and
39794
+ * drops comments). Each JSONPath expression is resolved to concrete
39795
+ * `(string | number)[]` paths against the parsed document, and each
39796
+ * concrete path becomes a minimal text edit that touches only the target
39797
+ * value's span — so inline arrays, comments,
39798
+ * indentation, and the trailing-newline preference all survive; a one-line
39799
+ * version bump produces a one-line diff.
39800
+ *
39801
+ * Insertion semantics: a concrete, wildcard-free JSONPath whose leaf
39802
+ * property does not exist yet is inserted after the last sibling using the
39803
+ * document's detected indent (the one case where indent detection still
39804
+ * matters). Wildcard expressions only ever update existing matches. Returns
39805
+ * `undefined` (no write) when nothing was updated or inserted.
38536
39806
  *
38537
39807
  * @param filePath - Absolute path to the JSON file
38538
39808
  * @param jsonPaths - JSONPath expressions to update
38539
39809
  * @param version - New version string
38540
39810
  * @returns Update result, or `undefined` if no changes were made
39811
+ *
39812
+ * @see {@link jsonPathResolve} for concrete-path enumeration
39813
+ * @see {@link VersionFiles.applyVersionEdit} for the per-path edit
38541
39814
  */
38542
39815
  static updateFile(filePath, jsonPaths, version) {
38543
- const content = (0, node_fs.readFileSync)(filePath, "utf-8");
38544
- const indent = VersionFiles.detectIndent(content);
38545
- const trailingNewline = content.endsWith("\n");
38546
- const obj = JSON.parse(content);
38547
- const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
38548
- let totalUpdated = 0;
38549
- for (const jp of jsonPaths) totalUpdated += jsonPathSet(obj, jp, version);
38550
- if (totalUpdated === 0) return;
38551
- let output = JSON.stringify(obj, null, indent);
38552
- if (trailingNewline) output += "\n";
38553
- (0, node_fs.writeFileSync)(filePath, output, "utf-8");
39816
+ const original = (0, node_fs.readFileSync)(filePath, "utf-8");
39817
+ const { content, previousValues, totalChanged } = VersionFiles.computeUpdate(original, jsonPaths, version);
39818
+ if (totalChanged === 0) return;
39819
+ (0, node_fs.writeFileSync)(filePath, content, "utf-8");
38554
39820
  return {
38555
39821
  filePath,
38556
39822
  jsonPaths,
@@ -38559,6 +39825,83 @@ var VersionFiles = class VersionFiles {
38559
39825
  };
38560
39826
  }
38561
39827
  /**
39828
+ * Compute the full update for a document without touching the filesystem:
39829
+ * the edited content, the previous values at every matched path, and how
39830
+ * many locations actually changed.
39831
+ *
39832
+ * @remarks
39833
+ * This is the single decision path shared by {@link VersionFiles.updateFile}
39834
+ * and the dry-run branches of the two process methods, so a preview reports
39835
+ * exactly the files a real run would write — including pending inserts of a
39836
+ * not-yet-existing wildcard-free leaf, and excluding same-value no-ops.
39837
+ *
39838
+ * @param original - Document text as read from disk
39839
+ * @param jsonPaths - JSONPath expressions to update
39840
+ * @param version - New version string
39841
+ * @returns The updated content, previous values, and changed-location count
39842
+ */
39843
+ static computeUpdate(original, jsonPaths, version) {
39844
+ let content = original;
39845
+ const obj = effect.Effect.runSync(parse$2(content));
39846
+ const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
39847
+ const indent = VersionFiles.detectIndent(content);
39848
+ const eol = content.includes("\r\n") ? "\r\n" : "\n";
39849
+ let totalChanged = 0;
39850
+ for (const jp of jsonPaths) {
39851
+ const segments = parseJsonPath(jp);
39852
+ if (segments.length === 0) continue;
39853
+ const hasWildcard = segments.some((segment) => segment.type === "wildcard");
39854
+ let concretePaths;
39855
+ if (hasWildcard) concretePaths = jsonPathResolve(obj, jp);
39856
+ else {
39857
+ const direct = segments.map((segment) => segment.type === "property" ? segment.key : segment.index);
39858
+ concretePaths = jsonPathResolve(obj, jp).length > 0 || typeof direct[direct.length - 1] === "string" ? [direct] : [];
39859
+ }
39860
+ for (const concretePath of concretePaths) {
39861
+ const updated = VersionFiles.applyVersionEdit(content, concretePath, version, indent, eol);
39862
+ if (updated !== void 0) {
39863
+ content = updated;
39864
+ totalChanged += 1;
39865
+ }
39866
+ }
39867
+ }
39868
+ return {
39869
+ content,
39870
+ previousValues,
39871
+ totalChanged
39872
+ };
39873
+ }
39874
+ /**
39875
+ * Compute the format-preserving edit for a single concrete path, returning
39876
+ * the updated document, or `undefined` when nothing changed.
39877
+ *
39878
+ * @remarks
39879
+ * Delegates to `jsonc-effect`'s {@link modify} + {@link applyEdits}
39880
+ * (requires `jsonc-effect >= 0.3.1`, whose edit spans touch only the target
39881
+ * value), so every other byte of the document is preserved. When the leaf
39882
+ * of a wildcard-free path does not exist, `modify` inserts the property
39883
+ * after the last sibling using the supplied formatting options — the only
39884
+ * case where the detected indent matters. A path whose parent is missing or
39885
+ * not an object cannot be navigated; the resulting modification error is
39886
+ * caught and reported as "no change" so the file is left alone.
39887
+ *
39888
+ * @param content - Current document text
39889
+ * @param concretePath - A wildcard-free `(string | number)[]` path
39890
+ * @param version - New version string
39891
+ * @param indentUnit - One indentation level, for inserted text
39892
+ * @param eol - End-of-line sequence, for inserted text
39893
+ * @returns The updated document, or `undefined` if the path was unchanged
39894
+ */
39895
+ static applyVersionEdit(content, concretePath, version, indentUnit, eol) {
39896
+ const insertSpaces = !indentUnit.includes(" ");
39897
+ const program = modify(content, [...concretePath], version, { formattingOptions: {
39898
+ insertSpaces,
39899
+ tabSize: insertSpaces ? indentUnit.length : 1,
39900
+ eol
39901
+ } }).pipe(effect.Effect.flatMap((edits) => applyEdits$1(content, edits)), effect.Effect.map((updated) => updated === content ? void 0 : updated), effect.Effect.catchTag("JsoncModificationError", () => effect.Effect.succeed(void 0)));
39902
+ return effect.Effect.runSync(program);
39903
+ }
39904
+ /**
38562
39905
  * Orchestrate the full version file update flow.
38563
39906
  *
38564
39907
  * @remarks
@@ -38584,9 +39927,8 @@ var VersionFiles = class VersionFiles {
38584
39927
  try {
38585
39928
  if (dryRun) {
38586
39929
  const content = (0, node_fs.readFileSync)(filePath, "utf-8");
38587
- const obj = JSON.parse(content);
38588
- const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
38589
- if (previousValues.length > 0) updates.push({
39930
+ const { previousValues, totalChanged } = VersionFiles.computeUpdate(content, jsonPaths, version);
39931
+ if (totalChanged > 0) updates.push({
38590
39932
  filePath,
38591
39933
  jsonPaths,
38592
39934
  version,
@@ -38630,9 +39972,8 @@ var VersionFiles = class VersionFiles {
38630
39972
  for (const filePath of vf.matchedFiles) try {
38631
39973
  if (dryRun) {
38632
39974
  const content = (0, node_fs.readFileSync)(filePath, "utf-8");
38633
- const obj = JSON.parse(content);
38634
- const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
38635
- if (previousValues.length > 0) updates.push({
39975
+ const { previousValues, totalChanged } = VersionFiles.computeUpdate(content, jsonPaths, scope.version);
39976
+ if (totalChanged > 0) updates.push({
38636
39977
  filePath,
38637
39978
  jsonPaths,
38638
39979
  version: scope.version,