0
# Schema & Configuration
1
2
Extensible schema system with YAML 1.1 and 1.2 support, custom tag definitions, and comprehensive configuration options for parsing, stringifying, and document handling. This provides complete control over YAML processing behavior and output formatting.
3
4
## Capabilities
5
6
### Schema System
7
8
The Schema class manages YAML type definitions, tag handlers, and version-specific behaviors.
9
10
```typescript { .api }
11
class Schema {
12
/** Schema name identifier */
13
name: string;
14
15
/** Supported YAML version */
16
version: '1.1' | '1.2' | 'next';
17
18
/** Schema tags collection */
19
tags: readonly Tag[];
20
21
/**
22
* Create schema with options
23
* @param options - Schema configuration options
24
*/
25
constructor(options: SchemaOptions);
26
27
/**
28
* Create deep clone of schema
29
* @returns Cloned schema instance
30
*/
31
clone(): Schema;
32
33
/**
34
* Get tag by name or class
35
* @param name - Tag name or constructor
36
* @returns Tag definition or undefined
37
*/
38
getTag(name: string | { new(...args: any[]): any }): Tag | undefined;
39
}
40
41
interface SchemaOptions {
42
/** YAML version to support */
43
version?: '1.1' | '1.2' | 'next';
44
45
/** Built-in schema to extend */
46
schema?: 'core' | 'failsafe' | 'json' | 'yaml-1.1';
47
48
/** Additional custom tags */
49
customTags?: (TagId | Tag)[];
50
51
/** Map entry sorting function */
52
sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
53
54
/** Merge key handling */
55
merge?: boolean;
56
57
/** Resolve unknown tags */
58
resolveUnknownTags?: boolean;
59
}
60
```
61
62
**Usage Examples:**
63
64
```typescript
65
import { Schema, parseDocument, stringify } from "yaml";
66
67
// Create custom schema
68
const customSchema = new Schema({
69
version: '1.2',
70
schema: 'core',
71
customTags: [
72
{
73
tag: '!date',
74
resolve: (str) => new Date(str),
75
stringify: (date) => date.toISOString().split('T')[0]
76
},
77
{
78
tag: '!env',
79
resolve: (str) => process.env[str] || '',
80
stringify: (value) => `\${${value}}`
81
}
82
],
83
sortMapEntries: true
84
});
85
86
// Use schema in parsing
87
const doc = parseDocument(`
88
created: !date 2023-12-01
89
api_key: !env API_KEY
90
config:
91
timeout: 30
92
retries: 3
93
`, { schema: customSchema });
94
95
console.log(doc.toJS());
96
// Result: { created: Date(2023-12-01), api_key: 'actual-env-value', config: {...} }
97
98
// Clone and modify schema
99
const extendedSchema = customSchema.clone();
100
// Add more custom tags to extendedSchema
101
```
102
103
### Built-in Schemas
104
105
The library provides several built-in schemas for different YAML specifications and use cases.
106
107
```typescript { .api }
108
// Built-in schema types
109
type BuiltinSchema = 'core' | 'failsafe' | 'json' | 'yaml-1.1';
110
111
/**
112
* Get built-in schema by name
113
* - 'failsafe': Basic YAML types only (strings, sequences, mappings)
114
* - 'json': JSON-compatible types (null, boolean, number, string, array, object)
115
* - 'core': YAML 1.2 core schema with common types
116
* - 'yaml-1.1': YAML 1.1 schema with extended types
117
*/
118
```
119
120
**Usage Examples:**
121
122
```typescript
123
import { parseDocument, stringify } from "yaml";
124
125
// JSON-compatible parsing
126
const jsonDoc = parseDocument(`
127
number: 42
128
boolean: true
129
null_value: null
130
array: [1, 2, 3]
131
object: {key: value}
132
`, { schema: 'json' });
133
134
// YAML 1.1 with extended types
135
const yaml11Doc = parseDocument(`
136
timestamp: 2023-12-01 10:30:00
137
binary: !!binary |
138
R0lGODlhDAAMAIQAAP//9/X17unM
139
octal: 0o755
140
set: !!set
141
? item1
142
? item2
143
? item3
144
ordered_map: !!omap
145
- key1: value1
146
- key2: value2
147
`, { schema: 'yaml-1.1' });
148
149
// Core schema (default for YAML 1.2)
150
const coreDoc = parseDocument(`
151
string: hello world
152
integer: 42
153
float: 3.14159
154
boolean: true
155
null_value: null
156
timestamp: 2023-12-01T10:30:00Z
157
`, { schema: 'core' });
158
```
159
160
### Parsing Options
161
162
Comprehensive options for controlling YAML parsing behavior.
163
164
```typescript { .api }
165
interface ParseOptions {
166
/** Keep CST (Concrete Syntax Tree) nodes in parsed output */
167
keepCstNodes?: boolean;
168
169
/** Keep node type information in output */
170
keepNodeTypes?: boolean;
171
172
/** Keep Uint8Array instances in JSON output instead of converting */
173
keepBlobsInJSON?: boolean;
174
175
/** Maximum number of alias nodes to resolve (prevents circular references) */
176
maxAliasCount?: number;
177
178
/** Add line/column position info to error messages */
179
prettyErrors?: boolean;
180
181
/** Line position tracker for error reporting */
182
lineCounter?: LineCounter | boolean;
183
184
/** Log level for parsing messages */
185
logLevel?: LogLevelId;
186
187
/** Enable strict parsing mode */
188
strict?: boolean;
189
190
/** Unique key requirement in mappings */
191
uniqueKeys?: boolean;
192
193
/** Version of YAML specification to follow */
194
version?: '1.1' | '1.2' | 'next';
195
}
196
```
197
198
### Document Options
199
200
Options for document-level configuration and behavior.
201
202
```typescript { .api }
203
interface DocumentOptions {
204
/** Anchor prefix for generated anchors */
205
anchorPrefix?: string;
206
207
/** Keep undefined values in output */
208
keepUndefined?: boolean;
209
210
/** Log level for document operations */
211
logLevel?: LogLevelId;
212
213
/** Document version */
214
version?: '1.1' | '1.2' | 'next';
215
216
/** Enable merge key support (<<) */
217
merge?: boolean;
218
219
/** Transform document before conversion */
220
reviver?: Reviver;
221
222
/** Transform document during creation */
223
replacer?: Replacer;
224
225
/** Schema to use for document */
226
schema?: BuiltinSchema;
227
228
/** Custom tags to include */
229
customTags?: (TagId | Tag)[];
230
231
/** Sort map entries */
232
sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
233
234
/** Convert maps with numeric keys to arrays */
235
mapAsMap?: boolean;
236
237
/** Maximum key length allowed */
238
maxAliasCount?: number;
239
}
240
241
type Reviver = (this: unknown, key: unknown, value: unknown) => unknown;
242
type Replacer = (this: unknown, key: string, value: unknown) => unknown | Array<string | number>;
243
```
244
245
### String Output Options
246
247
Extensive formatting options for controlling YAML string output.
248
249
```typescript { .api }
250
interface ToStringOptions {
251
/** Use block quote style for multiline strings */
252
blockQuote?: boolean | 'folded' | 'literal';
253
254
/** Default type for object keys */
255
defaultKeyType?: Scalar.Type | null;
256
257
/** Default string representation type */
258
defaultStringType?: Scalar.Type;
259
260
/** Include document directives (%YAML, %TAG) */
261
directives?: boolean | null;
262
263
/** Number of spaces for indentation */
264
indent?: number;
265
266
/** Use block style for sequences */
267
indentSeq?: boolean | null;
268
269
/** Maximum line width before folding */
270
lineWidth?: number;
271
272
/** Minimum content width for single-line collections */
273
minContentWidth?: number;
274
275
/** String representation for null values */
276
nullStr?: string;
277
278
/** Use single quotes by default for strings */
279
singleQuote?: boolean | null;
280
281
/** Document end marker */
282
docEnd?: boolean;
283
284
/** Document start marker */
285
docStart?: boolean;
286
287
/** Comments to preserve */
288
commentString?: (comment: string) => string;
289
290
/** Force explicit keys for flow maps */
291
flowCollectionPadding?: boolean;
292
293
/** Fold options for long lines */
294
foldOptions?: FoldOptions;
295
}
296
297
interface FoldOptions {
298
/** Characters that must not be at line end */
299
lineWidth?: number;
300
/** Minimum content width */
301
minContentWidth?: number;
302
/** Handle content with indicators */
303
indicatorWidth?: number;
304
}
305
```
306
307
**Usage Examples:**
308
309
```typescript
310
import { stringify, parseDocument } from "yaml";
311
312
const data = {
313
title: "Configuration File",
314
description: "This is a very long description that should be folded across multiple lines when converted to YAML format for better readability",
315
servers: [
316
{ name: "server1", host: "192.168.1.100", port: 8080 },
317
{ name: "server2", host: "192.168.1.101", port: 8080 }
318
],
319
settings: {
320
timeout: 30,
321
debug: true,
322
feature_flags: ["auth", "logging", "monitoring"]
323
}
324
};
325
326
// Basic formatting
327
const basic = stringify(data);
328
329
// Custom formatting options
330
const formatted = stringify(data, {
331
indent: 4, // 4-space indentation
332
lineWidth: 80, // Maximum line width
333
blockQuote: 'folded', // Fold long strings
334
singleQuote: true, // Use single quotes
335
defaultStringType: 'QUOTE_SINGLE',
336
indentSeq: false, // Sequences at same level as parent
337
directives: true, // Include YAML directives
338
docStart: true, // Include document start marker
339
nullStr: '~' // Represent null as ~
340
});
341
342
console.log(formatted);
343
// Output:
344
// %YAML 1.2
345
// ---
346
// title: 'Configuration File'
347
// description: >-
348
// This is a very long description that should be folded across multiple
349
// lines when converted to YAML format for better readability
350
// servers:
351
// - name: 'server1'
352
// host: '192.168.1.100'
353
// port: 8080
354
// - name: 'server2'
355
// host: '192.168.1.101'
356
// port: 8080
357
// settings:
358
// timeout: 30
359
// debug: true
360
// feature_flags: ['auth', 'logging', 'monitoring']
361
```
362
363
### JavaScript Conversion Options
364
365
Options for converting YAML to JavaScript objects.
366
367
```typescript { .api }
368
interface ToJSOptions {
369
/** Reviver function for transforming values */
370
reviver?: Reviver;
371
372
/** Convert Map objects to plain objects */
373
mapAsMap?: boolean;
374
375
/** Maximum alias count during resolution */
376
maxAliasCount?: number;
377
378
/** Keep original node objects */
379
keepScalar?: boolean;
380
381
/** Callback for handling unknown tags */
382
onAnchor?: (value: unknown, count: number) => void;
383
384
/** Called when resolving unknown tags */
385
onTaggedValue?: (value: unknown) => unknown;
386
}
387
```
388
389
### Node Creation Options
390
391
Options for creating AST nodes from JavaScript values.
392
393
```typescript { .api }
394
interface CreateNodeOptions {
395
/** Anchor prefix for generated anchors */
396
anchorPrefix?: string;
397
398
/** Keep undefined values */
399
keepUndefined?: boolean;
400
401
/** Use flow style for collections */
402
flow?: boolean;
403
404
/** Map key comparison function */
405
compareKeys?: (a: unknown, b: unknown) => number;
406
407
/** Sort map entries */
408
sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
409
410
/** Tag name for the created node */
411
tag?: string;
412
413
/** Wrap scalars in Scalar objects */
414
wrapScalars?: boolean;
415
}
416
```
417
418
**Usage Examples:**
419
420
```typescript
421
import { parseDocument, stringify } from "yaml";
422
423
// Advanced parsing configuration
424
const doc = parseDocument(yamlSource, {
425
// Parsing options
426
prettyErrors: true,
427
lineCounter: true,
428
maxAliasCount: 100,
429
keepCstNodes: false,
430
431
// Document options
432
version: '1.2',
433
schema: 'core',
434
merge: true,
435
sortMapEntries: true,
436
keepUndefined: false,
437
438
// Schema options
439
customTags: [
440
{
441
tag: '!include',
442
resolve: (str) => require('fs').readFileSync(str, 'utf8')
443
}
444
]
445
});
446
447
// Advanced stringification
448
const yamlString = stringify(data, {
449
// String options
450
indent: 2,
451
lineWidth: 120,
452
blockQuote: 'literal',
453
singleQuote: false,
454
directives: true,
455
docStart: true,
456
docEnd: true,
457
458
// Document options
459
version: '1.2',
460
sortMapEntries: (a, b) => a.key < b.key ? -1 : 1,
461
462
// Creation options
463
flow: false,
464
anchorPrefix: 'ref'
465
});
466
467
// JavaScript conversion with options
468
const jsData = doc.toJS({
469
reviver: (key, value) => {
470
// Transform dates
471
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
472
return new Date(value);
473
}
474
return value;
475
},
476
mapAsMap: false,
477
maxAliasCount: 50
478
});
479
```
480
481
## Custom Tags
482
483
Define custom YAML tags for specialized data types and processing.
484
485
```typescript { .api }
486
interface Tag {
487
/** Tag name (e.g., '!!str', '!custom') */
488
tag: string;
489
490
/** Function to resolve tag value from string */
491
resolve?: (str: string, onError?: (msg: string) => void) => any;
492
493
/** Function to stringify value back to YAML */
494
stringify?: (item: any, ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void) => string;
495
496
/** Test if value should use this tag */
497
identify?: (value: any) => boolean;
498
499
/** Default type for scalars */
500
default?: boolean;
501
502
/** Tag class (for collection tags) */
503
class?: 'scalar' | 'seq' | 'map';
504
505
/** Format hint */
506
format?: string;
507
508
/** Test function for string format */
509
test?: RegExp | ((str: string) => boolean);
510
}
511
512
type TagId =
513
| 'binary' | 'bool' | 'float' | 'int' | 'null' | 'omap' | 'pairs'
514
| 'set' | 'str' | 'timestamp' | 'yaml';
515
```
516
517
**Usage Examples:**
518
519
```typescript
520
import { parseDocument, stringify, Schema } from "yaml";
521
522
// Define custom tags
523
const customTags = [
524
// Custom date tag
525
{
526
tag: '!date',
527
test: /^\d{4}-\d{2}-\d{2}$/,
528
resolve: (str) => new Date(str + 'T00:00:00Z'),
529
stringify: (date) => date.toISOString().split('T')[0]
530
},
531
532
// Environment variable tag
533
{
534
tag: '!env',
535
resolve: (str) => process.env[str] || '',
536
stringify: (value) => `\${${value}}`
537
},
538
539
// Base64 encoded data
540
{
541
tag: '!base64',
542
resolve: (str) => Buffer.from(str, 'base64'),
543
stringify: (buffer) => buffer.toString('base64')
544
}
545
];
546
547
// Use custom tags
548
const doc = parseDocument(`
549
created: !date 2023-12-01
550
api_key: !env API_SECRET_KEY
551
logo: !base64 iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==
552
`, { customTags });
553
554
console.log(doc.toJS());
555
// Result: {
556
// created: Date('2023-12-01T00:00:00.000Z'),
557
// api_key: 'actual-secret-value',
558
// logo: Buffer<...>
559
// }
560
561
// Stringify with custom tags
562
const output = stringify({
563
created: new Date('2023-12-01'),
564
data: Buffer.from('hello world', 'utf8')
565
}, { customTags });
566
567
console.log(output);
568
// created: !date 2023-12-01
569
// data: !base64 aGVsbG8gd29ybGQ=
570
```