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