jsonc-effect 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/index.d.ts +751 -0
- package/index.js +1424 -0
- package/package.json +58 -0
- package/tsdoc-metadata.json +11 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* jsonc-effect
|
|
3
|
+
*
|
|
4
|
+
* Pure Effect-TS implementation of a JSONC (JSON with Comments) parser.
|
|
5
|
+
* No external parser dependencies — scanner, parser, AST, and formatting
|
|
6
|
+
* are all implemented natively in Effect.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { Effect } from 'effect';
|
|
12
|
+
import { Equals } from 'effect/Types';
|
|
13
|
+
import { Option } from 'effect';
|
|
14
|
+
import { Schema } from 'effect';
|
|
15
|
+
import { Stream } from 'effect';
|
|
16
|
+
import { YieldableError } from 'effect/Cause';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Apply an array of edits to JSONC source text.
|
|
20
|
+
* Edits are applied in reverse offset order to avoid offset shifting.
|
|
21
|
+
*/
|
|
22
|
+
export declare const applyEdits: {
|
|
23
|
+
(edits: ReadonlyArray<JsoncEdit>): (text: string) => Effect.Effect<string>;
|
|
24
|
+
(text: string, edits: ReadonlyArray<JsoncEdit>): Effect.Effect<string>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create a JSONC scanner.
|
|
29
|
+
*
|
|
30
|
+
* @param text - The JSONC string to scan
|
|
31
|
+
* @param ignoreTrivia - If true, skip whitespace, line breaks, and comments
|
|
32
|
+
* @returns A JsoncScanner for iterating over tokens
|
|
33
|
+
*/
|
|
34
|
+
export declare const createScanner: (text: string, ignoreTrivia?: boolean) => JsoncScanner;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Find a node at a specific path in the AST.
|
|
38
|
+
*
|
|
39
|
+
* Traverses the AST following property names (strings) and
|
|
40
|
+
* array indices (numbers) in the path.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { Effect, Option, pipe } from "effect";
|
|
45
|
+
* import { parseTree, findNode } from "@spencerbeggs/jsonc-effect";
|
|
46
|
+
*
|
|
47
|
+
* // Data-first
|
|
48
|
+
* const node = Effect.gen(function* () {
|
|
49
|
+
* const root = yield* parseTree('{ "a": { "b": 1 } }');
|
|
50
|
+
* if (Option.isNone(root)) return Option.none();
|
|
51
|
+
* return yield* findNode(root.value, ["a", "b"]);
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* // Data-last (pipeline)
|
|
55
|
+
* const node2 = pipe(root, findNode(["a", "b"]));
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare const findNode: {
|
|
59
|
+
(path: JsoncPath): (root: JsoncNode) => Effect.Effect<Option.Option<JsoncNode>>;
|
|
60
|
+
(root: JsoncNode, path: JsoncPath): Effect.Effect<Option.Option<JsoncNode>>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Find the innermost node covering a character offset.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { Effect, Option, pipe } from "effect";
|
|
69
|
+
* import { parseTree, findNodeAtOffset } from "@spencerbeggs/jsonc-effect";
|
|
70
|
+
*
|
|
71
|
+
* // Data-last (pipeline)
|
|
72
|
+
* const node = pipe(root, findNodeAtOffset(5));
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare const findNodeAtOffset: {
|
|
76
|
+
(offset: number): (root: JsoncNode) => Effect.Effect<Option.Option<JsoncNode>>;
|
|
77
|
+
(root: JsoncNode, offset: number): Effect.Effect<Option.Option<JsoncNode>>;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Compute formatting edits for a JSONC document.
|
|
82
|
+
*
|
|
83
|
+
* Does NOT mutate the input — returns an array of edits to apply
|
|
84
|
+
* with applyEdits().
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* import { Effect } from "effect";
|
|
89
|
+
* import { format, applyEdits } from "@spencerbeggs/jsonc-effect";
|
|
90
|
+
*
|
|
91
|
+
* const edits = Effect.runSync(format('{"a":1}'));
|
|
92
|
+
* const formatted = Effect.runSync(applyEdits('{"a":1}', edits));
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare const format: (text: string, range?: JsoncRange | undefined, options?: Partial<JsoncFormattingOptions> | undefined) => Effect.Effect<readonly JsoncEdit[], never, never>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Format a JSONC document in one step (format + apply).
|
|
99
|
+
*/
|
|
100
|
+
export declare const formatAndApply: (text: string, range?: JsoncRange | undefined, options?: Partial<JsoncFormattingOptions> | undefined) => Effect.Effect<string, never, never>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get the JSON path to the node at a specific offset.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* import { Effect, pipe } from "effect";
|
|
108
|
+
* import { parseTree, getNodePath } from "@spencerbeggs/jsonc-effect";
|
|
109
|
+
*
|
|
110
|
+
* // Data-last (pipeline)
|
|
111
|
+
* const path = pipe(root, getNodePath(5));
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare const getNodePath: {
|
|
115
|
+
(targetOffset: number): (root: JsoncNode) => Effect.Effect<Option.Option<JsoncPath>>;
|
|
116
|
+
(root: JsoncNode, targetOffset: number): Effect.Effect<Option.Option<JsoncPath>>;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Evaluate a node subtree into a plain JavaScript value.
|
|
121
|
+
* Reconstructs objects and arrays from the AST.
|
|
122
|
+
*/
|
|
123
|
+
export declare const getNodeValue: (node: JsoncNode) => Effect.Effect<unknown, never, never>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A text edit to apply to a JSONC document.
|
|
127
|
+
*/
|
|
128
|
+
export declare class JsoncEdit extends JsoncEdit_base {
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
declare const JsoncEdit_base: Schema.Class<JsoncEdit, {
|
|
132
|
+
offset: typeof Schema.Number;
|
|
133
|
+
length: typeof Schema.Number;
|
|
134
|
+
content: typeof Schema.String;
|
|
135
|
+
}, Schema.Struct.Encoded<{
|
|
136
|
+
offset: typeof Schema.Number;
|
|
137
|
+
length: typeof Schema.Number;
|
|
138
|
+
content: typeof Schema.String;
|
|
139
|
+
}>, never, {
|
|
140
|
+
readonly content: string;
|
|
141
|
+
} & {
|
|
142
|
+
readonly length: number;
|
|
143
|
+
} & {
|
|
144
|
+
readonly offset: number;
|
|
145
|
+
}, {}, {}>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Union of all JSONC error types for exhaustive error handling.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* import { Effect } from "effect";
|
|
153
|
+
* import { parse, type JsoncError } from "jsonc-effect";
|
|
154
|
+
*
|
|
155
|
+
* const program = someJsoncOperation.pipe(
|
|
156
|
+
* Effect.catchTags({
|
|
157
|
+
* JsoncParseError: (e) => Effect.succeed("parse failed"),
|
|
158
|
+
* JsoncModificationError: (e) => Effect.succeed("modify failed"),
|
|
159
|
+
* JsoncNodeNotFoundError: (e) => Effect.succeed("node not found"),
|
|
160
|
+
* }),
|
|
161
|
+
* );
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export declare type JsoncError = JsoncParseError | JsoncNodeNotFoundError | JsoncModificationError;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Options controlling JSONC formatting behavior.
|
|
168
|
+
*/
|
|
169
|
+
export declare class JsoncFormattingOptions extends JsoncFormattingOptions_base {
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
declare const JsoncFormattingOptions_base: Schema.Class<JsoncFormattingOptions, {
|
|
173
|
+
tabSize: Schema.optionalWith<typeof Schema.Number, {
|
|
174
|
+
default: () => number;
|
|
175
|
+
}>;
|
|
176
|
+
insertSpaces: Schema.optionalWith<typeof Schema.Boolean, {
|
|
177
|
+
default: () => true;
|
|
178
|
+
}>;
|
|
179
|
+
eol: Schema.optionalWith<typeof Schema.String, {
|
|
180
|
+
default: () => string;
|
|
181
|
+
}>;
|
|
182
|
+
insertFinalNewline: Schema.optionalWith<typeof Schema.Boolean, {
|
|
183
|
+
default: () => false;
|
|
184
|
+
}>;
|
|
185
|
+
keepLines: Schema.optionalWith<typeof Schema.Boolean, {
|
|
186
|
+
default: () => false;
|
|
187
|
+
}>;
|
|
188
|
+
}, Schema.Struct.Encoded<{
|
|
189
|
+
tabSize: Schema.optionalWith<typeof Schema.Number, {
|
|
190
|
+
default: () => number;
|
|
191
|
+
}>;
|
|
192
|
+
insertSpaces: Schema.optionalWith<typeof Schema.Boolean, {
|
|
193
|
+
default: () => true;
|
|
194
|
+
}>;
|
|
195
|
+
eol: Schema.optionalWith<typeof Schema.String, {
|
|
196
|
+
default: () => string;
|
|
197
|
+
}>;
|
|
198
|
+
insertFinalNewline: Schema.optionalWith<typeof Schema.Boolean, {
|
|
199
|
+
default: () => false;
|
|
200
|
+
}>;
|
|
201
|
+
keepLines: Schema.optionalWith<typeof Schema.Boolean, {
|
|
202
|
+
default: () => false;
|
|
203
|
+
}>;
|
|
204
|
+
}>, never, {
|
|
205
|
+
readonly eol?: string;
|
|
206
|
+
} & {
|
|
207
|
+
readonly insertFinalNewline?: boolean;
|
|
208
|
+
} & {
|
|
209
|
+
readonly insertSpaces?: boolean;
|
|
210
|
+
} & {
|
|
211
|
+
readonly keepLines?: boolean;
|
|
212
|
+
} & {
|
|
213
|
+
readonly tabSize?: number;
|
|
214
|
+
}, {}, {}>;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Schema that transforms a JSONC string into an unknown JavaScript value.
|
|
218
|
+
*
|
|
219
|
+
* This is the first stage of a parsing pipeline:
|
|
220
|
+
* JSONC string → unknown → (your typed schema)
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* import { Schema } from "effect"
|
|
225
|
+
* import { JsoncFromString } from "jsonc-effect"
|
|
226
|
+
*
|
|
227
|
+
* const MyConfigFromJsonc = Schema.compose(JsoncFromString, MyConfigSchema)
|
|
228
|
+
* const config = Schema.decodeUnknownSync(MyConfigFromJsonc)(jsoncText)
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
export declare const JsoncFromString: Schema.Schema<unknown, string>;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Error raised when modify() produces invalid edits.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* import { Effect } from "effect";
|
|
239
|
+
* import { modify } from "jsonc-effect";
|
|
240
|
+
*
|
|
241
|
+
* const program = modify("{}", ["deep", "path"], 42).pipe(
|
|
242
|
+
* Effect.catchTag("JsoncModificationError", (e) => {
|
|
243
|
+
* console.error(e.path, e.reason);
|
|
244
|
+
* return Effect.succeed([]);
|
|
245
|
+
* }),
|
|
246
|
+
* );
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
export declare class JsoncModificationError extends JsoncModificationErrorBase<{
|
|
250
|
+
readonly path: ReadonlyArray<string | number>;
|
|
251
|
+
readonly reason: string;
|
|
252
|
+
}> {
|
|
253
|
+
get message(): string;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** @internal */
|
|
257
|
+
export declare const JsoncModificationErrorBase: new <A extends Record<string, any> = {}>(args: Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => YieldableError & {
|
|
258
|
+
readonly _tag: "JsoncModificationError";
|
|
259
|
+
} & Readonly<A>;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* AST node representing a parsed JSONC element.
|
|
263
|
+
* Parent field is intentionally omitted to avoid circular references.
|
|
264
|
+
*/
|
|
265
|
+
export declare class JsoncNode extends JsoncNode_base {
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
declare const JsoncNode_base: Schema.Class<JsoncNode, {
|
|
269
|
+
type: Schema.Literal<["object", "array", "property", "string", "number", "boolean", "null"]>;
|
|
270
|
+
value: Schema.optional<typeof Schema.Unknown>;
|
|
271
|
+
offset: typeof Schema.Number;
|
|
272
|
+
length: typeof Schema.Number;
|
|
273
|
+
colonOffset: Schema.optional<typeof Schema.Number>;
|
|
274
|
+
children: Schema.optional<Schema.Array$<Schema.suspend<JsoncNode, JsoncNode, never>>>;
|
|
275
|
+
}, Schema.Struct.Encoded<{
|
|
276
|
+
type: Schema.Literal<["object", "array", "property", "string", "number", "boolean", "null"]>;
|
|
277
|
+
value: Schema.optional<typeof Schema.Unknown>;
|
|
278
|
+
offset: typeof Schema.Number;
|
|
279
|
+
length: typeof Schema.Number;
|
|
280
|
+
colonOffset: Schema.optional<typeof Schema.Number>;
|
|
281
|
+
children: Schema.optional<Schema.Array$<Schema.suspend<JsoncNode, JsoncNode, never>>>;
|
|
282
|
+
}>, never, {
|
|
283
|
+
readonly children?: readonly JsoncNode[] | undefined;
|
|
284
|
+
} & {
|
|
285
|
+
readonly colonOffset?: number | undefined;
|
|
286
|
+
} & {
|
|
287
|
+
readonly value?: unknown;
|
|
288
|
+
} & {
|
|
289
|
+
readonly length: number;
|
|
290
|
+
} & {
|
|
291
|
+
readonly offset: number;
|
|
292
|
+
} & {
|
|
293
|
+
readonly type: "array" | "boolean" | "null" | "number" | "object" | "property" | "string";
|
|
294
|
+
}, {}, {}>;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Error raised when AST navigation fails to find a node at the given path.
|
|
298
|
+
*/
|
|
299
|
+
export declare class JsoncNodeNotFoundError extends JsoncNodeNotFoundErrorBase<{
|
|
300
|
+
readonly path: ReadonlyArray<string | number>;
|
|
301
|
+
readonly rootNodeType: string;
|
|
302
|
+
}> {
|
|
303
|
+
get message(): string;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** @internal */
|
|
307
|
+
export declare const JsoncNodeNotFoundErrorBase: new <A extends Record<string, any> = {}>(args: Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => YieldableError & {
|
|
308
|
+
readonly _tag: "JsoncNodeNotFoundError";
|
|
309
|
+
} & Readonly<A>;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* AST node types.
|
|
313
|
+
*/
|
|
314
|
+
export declare const JsoncNodeType: Schema.Literal<["object", "array", "property", "string", "number", "boolean", "null"]>;
|
|
315
|
+
|
|
316
|
+
export declare type JsoncNodeType = Schema.Schema.Type<typeof JsoncNodeType>;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Error raised when JSONC parsing encounters syntax errors.
|
|
320
|
+
* Contains an array of error details with position information.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* import { Effect } from "effect";
|
|
325
|
+
* import { parse, JsoncParseError } from "jsonc-effect";
|
|
326
|
+
*
|
|
327
|
+
* const program = parse("{ invalid }").pipe(
|
|
328
|
+
* Effect.catchTag("JsoncParseError", (e) => {
|
|
329
|
+
* console.error(e.errors); // Array of JsoncParseErrorDetail
|
|
330
|
+
* return Effect.succeed({});
|
|
331
|
+
* }),
|
|
332
|
+
* );
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
export declare class JsoncParseError extends JsoncParseErrorBase<{
|
|
336
|
+
readonly errors: ReadonlyArray<JsoncParseErrorDetail>;
|
|
337
|
+
readonly text: string;
|
|
338
|
+
readonly options?: Partial<JsoncParseOptions>;
|
|
339
|
+
}> {
|
|
340
|
+
get message(): string;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** @internal */
|
|
344
|
+
export declare const JsoncParseErrorBase: new <A extends Record<string, any> = {}>(args: Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => YieldableError & {
|
|
345
|
+
readonly _tag: "JsoncParseError";
|
|
346
|
+
} & Readonly<A>;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Error codes for JSONC parse errors.
|
|
350
|
+
*/
|
|
351
|
+
export declare const JsoncParseErrorCode: Schema.Literal<["InvalidSymbol", "InvalidNumberFormat", "PropertyNameExpected", "ValueExpected", "ColonExpected", "CommaExpected", "CloseBraceExpected", "CloseBracketExpected", "EndOfFileExpected", "InvalidCommentToken", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter"]>;
|
|
352
|
+
|
|
353
|
+
export declare type JsoncParseErrorCode = Schema.Schema.Type<typeof JsoncParseErrorCode>;
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Detail for a single parse error with location information.
|
|
357
|
+
*/
|
|
358
|
+
export declare class JsoncParseErrorDetail extends JsoncParseErrorDetail_base {
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
declare const JsoncParseErrorDetail_base: Schema.Class<JsoncParseErrorDetail, {
|
|
362
|
+
code: Schema.Literal<["InvalidSymbol", "InvalidNumberFormat", "PropertyNameExpected", "ValueExpected", "ColonExpected", "CommaExpected", "CloseBraceExpected", "CloseBracketExpected", "EndOfFileExpected", "InvalidCommentToken", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter"]>;
|
|
363
|
+
message: typeof Schema.String;
|
|
364
|
+
offset: typeof Schema.Number;
|
|
365
|
+
length: typeof Schema.Number;
|
|
366
|
+
startLine: typeof Schema.Number;
|
|
367
|
+
startCharacter: typeof Schema.Number;
|
|
368
|
+
}, Schema.Struct.Encoded<{
|
|
369
|
+
code: Schema.Literal<["InvalidSymbol", "InvalidNumberFormat", "PropertyNameExpected", "ValueExpected", "ColonExpected", "CommaExpected", "CloseBraceExpected", "CloseBracketExpected", "EndOfFileExpected", "InvalidCommentToken", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter"]>;
|
|
370
|
+
message: typeof Schema.String;
|
|
371
|
+
offset: typeof Schema.Number;
|
|
372
|
+
length: typeof Schema.Number;
|
|
373
|
+
startLine: typeof Schema.Number;
|
|
374
|
+
startCharacter: typeof Schema.Number;
|
|
375
|
+
}>, never, {
|
|
376
|
+
readonly code: "CloseBraceExpected" | "CloseBracketExpected" | "ColonExpected" | "CommaExpected" | "EndOfFileExpected" | "InvalidCharacter" | "InvalidCommentToken" | "InvalidEscapeCharacter" | "InvalidNumberFormat" | "InvalidSymbol" | "InvalidUnicode" | "PropertyNameExpected" | "UnexpectedEndOfComment" | "UnexpectedEndOfNumber" | "UnexpectedEndOfString" | "ValueExpected";
|
|
377
|
+
} & {
|
|
378
|
+
readonly length: number;
|
|
379
|
+
} & {
|
|
380
|
+
readonly message: string;
|
|
381
|
+
} & {
|
|
382
|
+
readonly offset: number;
|
|
383
|
+
} & {
|
|
384
|
+
readonly startCharacter: number;
|
|
385
|
+
} & {
|
|
386
|
+
readonly startLine: number;
|
|
387
|
+
}, {}, {}>;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Options controlling JSONC parse behavior.
|
|
391
|
+
*/
|
|
392
|
+
export declare class JsoncParseOptions extends JsoncParseOptions_base {
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
declare const JsoncParseOptions_base: Schema.Class<JsoncParseOptions, {
|
|
396
|
+
disallowComments: Schema.optionalWith<typeof Schema.Boolean, {
|
|
397
|
+
default: () => false;
|
|
398
|
+
}>;
|
|
399
|
+
allowTrailingComma: Schema.optionalWith<typeof Schema.Boolean, {
|
|
400
|
+
default: () => true;
|
|
401
|
+
}>;
|
|
402
|
+
allowEmptyContent: Schema.optionalWith<typeof Schema.Boolean, {
|
|
403
|
+
default: () => false;
|
|
404
|
+
}>;
|
|
405
|
+
}, Schema.Struct.Encoded<{
|
|
406
|
+
disallowComments: Schema.optionalWith<typeof Schema.Boolean, {
|
|
407
|
+
default: () => false;
|
|
408
|
+
}>;
|
|
409
|
+
allowTrailingComma: Schema.optionalWith<typeof Schema.Boolean, {
|
|
410
|
+
default: () => true;
|
|
411
|
+
}>;
|
|
412
|
+
allowEmptyContent: Schema.optionalWith<typeof Schema.Boolean, {
|
|
413
|
+
default: () => false;
|
|
414
|
+
}>;
|
|
415
|
+
}>, never, {
|
|
416
|
+
readonly allowEmptyContent?: boolean;
|
|
417
|
+
} & {
|
|
418
|
+
readonly allowTrailingComma?: boolean;
|
|
419
|
+
} & {
|
|
420
|
+
readonly disallowComments?: boolean;
|
|
421
|
+
}, {}, {}>;
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* A path to a location in a JSONC document.
|
|
425
|
+
*/
|
|
426
|
+
export declare const JsoncPath: Schema.Array$<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
|
|
427
|
+
|
|
428
|
+
export declare type JsoncPath = Schema.Schema.Type<typeof JsoncPath>;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* A range within a JSONC document.
|
|
432
|
+
*/
|
|
433
|
+
export declare class JsoncRange extends JsoncRange_base {
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
declare const JsoncRange_base: Schema.Class<JsoncRange, {
|
|
437
|
+
offset: typeof Schema.Number;
|
|
438
|
+
length: typeof Schema.Number;
|
|
439
|
+
}, Schema.Struct.Encoded<{
|
|
440
|
+
offset: typeof Schema.Number;
|
|
441
|
+
length: typeof Schema.Number;
|
|
442
|
+
}>, never, {
|
|
443
|
+
readonly length: number;
|
|
444
|
+
} & {
|
|
445
|
+
readonly offset: number;
|
|
446
|
+
}, {}, {}>;
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Scan error codes produced by the scanner.
|
|
450
|
+
*/
|
|
451
|
+
export declare const JsoncScanError: Schema.Literal<["None", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter", "InvalidSymbol"]>;
|
|
452
|
+
|
|
453
|
+
export declare type JsoncScanError = Schema.Schema.Type<typeof JsoncScanError>;
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* JSONC Scanner interface — a stateful cursor over input text.
|
|
457
|
+
*/
|
|
458
|
+
export declare interface JsoncScanner {
|
|
459
|
+
/** Advance to the next token and return its kind */
|
|
460
|
+
scan(): JsoncSyntaxKind;
|
|
461
|
+
/** Get the current token kind */
|
|
462
|
+
getToken(): JsoncSyntaxKind;
|
|
463
|
+
/** Get the string value of the current token */
|
|
464
|
+
getTokenValue(): string;
|
|
465
|
+
/** Get the character offset of the current token */
|
|
466
|
+
getTokenOffset(): number;
|
|
467
|
+
/** Get the length of the current token */
|
|
468
|
+
getTokenLength(): number;
|
|
469
|
+
/** Get the line number of the current token start */
|
|
470
|
+
getTokenStartLine(): number;
|
|
471
|
+
/** Get the character position within the line */
|
|
472
|
+
getTokenStartCharacter(): number;
|
|
473
|
+
/** Get the scan error for the current token */
|
|
474
|
+
getTokenError(): JsoncScanError;
|
|
475
|
+
/** Get the current scanner position */
|
|
476
|
+
getPosition(): number;
|
|
477
|
+
/** Set the scanner position */
|
|
478
|
+
setPosition(pos: number): void;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* A path segment: string for object keys, number for array indices.
|
|
483
|
+
*/
|
|
484
|
+
export declare const JsoncSegment: Schema.Union<[typeof Schema.String, typeof Schema.Number]>;
|
|
485
|
+
|
|
486
|
+
export declare type JsoncSegment = Schema.Schema.Type<typeof JsoncSegment>;
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Token types produced by the JSONC scanner.
|
|
490
|
+
* Uses string literals instead of numeric enums for self-documenting debug output.
|
|
491
|
+
*/
|
|
492
|
+
export declare const JsoncSyntaxKind: Schema.Literal<["OpenBrace", "CloseBrace", "OpenBracket", "CloseBracket", "Comma", "Colon", "Null", "True", "False", "String", "Number", "LineComment", "BlockComment", "LineBreak", "Trivia", "Unknown", "EOF"]>;
|
|
493
|
+
|
|
494
|
+
export declare type JsoncSyntaxKind = Schema.Schema.Type<typeof JsoncSyntaxKind>;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* A single token produced by the JSONC scanner.
|
|
498
|
+
*/
|
|
499
|
+
export declare class JsoncToken extends JsoncToken_base {
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
declare const JsoncToken_base: Schema.Class<JsoncToken, {
|
|
503
|
+
kind: Schema.Literal<["OpenBrace", "CloseBrace", "OpenBracket", "CloseBracket", "Comma", "Colon", "Null", "True", "False", "String", "Number", "LineComment", "BlockComment", "LineBreak", "Trivia", "Unknown", "EOF"]>;
|
|
504
|
+
value: typeof Schema.String;
|
|
505
|
+
offset: typeof Schema.Number;
|
|
506
|
+
length: typeof Schema.Number;
|
|
507
|
+
startLine: typeof Schema.Number;
|
|
508
|
+
startCharacter: typeof Schema.Number;
|
|
509
|
+
error: Schema.Literal<["None", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter", "InvalidSymbol"]>;
|
|
510
|
+
}, Schema.Struct.Encoded<{
|
|
511
|
+
kind: Schema.Literal<["OpenBrace", "CloseBrace", "OpenBracket", "CloseBracket", "Comma", "Colon", "Null", "True", "False", "String", "Number", "LineComment", "BlockComment", "LineBreak", "Trivia", "Unknown", "EOF"]>;
|
|
512
|
+
value: typeof Schema.String;
|
|
513
|
+
offset: typeof Schema.Number;
|
|
514
|
+
length: typeof Schema.Number;
|
|
515
|
+
startLine: typeof Schema.Number;
|
|
516
|
+
startCharacter: typeof Schema.Number;
|
|
517
|
+
error: Schema.Literal<["None", "UnexpectedEndOfComment", "UnexpectedEndOfString", "UnexpectedEndOfNumber", "InvalidUnicode", "InvalidEscapeCharacter", "InvalidCharacter", "InvalidSymbol"]>;
|
|
518
|
+
}>, never, {
|
|
519
|
+
readonly error: "InvalidCharacter" | "InvalidEscapeCharacter" | "InvalidSymbol" | "InvalidUnicode" | "None" | "UnexpectedEndOfComment" | "UnexpectedEndOfNumber" | "UnexpectedEndOfString";
|
|
520
|
+
} & {
|
|
521
|
+
readonly kind: "BlockComment" | "CloseBrace" | "CloseBracket" | "Colon" | "Comma" | "EOF" | "False" | "LineBreak" | "LineComment" | "Null" | "Number" | "OpenBrace" | "OpenBracket" | "String" | "Trivia" | "True" | "Unknown";
|
|
522
|
+
} & {
|
|
523
|
+
readonly length: number;
|
|
524
|
+
} & {
|
|
525
|
+
readonly offset: number;
|
|
526
|
+
} & {
|
|
527
|
+
readonly startCharacter: number;
|
|
528
|
+
} & {
|
|
529
|
+
readonly startLine: number;
|
|
530
|
+
} & {
|
|
531
|
+
readonly value: string;
|
|
532
|
+
}, {}, {}>;
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Discriminated union of JSONC visitor events.
|
|
536
|
+
*/
|
|
537
|
+
export declare type JsoncVisitorEvent = {
|
|
538
|
+
readonly _tag: "ObjectBegin";
|
|
539
|
+
readonly offset: number;
|
|
540
|
+
readonly length: number;
|
|
541
|
+
readonly path: ReadonlyArray<string | number>;
|
|
542
|
+
} | {
|
|
543
|
+
readonly _tag: "ObjectEnd";
|
|
544
|
+
readonly offset: number;
|
|
545
|
+
readonly length: number;
|
|
546
|
+
} | {
|
|
547
|
+
readonly _tag: "ObjectProperty";
|
|
548
|
+
readonly property: string;
|
|
549
|
+
readonly offset: number;
|
|
550
|
+
readonly length: number;
|
|
551
|
+
readonly path: ReadonlyArray<string | number>;
|
|
552
|
+
} | {
|
|
553
|
+
readonly _tag: "ArrayBegin";
|
|
554
|
+
readonly offset: number;
|
|
555
|
+
readonly length: number;
|
|
556
|
+
readonly path: ReadonlyArray<string | number>;
|
|
557
|
+
} | {
|
|
558
|
+
readonly _tag: "ArrayEnd";
|
|
559
|
+
readonly offset: number;
|
|
560
|
+
readonly length: number;
|
|
561
|
+
} | {
|
|
562
|
+
readonly _tag: "LiteralValue";
|
|
563
|
+
readonly value: unknown;
|
|
564
|
+
readonly offset: number;
|
|
565
|
+
readonly length: number;
|
|
566
|
+
readonly path: ReadonlyArray<string | number>;
|
|
567
|
+
} | {
|
|
568
|
+
readonly _tag: "Separator";
|
|
569
|
+
readonly character: string;
|
|
570
|
+
readonly offset: number;
|
|
571
|
+
readonly length: number;
|
|
572
|
+
} | {
|
|
573
|
+
readonly _tag: "Comment";
|
|
574
|
+
readonly offset: number;
|
|
575
|
+
readonly length: number;
|
|
576
|
+
} | {
|
|
577
|
+
readonly _tag: "Error";
|
|
578
|
+
readonly code: JsoncParseErrorCode;
|
|
579
|
+
readonly offset: number;
|
|
580
|
+
readonly length: number;
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Create a JSONC-to-unknown Schema with custom parse options.
|
|
585
|
+
*
|
|
586
|
+
* @remarks
|
|
587
|
+
* The encode direction uses `JSON.stringify` which produces standard
|
|
588
|
+
* JSON. Comments present in the original JSONC input are not preserved
|
|
589
|
+
* during round-trip encode/decode.
|
|
590
|
+
*
|
|
591
|
+
* @example
|
|
592
|
+
* ```typescript
|
|
593
|
+
* import { makeJsoncFromString } from "jsonc-effect"
|
|
594
|
+
*
|
|
595
|
+
* // Strict mode: no comments allowed
|
|
596
|
+
* const StrictJsoncFromString = makeJsoncFromString({
|
|
597
|
+
* disallowComments: true,
|
|
598
|
+
* allowTrailingComma: false,
|
|
599
|
+
* })
|
|
600
|
+
* ```
|
|
601
|
+
*/
|
|
602
|
+
export declare function makeJsoncFromString(options?: Partial<JsoncParseOptions>): Schema.Schema<unknown, string>;
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Create a composed Schema that parses JSONC and validates against
|
|
606
|
+
* a target schema in one step.
|
|
607
|
+
*
|
|
608
|
+
* @example
|
|
609
|
+
* ```typescript
|
|
610
|
+
* import { Schema } from "effect"
|
|
611
|
+
* import { makeJsoncSchema } from "jsonc-effect"
|
|
612
|
+
*
|
|
613
|
+
* const MyConfig = Schema.Struct({
|
|
614
|
+
* name: Schema.String,
|
|
615
|
+
* version: Schema.Number,
|
|
616
|
+
* })
|
|
617
|
+
*
|
|
618
|
+
* const MyConfigFromJsonc = makeJsoncSchema(MyConfig)
|
|
619
|
+
* const config = Schema.decodeUnknownSync(MyConfigFromJsonc)(jsoncText)
|
|
620
|
+
* ```
|
|
621
|
+
*/
|
|
622
|
+
export declare const makeJsoncSchema: <A, I>(targetSchema: Schema.Schema<A, I, never>, options?: Partial<JsoncParseOptions> | undefined) => Schema.Schema<A, string, never>;
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Compute edits to insert, replace, or remove a value at a JSON path.
|
|
626
|
+
* Setting value to undefined removes the property/element.
|
|
627
|
+
*
|
|
628
|
+
* @example
|
|
629
|
+
* ```ts
|
|
630
|
+
* import { Effect, pipe } from "effect";
|
|
631
|
+
* import { modify, applyEdits } from "@spencerbeggs/jsonc-effect";
|
|
632
|
+
*
|
|
633
|
+
* // Data-first
|
|
634
|
+
* const edits = Effect.runSync(modify('{ "a": 1 }', ["a"], 2));
|
|
635
|
+
*
|
|
636
|
+
* // Data-last (pipeline)
|
|
637
|
+
* const result = pipe(
|
|
638
|
+
* '{ "a": 1 }',
|
|
639
|
+
* modify(["a"], 2),
|
|
640
|
+
* Effect.flatMap((edits) => applyEdits('{ "a": 1 }', edits)),
|
|
641
|
+
* Effect.runSync,
|
|
642
|
+
* );
|
|
643
|
+
* ```
|
|
644
|
+
*/
|
|
645
|
+
export declare const modify: {
|
|
646
|
+
(path: JsoncPath, value: unknown, options?: {
|
|
647
|
+
formattingOptions?: Partial<JsoncFormattingOptions>;
|
|
648
|
+
}): (text: string) => Effect.Effect<ReadonlyArray<JsoncEdit>, JsoncModificationError>;
|
|
649
|
+
(text: string, path: JsoncPath, value: unknown, options?: {
|
|
650
|
+
formattingOptions?: Partial<JsoncFormattingOptions>;
|
|
651
|
+
}): Effect.Effect<ReadonlyArray<JsoncEdit>, JsoncModificationError>;
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Parse a JSONC string into a JavaScript value.
|
|
656
|
+
*
|
|
657
|
+
* @param text - The JSONC string to parse
|
|
658
|
+
* @param options - Optional parse options
|
|
659
|
+
* @returns An Effect that produces the parsed value or fails with JsoncParseError
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```ts
|
|
663
|
+
* import { Effect } from "effect";
|
|
664
|
+
* import { parse } from "@spencerbeggs/jsonc-effect";
|
|
665
|
+
*
|
|
666
|
+
* // Basic usage
|
|
667
|
+
* const value = Effect.runSync(parse('{ "key": 42 }'));
|
|
668
|
+
*
|
|
669
|
+
* // With options
|
|
670
|
+
* const strict = Effect.runSync(parse('{ "key": 42 }', { disallowComments: true }));
|
|
671
|
+
* ```
|
|
672
|
+
*/
|
|
673
|
+
export declare const parse: {
|
|
674
|
+
(text: string): Effect.Effect<unknown, JsoncParseError>;
|
|
675
|
+
(text: string, options: Partial<JsoncParseOptions>): Effect.Effect<unknown, JsoncParseError>;
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Parse a JSONC string into an AST.
|
|
680
|
+
*
|
|
681
|
+
* @param text - The JSONC string to parse
|
|
682
|
+
* @param options - Optional parse options
|
|
683
|
+
* @returns An Effect that produces Option.some(node) or Option.none() for empty content
|
|
684
|
+
*
|
|
685
|
+
* @example
|
|
686
|
+
* ```ts
|
|
687
|
+
* import { Effect, Option } from "effect";
|
|
688
|
+
* import { parseTree } from "@spencerbeggs/jsonc-effect";
|
|
689
|
+
*
|
|
690
|
+
* const result = Effect.runSync(parseTree('{ "a": 1 }'));
|
|
691
|
+
* if (Option.isSome(result)) {
|
|
692
|
+
* console.log(result.value.type); // "object"
|
|
693
|
+
* }
|
|
694
|
+
* ```
|
|
695
|
+
*/
|
|
696
|
+
export declare const parseTree: {
|
|
697
|
+
(text: string): Effect.Effect<Option.Option<JsoncNode>, JsoncParseError>;
|
|
698
|
+
(text: string, options: Partial<JsoncParseOptions>): Effect.Effect<Option.Option<JsoncNode>, JsoncParseError>;
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Remove all comments from JSONC text, producing valid JSON.
|
|
703
|
+
*
|
|
704
|
+
* @param text - The JSONC string to strip comments from
|
|
705
|
+
* @param replaceCh - Optional character to replace comments with (preserves offsets)
|
|
706
|
+
* @returns An Effect that produces the text with comments removed
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* ```ts
|
|
710
|
+
* import { Effect } from "effect";
|
|
711
|
+
* import { stripComments } from "@spencerbeggs/jsonc-effect";
|
|
712
|
+
*
|
|
713
|
+
* const json = Effect.runSync(stripComments('{ "a": 1 // comment\n}'));
|
|
714
|
+
* // '{ "a": 1 \n}'
|
|
715
|
+
* ```
|
|
716
|
+
*/
|
|
717
|
+
export declare const stripComments: {
|
|
718
|
+
(text: string): Effect.Effect<string>;
|
|
719
|
+
(text: string, replaceCh: string): Effect.Effect<string>;
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Create a Stream of visitor events from JSONC text.
|
|
724
|
+
*
|
|
725
|
+
* Uses a lazy generator internally — events are produced on demand
|
|
726
|
+
* as the stream is consumed, not pre-collected into memory.
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* ```ts
|
|
730
|
+
* import { Chunk, Effect, Stream } from "effect";
|
|
731
|
+
* import { visit } from "@spencerbeggs/jsonc-effect";
|
|
732
|
+
*
|
|
733
|
+
* // Collect all events
|
|
734
|
+
* const all = Effect.runSync(
|
|
735
|
+
* visit('{ "a": 1 }').pipe(Stream.runCollect, Effect.map(Chunk.toReadonlyArray)),
|
|
736
|
+
* );
|
|
737
|
+
*
|
|
738
|
+
* // Take only the first 3 events (lazy — won't scan entire document)
|
|
739
|
+
* const first3 = Effect.runSync(
|
|
740
|
+
* visit(largeDoc).pipe(Stream.take(3), Stream.runCollect, Effect.map(Chunk.toReadonlyArray)),
|
|
741
|
+
* );
|
|
742
|
+
* ```
|
|
743
|
+
*/
|
|
744
|
+
export declare const visit: (text: string, options?: Partial<JsoncParseOptions> | undefined) => Stream.Stream<JsoncVisitorEvent, never, never>;
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Visit JSONC text and collect all events matching a predicate.
|
|
748
|
+
*/
|
|
749
|
+
export declare const visitCollect: <A extends JsoncVisitorEvent>(text: string, predicate: (event: JsoncVisitorEvent) => event is A, options?: Partial<JsoncParseOptions> | undefined) => Effect.Effect<readonly A[], never, never>;
|
|
750
|
+
|
|
751
|
+
export { }
|