@savvy-web/silk 2.1.0 → 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.
@@ -362,7 +362,7 @@ const ChangesetConfigLive = effect.Layer.effect(ChangesetConfig, effect.Effect.g
362
362
  };
363
363
  }));
364
364
  //#endregion
365
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/errors/CatalogAssemblyError.js
365
+ //#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/errors/CatalogAssemblyError.js
366
366
  /**
367
367
  * Base constant for {@link CatalogAssemblyError}.
368
368
  *
@@ -389,7 +389,7 @@ var CatalogAssemblyError = class extends CatalogAssemblyErrorBase {
389
389
  }
390
390
  };
391
391
  //#endregion
392
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/errors/CatalogResolutionError.js
392
+ //#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/errors/CatalogResolutionError.js
393
393
  /**
394
394
  * Base constant for {@link CatalogResolutionError}.
395
395
  *
@@ -415,7 +415,7 @@ var CatalogResolutionError = class extends CatalogResolutionErrorBase {
415
415
  }
416
416
  };
417
417
  //#endregion
418
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/errors/GitReadError.js
418
+ //#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/errors/GitReadError.js
419
419
  /**
420
420
  * Base constant for {@link GitReadError}.
421
421
  *
@@ -440,7 +440,7 @@ var GitReadError = class extends GitReadErrorBase {
440
440
  }
441
441
  };
442
442
  //#endregion
443
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/errors/PackageNotFoundError.js
443
+ //#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/errors/PackageNotFoundError.js
444
444
  /**
445
445
  * Base constant for {@link PackageNotFoundError}.
446
446
  *
@@ -491,7 +491,7 @@ var PackageNotFoundError = class extends PackageNotFoundErrorBase {
491
491
  }
492
492
  };
493
493
  //#endregion
494
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/errors/WorkspaceDiscoveryError.js
494
+ //#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/errors/WorkspaceDiscoveryError.js
495
495
  /**
496
496
  * Base constant for {@link WorkspaceDiscoveryError}.
497
497
  *
@@ -542,7 +542,7 @@ var WorkspaceDiscoveryError = class extends WorkspaceDiscoveryErrorBase {
542
542
  }
543
543
  };
544
544
  //#endregion
545
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/errors/WorkspaceRootNotFoundError.js
545
+ //#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/errors/WorkspaceRootNotFoundError.js
546
546
  /**
547
547
  * Base constant for {@link WorkspaceRootNotFoundError}.
548
548
  *
@@ -592,7 +592,7 @@ var WorkspaceRootNotFoundError = class extends WorkspaceRootNotFoundErrorBase {
592
592
  }
593
593
  };
594
594
  //#endregion
595
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/services/WorkspaceDiscovery.js
595
+ //#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/services/WorkspaceDiscovery.js
596
596
  /**
597
597
  * Service for discovering workspace packages in a monorepo.
598
598
  *
@@ -642,7 +642,7 @@ var WorkspaceRootNotFoundError = class extends WorkspaceRootNotFoundErrorBase {
642
642
  */
643
643
  var WorkspaceDiscovery = class extends effect.Context.Tag("@spencerbeggs/workspaces-effect/WorkspaceDiscovery")() {};
644
644
  //#endregion
645
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/services/WorkspaceRoot.js
645
+ //#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/services/WorkspaceRoot.js
646
646
  /**
647
647
  * Service for finding the workspace root directory.
648
648
  *
@@ -689,7 +689,7 @@ var WorkspaceDiscovery = class extends effect.Context.Tag("@spencerbeggs/workspa
689
689
  */
690
690
  var WorkspaceRoot = class extends effect.Context.Tag("@spencerbeggs/workspaces-effect/WorkspaceRoot")() {};
691
691
  //#endregion
692
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/errors/YamlComposerError.js
692
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/errors/YamlComposerError.js
693
693
  /**
694
694
  * YAML composer error type.
695
695
  *
@@ -747,7 +747,7 @@ var YamlComposerError = class extends YamlComposerErrorBase {
747
747
  }
748
748
  };
749
749
  //#endregion
750
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/errors/YamlErrorDetail.js
750
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/errors/YamlErrorDetail.js
751
751
  /**
752
752
  * YAML error detail schema and error code types.
753
753
  *
@@ -800,7 +800,7 @@ var YamlErrorDetail = class extends effect.Schema.Class("YamlErrorDetail")({
800
800
  column: effect.Schema.Int.pipe(effect.Schema.nonNegative())
801
801
  }) {};
802
802
  //#endregion
803
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/schemas/CstNode.js
803
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/schemas/CstNode.js
804
804
  /**
805
805
  * YAML CST node schema and node type literal union.
806
806
  *
@@ -836,7 +836,7 @@ var CstNode = class CstNode extends effect.Schema.Class("CstNode")({
836
836
  children: effect.Schema.optional(effect.Schema.Array(effect.Schema.suspend(() => CstNode)))
837
837
  }) {};
838
838
  //#endregion
839
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/schemas/YamlShared.js
839
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/schemas/YamlShared.js
840
840
  /**
841
841
  * Shared YAML structural types used across the parse/stringify/format pipeline.
842
842
  *
@@ -864,7 +864,7 @@ effect.Schema.Class("YamlEdit")({
864
864
  content: effect.Schema.String
865
865
  });
866
866
  //#endregion
867
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/schemas/YamlAstNodes.js
867
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/schemas/YamlAstNodes.js
868
868
  /**
869
869
  * Internal module defining all mutually-referential YAML AST node schemas in
870
870
  * one place to avoid circular import cycles between individual schema files.
@@ -1075,7 +1075,7 @@ var YamlSeq = class extends effect.Schema.TaggedClass()("YamlSeq", {
1075
1075
  length: effect.Schema.Int.pipe(effect.Schema.nonNegative())
1076
1076
  }) {};
1077
1077
  //#endregion
1078
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/schemas/YamlDocument.js
1078
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/schemas/YamlDocument.js
1079
1079
  /**
1080
1080
  * YAML document and directive schemas.
1081
1081
  *
@@ -1153,7 +1153,7 @@ var YamlDocument = class extends effect.Schema.Class("YamlDocument")({
1153
1153
  hasDocumentStartTab: effect.Schema.optionalWith(effect.Schema.Boolean, { default: () => false })
1154
1154
  }) {};
1155
1155
  //#endregion
1156
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/schemas/YamlToken.js
1156
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/schemas/YamlToken.js
1157
1157
  /**
1158
1158
  * YAML token schema and token kind literal union.
1159
1159
  *
@@ -1188,7 +1188,7 @@ var YamlToken = class extends effect.Schema.Class("YamlToken")({
1188
1188
  column: effect.Schema.Int.pipe(effect.Schema.nonNegative())
1189
1189
  }) {};
1190
1190
  //#endregion
1191
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/utils/lexer.js
1191
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/utils/lexer.js
1192
1192
  /**
1193
1193
  * YAML 1.2 lexer — tokenizes raw YAML text into a stream of {@link YamlToken} values.
1194
1194
  *
@@ -1218,7 +1218,7 @@ var YamlToken = class extends effect.Schema.Class("YamlToken")({
1218
1218
  *
1219
1219
  * @public
1220
1220
  */
1221
- function createScanner$1(text) {
1221
+ function createScanner$2(text) {
1222
1222
  let pos = 0;
1223
1223
  let line = 0;
1224
1224
  let col = 0;
@@ -2169,7 +2169,7 @@ function createScanner$1(text) {
2169
2169
  * @public
2170
2170
  */
2171
2171
  function lex(text) {
2172
- return effect.Stream.unfold(createScanner$1(text), (scanner) => {
2172
+ return effect.Stream.unfold(createScanner$2(text), (scanner) => {
2173
2173
  const kind = scanner.scan();
2174
2174
  if (kind === null) return effect.Option.none();
2175
2175
  const token = new YamlToken({
@@ -2193,7 +2193,7 @@ function lexAll(text) {
2193
2193
  return effect.Stream.runCollect(lex(text)).pipe(effect.Effect.map((chunk) => [...chunk]));
2194
2194
  }
2195
2195
  //#endregion
2196
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/utils/parser.js
2196
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/utils/parser.js
2197
2197
  /**
2198
2198
  * YAML 1.2 CST parser — transforms a token stream into a Concrete Syntax Tree.
2199
2199
  *
@@ -2838,7 +2838,7 @@ function parseCSTAll(text) {
2838
2838
  return lexAll(text).pipe(effect.Effect.map((tokens) => parseDocuments(tokens, text)));
2839
2839
  }
2840
2840
  //#endregion
2841
- //#region ../../node_modules/.pnpm/yaml-effect@0.7.0_effect@3.21.4/node_modules/yaml-effect/utils/composer.js
2841
+ //#region ../../node_modules/.pnpm/yaml-effect@0.7.2_effect@3.21.4/node_modules/yaml-effect/utils/composer.js
2842
2842
  /**
2843
2843
  * YAML 1.2 Composer — transforms CST nodes into AST nodes with typed values.
2844
2844
  *
@@ -2847,16 +2847,29 @@ function parseCSTAll(text) {
2847
2847
  *
2848
2848
  * @packageDocumentation
2849
2849
  */
2850
+ let lineStartsText;
2851
+ let lineStartsCache = [];
2852
+ function getLineStarts(text) {
2853
+ if (lineStartsText === text) return lineStartsCache;
2854
+ const starts = [0];
2855
+ for (let i = 0; i < text.length; i++) if (text[i] === "\n") starts.push(i + 1);
2856
+ lineStartsText = text;
2857
+ lineStartsCache = starts;
2858
+ return starts;
2859
+ }
2850
2860
  function lineCol(text, offset) {
2851
- let line = 0;
2852
- let column = 0;
2853
- for (let i = 0; i < offset && i < text.length; i++) if (text[i] === "\n") {
2854
- line++;
2855
- column = 0;
2856
- } else column++;
2861
+ const starts = getLineStarts(text);
2862
+ const pos = Math.min(Math.max(offset, 0), text.length);
2863
+ let lo = 0;
2864
+ let hi = starts.length - 1;
2865
+ while (lo < hi) {
2866
+ const mid = lo + hi + 1 >> 1;
2867
+ if (starts[mid] <= pos) lo = mid;
2868
+ else hi = mid - 1;
2869
+ }
2857
2870
  return {
2858
- line,
2859
- column
2871
+ line: lo,
2872
+ column: pos - starts[lo]
2860
2873
  };
2861
2874
  }
2862
2875
  const NULL_RE = /^(?:null|Null|NULL|~)$/;
@@ -6300,7 +6313,7 @@ function parseDocument(text, options) {
6300
6313
  *
6301
6314
  * @public
6302
6315
  */
6303
- function parse$2(text, options) {
6316
+ function parse$3(text, options) {
6304
6317
  const uniqueKeys = options?.uniqueKeys ?? true;
6305
6318
  return parseDocument(text, options).pipe(effect.Effect.flatMap((doc) => {
6306
6319
  if (uniqueKeys) {
@@ -6315,14 +6328,14 @@ function parse$2(text, options) {
6315
6328
  }));
6316
6329
  }
6317
6330
  //#endregion
6318
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/catalog/workspace-manifest.js
6331
+ //#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/layers/catalog/workspace-manifest.js
6319
6332
  /**
6320
6333
  * Parse a pnpm-workspace.yaml text into its catalog/config-dependency/packages
6321
6334
  * slice. Pure with respect to the filesystem.
6322
6335
  *
6323
6336
  * @public
6324
6337
  */
6325
- const workspaceManifestFromYaml = (content) => parse$2(content).pipe(effect.Effect.mapError((e) => new CatalogAssemblyError({
6338
+ const workspaceManifestFromYaml = (content) => parse$3(content).pipe(effect.Effect.mapError((e) => new CatalogAssemblyError({
6326
6339
  source: "manifest",
6327
6340
  reason: `invalid yaml: ${String(e)}`
6328
6341
  })), effect.Effect.map((parsed) => {
@@ -6383,7 +6396,7 @@ function checkDefaultCatalogIsDefinedOnce(manifest) {
6383
6396
  if (manifest.catalog != null && manifest.catalogs?.default != null) throw new PnpmError("INVALID_CATALOGS_CONFIGURATION", "The 'default' catalog was defined multiple times. Use the 'catalog' field or 'catalogs.default', but not both.");
6384
6397
  }
6385
6398
  //#endregion
6386
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/catalog/assemble.js
6399
+ //#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/layers/catalog/assemble.js
6387
6400
  /** Merge catalog sources; later sources win per dependency within a catalog. */
6388
6401
  function mergeCatalogs(...sources) {
6389
6402
  const result = {};
@@ -6464,7 +6477,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
6464
6477
  };
6465
6478
  }
6466
6479
  //#endregion
6467
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/catalog/resolve.js
6480
+ //#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/layers/catalog/resolve.js
6468
6481
  const DEP_FIELDS = [
6469
6482
  "dependencies",
6470
6483
  "devDependencies",
@@ -6534,7 +6547,7 @@ function resolveManifest(catalogs, workspaceVersions, manifest) {
6534
6547
  return out;
6535
6548
  }
6536
6549
  //#endregion
6537
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/schemas/CatalogSet.js
6550
+ //#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/CatalogSet.js
6538
6551
  /**
6539
6552
  * An immutable, fully-normalized catalog collection with the one
6540
6553
  * resolution semantic shared by live and point-in-time resolution.
@@ -6624,7 +6637,7 @@ var CatalogSet = class CatalogSet extends effect.Schema.Class("CatalogSet")({ en
6624
6637
  }
6625
6638
  };
6626
6639
  //#endregion
6627
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/point-in-time/worktree-catalogs.js
6640
+ //#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/layers/point-in-time/worktree-catalogs.js
6628
6641
  /**
6629
6642
  * The ONE code path that reads the working tree's catalog sources
6630
6643
  * (`pnpm-workspace.yaml` + `pnpm-lock.yaml`). Consumed by
@@ -6641,7 +6654,7 @@ var CatalogSet = class CatalogSet extends effect.Schema.Class("CatalogSet")({ en
6641
6654
  *
6642
6655
  * @internal
6643
6656
  */
6644
- const lockfileCatalogsFromText = (text) => parse$2(text).pipe(effect.Effect.map((parsed) => CatalogSet.fromLockfileCatalogs(parsed?.catalogs)), effect.Effect.orElseSucceed(() => CatalogSet.empty()));
6657
+ const lockfileCatalogsFromText = (text) => parse$3(text).pipe(effect.Effect.map((parsed) => CatalogSet.fromLockfileCatalogs(parsed?.catalogs)), effect.Effect.orElseSucceed(() => CatalogSet.empty()));
6645
6658
  /**
6646
6659
  * Read the working tree's catalog state at `root`.
6647
6660
  *
@@ -8169,7 +8182,7 @@ minimatch.Minimatch = Minimatch;
8169
8182
  minimatch.escape = escape;
8170
8183
  minimatch.unescape = unescape;
8171
8184
  //#endregion
8172
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/schemas/core.js
8185
+ //#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/core.js
8173
8186
  /**
8174
8187
  * Schema for supported package manager identifiers.
8175
8188
  *
@@ -8431,7 +8444,1286 @@ effect.Schema.Class("WorkspaceInfo")({
8431
8444
  patterns: effect.Schema.Array(effect.Schema.String)
8432
8445
  });
8433
8446
  //#endregion
8434
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/schemas/WorkspaceStateSnapshot.js
8447
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/errors.js
8448
+ /**
8449
+ * JSONC error types using Effect's Data.TaggedError pattern.
8450
+ *
8451
+ * @packageDocumentation
8452
+ */
8453
+ /**
8454
+ * Error codes representing specific JSONC parse failures.
8455
+ *
8456
+ * @remarks
8457
+ * Each code maps to a distinct syntactic error the parser can encounter,
8458
+ * from invalid symbols and number formats to missing delimiters and
8459
+ * unexpected end-of-input conditions.
8460
+ *
8461
+ * @see {@link JsoncParseErrorDetail} — carries one of these codes alongside
8462
+ * position information
8463
+ *
8464
+ * @public
8465
+ */
8466
+ const JsoncParseErrorCode = effect.Schema.Literal("InvalidSymbol", "InvalidNumberFormat", "PropertyNameExpected", "ValueExpected", "ColonExpected", "CommaExpected", "CloseBraceExpected", "CloseBracketExpected", "EndOfFileExpected", "InvalidCommentToken", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter");
8467
+ /**
8468
+ * Detail for a single parse error, including the error code, a human-readable
8469
+ * message, and the exact position within the source document.
8470
+ *
8471
+ * @remarks
8472
+ * - `code` — a {@link (JsoncParseErrorCode:type)} identifying the error kind.
8473
+ * - `message` — a descriptive message suitable for display.
8474
+ * - `offset` — zero-based character offset where the error occurred.
8475
+ * - `length` — character length of the problematic span.
8476
+ * - `startLine` — zero-based line number of the error.
8477
+ * - `startCharacter` — zero-based column within `startLine`.
8478
+ *
8479
+ * @see {@link JsoncParseError} — aggregates an array of these details
8480
+ *
8481
+ * @example
8482
+ * ```ts
8483
+ * import { JsoncParseErrorDetail } from "jsonc-effect";
8484
+ *
8485
+ * const detail = new JsoncParseErrorDetail({
8486
+ * code: "ValueExpected",
8487
+ * message: "Value expected",
8488
+ * offset: 5,
8489
+ * length: 1,
8490
+ * startLine: 0,
8491
+ * startCharacter: 5,
8492
+ * });
8493
+ *
8494
+ * console.log(detail.code); // "ValueExpected"
8495
+ * console.log(detail.offset); // 5
8496
+ * ```
8497
+ *
8498
+ * @public
8499
+ */
8500
+ var JsoncParseErrorDetail = class extends effect.Schema.Class("JsoncParseErrorDetail")({
8501
+ code: JsoncParseErrorCode,
8502
+ message: effect.Schema.String,
8503
+ offset: effect.Schema.Number,
8504
+ length: effect.Schema.Number,
8505
+ startLine: effect.Schema.Number,
8506
+ startCharacter: effect.Schema.Number
8507
+ }) {};
8508
+ /**
8509
+ * Base class for {@link JsoncParseError}; not intended to be constructed or
8510
+ * caught directly — use `JsoncParseError` instead.
8511
+ *
8512
+ * @privateRemarks
8513
+ * The `*Base` pattern is required because `Data.TaggedError` produces complex
8514
+ * type signatures involving intersection types and branded generics that
8515
+ * api-extractor cannot roll up into a single `.d.ts` bundle. Exporting the
8516
+ * base separately lets the public `JsoncParseError` class extend it with
8517
+ * concrete fields, giving api-extractor a simple class declaration to work
8518
+ * with. It is tagged `@public` (rather than `@internal`) because it appears
8519
+ * in `JsoncParseError`'s heritage clause in the public `.d.ts`, and API
8520
+ * Extractor requires release tags to be compatible across a signature.
8521
+ *
8522
+ * @public
8523
+ */
8524
+ const JsoncParseErrorBase = effect.Data.TaggedError("JsoncParseError");
8525
+ /**
8526
+ * Error raised when JSONC parsing encounters one or more syntax errors.
8527
+ *
8528
+ * @remarks
8529
+ * Contains the full source `text`, the `options` used for parsing, and an
8530
+ * `errors` array of {@link JsoncParseErrorDetail} instances with precise
8531
+ * position information for each problem found.
8532
+ *
8533
+ * @see {@link parse} — may fail with this error
8534
+ * @see {@link parseTree} — may fail with this error
8535
+ *
8536
+ * @example Catching with `Effect.catchTag`
8537
+ * ```ts
8538
+ * import { Effect } from "effect";
8539
+ * import { parse } from "jsonc-effect";
8540
+ *
8541
+ * const program = parse("{ invalid }").pipe(
8542
+ * Effect.catchTag("JsoncParseError", (e) => {
8543
+ * console.error(e.errors); // Array of JsoncParseErrorDetail
8544
+ * return Effect.succeed({});
8545
+ * }),
8546
+ * );
8547
+ * ```
8548
+ *
8549
+ * @example Inspecting error details
8550
+ * ```ts
8551
+ * import { Effect } from "effect";
8552
+ * import { parse } from "jsonc-effect";
8553
+ *
8554
+ * const program = parse("{ invalid }").pipe(
8555
+ * Effect.catchTag("JsoncParseError", (e) => {
8556
+ * for (const detail of e.errors) {
8557
+ * console.error(
8558
+ * `[${detail.code}] ${detail.message} at line ${detail.startLine}:${detail.startCharacter}`,
8559
+ * );
8560
+ * }
8561
+ * return Effect.succeed({});
8562
+ * }),
8563
+ * );
8564
+ * ```
8565
+ *
8566
+ * @public
8567
+ */
8568
+ var JsoncParseError = class extends JsoncParseErrorBase {
8569
+ get message() {
8570
+ const count = this.errors.length;
8571
+ return `JSONC parse failed with ${count} error${count !== 1 ? "s" : ""}: ${this.errors.map((e) => e.message).join("; ")}`;
8572
+ }
8573
+ };
8574
+ effect.Data.TaggedError("JsoncNodeNotFoundError");
8575
+ /**
8576
+ * Base class for {@link JsoncModificationError}; not intended to be
8577
+ * constructed or caught directly — use `JsoncModificationError` instead.
8578
+ *
8579
+ * @privateRemarks
8580
+ * Uses the same `*Base` pattern as {@link JsoncParseErrorBase} to work
8581
+ * around api-extractor's inability to roll up the complex type produced
8582
+ * by `Data.TaggedError` into a single `.d.ts` declaration. Tagged `@public`
8583
+ * for the same heritage-clause-compatibility reason as `JsoncParseErrorBase`.
8584
+ *
8585
+ * @public
8586
+ */
8587
+ const JsoncModificationErrorBase = effect.Data.TaggedError("JsoncModificationError");
8588
+ /**
8589
+ * Error raised when {@link modify} produces invalid edits or encounters
8590
+ * an unsupported modification scenario.
8591
+ *
8592
+ * @remarks
8593
+ * Contains the `path` where modification was attempted and a `reason`
8594
+ * string explaining why it failed.
8595
+ *
8596
+ * @see {@link modify} — may fail with this error
8597
+ *
8598
+ * @example
8599
+ * ```ts
8600
+ * import { Effect } from "effect";
8601
+ * import { modify } from "jsonc-effect";
8602
+ *
8603
+ * const program = modify("{}", ["deep", "path"], 42).pipe(
8604
+ * Effect.catchTag("JsoncModificationError", (e) => {
8605
+ * console.error(`Failed at [${e.path.join(", ")}]: ${e.reason}`);
8606
+ * return Effect.succeed([]);
8607
+ * }),
8608
+ * );
8609
+ * ```
8610
+ *
8611
+ * @public
8612
+ */
8613
+ var JsoncModificationError = class extends JsoncModificationErrorBase {
8614
+ get message() {
8615
+ return `Modification failed at path [${this.path.join(", ")}]: ${this.reason}`;
8616
+ }
8617
+ };
8618
+ //#endregion
8619
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/scanner.js
8620
+ const isWhitespace = (ch) => ch === 32 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch === 65279;
8621
+ const isLineBreak$1 = (ch) => ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
8622
+ const isDigit$1 = (ch) => ch >= 48 && ch <= 57;
8623
+ /**
8624
+ * Create a stateful {@link JsoncScanner} for the given JSONC string.
8625
+ *
8626
+ * @param text - JSONC string to tokenize
8627
+ * @param ignoreTrivia - If `true`, the scanner automatically skips whitespace,
8628
+ * line-break, and comment tokens so that only structural tokens are returned
8629
+ * (default: `false`).
8630
+ * @returns A stateful {@link JsoncScanner} positioned before the first token.
8631
+ *
8632
+ * @remarks
8633
+ * When `ignoreTrivia` is `true` the scanner is suitable for building parsers
8634
+ * that only care about structural tokens (`OpenBrace`, `String`, `Number`,
8635
+ * etc.). Set it to `false` (the default) when you need to preserve comments
8636
+ * or whitespace — for example in a formatter or a comment-stripping pass.
8637
+ *
8638
+ * @see {@link JsoncScanner} — the interface returned by this factory
8639
+ * @see {@link parse} — higher-level API that uses a scanner internally
8640
+ *
8641
+ * @example
8642
+ * Tokenizing a JSONC string and printing each token:
8643
+ * ```ts
8644
+ * import type { JsoncSyntaxKind } from "jsonc-effect";
8645
+ * import { createScanner } from "jsonc-effect";
8646
+ *
8647
+ * const scanner = createScanner('{ "name": "jsonc" }', true);
8648
+ * let kind: JsoncSyntaxKind;
8649
+ * do {
8650
+ * kind = scanner.scan();
8651
+ * console.log(kind, scanner.getTokenValue());
8652
+ * } while (kind !== "EOF");
8653
+ * ```
8654
+ *
8655
+ * @privateRemarks
8656
+ * Ported from Microsoft's jsonc-parser (MIT), adapted to use string literal
8657
+ * token types instead of numeric enums.
8658
+ *
8659
+ * @public
8660
+ */
8661
+ const createScanner$1 = (text, ignoreTrivia = false) => {
8662
+ const len = text.length;
8663
+ let pos = 0;
8664
+ let tokenOffset = 0;
8665
+ let token = "Unknown";
8666
+ let tokenValue = "";
8667
+ let tokenError = "None";
8668
+ let lineNumber = 0;
8669
+ let lineStartOffset = 0;
8670
+ let tokenStartLine = 0;
8671
+ let tokenStartCharacter = 0;
8672
+ const scanHexDigits = (count) => {
8673
+ let value = 0;
8674
+ for (let i = 0; i < count; i++) {
8675
+ if (pos >= len) return -1;
8676
+ const ch = text.charCodeAt(pos);
8677
+ if (ch >= 48 && ch <= 57) value = value * 16 + (ch - 48);
8678
+ else if (ch >= 65 && ch <= 70) value = value * 16 + (ch - 65 + 10);
8679
+ else if (ch >= 97 && ch <= 102) value = value * 16 + (ch - 97 + 10);
8680
+ else return -1;
8681
+ pos++;
8682
+ }
8683
+ return value;
8684
+ };
8685
+ const scanString = () => {
8686
+ let result = "";
8687
+ pos++;
8688
+ let start = pos;
8689
+ while (pos < len) {
8690
+ const ch = text.charCodeAt(pos);
8691
+ if (ch === 34) {
8692
+ result += text.substring(start, pos);
8693
+ pos++;
8694
+ return result;
8695
+ }
8696
+ if (ch === 92) {
8697
+ result += text.substring(start, pos);
8698
+ pos++;
8699
+ if (pos >= len) {
8700
+ tokenError = "UnexpectedEndOfString";
8701
+ return result;
8702
+ }
8703
+ const escaped = text.charCodeAt(pos);
8704
+ pos++;
8705
+ switch (escaped) {
8706
+ case 34:
8707
+ result += "\"";
8708
+ break;
8709
+ case 92:
8710
+ result += "\\";
8711
+ break;
8712
+ case 47:
8713
+ result += "/";
8714
+ break;
8715
+ case 98:
8716
+ result += "\b";
8717
+ break;
8718
+ case 102:
8719
+ result += "\f";
8720
+ break;
8721
+ case 110:
8722
+ result += "\n";
8723
+ break;
8724
+ case 114:
8725
+ result += "\r";
8726
+ break;
8727
+ case 116:
8728
+ result += " ";
8729
+ break;
8730
+ case 117: {
8731
+ const value = scanHexDigits(4);
8732
+ if (value >= 0) result += String.fromCharCode(value);
8733
+ else tokenError = "InvalidUnicode";
8734
+ break;
8735
+ }
8736
+ default:
8737
+ tokenError = "InvalidEscapeCharacter";
8738
+ break;
8739
+ }
8740
+ start = pos;
8741
+ } else if (isLineBreak$1(ch)) {
8742
+ tokenError = "UnexpectedEndOfString";
8743
+ return result + text.substring(start, pos);
8744
+ } else pos++;
8745
+ }
8746
+ tokenError = "UnexpectedEndOfString";
8747
+ return result + text.substring(start, pos);
8748
+ };
8749
+ const scanNumber = () => {
8750
+ const start = pos;
8751
+ if (text.charCodeAt(pos) === 45) pos++;
8752
+ if (text.charCodeAt(pos) === 48) pos++;
8753
+ else {
8754
+ if (!isDigit$1(text.charCodeAt(pos))) {
8755
+ tokenError = "UnexpectedEndOfNumber";
8756
+ return text.substring(start, pos);
8757
+ }
8758
+ pos++;
8759
+ while (pos < len && isDigit$1(text.charCodeAt(pos))) pos++;
8760
+ }
8761
+ if (pos < len && text.charCodeAt(pos) === 46) {
8762
+ pos++;
8763
+ if (!isDigit$1(text.charCodeAt(pos))) {
8764
+ tokenError = "UnexpectedEndOfNumber";
8765
+ return text.substring(start, pos);
8766
+ }
8767
+ pos++;
8768
+ while (pos < len && isDigit$1(text.charCodeAt(pos))) pos++;
8769
+ }
8770
+ if (pos < len && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
8771
+ pos++;
8772
+ if (pos < len && (text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45)) pos++;
8773
+ if (!isDigit$1(text.charCodeAt(pos))) {
8774
+ tokenError = "UnexpectedEndOfNumber";
8775
+ return text.substring(start, pos);
8776
+ }
8777
+ pos++;
8778
+ while (pos < len && isDigit$1(text.charCodeAt(pos))) pos++;
8779
+ }
8780
+ return text.substring(start, pos);
8781
+ };
8782
+ const scan = () => {
8783
+ tokenValue = "";
8784
+ tokenError = "None";
8785
+ if (pos >= len) {
8786
+ tokenOffset = len;
8787
+ tokenStartLine = lineNumber;
8788
+ tokenStartCharacter = pos - lineStartOffset;
8789
+ token = "EOF";
8790
+ return token;
8791
+ }
8792
+ let ch = text.charCodeAt(pos);
8793
+ if (isWhitespace(ch)) {
8794
+ tokenOffset = pos;
8795
+ tokenStartLine = lineNumber;
8796
+ tokenStartCharacter = pos - lineStartOffset;
8797
+ do {
8798
+ pos++;
8799
+ ch = pos < len ? text.charCodeAt(pos) : 0;
8800
+ } while (isWhitespace(ch));
8801
+ tokenValue = text.substring(tokenOffset, pos);
8802
+ if (ignoreTrivia) return scan();
8803
+ token = "Trivia";
8804
+ return token;
8805
+ }
8806
+ if (isLineBreak$1(ch)) {
8807
+ tokenOffset = pos;
8808
+ tokenStartLine = lineNumber;
8809
+ tokenStartCharacter = pos - lineStartOffset;
8810
+ pos++;
8811
+ if (ch === 13 && pos < len && text.charCodeAt(pos) === 10) pos++;
8812
+ lineNumber++;
8813
+ lineStartOffset = pos;
8814
+ tokenValue = text.substring(tokenOffset, pos);
8815
+ if (ignoreTrivia) return scan();
8816
+ token = "LineBreak";
8817
+ return token;
8818
+ }
8819
+ tokenOffset = pos;
8820
+ tokenStartLine = lineNumber;
8821
+ tokenStartCharacter = pos - lineStartOffset;
8822
+ switch (ch) {
8823
+ case 123:
8824
+ pos++;
8825
+ tokenValue = "{";
8826
+ token = "OpenBrace";
8827
+ return token;
8828
+ case 125:
8829
+ pos++;
8830
+ tokenValue = "}";
8831
+ token = "CloseBrace";
8832
+ return token;
8833
+ case 91:
8834
+ pos++;
8835
+ tokenValue = "[";
8836
+ token = "OpenBracket";
8837
+ return token;
8838
+ case 93:
8839
+ pos++;
8840
+ tokenValue = "]";
8841
+ token = "CloseBracket";
8842
+ return token;
8843
+ case 58:
8844
+ pos++;
8845
+ tokenValue = ":";
8846
+ token = "Colon";
8847
+ return token;
8848
+ case 44:
8849
+ pos++;
8850
+ tokenValue = ",";
8851
+ token = "Comma";
8852
+ return token;
8853
+ case 34:
8854
+ tokenValue = scanString();
8855
+ token = "String";
8856
+ return token;
8857
+ case 47: {
8858
+ const nextCh = pos + 1 < len ? text.charCodeAt(pos + 1) : 0;
8859
+ if (nextCh === 47) {
8860
+ pos += 2;
8861
+ while (pos < len && !isLineBreak$1(text.charCodeAt(pos))) pos++;
8862
+ tokenValue = text.substring(tokenOffset, pos);
8863
+ if (ignoreTrivia) return scan();
8864
+ token = "LineComment";
8865
+ return token;
8866
+ }
8867
+ if (nextCh === 42) {
8868
+ pos += 2;
8869
+ const safeLen = len - 1;
8870
+ let commentClosed = false;
8871
+ while (pos < safeLen) {
8872
+ const cch = text.charCodeAt(pos);
8873
+ if (isLineBreak$1(cch)) {
8874
+ if (cch === 13 && pos + 1 < len && text.charCodeAt(pos + 1) === 10) pos++;
8875
+ pos++;
8876
+ lineNumber++;
8877
+ lineStartOffset = pos;
8878
+ } else if (cch === 42 && text.charCodeAt(pos + 1) === 47) {
8879
+ pos += 2;
8880
+ commentClosed = true;
8881
+ break;
8882
+ } else pos++;
8883
+ }
8884
+ if (!commentClosed) {
8885
+ pos = len;
8886
+ tokenError = "UnexpectedEndOfComment";
8887
+ }
8888
+ tokenValue = text.substring(tokenOffset, pos);
8889
+ if (ignoreTrivia) return scan();
8890
+ token = "BlockComment";
8891
+ return token;
8892
+ }
8893
+ pos++;
8894
+ tokenValue = text.substring(tokenOffset, pos);
8895
+ token = "Unknown";
8896
+ tokenError = "InvalidCharacter";
8897
+ return token;
8898
+ }
8899
+ case 45:
8900
+ if (pos + 1 < len && isDigit$1(text.charCodeAt(pos + 1))) {
8901
+ tokenValue = scanNumber();
8902
+ token = "Number";
8903
+ return token;
8904
+ }
8905
+ pos++;
8906
+ tokenValue = "-";
8907
+ token = "Unknown";
8908
+ tokenError = "InvalidSymbol";
8909
+ return token;
8910
+ default:
8911
+ if (isDigit$1(ch)) {
8912
+ tokenValue = scanNumber();
8913
+ token = "Number";
8914
+ return token;
8915
+ }
8916
+ if (ch >= 97 && ch <= 122) {
8917
+ const start = pos;
8918
+ pos++;
8919
+ while (pos < len) {
8920
+ const kch = text.charCodeAt(pos);
8921
+ if (kch >= 97 && kch <= 122) pos++;
8922
+ else break;
8923
+ }
8924
+ tokenValue = text.substring(start, pos);
8925
+ switch (tokenValue) {
8926
+ case "true":
8927
+ token = "True";
8928
+ return token;
8929
+ case "false":
8930
+ token = "False";
8931
+ return token;
8932
+ case "null":
8933
+ token = "Null";
8934
+ return token;
8935
+ default:
8936
+ token = "Unknown";
8937
+ tokenError = "InvalidSymbol";
8938
+ return token;
8939
+ }
8940
+ }
8941
+ pos++;
8942
+ tokenValue = text.substring(tokenOffset, pos);
8943
+ token = "Unknown";
8944
+ tokenError = "InvalidCharacter";
8945
+ return token;
8946
+ }
8947
+ };
8948
+ return {
8949
+ scan,
8950
+ getToken: () => token,
8951
+ getTokenValue: () => tokenValue,
8952
+ getTokenOffset: () => tokenOffset,
8953
+ getTokenLength: () => pos - tokenOffset,
8954
+ getTokenStartLine: () => tokenStartLine,
8955
+ getTokenStartCharacter: () => tokenStartCharacter,
8956
+ getTokenError: () => tokenError,
8957
+ getPosition: () => pos,
8958
+ setPosition: (newPos) => {
8959
+ pos = newPos;
8960
+ tokenValue = "";
8961
+ token = "Unknown";
8962
+ tokenError = "None";
8963
+ }
8964
+ };
8965
+ };
8966
+ //#endregion
8967
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/parse.js
8968
+ /**
8969
+ * JSONC Parser — converts token stream into JavaScript values or AST nodes.
8970
+ *
8971
+ * Pure Effect implementation using recursive descent parsing.
8972
+ * Reference: Microsoft's jsonc-parser parser design (MIT).
8973
+ *
8974
+ * @packageDocumentation
8975
+ */
8976
+ /**
8977
+ * Parse a JSONC string into a JavaScript value.
8978
+ *
8979
+ * @param text - JSONC string to parse
8980
+ * @param options - Optional {@link JsoncParseOptions} controlling comment and
8981
+ * trailing-comma handling.
8982
+ * @returns `Effect<unknown, JsoncParseError>` — succeeds with the parsed value
8983
+ * or fails with a {@link JsoncParseError} containing every error encountered.
8984
+ *
8985
+ * @remarks
8986
+ * The return type is `unknown` (not `any`) so consumers are forced to narrow
8987
+ * the result, which is safer in Effect pipelines. By default
8988
+ * `allowTrailingComma` is `true`, matching common JSONC conventions used in
8989
+ * VS Code settings and `tsconfig.json`.
8990
+ *
8991
+ * @see {@link parseTree} — parse into an AST instead of a plain value
8992
+ * @see {@link JsoncParseOptions} — available parse options
8993
+ * @see {@link JsoncParseError} — the tagged error type on the failure channel
8994
+ *
8995
+ * @example
8996
+ * Basic parsing:
8997
+ * ```ts
8998
+ * import { Effect } from "effect";
8999
+ * import { parse } from "jsonc-effect";
9000
+ *
9001
+ * const value = Effect.runSync(parse('{ "key": 42 }'));
9002
+ * console.log(value); // { key: 42 }
9003
+ * ```
9004
+ *
9005
+ * @example
9006
+ * Parsing with options:
9007
+ * ```ts
9008
+ * import { Effect } from "effect";
9009
+ * import { parse } from "jsonc-effect";
9010
+ *
9011
+ * const value = Effect.runSync(
9012
+ * parse('{ "key": 42 }', { disallowComments: true }),
9013
+ * );
9014
+ * ```
9015
+ *
9016
+ * @example
9017
+ * Error handling with `catchTag`:
9018
+ * ```ts
9019
+ * import { Effect } from "effect";
9020
+ * import { parse } from "jsonc-effect";
9021
+ *
9022
+ * const program = parse("{ bad }").pipe(
9023
+ * Effect.catchTag("JsoncParseError", (err) =>
9024
+ * Effect.succeed({ fallback: true, errors: err.errors }),
9025
+ * ),
9026
+ * );
9027
+ *
9028
+ * const result = Effect.runSync(program);
9029
+ * console.log(result);
9030
+ * ```
9031
+ *
9032
+ * @example
9033
+ * Using `Effect.gen`:
9034
+ * ```ts
9035
+ * import { Effect } from "effect";
9036
+ * import { parse } from "jsonc-effect";
9037
+ *
9038
+ * const program = Effect.gen(function* () {
9039
+ * const config = yield* parse('{ "port": 3000 }');
9040
+ * return config;
9041
+ * });
9042
+ *
9043
+ * const result = Effect.runSync(program);
9044
+ * console.log(result); // { port: 3000 }
9045
+ * ```
9046
+ *
9047
+ * @privateRemarks
9048
+ * Uses {@link createScanner} internally with a recursive descent parser.
9049
+ * The scanner is created with `ignoreTrivia = false` so the parser can
9050
+ * report comment-related errors when `disallowComments` is set.
9051
+ *
9052
+ * @public
9053
+ */
9054
+ const parse$2 = (text, options) => effect.Effect.sync(() => parseInternal(text, options ?? {}, false)).pipe(effect.Effect.flatMap(({ value, errors }) => {
9055
+ if (errors.length > 0) return effect.Effect.fail(new JsoncParseError({
9056
+ errors,
9057
+ text,
9058
+ ...options !== void 0 ? { options } : {}
9059
+ }));
9060
+ return effect.Effect.succeed(value);
9061
+ }));
9062
+ function parseInternal(text, options, buildTree) {
9063
+ const scanner = createScanner$1(text, false);
9064
+ const errors = [];
9065
+ const disallowComments = options.disallowComments ?? false;
9066
+ const allowTrailingComma = options.allowTrailingComma ?? true;
9067
+ const allowEmptyContent = options.allowEmptyContent ?? false;
9068
+ let currentToken = "Unknown";
9069
+ function token() {
9070
+ return currentToken;
9071
+ }
9072
+ function scanNext() {
9073
+ for (;;) {
9074
+ currentToken = scanner.scan();
9075
+ switch (scanner.getTokenError()) {
9076
+ case "InvalidUnicode":
9077
+ handleError("InvalidUnicode");
9078
+ break;
9079
+ case "InvalidEscapeCharacter":
9080
+ handleError("InvalidEscapeCharacter");
9081
+ break;
9082
+ case "UnexpectedEndOfNumber":
9083
+ handleError("InvalidNumberFormat");
9084
+ break;
9085
+ case "UnexpectedEndOfComment":
9086
+ handleError("UnexpectedEndOfComment");
9087
+ break;
9088
+ case "UnexpectedEndOfString":
9089
+ handleError("UnexpectedEndOfString");
9090
+ break;
9091
+ case "InvalidCharacter":
9092
+ handleError("InvalidCharacter");
9093
+ break;
9094
+ }
9095
+ switch (currentToken) {
9096
+ case "LineComment":
9097
+ case "BlockComment":
9098
+ if (disallowComments) handleError("InvalidCommentToken");
9099
+ break;
9100
+ case "Trivia":
9101
+ case "LineBreak": break;
9102
+ default: return currentToken;
9103
+ }
9104
+ }
9105
+ }
9106
+ function tokenEnd() {
9107
+ return scanner.getTokenOffset() + scanner.getTokenLength();
9108
+ }
9109
+ function handleError(code, skipUntilAfter = [], skipUntil = []) {
9110
+ errors.push(new JsoncParseErrorDetail({
9111
+ code,
9112
+ message: formatError(code, scanner.getTokenOffset()),
9113
+ offset: scanner.getTokenOffset(),
9114
+ length: scanner.getTokenLength(),
9115
+ startLine: scanner.getTokenStartLine(),
9116
+ startCharacter: scanner.getTokenStartCharacter()
9117
+ }));
9118
+ if (skipUntilAfter.length > 0 || skipUntil.length > 0) {
9119
+ let t = token();
9120
+ while (t !== "EOF") {
9121
+ if (skipUntilAfter.includes(t)) {
9122
+ scanNext();
9123
+ break;
9124
+ }
9125
+ if (skipUntil.includes(t)) break;
9126
+ t = scanNext();
9127
+ }
9128
+ }
9129
+ }
9130
+ function parseValue() {
9131
+ switch (token()) {
9132
+ case "OpenBracket": return parseArray();
9133
+ case "OpenBrace": return parseObject();
9134
+ case "String": return parseString();
9135
+ case "Number": return parseNumber();
9136
+ case "True":
9137
+ scanNext();
9138
+ return true;
9139
+ case "False":
9140
+ scanNext();
9141
+ return false;
9142
+ case "Null":
9143
+ scanNext();
9144
+ return null;
9145
+ default: return;
9146
+ }
9147
+ }
9148
+ function parseString() {
9149
+ const value = scanner.getTokenValue();
9150
+ scanNext();
9151
+ return value;
9152
+ }
9153
+ function parseNumber() {
9154
+ const value = Number.parseFloat(scanner.getTokenValue());
9155
+ scanNext();
9156
+ return value;
9157
+ }
9158
+ function parseArray() {
9159
+ scanNext();
9160
+ const arr = [];
9161
+ let needsComma = false;
9162
+ while (token() !== "CloseBracket" && token() !== "EOF") {
9163
+ if (token() === "Comma") {
9164
+ if (!needsComma) handleError("ValueExpected");
9165
+ scanNext();
9166
+ if (token() === "CloseBracket" && allowTrailingComma) break;
9167
+ } else if (needsComma) handleError("CommaExpected");
9168
+ const value = parseValue();
9169
+ if (value === void 0) handleError("ValueExpected", [], ["CloseBracket", "Comma"]);
9170
+ else arr.push(value);
9171
+ needsComma = true;
9172
+ }
9173
+ if (token() !== "CloseBracket") handleError("CloseBracketExpected");
9174
+ else scanNext();
9175
+ return arr;
9176
+ }
9177
+ function parseObject() {
9178
+ scanNext();
9179
+ const obj = {};
9180
+ let needsComma = false;
9181
+ while (token() !== "CloseBrace" && token() !== "EOF") {
9182
+ if (token() === "Comma") {
9183
+ if (!needsComma) handleError("PropertyNameExpected");
9184
+ scanNext();
9185
+ if (token() === "CloseBrace" && allowTrailingComma) break;
9186
+ } else if (needsComma) handleError("CommaExpected");
9187
+ if (token() !== "String") {
9188
+ handleError("PropertyNameExpected", [], ["CloseBrace", "Comma"]);
9189
+ continue;
9190
+ }
9191
+ const key = scanner.getTokenValue();
9192
+ scanNext();
9193
+ if (token() !== "Colon") {
9194
+ handleError("ColonExpected", [], ["CloseBrace", "Comma"]);
9195
+ continue;
9196
+ }
9197
+ scanNext();
9198
+ const value = parseValue();
9199
+ if (value === void 0) handleError("ValueExpected", [], ["CloseBrace", "Comma"]);
9200
+ else obj[key] = value;
9201
+ needsComma = true;
9202
+ }
9203
+ if (token() !== "CloseBrace") handleError("CloseBraceExpected");
9204
+ else scanNext();
9205
+ return obj;
9206
+ }
9207
+ function parseValueTree() {
9208
+ switch (token()) {
9209
+ case "OpenBracket": return parseArrayTree();
9210
+ case "OpenBrace": return parseObjectTree();
9211
+ case "String": {
9212
+ const node = {
9213
+ type: "string",
9214
+ offset: scanner.getTokenOffset(),
9215
+ length: 0,
9216
+ value: scanner.getTokenValue()
9217
+ };
9218
+ const end = tokenEnd();
9219
+ scanNext();
9220
+ node.length = end - node.offset;
9221
+ return node;
9222
+ }
9223
+ case "Number": {
9224
+ const node = {
9225
+ type: "number",
9226
+ offset: scanner.getTokenOffset(),
9227
+ length: 0,
9228
+ value: Number.parseFloat(scanner.getTokenValue())
9229
+ };
9230
+ const end = tokenEnd();
9231
+ scanNext();
9232
+ node.length = end - node.offset;
9233
+ return node;
9234
+ }
9235
+ case "True": {
9236
+ const node = {
9237
+ type: "boolean",
9238
+ offset: scanner.getTokenOffset(),
9239
+ length: 0,
9240
+ value: true
9241
+ };
9242
+ const end = tokenEnd();
9243
+ scanNext();
9244
+ node.length = end - node.offset;
9245
+ return node;
9246
+ }
9247
+ case "False": {
9248
+ const node = {
9249
+ type: "boolean",
9250
+ offset: scanner.getTokenOffset(),
9251
+ length: 0,
9252
+ value: false
9253
+ };
9254
+ const end = tokenEnd();
9255
+ scanNext();
9256
+ node.length = end - node.offset;
9257
+ return node;
9258
+ }
9259
+ case "Null": {
9260
+ const node = {
9261
+ type: "null",
9262
+ offset: scanner.getTokenOffset(),
9263
+ length: 0,
9264
+ value: null
9265
+ };
9266
+ const end = tokenEnd();
9267
+ scanNext();
9268
+ node.length = end - node.offset;
9269
+ return node;
9270
+ }
9271
+ default: return;
9272
+ }
9273
+ }
9274
+ function parseArrayTree() {
9275
+ const node = {
9276
+ type: "array",
9277
+ offset: scanner.getTokenOffset(),
9278
+ length: 0,
9279
+ children: []
9280
+ };
9281
+ scanNext();
9282
+ let needsComma = false;
9283
+ while (token() !== "CloseBracket" && token() !== "EOF") {
9284
+ if (token() === "Comma") {
9285
+ if (!needsComma) handleError("ValueExpected");
9286
+ scanNext();
9287
+ if (token() === "CloseBracket" && allowTrailingComma) break;
9288
+ } else if (needsComma) handleError("CommaExpected");
9289
+ const child = parseValueTree();
9290
+ if (child) node.children.push(child);
9291
+ else handleError("ValueExpected", [], ["CloseBracket", "Comma"]);
9292
+ needsComma = true;
9293
+ }
9294
+ let end;
9295
+ if (token() !== "CloseBracket") {
9296
+ handleError("CloseBracketExpected");
9297
+ end = scanner.getTokenOffset();
9298
+ } else {
9299
+ end = tokenEnd();
9300
+ scanNext();
9301
+ }
9302
+ node.length = end - node.offset;
9303
+ return node;
9304
+ }
9305
+ function parseObjectTree() {
9306
+ const node = {
9307
+ type: "object",
9308
+ offset: scanner.getTokenOffset(),
9309
+ length: 0,
9310
+ children: []
9311
+ };
9312
+ scanNext();
9313
+ let needsComma = false;
9314
+ while (token() !== "CloseBrace" && token() !== "EOF") {
9315
+ if (token() === "Comma") {
9316
+ if (!needsComma) handleError("PropertyNameExpected");
9317
+ scanNext();
9318
+ if (token() === "CloseBrace" && allowTrailingComma) break;
9319
+ } else if (needsComma) handleError("CommaExpected");
9320
+ if (token() !== "String") {
9321
+ handleError("PropertyNameExpected", [], ["CloseBrace", "Comma"]);
9322
+ continue;
9323
+ }
9324
+ const property = {
9325
+ type: "property",
9326
+ offset: scanner.getTokenOffset(),
9327
+ length: 0,
9328
+ children: []
9329
+ };
9330
+ const keyNode = {
9331
+ type: "string",
9332
+ offset: scanner.getTokenOffset(),
9333
+ length: 0,
9334
+ value: scanner.getTokenValue()
9335
+ };
9336
+ const keyEnd = tokenEnd();
9337
+ scanNext();
9338
+ keyNode.length = keyEnd - keyNode.offset;
9339
+ property.children.push(keyNode);
9340
+ if (token() !== "Colon") {
9341
+ handleError("ColonExpected", [], ["CloseBrace", "Comma"]);
9342
+ property.length = scanner.getTokenOffset() - property.offset;
9343
+ node.children.push(property);
9344
+ continue;
9345
+ }
9346
+ property.colonOffset = scanner.getTokenOffset();
9347
+ scanNext();
9348
+ const valueNode = parseValueTree();
9349
+ if (valueNode) {
9350
+ property.children.push(valueNode);
9351
+ property.length = valueNode.offset + valueNode.length - property.offset;
9352
+ } else {
9353
+ handleError("ValueExpected", [], ["CloseBrace", "Comma"]);
9354
+ property.length = scanner.getTokenOffset() - property.offset;
9355
+ }
9356
+ node.children.push(property);
9357
+ needsComma = true;
9358
+ }
9359
+ let end;
9360
+ if (token() !== "CloseBrace") {
9361
+ handleError("CloseBraceExpected");
9362
+ end = scanner.getTokenOffset();
9363
+ } else {
9364
+ end = tokenEnd();
9365
+ scanNext();
9366
+ }
9367
+ node.length = end - node.offset;
9368
+ return node;
9369
+ }
9370
+ scanNext();
9371
+ if (buildTree) {
9372
+ const root = parseValueTree();
9373
+ if (token() !== "EOF") handleError("EndOfFileExpected");
9374
+ if (!root && !allowEmptyContent) handleError("ValueExpected");
9375
+ return {
9376
+ value: void 0,
9377
+ root,
9378
+ errors
9379
+ };
9380
+ }
9381
+ const value = parseValue();
9382
+ if (token() !== "EOF") handleError("EndOfFileExpected");
9383
+ if (value === void 0 && !allowEmptyContent) handleError("ValueExpected");
9384
+ return {
9385
+ value,
9386
+ root: void 0,
9387
+ errors
9388
+ };
9389
+ }
9390
+ function formatError(code, offset) {
9391
+ switch (code) {
9392
+ case "InvalidSymbol": return `Invalid symbol at offset ${offset}`;
9393
+ case "InvalidNumberFormat": return `Invalid number format at offset ${offset}`;
9394
+ case "PropertyNameExpected": return `Property name expected at offset ${offset}`;
9395
+ case "ValueExpected": return `Value expected at offset ${offset}`;
9396
+ case "ColonExpected": return `Colon expected at offset ${offset}`;
9397
+ case "CommaExpected": return `Comma expected at offset ${offset}`;
9398
+ case "CloseBraceExpected": return `Close brace expected at offset ${offset}`;
9399
+ case "CloseBracketExpected": return `Close bracket expected at offset ${offset}`;
9400
+ case "EndOfFileExpected": return `End of file expected at offset ${offset}`;
9401
+ case "InvalidCommentToken": return `Comments not allowed at offset ${offset}`;
9402
+ case "UnexpectedEndOfComment": return `Unexpected end of comment at offset ${offset}`;
9403
+ case "UnexpectedEndOfString": return `Unexpected end of string at offset ${offset}`;
9404
+ case "UnexpectedEndOfNumber": return `Unexpected end of number at offset ${offset}`;
9405
+ case "InvalidUnicode": return `Invalid unicode escape at offset ${offset}`;
9406
+ case "InvalidEscapeCharacter": return `Invalid escape character at offset ${offset}`;
9407
+ case "InvalidCharacter": return `Invalid character at offset ${offset}`;
9408
+ default: return `Parse error at offset ${offset}`;
9409
+ }
9410
+ }
9411
+ //#endregion
9412
+ //#region ../../node_modules/.pnpm/jsonc-effect@0.3.1_effect@3.21.4/node_modules/jsonc-effect/format.js
9413
+ /**
9414
+ * Apply an array of text edits to JSONC source text.
9415
+ *
9416
+ * This is a {@link https://effect.website/docs/function-dual | Function.dual}
9417
+ * that supports both data-first and data-last (pipeline) usage.
9418
+ *
9419
+ * @param text - The original JSONC source text.
9420
+ * @param edits - A read-only array of {@link JsoncEdit} objects, typically
9421
+ * produced by {@link format} or {@link modify}.
9422
+ * @returns An `Effect` that succeeds with the edited string.
9423
+ *
9424
+ * @remarks
9425
+ * Edits are sorted in reverse offset order before application so that
9426
+ * earlier edits do not shift the offsets of later ones. The original `edits`
9427
+ * array is not mutated.
9428
+ *
9429
+ * @see {@link format} to compute formatting edits.
9430
+ * @see {@link modify} to compute structural edits (insert, replace, remove).
9431
+ *
9432
+ * @example Data-first usage
9433
+ * ```ts
9434
+ * import { Effect } from "effect";
9435
+ * import { format, applyEdits } from "jsonc-effect";
9436
+ *
9437
+ * const input = '{"a":1}';
9438
+ * const edits = Effect.runSync(format(input));
9439
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9440
+ * ```
9441
+ *
9442
+ * @example Pipeline with modify
9443
+ * ```ts
9444
+ * import { Effect, pipe } from "effect";
9445
+ * import { modify, applyEdits } from "jsonc-effect";
9446
+ *
9447
+ * const input = '{ "a": 1 }';
9448
+ * const result = pipe(
9449
+ * input,
9450
+ * modify(["a"], 42),
9451
+ * Effect.flatMap((edits) => applyEdits(input, edits)),
9452
+ * Effect.runSync,
9453
+ * );
9454
+ * ```
9455
+ *
9456
+ * @public
9457
+ */
9458
+ const applyEdits$1 = effect.Function.dual(2, (text, edits) => effect.Effect.sync(() => {
9459
+ const sorted = [...edits].sort((a, b) => b.offset - a.offset);
9460
+ let result = text;
9461
+ for (const edit of sorted) result = result.substring(0, edit.offset) + edit.content + result.substring(edit.offset + edit.length);
9462
+ return result;
9463
+ }));
9464
+ /**
9465
+ * Compute edits to insert, replace, or remove a value at a JSON path.
9466
+ *
9467
+ * This is a {@link https://effect.website/docs/function-dual | Function.dual}
9468
+ * that supports both data-first and data-last (pipeline) usage.
9469
+ *
9470
+ * @param text - The JSONC source text to modify.
9471
+ * @param path - A {@link (JsoncPath:type)} (array of string keys and numeric indices)
9472
+ * identifying the target location in the JSON structure.
9473
+ * @param value - The value to set. Pass `undefined` to remove the
9474
+ * property or array element at the given path.
9475
+ * @param options - Optional object with `formattingOptions` controlling
9476
+ * indent size, tabs vs. spaces, and EOL style for generated text.
9477
+ * @returns An `Effect` that succeeds with a read-only array of
9478
+ * {@link JsoncEdit} objects, or fails with a
9479
+ * {@link JsoncModificationError} if the path cannot be navigated.
9480
+ *
9481
+ * @remarks
9482
+ * Setting `value` to `undefined` removes the targeted property or element,
9483
+ * including its surrounding comma. When inserting a new property into an
9484
+ * object, it is appended after the last existing property.
9485
+ *
9486
+ * @see {@link applyEdits} to apply the returned edits to the source text.
9487
+ * @see {@link JsoncModificationError} for the error type on navigation failure.
9488
+ *
9489
+ * @example Update an existing property
9490
+ * ```ts
9491
+ * import { Effect } from "effect";
9492
+ * import { modify, applyEdits } from "jsonc-effect";
9493
+ *
9494
+ * const input = '{ "a": 1 }';
9495
+ * const edits = Effect.runSync(modify(input, ["a"], 2));
9496
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9497
+ * ```
9498
+ *
9499
+ * @example Insert a new property
9500
+ * ```ts
9501
+ * import { Effect } from "effect";
9502
+ * import { modify, applyEdits } from "jsonc-effect";
9503
+ *
9504
+ * const input = '{ "a": 1 }';
9505
+ * const edits = Effect.runSync(modify(input, ["b"], "hello"));
9506
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9507
+ * ```
9508
+ *
9509
+ * @example Remove a property
9510
+ * ```ts
9511
+ * import { Effect } from "effect";
9512
+ * import { modify, applyEdits } from "jsonc-effect";
9513
+ *
9514
+ * const input = '{ "a": 1, "b": 2 }';
9515
+ * const edits = Effect.runSync(modify(input, ["a"], undefined));
9516
+ * const result: string = Effect.runSync(applyEdits(input, edits));
9517
+ * ```
9518
+ *
9519
+ * @example Pipeline (data-last) usage
9520
+ * ```ts
9521
+ * import { Effect, pipe } from "effect";
9522
+ * import { modify, applyEdits } from "jsonc-effect";
9523
+ *
9524
+ * const input = '{ "a": 1 }';
9525
+ * const result = pipe(
9526
+ * input,
9527
+ * modify(["a"], 42),
9528
+ * Effect.flatMap((edits) => applyEdits(input, edits)),
9529
+ * Effect.runSync,
9530
+ * );
9531
+ * ```
9532
+ *
9533
+ * @privateRemarks
9534
+ * Uses its own scanner-based navigation to locate the target path rather
9535
+ * than building a full AST via `parseTree`. This keeps the implementation
9536
+ * lightweight and avoids an intermediate allocation.
9537
+ *
9538
+ * @public
9539
+ */
9540
+ const modify = effect.Function.dual((args) => typeof args[0] === "string" && Array.isArray(args[1]), (text, path, value, options) => effect.Effect.try({
9541
+ try: () => modifyImpl(text, path, value, options?.formattingOptions),
9542
+ catch: (e) => new JsoncModificationError({
9543
+ path,
9544
+ reason: String(e)
9545
+ })
9546
+ }));
9547
+ function modifyImpl(text, path, value, formattingOptions) {
9548
+ const opts = {
9549
+ tabSize: formattingOptions?.tabSize ?? 2,
9550
+ insertSpaces: formattingOptions?.insertSpaces ?? true,
9551
+ eol: formattingOptions?.eol ?? "\n"
9552
+ };
9553
+ const indentUnit = opts.insertSpaces ? " ".repeat(opts.tabSize) : " ";
9554
+ if (path.length === 0) {
9555
+ const content = value === void 0 ? "" : JSON.stringify(value, null, opts.tabSize);
9556
+ return [{
9557
+ offset: 0,
9558
+ length: text.length,
9559
+ content
9560
+ }];
9561
+ }
9562
+ const scanner = createScanner$1(text, true);
9563
+ let currentToken = scanner.scan();
9564
+ function tokenEnd() {
9565
+ return scanner.getTokenOffset() + scanner.getTokenLength();
9566
+ }
9567
+ function skipValue() {
9568
+ switch (currentToken) {
9569
+ case "OpenBrace": {
9570
+ let end = tokenEnd();
9571
+ currentToken = scanner.scan();
9572
+ let first = true;
9573
+ while (currentToken !== "CloseBrace" && currentToken !== "EOF") {
9574
+ if (!first && currentToken === "Comma") currentToken = scanner.scan();
9575
+ if (currentToken === "String") {
9576
+ currentToken = scanner.scan();
9577
+ if (currentToken === "Colon") {
9578
+ currentToken = scanner.scan();
9579
+ end = skipValue();
9580
+ }
9581
+ } else {
9582
+ end = tokenEnd();
9583
+ currentToken = scanner.scan();
9584
+ }
9585
+ first = false;
9586
+ }
9587
+ if (currentToken === "CloseBrace") {
9588
+ end = tokenEnd();
9589
+ currentToken = scanner.scan();
9590
+ }
9591
+ return end;
9592
+ }
9593
+ case "OpenBracket": {
9594
+ let end = tokenEnd();
9595
+ currentToken = scanner.scan();
9596
+ let first = true;
9597
+ while (currentToken !== "CloseBracket" && currentToken !== "EOF") {
9598
+ if (!first && currentToken === "Comma") currentToken = scanner.scan();
9599
+ end = skipValue();
9600
+ first = false;
9601
+ }
9602
+ if (currentToken === "CloseBracket") {
9603
+ end = tokenEnd();
9604
+ currentToken = scanner.scan();
9605
+ }
9606
+ return end;
9607
+ }
9608
+ default: {
9609
+ const end = tokenEnd();
9610
+ currentToken = scanner.scan();
9611
+ return end;
9612
+ }
9613
+ }
9614
+ }
9615
+ let depth = 0;
9616
+ for (const segment of path) {
9617
+ depth++;
9618
+ if (typeof segment === "string") {
9619
+ if (currentToken !== "OpenBrace") throw new Error(`Expected object at depth ${depth}`);
9620
+ currentToken = scanner.scan();
9621
+ let found = false;
9622
+ let lastValueEnd = scanner.getTokenOffset();
9623
+ let isFirst = true;
9624
+ while (currentToken !== "CloseBrace" && currentToken !== "EOF") {
9625
+ if (!isFirst && currentToken === "Comma") currentToken = scanner.scan();
9626
+ if (currentToken === "String") {
9627
+ const key = scanner.getTokenValue();
9628
+ currentToken = scanner.scan();
9629
+ if (currentToken === "Colon") currentToken = scanner.scan();
9630
+ if (key === segment) {
9631
+ found = true;
9632
+ if (depth === path.length) {
9633
+ const valueStart = scanner.getTokenOffset();
9634
+ const prevEnd = valueStart;
9635
+ const valueEnd = skipValue();
9636
+ if (value === void 0) {
9637
+ let removeStart = valueStart;
9638
+ let removeEnd = valueEnd;
9639
+ const keyStart = text.substring(0, valueStart).lastIndexOf(`"${segment}"`);
9640
+ if (keyStart >= 0) removeStart = keyStart;
9641
+ const commaPosBefore = text.substring(0, removeStart).trimEnd().lastIndexOf(",");
9642
+ if (commaPosBefore >= 0) removeStart = commaPosBefore;
9643
+ else {
9644
+ const trimmedAfter = text.substring(removeEnd).match(/^(\s*,)/);
9645
+ if (trimmedAfter) removeEnd += trimmedAfter[1].length;
9646
+ }
9647
+ return [{
9648
+ offset: removeStart,
9649
+ length: removeEnd - removeStart,
9650
+ content: ""
9651
+ }];
9652
+ }
9653
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9654
+ return [{
9655
+ offset: prevEnd,
9656
+ length: valueEnd - prevEnd,
9657
+ content: serialized
9658
+ }];
9659
+ }
9660
+ break;
9661
+ }
9662
+ lastValueEnd = skipValue();
9663
+ } else {
9664
+ currentToken = scanner.scan();
9665
+ lastValueEnd = scanner.getTokenOffset();
9666
+ }
9667
+ isFirst = false;
9668
+ }
9669
+ if (!found && depth === path.length && value !== void 0) {
9670
+ const indent = indentUnit.repeat(depth);
9671
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9672
+ const insertText = isFirst ? `${opts.eol}${indent}"${segment}": ${serialized}${opts.eol}${indentUnit.repeat(depth - 1)}` : `,${opts.eol}${indent}"${segment}": ${serialized}`;
9673
+ return [{
9674
+ offset: lastValueEnd,
9675
+ length: 0,
9676
+ content: insertText
9677
+ }];
9678
+ }
9679
+ } else {
9680
+ if (currentToken !== "OpenBracket") throw new Error(`Expected array at depth ${depth}`);
9681
+ currentToken = scanner.scan();
9682
+ let idx = 0;
9683
+ let lastEnd = scanner.getTokenOffset();
9684
+ while (currentToken !== "CloseBracket" && currentToken !== "EOF") {
9685
+ if (idx > 0 && currentToken === "Comma") currentToken = scanner.scan();
9686
+ if (idx === segment) {
9687
+ if (depth === path.length) {
9688
+ const valueStart = scanner.getTokenOffset();
9689
+ const valueEnd = skipValue();
9690
+ if (value === void 0) {
9691
+ let removeEnd = valueEnd;
9692
+ if (text.substring(removeEnd).trimStart().startsWith(",")) removeEnd = text.indexOf(",", removeEnd) + 1;
9693
+ return [{
9694
+ offset: valueStart,
9695
+ length: removeEnd - valueStart,
9696
+ content: ""
9697
+ }];
9698
+ }
9699
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9700
+ return [{
9701
+ offset: valueStart,
9702
+ length: valueEnd - valueStart,
9703
+ content: serialized
9704
+ }];
9705
+ }
9706
+ break;
9707
+ }
9708
+ lastEnd = skipValue();
9709
+ idx++;
9710
+ }
9711
+ if (idx <= segment && depth === path.length && value !== void 0) {
9712
+ const indent = indentUnit.repeat(depth);
9713
+ const serialized = JSON.stringify(value, null, opts.tabSize);
9714
+ const insertText = idx === 0 ? `${opts.eol}${indent}${serialized}${opts.eol}${indentUnit.repeat(depth - 1)}` : `,${opts.eol}${indent}${serialized}`;
9715
+ return [{
9716
+ offset: lastEnd,
9717
+ length: 0,
9718
+ content: insertText
9719
+ }];
9720
+ }
9721
+ }
9722
+ }
9723
+ return [];
9724
+ }
9725
+ //#endregion
9726
+ //#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
8435
9727
  const DepRecord = effect.Schema.optionalWith(effect.Schema.Record({
8436
9728
  key: effect.Schema.String,
8437
9729
  value: effect.Schema.String
@@ -8500,7 +9792,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
8500
9792
  }
8501
9793
  };
8502
9794
  //#endregion
8503
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/services/PointInTimeWorkspace.js
9795
+ //#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/services/PointInTimeWorkspace.js
8504
9796
  /**
8505
9797
  * Service for reading a monorepo's workspace state at a specific moment: any
8506
9798
  * git ref (via `git show`/`git ls-tree`, without checking the ref out) or the
@@ -8527,7 +9819,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
8527
9819
  */
8528
9820
  var PointInTimeWorkspace = class extends effect.Context.Tag("@spencerbeggs/workspaces-effect/PointInTimeWorkspace")() {};
8529
9821
  //#endregion
8530
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/discovery/glob-core.js
9822
+ //#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/layers/discovery/glob-core.js
8531
9823
  const normalize$1 = (pattern) => pattern.replace(/\/\*\*$/, "/*");
8532
9824
  const toRegex = (glob) => new RegExp(`^${glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]")}$`);
8533
9825
  /**
@@ -8570,7 +9862,7 @@ const compileWorkspaceGlobs = (patterns) => {
8570
9862
  };
8571
9863
  };
8572
9864
  //#endregion
8573
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/point-in-time/git.js
9865
+ //#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/layers/point-in-time/git.js
8574
9866
  /**
8575
9867
  * Stderr shapes that mean "the path is not present at this ref" rather than
8576
9868
  * "the git command failed."
@@ -8662,7 +9954,7 @@ const makeGitReader = (executor, options) => {
8662
9954
  };
8663
9955
  };
8664
9956
  //#endregion
8665
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/PointInTimeWorkspaceLive.js
9957
+ //#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/layers/PointInTimeWorkspaceLive.js
8666
9958
  /**
8667
9959
  * Live layer for the {@link PointInTimeWorkspace} service.
8668
9960
  *
@@ -8717,7 +10009,7 @@ const packageSnapshotFromJson = (text, relativePath) => {
8717
10009
  *
8718
10010
  * @internal
8719
10011
  */
8720
- 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()));
10012
+ 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()));
8721
10013
  /**
8722
10014
  * Live layer for the {@link PointInTimeWorkspace} service.
8723
10015
  *
@@ -8803,7 +10095,7 @@ const PointInTimeWorkspaceLive = effect.Layer.effect(PointInTimeWorkspace, effec
8803
10095
  });
8804
10096
  }));
8805
10097
  //#endregion
8806
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/schemas/publish.js
10098
+ //#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/publish.js
8807
10099
  /**
8808
10100
  * Schema for package publish targets.
8809
10101
  *
@@ -8846,7 +10138,7 @@ var PublishTarget = class extends effect.Schema.Class("PublishTarget")({
8846
10138
  provenance: effect.Schema.optionalWith(effect.Schema.Boolean, { default: () => false })
8847
10139
  }) {};
8848
10140
  //#endregion
8849
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/services/PublishabilityDetector.js
10141
+ //#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/services/PublishabilityDetector.js
8850
10142
  /**
8851
10143
  * Service for detecting whether a workspace package is publishable and
8852
10144
  * identifying its publish targets (npm, GitHub Packages, etc.).
@@ -8908,7 +10200,7 @@ var PublishTarget = class extends effect.Schema.Class("PublishTarget")({
8908
10200
  */
8909
10201
  var PublishabilityDetector = class extends effect.Context.Tag("@spencerbeggs/workspaces-effect/PublishabilityDetector")() {};
8910
10202
  //#endregion
8911
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/PublishabilityDetectorLive.js
10203
+ //#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/layers/PublishabilityDetectorLive.js
8912
10204
  /**
8913
10205
  * Default live implementation of the {@link PublishabilityDetector} service.
8914
10206
  *
@@ -8980,7 +10272,7 @@ const PublishabilityDetectorLive = effect.Layer.succeed(PublishabilityDetector,
8980
10272
  return targets;
8981
10273
  }).pipe(effect.Effect.withSpan("PublishabilityDetector.detect", { attributes: { "workspace.package": pkg.name } })) });
8982
10274
  //#endregion
8983
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/WorkspaceDiscoveryLive.js
10275
+ //#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/layers/WorkspaceDiscoveryLive.js
8984
10276
  /**
8985
10277
  * Live implementation of the {@link WorkspaceDiscovery} service.
8986
10278
  *
@@ -9267,7 +10559,7 @@ const WorkspaceDiscoveryLive = effect.Layer.effect(WorkspaceDiscovery, effect.Ef
9267
10559
  };
9268
10560
  }));
9269
10561
  //#endregion
9270
- //#region ../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect+platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/layers/WorkspaceRootLive.js
10562
+ //#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/layers/WorkspaceRootLive.js
9271
10563
  /**
9272
10564
  * Live implementation of the {@link WorkspaceRoot} service.
9273
10565
  *
@@ -34056,7 +35348,7 @@ var ChangelogTransformer = class ChangelogTransformer {
34056
35348
  }
34057
35349
  };
34058
35350
  //#endregion
34059
- //#region ../../node_modules/.pnpm/fdir@6.5.0_picomatch@4.0.4/node_modules/fdir/dist/index.mjs
35351
+ //#region ../../node_modules/.pnpm/fdir@6.5.0_picomatch@4.0.5/node_modules/fdir/dist/index.mjs
34060
35352
  var __require = /* @__PURE__ */ (0, module$1.createRequire)(require("url").pathToFileURL(__filename).href);
34061
35353
  function cleanPath(path$11) {
34062
35354
  let normalized = (0, path.normalize)(path$11);
@@ -34564,7 +35856,7 @@ var Builder = class {
34564
35856
  }
34565
35857
  };
34566
35858
  //#endregion
34567
- //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/constants.js
35859
+ //#region ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/constants.js
34568
35860
  var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34569
35861
  const WIN_SLASH = "\\\\/";
34570
35862
  const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
@@ -34733,7 +36025,7 @@ var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34733
36025
  };
34734
36026
  }));
34735
36027
  //#endregion
34736
- //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/utils.js
36028
+ //#region ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/utils.js
34737
36029
  var require_utils$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
34738
36030
  const { REGEX_BACKSLASH, REGEX_REMOVE_BACKSLASH, REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL } = require_constants();
34739
36031
  exports.isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val);
@@ -34781,7 +36073,7 @@ var require_utils$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
34781
36073
  };
34782
36074
  }));
34783
36075
  //#endregion
34784
- //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/scan.js
36076
+ //#region ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/scan.js
34785
36077
  var require_scan = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34786
36078
  const utils = require_utils$1();
34787
36079
  const { CHAR_ASTERISK, CHAR_AT, CHAR_BACKWARD_SLASH, CHAR_COMMA, CHAR_DOT, CHAR_EXCLAMATION_MARK, CHAR_FORWARD_SLASH, CHAR_LEFT_CURLY_BRACE, CHAR_LEFT_PARENTHESES, CHAR_LEFT_SQUARE_BRACKET, CHAR_PLUS, CHAR_QUESTION_MARK, CHAR_RIGHT_CURLY_BRACE, CHAR_RIGHT_PARENTHESES, CHAR_RIGHT_SQUARE_BRACKET } = require_constants();
@@ -35068,7 +36360,7 @@ var require_scan = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35068
36360
  module.exports = scan;
35069
36361
  }));
35070
36362
  //#endregion
35071
- //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/parse.js
36363
+ //#region ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/parse.js
35072
36364
  var require_parse$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35073
36365
  const constants = require_constants();
35074
36366
  const utils = require_utils$1();
@@ -35223,7 +36515,10 @@ var require_parse$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35223
36515
  }
35224
36516
  }
35225
36517
  };
35226
- const getStarExtglobSequenceOutput = (pattern) => {
36518
+ const buildCharClassStar = (chars) => {
36519
+ return `${chars.length === 1 ? utils.escapeRegex(chars[0]) : `[${chars.map((ch) => utils.escapeRegex(ch)).join("")}]`}*`;
36520
+ };
36521
+ const getStarExtglobSequenceChars = (pattern) => {
35227
36522
  let index = 0;
35228
36523
  const chars = [];
35229
36524
  while (index < pattern.length) {
@@ -35237,7 +36532,7 @@ var require_parse$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35237
36532
  index += match.end + 1;
35238
36533
  }
35239
36534
  if (chars.length < 1) return;
35240
- return `${chars.length === 1 ? utils.escapeRegex(chars[0]) : `[${chars.map((ch) => utils.escapeRegex(ch)).join("")}]`}*`;
36535
+ return chars;
35241
36536
  };
35242
36537
  const repeatedExtglobRecursion = (pattern) => {
35243
36538
  let depth = 0;
@@ -35257,14 +36552,28 @@ var require_parse$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35257
36552
  if (branches.length > 1) {
35258
36553
  if (branches.some((branch) => branch === "") || branches.some((branch) => /^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) return { risky: true };
35259
36554
  }
36555
+ const safeChars = [];
36556
+ let sawStarSequence = false;
36557
+ let combinable = true;
35260
36558
  for (const branch of branches) {
35261
- const safeOutput = getStarExtglobSequenceOutput(branch);
35262
- if (safeOutput) return {
35263
- risky: true,
35264
- safeOutput
35265
- };
36559
+ const chars = getStarExtglobSequenceChars(branch);
36560
+ if (chars) {
36561
+ sawStarSequence = true;
36562
+ safeChars.push(...chars);
36563
+ continue;
36564
+ }
36565
+ const literal = normalizeSimpleBranch(branch);
36566
+ if (literal && literal.length === 1) {
36567
+ safeChars.push(literal);
36568
+ continue;
36569
+ }
36570
+ combinable = false;
35266
36571
  if (repeatedExtglobRecursion(branch) > max) return { risky: true };
35267
36572
  }
36573
+ if (sawStarSequence) return combinable ? {
36574
+ risky: true,
36575
+ safeOutput: buildCharClassStar([...new Set(safeChars)])
36576
+ } : { risky: true };
35268
36577
  return { risky: false };
35269
36578
  };
35270
36579
  /**
@@ -36125,7 +37434,7 @@ var require_parse$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36125
37434
  module.exports = parse;
36126
37435
  }));
36127
37436
  //#endregion
36128
- //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/picomatch.js
37437
+ //#region ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/picomatch.js
36129
37438
  var require_picomatch$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36130
37439
  const scan = require_scan();
36131
37440
  const parse = require_parse$1();
@@ -36146,6 +37455,18 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36146
37455
  * const isMatch = picomatch('*.!(*a)');
36147
37456
  * console.log(isMatch('a.a')); //=> false
36148
37457
  * console.log(isMatch('a.b')); //=> true
37458
+ *
37459
+ * // For environments without `node.js`, `picomatch/posix` provides you a dependency-free matcher, without automatic OS detection.
37460
+ * const picomatch = require('picomatch/posix');
37461
+ * // the same API, defaulting to posix paths
37462
+ * const isMatch = picomatch('a/*');
37463
+ * console.log(isMatch('a\\b')); //=> false
37464
+ * console.log(isMatch('a/b')); //=> true
37465
+ *
37466
+ * // you can still configure the matcher function to accept windows paths
37467
+ * const isMatch = picomatch('a/*', { options: windows });
37468
+ * console.log(isMatch('a\\b')); //=> true
37469
+ * console.log(isMatch('a/b')); //=> true
36149
37470
  * ```
36150
37471
  * @name picomatch
36151
37472
  * @param {String|Array} `globs` One or more glob patterns.
@@ -36264,8 +37585,8 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36264
37585
  * @return {Boolean}
36265
37586
  * @api public
36266
37587
  */
36267
- picomatch.matchBase = (input, glob, options) => {
36268
- return (glob instanceof RegExp ? glob : picomatch.makeRe(glob, options)).test(utils.basename(input));
37588
+ picomatch.matchBase = (input, glob, options, posix = options && options.windows) => {
37589
+ return (glob instanceof RegExp ? glob : picomatch.makeRe(glob, options)).test(utils.basename(input, { windows: posix }));
36269
37590
  };
36270
37591
  /**
36271
37592
  * Returns true if **any** of the given glob `patterns` match the specified `string`.
@@ -38198,23 +39519,46 @@ function parseJsonPath(path) {
38198
39519
  * @internal
38199
39520
  */
38200
39521
  function jsonPathGet(obj, path) {
39522
+ return walkJsonPath(obj, path).map((entry) => entry.node);
39523
+ }
39524
+ /**
39525
+ * Shared breadth-first traversal behind {@link jsonPathGet} and
39526
+ * {@link jsonPathResolve}: each segment fans out the current set of matched
39527
+ * entries, carrying both the node and the concrete path taken to reach it.
39528
+ * The two public functions differ only in which half of the entry they keep.
39529
+ */
39530
+ function walkJsonPath(obj, path) {
38201
39531
  const segments = parseJsonPath(path);
38202
- let current = [obj];
39532
+ let current = [{
39533
+ node: obj,
39534
+ path: []
39535
+ }];
38203
39536
  for (const segment of segments) {
38204
39537
  const next = [];
38205
- for (const node of current) {
39538
+ for (const { node, path: nodePath } of current) {
38206
39539
  if (node === null || node === void 0 || typeof node !== "object") continue;
38207
39540
  switch (segment.type) {
38208
39541
  case "property": {
38209
39542
  const value = node[segment.key];
38210
- if (value !== void 0) next.push(value);
39543
+ if (value !== void 0) next.push({
39544
+ node: value,
39545
+ path: [...nodePath, segment.key]
39546
+ });
38211
39547
  break;
38212
39548
  }
38213
39549
  case "index":
38214
- if (Array.isArray(node) && segment.index < node.length) next.push(node[segment.index]);
39550
+ if (Array.isArray(node) && segment.index < node.length) next.push({
39551
+ node: node[segment.index],
39552
+ path: [...nodePath, segment.index]
39553
+ });
38215
39554
  break;
38216
39555
  case "wildcard":
38217
- if (Array.isArray(node)) next.push(...node);
39556
+ if (Array.isArray(node)) node.forEach((element, index) => {
39557
+ next.push({
39558
+ node: element,
39559
+ path: [...nodePath, index]
39560
+ });
39561
+ });
38218
39562
  break;
38219
39563
  }
38220
39564
  }
@@ -38223,81 +39567,37 @@ function jsonPathGet(obj, path) {
38223
39567
  return current;
38224
39568
  }
38225
39569
  /**
38226
- * Mutate all matching locations in an object in-place.
39570
+ * Resolve a JSONPath expression to the concrete paths of every existing match.
38227
39571
  *
38228
39572
  * @remarks
38229
- * Walks to the parent(s) of the final segment, then sets the value
38230
- * at each matching location. Only updates existing keys/indices;
38231
- * does not create new properties or extend arrays. Returns the count
38232
- * of locations actually updated.
39573
+ * Uses the same breadth-first expansion as {@link jsonPathGet}, but instead of
39574
+ * collecting the matched *values* it records the concrete `(string | number)[]`
39575
+ * path taken to reach each one. Wildcards and indices are materialized into the
39576
+ * numeric array index actually traversed, so the returned paths are directly
39577
+ * consumable by structural editors such as `jsonc-effect`'s `modify`, which
39578
+ * require a fully concrete path (no wildcards).
39579
+ *
39580
+ * Only existing locations are returned; nothing is created. A path with no
39581
+ * matches yields an empty array, and the empty path (`"$."`) yields a single
39582
+ * empty concrete path (the document root).
38233
39583
  *
38234
- * @param obj - The object to modify in-place
39584
+ * @param obj - The object to query
38235
39585
  * @param path - JSONPath string (e.g., `"$.packages[*].version"`)
38236
- * @param value - The value to set at each matching location
38237
- * @returns The number of locations updated (0 if no matches or empty path)
39586
+ * @returns Array of concrete paths, each an array of string keys / numeric indices
38238
39587
  *
38239
39588
  * @example
38240
39589
  * ```typescript
38241
- * import { jsonPathSet } from "../utils/jsonpath.js";
39590
+ * import { jsonPathResolve } from "../utils/jsonpath.js";
38242
39591
  *
38243
- * const obj = { version: "1.0.0" };
38244
- * const count = jsonPathSet(obj, "$.version", "2.0.0");
38245
- * // count === 1, obj.version === "2.0.0"
39592
+ * const obj = { packages: [{ version: "1.0.0" }, { version: "2.0.0" }] };
39593
+ * const paths = jsonPathResolve(obj, "$.packages[*].version");
39594
+ * // [["packages", 0, "version"], ["packages", 1, "version"]]
38246
39595
  * ```
38247
39596
  *
38248
39597
  * @internal
38249
39598
  */
38250
- function jsonPathSet(obj, path, value) {
38251
- const segments = parseJsonPath(path);
38252
- if (segments.length === 0) return 0;
38253
- const lastSegment = segments[segments.length - 1];
38254
- const parentSegments = segments.slice(0, -1);
38255
- let parents = [obj];
38256
- for (const segment of parentSegments) {
38257
- const next = [];
38258
- for (const node of parents) {
38259
- if (node === null || node === void 0 || typeof node !== "object") continue;
38260
- switch (segment.type) {
38261
- case "property": {
38262
- const child = node[segment.key];
38263
- if (child !== void 0) next.push(child);
38264
- break;
38265
- }
38266
- case "index":
38267
- if (Array.isArray(node) && segment.index < node.length) next.push(node[segment.index]);
38268
- break;
38269
- case "wildcard":
38270
- if (Array.isArray(node)) next.push(...node);
38271
- break;
38272
- }
38273
- }
38274
- parents = next;
38275
- }
38276
- let count = 0;
38277
- for (const parent of parents) {
38278
- if (parent === null || parent === void 0 || typeof parent !== "object") continue;
38279
- switch (lastSegment.type) {
38280
- case "property":
38281
- if (lastSegment.key in parent) {
38282
- parent[lastSegment.key] = value;
38283
- count++;
38284
- }
38285
- break;
38286
- case "index":
38287
- if (Array.isArray(parent) && lastSegment.index < parent.length) {
38288
- parent[lastSegment.index] = value;
38289
- count++;
38290
- }
38291
- break;
38292
- case "wildcard":
38293
- if (Array.isArray(parent)) for (let i = 0; i < parent.length; i++) {
38294
- parent[i] = value;
38295
- count++;
38296
- }
38297
- break;
38298
- }
38299
- }
38300
- return count;
39599
+ function jsonPathResolve(obj, path) {
39600
+ return walkJsonPath(obj, path).map((entry) => entry.path);
38301
39601
  }
38302
39602
  //#endregion
38303
39603
  //#region ../silk-effects/dist/dev/pkg/changesets/utils/version-files.js
@@ -38488,31 +39788,39 @@ var VersionFiles = class VersionFiles {
38488
39788
  return content.match(/^(\s+)"/m)?.[1] ?? " ";
38489
39789
  }
38490
39790
  /**
38491
- * Update JSON file at specified JSONPath locations.
39791
+ * Update a JSON (or JSONC) file at specified JSONPath locations,
39792
+ * preserving the original formatting byte-for-byte.
38492
39793
  *
38493
39794
  * @remarks
38494
- * Reads the file, detects its indentation style and trailing newline
38495
- * preference, applies all JSONPath updates via {@link jsonPathSet},
38496
- * and writes the result back preserving the original formatting.
38497
- * Returns `undefined` if no JSONPath locations matched (no write occurs).
39795
+ * The write is performed with `jsonc-effect`'s format-preserving
39796
+ * `modify`/`applyEdits` rather than a `JSON.parse`/`JSON.stringify`
39797
+ * round-trip (which always explodes inline arrays one-element-per-line and
39798
+ * drops comments). Each JSONPath expression is resolved to concrete
39799
+ * `(string | number)[]` paths against the parsed document, and each
39800
+ * concrete path becomes a minimal text edit that touches only the target
39801
+ * value's span — so inline arrays, comments,
39802
+ * indentation, and the trailing-newline preference all survive; a one-line
39803
+ * version bump produces a one-line diff.
39804
+ *
39805
+ * Insertion semantics: a concrete, wildcard-free JSONPath whose leaf
39806
+ * property does not exist yet is inserted after the last sibling using the
39807
+ * document's detected indent (the one case where indent detection still
39808
+ * matters). Wildcard expressions only ever update existing matches. Returns
39809
+ * `undefined` (no write) when nothing was updated or inserted.
38498
39810
  *
38499
39811
  * @param filePath - Absolute path to the JSON file
38500
39812
  * @param jsonPaths - JSONPath expressions to update
38501
39813
  * @param version - New version string
38502
39814
  * @returns Update result, or `undefined` if no changes were made
39815
+ *
39816
+ * @see {@link jsonPathResolve} for concrete-path enumeration
39817
+ * @see {@link VersionFiles.applyVersionEdit} for the per-path edit
38503
39818
  */
38504
39819
  static updateFile(filePath, jsonPaths, version) {
38505
- const content = (0, node_fs.readFileSync)(filePath, "utf-8");
38506
- const indent = VersionFiles.detectIndent(content);
38507
- const trailingNewline = content.endsWith("\n");
38508
- const obj = JSON.parse(content);
38509
- const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
38510
- let totalUpdated = 0;
38511
- for (const jp of jsonPaths) totalUpdated += jsonPathSet(obj, jp, version);
38512
- if (totalUpdated === 0) return;
38513
- let output = JSON.stringify(obj, null, indent);
38514
- if (trailingNewline) output += "\n";
38515
- (0, node_fs.writeFileSync)(filePath, output, "utf-8");
39820
+ const original = (0, node_fs.readFileSync)(filePath, "utf-8");
39821
+ const { content, previousValues, totalChanged } = VersionFiles.computeUpdate(original, jsonPaths, version);
39822
+ if (totalChanged === 0) return;
39823
+ (0, node_fs.writeFileSync)(filePath, content, "utf-8");
38516
39824
  return {
38517
39825
  filePath,
38518
39826
  jsonPaths,
@@ -38521,6 +39829,83 @@ var VersionFiles = class VersionFiles {
38521
39829
  };
38522
39830
  }
38523
39831
  /**
39832
+ * Compute the full update for a document without touching the filesystem:
39833
+ * the edited content, the previous values at every matched path, and how
39834
+ * many locations actually changed.
39835
+ *
39836
+ * @remarks
39837
+ * This is the single decision path shared by {@link VersionFiles.updateFile}
39838
+ * and the dry-run branches of the two process methods, so a preview reports
39839
+ * exactly the files a real run would write — including pending inserts of a
39840
+ * not-yet-existing wildcard-free leaf, and excluding same-value no-ops.
39841
+ *
39842
+ * @param original - Document text as read from disk
39843
+ * @param jsonPaths - JSONPath expressions to update
39844
+ * @param version - New version string
39845
+ * @returns The updated content, previous values, and changed-location count
39846
+ */
39847
+ static computeUpdate(original, jsonPaths, version) {
39848
+ let content = original;
39849
+ const obj = effect.Effect.runSync(parse$2(content));
39850
+ const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
39851
+ const indent = VersionFiles.detectIndent(content);
39852
+ const eol = content.includes("\r\n") ? "\r\n" : "\n";
39853
+ let totalChanged = 0;
39854
+ for (const jp of jsonPaths) {
39855
+ const segments = parseJsonPath(jp);
39856
+ if (segments.length === 0) continue;
39857
+ const hasWildcard = segments.some((segment) => segment.type === "wildcard");
39858
+ let concretePaths;
39859
+ if (hasWildcard) concretePaths = jsonPathResolve(obj, jp);
39860
+ else {
39861
+ const direct = segments.map((segment) => segment.type === "property" ? segment.key : segment.index);
39862
+ concretePaths = jsonPathResolve(obj, jp).length > 0 || typeof direct[direct.length - 1] === "string" ? [direct] : [];
39863
+ }
39864
+ for (const concretePath of concretePaths) {
39865
+ const updated = VersionFiles.applyVersionEdit(content, concretePath, version, indent, eol);
39866
+ if (updated !== void 0) {
39867
+ content = updated;
39868
+ totalChanged += 1;
39869
+ }
39870
+ }
39871
+ }
39872
+ return {
39873
+ content,
39874
+ previousValues,
39875
+ totalChanged
39876
+ };
39877
+ }
39878
+ /**
39879
+ * Compute the format-preserving edit for a single concrete path, returning
39880
+ * the updated document, or `undefined` when nothing changed.
39881
+ *
39882
+ * @remarks
39883
+ * Delegates to `jsonc-effect`'s {@link modify} + {@link applyEdits}
39884
+ * (requires `jsonc-effect >= 0.3.1`, whose edit spans touch only the target
39885
+ * value), so every other byte of the document is preserved. When the leaf
39886
+ * of a wildcard-free path does not exist, `modify` inserts the property
39887
+ * after the last sibling using the supplied formatting options — the only
39888
+ * case where the detected indent matters. A path whose parent is missing or
39889
+ * not an object cannot be navigated; the resulting modification error is
39890
+ * caught and reported as "no change" so the file is left alone.
39891
+ *
39892
+ * @param content - Current document text
39893
+ * @param concretePath - A wildcard-free `(string | number)[]` path
39894
+ * @param version - New version string
39895
+ * @param indentUnit - One indentation level, for inserted text
39896
+ * @param eol - End-of-line sequence, for inserted text
39897
+ * @returns The updated document, or `undefined` if the path was unchanged
39898
+ */
39899
+ static applyVersionEdit(content, concretePath, version, indentUnit, eol) {
39900
+ const insertSpaces = !indentUnit.includes(" ");
39901
+ const program = modify(content, [...concretePath], version, { formattingOptions: {
39902
+ insertSpaces,
39903
+ tabSize: insertSpaces ? indentUnit.length : 1,
39904
+ eol
39905
+ } }).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)));
39906
+ return effect.Effect.runSync(program);
39907
+ }
39908
+ /**
38524
39909
  * Orchestrate the full version file update flow.
38525
39910
  *
38526
39911
  * @remarks
@@ -38546,9 +39931,8 @@ var VersionFiles = class VersionFiles {
38546
39931
  try {
38547
39932
  if (dryRun) {
38548
39933
  const content = (0, node_fs.readFileSync)(filePath, "utf-8");
38549
- const obj = JSON.parse(content);
38550
- const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
38551
- if (previousValues.length > 0) updates.push({
39934
+ const { previousValues, totalChanged } = VersionFiles.computeUpdate(content, jsonPaths, version);
39935
+ if (totalChanged > 0) updates.push({
38552
39936
  filePath,
38553
39937
  jsonPaths,
38554
39938
  version,
@@ -38592,9 +39976,8 @@ var VersionFiles = class VersionFiles {
38592
39976
  for (const filePath of vf.matchedFiles) try {
38593
39977
  if (dryRun) {
38594
39978
  const content = (0, node_fs.readFileSync)(filePath, "utf-8");
38595
- const obj = JSON.parse(content);
38596
- const previousValues = jsonPaths.flatMap((jp) => jsonPathGet(obj, jp));
38597
- if (previousValues.length > 0) updates.push({
39979
+ const { previousValues, totalChanged } = VersionFiles.computeUpdate(content, jsonPaths, scope.version);
39980
+ if (totalChanged > 0) updates.push({
38598
39981
  filePath,
38599
39982
  jsonPaths,
38600
39983
  version: scope.version,