@functional-examples/devkit 0.0.0-alpha.1

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.
Files changed (45) hide show
  1. package/dist/glob/glob.d.ts +34 -0
  2. package/dist/glob/glob.d.ts.map +1 -0
  3. package/dist/glob/glob.js +36 -0
  4. package/dist/glob/glob.js.map +1 -0
  5. package/dist/glob/index.d.ts +3 -0
  6. package/dist/glob/index.d.ts.map +1 -0
  7. package/dist/glob/index.js +3 -0
  8. package/dist/glob/index.js.map +1 -0
  9. package/dist/glob/match.d.ts +29 -0
  10. package/dist/glob/match.d.ts.map +1 -0
  11. package/dist/glob/match.js +50 -0
  12. package/dist/glob/match.js.map +1 -0
  13. package/dist/index.d.ts +6 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/json/errors.d.ts +41 -0
  18. package/dist/json/errors.d.ts.map +1 -0
  19. package/dist/json/errors.js +102 -0
  20. package/dist/json/errors.js.map +1 -0
  21. package/dist/json/index.d.ts +3 -0
  22. package/dist/json/index.d.ts.map +1 -0
  23. package/dist/json/index.js +3 -0
  24. package/dist/json/index.js.map +1 -0
  25. package/dist/json/parse.d.ts +45 -0
  26. package/dist/json/parse.d.ts.map +1 -0
  27. package/dist/json/parse.js +122 -0
  28. package/dist/json/parse.js.map +1 -0
  29. package/dist/types/guards.d.ts +2 -0
  30. package/dist/types/guards.d.ts.map +1 -0
  31. package/dist/types/guards.js +2 -0
  32. package/dist/types/guards.js.map +1 -0
  33. package/dist/types/index.d.ts +463 -0
  34. package/dist/types/index.d.ts.map +1 -0
  35. package/dist/types/index.js +5 -0
  36. package/dist/types/index.js.map +1 -0
  37. package/dist/yaml/index.d.ts +2 -0
  38. package/dist/yaml/index.d.ts.map +1 -0
  39. package/dist/yaml/index.js +2 -0
  40. package/dist/yaml/index.js.map +1 -0
  41. package/dist/yaml/parse.d.ts +48 -0
  42. package/dist/yaml/parse.d.ts.map +1 -0
  43. package/dist/yaml/parse.js +84 -0
  44. package/dist/yaml/parse.js.map +1 -0
  45. package/package.json +77 -0
@@ -0,0 +1,463 @@
1
+ /**
2
+ * Core type definitions for functional-examples
3
+ */
4
+ import type { CLI } from 'cli-forge';
5
+ import type { Dirent } from 'node:fs';
6
+ /**
7
+ * A single validation error.
8
+ */
9
+ export interface ValidationError {
10
+ /** JSON path to the invalid value (e.g., "metadata.tags[0]") */
11
+ path: string;
12
+ /** Human-readable error message */
13
+ message: string;
14
+ }
15
+ /**
16
+ * Result of a validation operation.
17
+ */
18
+ export interface ValidationResult {
19
+ /** Whether validation passed */
20
+ success: boolean;
21
+ /** Validation errors (empty if success is true) */
22
+ errors: ValidationError[];
23
+ }
24
+ /**
25
+ * Base metadata that all examples should have.
26
+ * Used for type constraints when users want stricter typing.
27
+ */
28
+ export interface BaseMetadata {
29
+ /** Unique identifier for the example */
30
+ id: string;
31
+ /** Human-readable title */
32
+ title: string;
33
+ /** Description of what the example demonstrates */
34
+ description?: string;
35
+ }
36
+ /**
37
+ * Augmentable registry for example metadata typing.
38
+ *
39
+ * Run `functional-examples generate` to create a declaration file that
40
+ * augments this interface, providing type-safe metadata for your examples.
41
+ *
42
+ * @example Manual augmentation (or use `generate` command):
43
+ * ```typescript
44
+ * declare module '@functional-examples/devkit' {
45
+ * interface ExampleMetadataRegistry {
46
+ * metadata: {
47
+ * id: string;
48
+ * title: string;
49
+ * tags?: string[];
50
+ * };
51
+ * }
52
+ * }
53
+ * ```
54
+ */
55
+ export interface ExampleMetadataRegistry {
56
+ }
57
+ /**
58
+ * Resolved example metadata type.
59
+ *
60
+ * If `ExampleMetadataRegistry` has been augmented with a `metadata` property,
61
+ * this resolves to that type. Otherwise, falls back to `Record<string, unknown>`.
62
+ *
63
+ * This allows the `generate` command to provide project-specific types that
64
+ * automatically apply to all `Example` types without explicit generic parameters.
65
+ */
66
+ export type ExampleMetadata = ExampleMetadataRegistry extends {
67
+ metadata: infer T;
68
+ } ? T : Record<string, unknown>;
69
+ /**
70
+ * Parsed code region from #region markers.
71
+ */
72
+ export interface ParsedRegion {
73
+ /** Region identifier from #region <id> */
74
+ id: string;
75
+ /** Content between region markers (markers stripped) */
76
+ content: string;
77
+ /** Line number where #region marker appears (1-based) */
78
+ startLine: number;
79
+ /** Line number where #endregion marker appears (1-based) */
80
+ endLine: number;
81
+ }
82
+ /**
83
+ * A file within an example, with optional processed content.
84
+ */
85
+ export interface ExampleFile {
86
+ /** Absolute path to the file */
87
+ absolutePath: string;
88
+ /** Path relative to example root */
89
+ relativePath: string;
90
+ /** @deprecated Use absolutePath instead */
91
+ path?: string;
92
+ /** Raw file contents (may be lazy-loaded) */
93
+ raw?: string;
94
+ /** Parsed content with metadata/markers stripped */
95
+ parsed?: string;
96
+ /** Extracted code regions */
97
+ hunks?: ParsedRegion[];
98
+ }
99
+ /**
100
+ * A discovered example with metadata and files.
101
+ * This is the base type returned by extractors.
102
+ *
103
+ * Metadata is typed via `ExampleMetadata` by default, which can be augmented
104
+ * by running `functional-examples generate`. You can also pass an explicit
105
+ * generic parameter for custom typing.
106
+ */
107
+ export interface Example<TMetadata = ExampleMetadata> {
108
+ /** Unique identifier for this example */
109
+ id: string;
110
+ /** Human-readable title */
111
+ title: string;
112
+ /** Optional description */
113
+ description?: string;
114
+ /** Absolute path to the example root (file or directory) */
115
+ rootPath: string;
116
+ /** All files belonging to this example */
117
+ files: ExampleFile[];
118
+ /** Additional metadata (loosely typed unless user provides schema) */
119
+ metadata: TMetadata;
120
+ /** Which extractor produced this example */
121
+ extractorName: string;
122
+ }
123
+ /**
124
+ * An example after processing by the scanner.
125
+ * Includes computed fields like displayPath that are added during scanning.
126
+ */
127
+ export interface ScannedExample<TMetadata = ExampleMetadata> extends Example<TMetadata> {
128
+ /**
129
+ * Path relative to the config/scan root, useful for display in errors
130
+ * and snapshots (avoids machine-specific absolute paths).
131
+ */
132
+ displayPath: string;
133
+ }
134
+ /**
135
+ * Error encountered during extraction
136
+ */
137
+ export interface ExtractorError {
138
+ /** Path where error occurred */
139
+ path: string;
140
+ /** Error message */
141
+ message: string;
142
+ /** Original error if available */
143
+ cause?: Error;
144
+ }
145
+ /**
146
+ * Options passed to extractor during extraction
147
+ */
148
+ export interface ExtractorOptions {
149
+ /** Absolute path to the config root (for context/relative paths) */
150
+ rootPath: string;
151
+ /** Glob patterns to exclude (for internal filtering within directories) */
152
+ exclude?: string[];
153
+ /** Signal for cancellation */
154
+ signal?: AbortSignal;
155
+ }
156
+ /**
157
+ * Result from a candidate-based extractor
158
+ */
159
+ export interface ExtractorResult<TMetadata = Record<string, unknown>> {
160
+ /** All examples found by this extractor */
161
+ examples: Example<TMetadata>[];
162
+ /** Errors encountered during extraction */
163
+ errors: ExtractorError[];
164
+ /** Files claimed by this extractor (absolute paths, for conflict detection) */
165
+ claimedFiles: Set<string>;
166
+ }
167
+ /**
168
+ * Candidate-based extractor interface.
169
+ * Called with pre-filtered candidates (files and/or directories).
170
+ * Extractor decides which candidates it can handle.
171
+ */
172
+ export interface Extractor<TMetadata = Record<string, unknown>> {
173
+ /** Unique name for this extractor */
174
+ readonly name: string;
175
+ /**
176
+ * Extract examples from the provided candidates.
177
+ * Candidates are pre-filtered by include/exclude patterns.
178
+ *
179
+ * @param candidates - Dirent entries (files and/or directories) to consider
180
+ * @param options - Extraction options including rootPath for context
181
+ * @returns All examples found and files claimed
182
+ */
183
+ extract(candidates: Dirent[], options: ExtractorOptions): Promise<ExtractorResult<TMetadata>>;
184
+ }
185
+ /**
186
+ * Factory function to create an extractor with options
187
+ */
188
+ export type ExtractorFactory<TOptions = Record<string, unknown>, TMetadata = Record<string, unknown>> = (options?: TOptions) => Extractor<TMetadata>;
189
+ /**
190
+ * Context passed through the FileContentsParser pipeline.
191
+ * Each parser receives this, transforms it, and returns an updated version.
192
+ */
193
+ export interface FileParseContext {
194
+ /** Original file content, never modified */
195
+ raw: string;
196
+ /** Transformed content (frontmatter/markers stripped) */
197
+ parsed: string;
198
+ /** Extracted code regions (only explicit #region blocks) */
199
+ hunks: ParsedRegion[];
200
+ /** Metadata extracted by parsers */
201
+ metadata: Record<string, unknown>;
202
+ /** Absolute path to the file */
203
+ filePath: string;
204
+ }
205
+ /**
206
+ * Parser that processes file contents in a pipeline.
207
+ * Receives accumulated context, transforms it, returns updated context.
208
+ */
209
+ export interface FileContentsParser {
210
+ /** Unique parser name for debugging/logging */
211
+ readonly name: string;
212
+ /**
213
+ * Process file content and return updated context.
214
+ * @param context - Current accumulated parse context
215
+ * @returns Updated context (should not mutate input)
216
+ */
217
+ parse(context: FileParseContext): FileParseContext | Promise<FileParseContext>;
218
+ }
219
+ /**
220
+ * Schema definitions for a plugin (JSON Schema format).
221
+ * Used for IDE autocomplete and documentation generation.
222
+ */
223
+ export interface PluginSchemas {
224
+ /**
225
+ * JSON Schema for plugin options (passed to createPlugin()).
226
+ * Used to generate config file schema for IDE autocomplete.
227
+ */
228
+ options?: string;
229
+ /**
230
+ * JSON Schema for metadata this plugin produces or expects.
231
+ * Used for metadata.d.ts generation and documentation.
232
+ */
233
+ metadata?: string;
234
+ }
235
+ /**
236
+ * Validator functions for a plugin.
237
+ * Allows plugins to use any validation library (Zod, TypeBox, etc.)
238
+ */
239
+ export interface PluginValidators<TMetadata = Record<string, unknown>> {
240
+ /**
241
+ * Validates plugin options before extraction begins.
242
+ * Called during config resolution.
243
+ * @param options - The options passed to the plugin factory
244
+ */
245
+ options?: (options: unknown) => ValidationResult;
246
+ /**
247
+ * Validates extracted metadata after all extractors complete.
248
+ * Called for each example's metadata.
249
+ * @param metadata - The metadata from an extracted example
250
+ */
251
+ metadata?: (metadata: TMetadata) => ValidationResult;
252
+ }
253
+ /**
254
+ * Scan configuration options.
255
+ */
256
+ export interface ScanConfig {
257
+ /** Include patterns (applied after extraction) */
258
+ include?: string[];
259
+ /** Exclude patterns (applied after extraction) */
260
+ exclude?: string[];
261
+ /** Base Path for scan. Differs from `root` in that it only impacts scanning. */
262
+ root?: string;
263
+ }
264
+ /**
265
+ * Path-to-extractor mapping for conflict resolution.
266
+ */
267
+ export interface PathMapping {
268
+ /** Glob pattern for paths */
269
+ pattern: string;
270
+ /** Extractor name that wins for matching paths */
271
+ extractor: string;
272
+ }
273
+ /**
274
+ * Error from config validation.
275
+ */
276
+ export interface ConfigValidationError {
277
+ /** JSON path to the invalid value */
278
+ path: string;
279
+ /** Human-readable error message */
280
+ message: string;
281
+ /** Location code (e.g., Zod issue code) */
282
+ location?: string;
283
+ /** Suggested fix for the error */
284
+ fix?: string;
285
+ }
286
+ /**
287
+ * Wrapper for a plugin's validator function with plugin name context.
288
+ */
289
+ export interface PluginValidatorEntry<T = unknown> {
290
+ pluginName: string;
291
+ validate: (value: T) => ValidationResult;
292
+ }
293
+ /**
294
+ * Schema entry from a plugin with plugin name context.
295
+ */
296
+ export interface PluginSchemaEntry {
297
+ pluginName: string;
298
+ options?: string;
299
+ metadata?: string;
300
+ }
301
+ /**
302
+ * Plugin registry interface for accessing validators/schemas.
303
+ * Full implementation is in plugins/registry.ts.
304
+ */
305
+ export interface PluginRegistryInterface {
306
+ /** Register a plugin */
307
+ register(plugin: Plugin): void;
308
+ /** Get all registered plugins */
309
+ getPlugins(): readonly Plugin[];
310
+ /** Get plugins for a file extension */
311
+ getPluginsForExtension(extension: string): Plugin[];
312
+ /** Get all extractors from plugins */
313
+ getExtractors(): Extractor[];
314
+ /** Get parsers for a file extension */
315
+ getParsersForExtension(extension: string): FileContentsParser[];
316
+ /** Get all options validators */
317
+ getOptionsValidators(): PluginValidatorEntry<unknown>[];
318
+ /** Get all metadata validators */
319
+ getMetadataValidators(): PluginValidatorEntry[];
320
+ /** Get all schemas from plugins */
321
+ getSchemas(): PluginSchemaEntry[];
322
+ }
323
+ /**
324
+ * Reference to an extractor package (for config files)
325
+ */
326
+ export interface ExtractorConfig {
327
+ /** Package name */
328
+ name: string;
329
+ /** Module specifier (package name or path) */
330
+ module: string;
331
+ /** Options to pass to the extractor factory */
332
+ options?: Record<string, unknown>;
333
+ }
334
+ /**
335
+ * Extractor can be specified as string (package name) or full config
336
+ */
337
+ export type ExtractorReference = string | ExtractorConfig;
338
+ /**
339
+ * An extractor can be a reference (to load) or an instance
340
+ */
341
+ export type ExtractorConfigOrFunction<TMetadata = Record<string, unknown>> = ExtractorReference | Extractor<TMetadata>;
342
+ /**
343
+ * JSON Schema object for metadata validation.
344
+ * Subset of JSON Schema spec used for config files.
345
+ */
346
+ export interface JSONSchemaObject {
347
+ type?: string;
348
+ properties?: Record<string, JSONSchemaObject>;
349
+ required?: string[];
350
+ items?: JSONSchemaObject;
351
+ enum?: unknown[];
352
+ const?: unknown;
353
+ description?: string;
354
+ [key: string]: unknown;
355
+ }
356
+ /**
357
+ * Configuration for the generate command output.
358
+ */
359
+ export interface GenerateConfig {
360
+ /** Output directory for generated files (default: .functional-examples) */
361
+ outputDir?: string;
362
+ }
363
+ export interface Config<TMetadata = Record<string, unknown>> {
364
+ /** Plugins to use for scanning and parsing (recommended) */
365
+ plugins?: Plugin<TMetadata>[];
366
+ /** Scan options */
367
+ scan?: ScanConfig;
368
+ /** Path mappings for conflict resolution */
369
+ pathMappings?: PathMapping[];
370
+ /**
371
+ * JSON Schema defining the expected metadata structure for examples.
372
+ * This is the user's base metadata contract - all examples must conform to it.
373
+ * Overrides plugin metadata schemas on conflict.
374
+ *
375
+ * @example
376
+ * ```typescript
377
+ * metadata: {
378
+ * type: 'object',
379
+ * properties: {
380
+ * id: { type: 'string' },
381
+ * title: { type: 'string' },
382
+ * category: { type: 'string', enum: ['tutorial', 'recipe', 'reference'] },
383
+ * },
384
+ * required: ['id', 'title', 'category'],
385
+ * }
386
+ * ```
387
+ */
388
+ metadata?: JSONSchemaObject;
389
+ /** Configuration for schema/type generation */
390
+ generate?: GenerateConfig;
391
+ /**
392
+ * Root path used for scanning + more
393
+ */
394
+ root?: string;
395
+ }
396
+ /**
397
+ * Full configuration (alias for BaseConfig)
398
+ */
399
+ export type ConfigWithRoot<TMetadata = Record<string, unknown>> = Config<TMetadata> & {
400
+ root: string;
401
+ };
402
+ /**
403
+ * Resolved configuration with actual extractor instances.
404
+ * This is the runtime-ready configuration after all plugins are loaded.
405
+ */
406
+ export interface ResolvedConfig<TMetadata = Record<string, unknown>> extends ConfigWithRoot<TMetadata> {
407
+ /** Resolved extractor instances */
408
+ extractors: Extractor<TMetadata>[];
409
+ /** Resolved plugins */
410
+ plugins: Plugin<TMetadata>[];
411
+ /** Plugin registry for accessing validators/schemas */
412
+ registry: PluginRegistryInterface;
413
+ /** Path mappings for conflict resolution */
414
+ pathMappings: PathMapping[];
415
+ /** Scan configuration with defaults applied */
416
+ scan: Required<ScanConfig>;
417
+ /** Config validation errors (options validation failures) */
418
+ validationErrors: ConfigValidationError[];
419
+ /** Root Path of Config File */
420
+ root: string;
421
+ }
422
+ /**
423
+ * Plugin commands can be a static array or a function that receives
424
+ * the resolved config and returns commands (sync or async).
425
+ */
426
+ export type PluginCommands<TMetadata = Record<string, unknown>> = CLI[] | ((config: ResolvedConfig<TMetadata>) => CLI[] | Promise<CLI[]>);
427
+ /**
428
+ * Plugin containing optional extractors, parsers, schemas, and validators.
429
+ * Auto-registers for declared file extensions.
430
+ */
431
+ export interface Plugin<TMetadata = Record<string, unknown>> {
432
+ /** Unique plugin name */
433
+ readonly name: string;
434
+ /** File extensions this plugin handles (e.g., ['.ts', '.tsx', '.js', '.jsx']) */
435
+ readonly extensions?: string[];
436
+ /** Extractor that finds examples in a directory tree */
437
+ readonly extractor?: Extractor<TMetadata>;
438
+ /** Parser that processes file contents (runs in pipeline order) */
439
+ readonly fileContentsParser?: FileContentsParser;
440
+ /**
441
+ * JSON Schema definitions for IDE tooling.
442
+ * @see PluginSchemas
443
+ */
444
+ readonly schemas?: PluginSchemas;
445
+ /**
446
+ * Runtime validators for options and metadata.
447
+ * @see PluginValidators
448
+ */
449
+ readonly validators?: PluginValidators<TMetadata>;
450
+ /**
451
+ * CLI commands provided by this plugin.
452
+ * Can be static commands or a function that receives the resolved config.
453
+ * @see PluginCommands
454
+ */
455
+ readonly commands?: PluginCommands<TMetadata>;
456
+ /**
457
+ * Options passed to the plugin factory (for validation introspection).
458
+ * Plugin factories should set this to enable options validation.
459
+ * @internal
460
+ */
461
+ readonly _options?: unknown;
462
+ }
463
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core type definitions for functional-examples
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,2 @@
1
+ export { YamlParseError, parseYaml, tryParseYaml } from './parse.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/yaml/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { YamlParseError, parseYaml, tryParseYaml } from './parse.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/yaml/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Resets the cached import promise. Used for testing only.
3
+ * @internal
4
+ */
5
+ export declare function _resetYamlImportCache(): void;
6
+ /**
7
+ * Error thrown when YAML parsing fails.
8
+ * Includes optional position information for diagnostics.
9
+ */
10
+ export declare class YamlParseError extends Error {
11
+ readonly line?: number;
12
+ readonly column?: number;
13
+ readonly filePath?: string;
14
+ constructor(message: string, options?: {
15
+ line?: number;
16
+ column?: number;
17
+ filePath?: string;
18
+ });
19
+ }
20
+ /**
21
+ * Parse a YAML string into a typed value.
22
+ *
23
+ * Requires the `yaml` peer dependency to be installed.
24
+ *
25
+ * @param content - The YAML string to parse
26
+ * @param filePath - Optional file path for error messages
27
+ * @returns The parsed value
28
+ * @throws {YamlParseError} If parsing fails
29
+ */
30
+ export declare function parseYaml<T = unknown>(content: string, filePath?: string): Promise<T>;
31
+ /**
32
+ * Try to parse a YAML string, returning a discriminated union result
33
+ * instead of throwing.
34
+ *
35
+ * Requires the `yaml` peer dependency to be installed.
36
+ *
37
+ * @param content - The YAML string to parse
38
+ * @param filePath - Optional file path for error messages
39
+ * @returns A result with either `{ success: true, data }` or `{ success: false, error }`
40
+ */
41
+ export declare function tryParseYaml<T = unknown>(content: string, filePath?: string): Promise<{
42
+ success: true;
43
+ data: T;
44
+ } | {
45
+ success: false;
46
+ error: YamlParseError;
47
+ }>;
48
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/yaml/parse.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAGzB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;CAQlE;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,OAAO,EACzC,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,CAAC,CAaZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,EAC5C,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CACR;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CACvE,CAaA"}
@@ -0,0 +1,84 @@
1
+ let yamlPromise = null;
2
+ function importYaml() {
3
+ if (!yamlPromise) {
4
+ yamlPromise = import('yaml').catch(() => {
5
+ yamlPromise = null;
6
+ throw new Error('yaml is required to use @functional-examples/devkit/yaml. ' +
7
+ 'Install it with: pnpm add yaml');
8
+ });
9
+ }
10
+ return yamlPromise;
11
+ }
12
+ /**
13
+ * Resets the cached import promise. Used for testing only.
14
+ * @internal
15
+ */
16
+ export function _resetYamlImportCache() {
17
+ yamlPromise = null;
18
+ }
19
+ /**
20
+ * Error thrown when YAML parsing fails.
21
+ * Includes optional position information for diagnostics.
22
+ */
23
+ export class YamlParseError extends Error {
24
+ line;
25
+ column;
26
+ filePath;
27
+ constructor(message, options) {
28
+ super(message);
29
+ this.name = 'YamlParseError';
30
+ this.line = options?.line;
31
+ this.column = options?.column;
32
+ this.filePath = options?.filePath;
33
+ }
34
+ }
35
+ /**
36
+ * Parse a YAML string into a typed value.
37
+ *
38
+ * Requires the `yaml` peer dependency to be installed.
39
+ *
40
+ * @param content - The YAML string to parse
41
+ * @param filePath - Optional file path for error messages
42
+ * @returns The parsed value
43
+ * @throws {YamlParseError} If parsing fails
44
+ */
45
+ export async function parseYaml(content, filePath) {
46
+ const { parse } = await importYaml();
47
+ try {
48
+ return parse(content);
49
+ }
50
+ catch (e) {
51
+ const err = e instanceof Error ? e : new Error(String(e));
52
+ const posMatch = err.message.match(/at line (\d+), column (\d+)/);
53
+ throw new YamlParseError(err.message, {
54
+ line: posMatch ? Number(posMatch[1]) : undefined,
55
+ column: posMatch ? Number(posMatch[2]) : undefined,
56
+ filePath,
57
+ });
58
+ }
59
+ }
60
+ /**
61
+ * Try to parse a YAML string, returning a discriminated union result
62
+ * instead of throwing.
63
+ *
64
+ * Requires the `yaml` peer dependency to be installed.
65
+ *
66
+ * @param content - The YAML string to parse
67
+ * @param filePath - Optional file path for error messages
68
+ * @returns A result with either `{ success: true, data }` or `{ success: false, error }`
69
+ */
70
+ export async function tryParseYaml(content, filePath) {
71
+ try {
72
+ const data = await parseYaml(content, filePath);
73
+ return { success: true, data };
74
+ }
75
+ catch (e) {
76
+ const error = e instanceof YamlParseError
77
+ ? e
78
+ : new YamlParseError(e instanceof Error ? e.message : String(e), {
79
+ filePath,
80
+ });
81
+ return { success: false, error };
82
+ }
83
+ }
84
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/yaml/parse.ts"],"names":[],"mappings":"AAAA,IAAI,WAAW,GAA0C,IAAI,CAAC;AAE9D,SAAS,UAAU;IACjB,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACtC,WAAW,GAAG,IAAI,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,4DAA4D;gBAC1D,gCAAgC,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,IAAI,CAAU;IACd,MAAM,CAAU;IAChB,QAAQ,CAAU;IAE3B,YACE,OAAe,EACf,OAA+D;QAE/D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;IACpC,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAe,EACf,QAAiB;IAEjB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,KAAK,CAAC,OAAO,CAAM,CAAC;IAC7B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAClE,MAAM,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE;YACpC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;YAChD,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;YAClD,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,QAAiB;IAIjB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAI,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,KAAK,GACT,CAAC,YAAY,cAAc;YACzB,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;gBAC7D,QAAQ;aACT,CAAC,CAAC;QACT,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACnC,CAAC;AACH,CAAC"}