@amritk/mjst 0.26.1 → 0.27.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/AI.md CHANGED
@@ -68,9 +68,9 @@ add one more entry point to the validator half and work under either flag.
68
68
  ## Common flags
69
69
 
70
70
  `--schema` / `--schema-dir`, `--out-dir` / `--out-file`, `--input`,
71
- `--validators` / `--validators-only`, `--examples`, `--message-contracts`,
72
- `--discriminator`, `--types-only`, `--build`, `--strict`, `--strip-unknown`,
73
- `--unknown-keys count-keys|count-enumerable`, `--readonly`,
71
+ `--validators` / `--validators-only`, `--branch-errors`, `--examples`,
72
+ `--message-contracts`, `--discriminator`, `--types-only`, `--build`, `--strict`,
73
+ `--strip-unknown`, `--unknown-keys count-keys|count-enumerable`, `--readonly`,
74
74
  `--import-ext ts|js`, `--config <path>`, `--resolve-remote` /
75
75
  `--allowed-hosts` (SSRF-guarded remote `$ref`s).
76
76
 
package/README.md CHANGED
@@ -117,16 +117,33 @@ carries both halves — and with `--build`. It cannot be combined with `--types-
117
117
  Ask for no validators and there is nothing to collide with, so the parser keeps `schema.ts` and
118
118
  its own type, and no `validation-result.ts` is emitted at all.
119
119
 
120
- Three flags shape the validators, and each needs `--validators` alongside it:
120
+ Pass `--validators-only` instead to emit the validator half with no parser at all: the type,
121
+ `isX`, `validateX`, and whichever of the flags below were asked for. It implies `--validators`,
122
+ and is the shape to reach for when the generated code only ever judges input it did not produce.
123
+
124
+ Four flags shape the validators, and each needs `--validators` (or `--validators-only`)
125
+ alongside it:
121
126
 
122
127
  - `--check` adds `checkX`, the same `ValidationResult` as `validateX` but stopped at the first
123
128
  violation, so it costs one error object rather than however many the document earns.
124
129
  - `--coerce` adds `coerceX`, which moves scalars toward the declared type and then validates.
125
130
  - `--repair` adds `repairX`, which coerces, validates, and then repairs each rejected position
126
131
  to a value the schema supplies.
132
+ - `--branch-errors` explains a failing `anyOf`/`oneOf` with the errors of the branch it meant,
133
+ instead of the bare "must match a schema in anyOf".
127
134
 
128
135
  ### Running the generated output
129
136
 
137
+ > [!IMPORTANT]
138
+ > **Type-checking the output as part of your own project?** Pass `--import-ext js`. The `.ts`
139
+ > default is for running the sources directly, and without `allowImportingTsExtensions` in your
140
+ > `tsconfig.json`, tsc rejects every one of those imports with `TS5097`. The output itself
141
+ > compiles under `strict`, `exactOptionalPropertyTypes`, `noUncheckedIndexedAccess` and
142
+ > `noPropertyAccessFromIndexSignature`. If your project turns on something it does not satisfy,
143
+ > `--banner "// @ts-nocheck"` writes the directive at the top of every generated file outside
144
+ > `_helpers/` (text made only of `//` lines is emitted as written, not wrapped in a JSDoc block, which TypeScript
145
+ > would not read a directive from).
146
+
130
147
  By default mjst emits relative imports with the literal `.ts` extension (e.g.
131
148
  `import { parseUser } from './user.ts'`), so the generated sources run **as-is** — no build
132
149
  step — under:
@@ -264,6 +281,8 @@ rules:
264
281
 
265
282
  By default `mjst lint` dereferences `$ref`, `$dynamicRef`/`$dynamicAnchor`, and `$recursiveRef`/`$recursiveAnchor` before running rules, so rules with `resolved: true` (the ruleset default) see through references. Internal and local cross-file refs resolve from disk — a finding on a cross-file node reports that file's own `line:column` — as long as they stay inside the linted document's own directory; use `--allowed-roots` to let a document reach a shared sibling folder. Remote refs are only fetched when you opt in with `--resolve-remote` or `--allowed-hosts`.
266
283
 
284
+ A YAML file holding several `---` documents is linted as an array of them, and each document resolves as a root of its own: a `#/…` ref points into the document it is written in, and its findings land on that document's own lines. A `$ref` to a YAML file that does not parse cleanly (a syntax error, or more than one document) is reported as an unresolved ref at the `$ref`, like a missing file.
285
+
267
286
  The exit code is `0` when no finding reaches `--fail-severity`, `1` when one does, and `2` on a usage error. Run `mjst lint --help` for the full list.
268
287
 
269
288
  ---
@@ -315,7 +334,7 @@ npx mjst markdown ./config.schema.json --table --readme ./README.md
315
334
  | --- | --- |
316
335
  | `<schema>` | The JSON Schema to document (positional, required). |
317
336
  | `--out-dir` | Directory the prose reference pages are written to (default: the current directory). |
318
- | `--file` | Output path of the index page (default: the schema's `x-mjst.file`, then `index.md`). |
337
+ | `--file` | Output path of the index page (default: the schema's `x-mjst.markdown.file`, then `index.md`). |
319
338
  | `--title` | Page title (default: the schema's `title`). |
320
339
  | `--language` | Fence language for derived examples and literals (default: `json`). |
321
340
  | `--layout` | Default layout for nested properties: `headings` (default), `table`, or `none`. |
@@ -329,7 +348,23 @@ npx mjst markdown ./config.schema.json --table --readme ./README.md
329
348
  | `--table` | Render the HTML config table instead of the prose pages. |
330
349
  | `--readme` | Markdown file the table is spliced into (default: `README.md`). Requires `--table`. |
331
350
 
332
- Under `--table` only the content between `<!-- config-table-start -->
351
+ Under `--table` only the content between the `config-table-start` and
352
+ `config-table-end` HTML comment markers is replaced; a file that exists without
353
+ both markers is left untouched and the run fails, rather than clobbering
354
+ hand-written prose.
355
+ The prose pages have no such deal — the generator owns them and overwrites them
356
+ wholesale. The table and page flags are mutually exclusive: passing a page flag
357
+ with `--table` is a usage error rather than a silently ignored option.
358
+
359
+ The exit code is `0` on success, `1` when generation fails (malformed schema, a
360
+ readme without markers, a page declaration the schema contradicts), and `2` on a
361
+ usage error. Run `mjst markdown --help` for details.
362
+
363
+ ---
364
+
365
+ ## Configuration reference
366
+
367
+ <!-- config-table-start -->
333
368
  <table>
334
369
  <thead>
335
370
  <tr>
@@ -437,7 +472,7 @@ Under `--table` only the content between `<!-- config-table-start -->
437
472
  <td align="center"><code>false</code></td>
438
473
  </tr>
439
474
  <tr>
440
- <td colspan="4">Also emit a coerceX alongside each validateX. It moves scalars toward the type the schema declares and then runs the very same validateX over the result, so a config value written the YAML way reads the same whether it came from a config file or an extension. The input is never modified and nothing is substituted: a value that cannot be coerced into a valid one reaches the validator untouched, so the error names what the caller actually wrote, with the keyword and params that rejected it. The table is Ajv's coerceTypes minus the cells where Ajv guesses — no whitespace-to-zero, no hex or Infinity strings, and nothing coerced to or from null, deliberately, since null usually means not set — so every scalar this coerces, Ajv coerces to the same value, and the rest become errors rather than silent repairs. Coercion reaches through $ref, allOf, if/then/else and unions. At a union a value that already matches a branch as written is left alone; otherwise each branch coerces it its own way, and the result is taken only when every branch that then accepts it agrees on it. So the answer does not depend on the order the union was written in, and a const false branch keeps false where Ajv turns it into the string false through an earlier string branch. A valid document comes back as the very same object, and against Ajv cloning its input first coerceX runs 5–36× faster on valid input and 1.4–2.1× faster on input that needs coercing. Requires validators.</td>
475
+ <td colspan="4">Also emit a coerceX alongside each validateX. It moves scalars toward the type the schema declares and then runs the very same validateX over the result, so a config value written the YAML way reads the same whether it came from a config file or an extension. The input is never modified and nothing is substituted: a value that cannot be coerced into a valid one reaches the validator untouched, so the error names what the caller actually wrote, with the keyword and params that rejected it. The table is Ajv's coerceTypes minus the cells where Ajv guesses — no whitespace-to-zero, no hex or Infinity strings, and nothing coerced to or from null, deliberately, since null usually means not set — so every scalar this coerces, Ajv coerces to the same value, and the rest become errors rather than silent repairs. Moving off Ajv, check how your callers treat a rejected value: a caller that reads rejection as absence silently drops any block holding a null that Ajv used to coerce, so surface the errors or allow null in the schema. Coercion reaches through $ref, allOf, if/then/else and unions. At a union a value that already matches a branch as written is left alone; otherwise each branch coerces it its own way, and the result is taken only when every branch that then accepts it agrees on it. So the answer does not depend on the order the union was written in, and a const false branch keeps false where Ajv turns it into the string false through an earlier string branch. A valid document comes back as the very same object. Where the caller cannot let Ajv mutate its input, so Ajv has to clone it first, coerceX runs 5–36× faster on valid input and 1.4–2.1× faster on input that needs coercing; where the caller lets Ajv coerce its document in place there is no clone to save, and on a large document Ajv can come out modestly ahead. Requires validators.</td>
441
476
  </tr>
442
477
  <tr>
443
478
  <td>🔧 <code>repair</code></td>
@@ -446,7 +481,7 @@ Under `--table` only the content between `<!-- config-table-start -->
446
481
  <td align="center"><code>false</code></td>
447
482
  </tr>
448
483
  <tr>
449
- <td colspan="4">Also emit a repairX alongside each validateX. It coerces, runs the very same validateX, and then repairs each position the validator rejected to a value the schema itself supplies — a default, a const, the first enum member, or a fallback built to satisfy that position's own bounds — re-validating until the document is accepted or nothing further can be repaired. The repairs it reports are the validator's own errors, the ones a repair was found for, so a caller logs the same path, keyword and params it would have been rejected with and the two can never drift apart. A document needing nothing comes back valid with an empty repairs list; one fully repaired comes back valid with a non-empty one, leaving the caller to decide whether that is acceptable; one that could not be fully repaired comes back invalid carrying both the repairs applied and the errors still outstanding. The input is never modified and everything the repair did not touch is shared. Implies coerce, so a value merely written in the wrong type is right before the validator sees it and never counts as a repair. Requires validators.</td>
484
+ <td colspan="4">Also emit a repairX alongside each validateX. It coerces, runs the very same validateX, and then repairs each position the validator rejected to a value the schema itself supplies — a default, a const, the first enum member, or a fallback built to satisfy that position's own bounds — re-validating until the document is accepted or nothing further can be repaired. The repairs it reports are the validator's own errors, the ones a repair was found for, so a caller logs the same path, keyword and params it would have been rejected with and the two can never drift apart. A document needing nothing comes back valid with an empty repairs list; one fully repaired comes back valid with a non-empty one, leaving the caller to decide whether that is acceptable; one that could not be fully repaired comes back invalid carrying both the repairs applied and the errors still outstanding. The input is never modified and everything the repair did not touch is shared. Repair is an autofix tool, not a stricter validator: it accepts documents validateX rejects by repairing them, and accepting only a valid result with an empty repairs list gives exactly the verdicts coerceX gives, so a loader that must reject a typo wants coerceX and repairX is for producing a fixed document. Implies coerce, so a value merely written in the wrong type is right before the validator sees it and never counts as a repair. Requires validators.</td>
450
485
  </tr>
451
486
  <tr>
452
487
  <td>🌿 <code>branchErrors</code></td>
@@ -455,304 +490,7 @@ Under `--table` only the content between `<!-- config-table-start -->
455
490
  <td align="center"><code>false</code></td>
456
491
  </tr>
457
492
  <tr>
458
- <td colspan="4">Explain a failing anyOf/oneOf with the errors of the branch it meant, instead of the bare "must match a schema in anyOf" that names no field and no reason. The branch that rejected the value's kind is dropped first, so a string-or-object union is left with the one branch that was talking about this value; where several remain, a discriminator breaks the tie; where none stands out, nothing extra is reported. Off by default and off costs nothing — the generated code is exactly what it would be without the option. On, each branch keeps what it complained about: a push per failing branch and one lazily-created array per combinator that had one. Requires validators.</td>
459
- </tr>
460
- <tr>
461
- <td>🎲 <code>examples</code></td>
462
- <td><code>--examples</code></td>
463
- <td><code>boolean</code></td>
464
- <td align="center"><code>false</code></td>
465
- </tr>
466
- <tr>
467
- <td colspan="4">Also emit test-data files for every schema into an examples/ subdirectory of the output destination: a fast-check arbitrary (FooArbitrary) that produces schema-valid values and a concrete fooExample value. Under schemaDir the examples mirror the schema layout so they never collide with the parser output. The generated arbitraries import fast-check, which consumers must install as a (dev) dependency; the static example values have no runtime dependencies.</td>
468
- </tr>
469
- <tr>
470
- <td>🔌 <code>messageContracts</code></td>
471
- <td><code>--message-contracts</code></td>
472
- <td><code>boolean</code></td>
473
- <td align="center"><code>false</code></td>
474
- </tr>
475
- <tr>
476
- <td colspan="4">Also emit a @amritk/api channel contract per AsyncAPI channel into a contracts/ subdirectory: one defineMessages({ ... }) module naming every message that channel carries — keyed by the value its discriminator property carries on the wire, with that property stripped out of each payload because the runtime removes it before validating — plus a barrel re-exporting them. Requires input 'asyncapi', which is the only input that has channels and operations to project from. Incompatible with typesOnly: a contract is a runtime value, not a type. The generated modules import @amritk/api, which the consuming project must install; it is not a dependency of the generated parsers.</td>
477
- </tr>
478
- <tr>
479
- <td>🏷️ <code>discriminator</code></td>
480
- <td><code>--discriminator &lt;prop&gt;</code></td>
481
- <td><code>string</code></td>
482
- <td align="center"><code>"type"</code></td>
483
- </tr>
484
- <tr>
485
- <td colspan="4">Property name that says which message a frame is, for the contracts messageContracts emits. Defaults to 'type', matching @amritk/api. A channel that declares its own with 'x-mjst': { 'discriminator': '...' } keeps it — one flag covers a whole run, and a run may span channels that disagree. Only meaningful together with messageContracts.<br><strong>Examples:</strong> <code>"event"</code></td>
486
- </tr>
487
- <tr>
488
- <td>🔨 <code>build</code></td>
489
- <td><code>--build</code></td>
490
- <td><code>boolean</code></td>
491
- <td align="center"><code>false</code></td>
492
- </tr>
493
- <tr>
494
- <td colspan="4">Compile the generated TypeScript files to .js and .d.ts output. A temporary tsconfig is written to the output directory, tsc is invoked, and the intermediate .ts source files are removed when compilation succeeds.</td>
495
- </tr>
496
- <tr>
497
- <td>💥 <code>force</code></td>
498
- <td><code>--force</code></td>
499
- <td><code>boolean</code></td>
500
- <td align="center"><code>false</code></td>
501
- </tr>
502
- <tr>
503
- <td colspan="4">Deprecated and ignored. Generated files always replace whatever is at their path, so this flag no longer does anything; it is still accepted so existing scripts and config files keep running. Reverting an unwanted replacement is version control's job. Compilation under build still only removes the intermediate sources the run itself generated.</td>
504
- </tr>
505
- <tr>
506
- <td>⚠️ <code>logWarnings</code></td>
507
- <td><code>--log-warnings</code></td>
508
- <td><code>boolean</code></td>
509
- <td align="center"><code>false</code></td>
510
- </tr>
511
- <tr>
512
- <td colspan="4">Emit a console.warn in the generated parsers for every input key that is not declared in the schema's properties. Useful for detecting schema drift or unexpected data shapes at runtime.</td>
513
- </tr>
514
- <tr>
515
- <td>🚫 <code>strict</code></td>
516
- <td><code>--strict</code></td>
517
- <td><code>boolean</code></td>
518
- <td align="center"><code>false</code></td>
519
- </tr>
520
- <tr>
521
- <td colspan="4">Generate parsers that throw on type/shape mismatches (wrong type, missing required property, enum/pattern/min/max violations) instead of coercing invalid input to default values. When a schema sets additionalProperties: false, undeclared keys throw too; otherwise they are still allowed.</td>
522
- </tr>
523
- <tr>
524
- <td>🧹 <code>stripUnknown</code></td>
525
- <td><code>--strip-unknown</code></td>
526
- <td><code>boolean</code></td>
527
- <td align="center"><code>false</code></td>
528
- </tr>
529
- <tr>
530
- <td colspan="4">Build each parser's result from the schema's declared properties only, silently dropping undeclared input keys at every nesting level (zod's .strip()). Extras are never a validation error, so this composes with strict (which still throws on wrong types and missing required properties) and yields to additionalProperties: false, which rejects rather than strips in strict mode.</td>
531
- </tr>
532
- <tr>
533
- <td>🔡 <code>caseInsensitive</code></td>
534
- <td><code>--case-insensitive</code></td>
535
- <td><code>boolean</code></td>
536
- <td align="center"><code>false</code></td>
537
- </tr>
538
- <tr>
539
- <td colspan="4">Normalize a mis-cased string to the exact casing of a declared enum/const member it matches case-insensitively (e.g. hElLo → hello) instead of coercing to the default. Coerce mode only — strict parsers still reject a casing mismatch. Correctly-cased input keeps the exact-match fast path, so the hot path is unaffected.</td>
540
- </tr>
541
- <tr>
542
- <td>🔒 <code>readonly</code></td>
543
- <td><code>--readonly</code></td>
544
- <td><code>boolean</code></td>
545
- <td align="center"><code>false</code></td>
546
- </tr>
547
- <tr>
548
- <td colspan="4">Emit every property, array, and record in the generated type definitions as readonly, producing deeply immutable types. Affects type definitions only; the generated parsers still build and return plain objects.</td>
549
- </tr>
550
- <tr>
551
- <td>🔢 <code>unknownKeys</code></td>
552
- <td><code>--unknown-keys &lt;strategy&gt;</code></td>
553
- <td><code>string</code></td>
554
- <td align="center"><code>"count-keys"</code></td>
555
- </tr>
556
- <tr>
557
- <td colspan="4">How generated fast paths (parsers and validators alike) prove a closed object — additionalProperties: false, or a stripUnknown build — carries no undeclared key. 'count-keys' compares Object.keys(obj).length and is the faster form on JavaScriptCore (Bun), where a for…in over a non-extensible object takes the engine's slow path and halves strict-parse throughput. 'count-enumerable' counts with for…in and allocates nothing; it was the faster form on Node 22, but on Node 26 'count-keys' ties or wins there too. Keep the default unless you are pinned to an older V8 and have measured your own shapes; the generated code never detects its runtime.<br><strong>Allowed:</strong> <code>"count-enumerable"</code>, <code>"count-keys"</code></td>
558
- </tr>
559
- <tr>
560
- <td>🧪 <code>formats</code></td>
561
- <td><code>--formats &lt;list&gt;</code></td>
562
- <td><code>string | array</code></td>
563
- <td align="center"></td>
564
- </tr>
565
- <tr>
566
- <td colspan="4">String formats the generated validators enforce: "all", or a comma-separated list (e.g. uuid,date-time,email). Omitted, format stays an annotation — JSON Schema's own reading, and what @amritk/runtime-validators does when given no formats. Set it to whatever validates the same schemas at runtime (@amritk/lint and createApi({ formats }) run the interpreter with formats on) so the build-time and runtime answers agree. Both validateX and the flat isX check them, against a formats.ts emitted alongside the validators.</td>
567
- </tr>
568
- <tr>
569
- <td>🧰 <code>helpers</code></td>
570
- <td><code>--helpers &lt;mode&gt;</code></td>
571
- <td><code>string</code></td>
572
- <td align="center"></td>
573
- </tr>
574
- <tr>
575
- <td colspan="4">Controls how generated parsers reference their runtime helpers. 'package' emits imports from @amritk/helpers (requires it to be installed in the consumer project). 'embedded' ships the helper source under outDir/_helpers/ so the output is self-contained. When omitted, the CLI auto-detects: it picks 'package' only when @amritk/helpers is a declared dependency (dependencies/devDependencies) of the nearest package.json above outDir, otherwise 'embedded'. Requiring a declaration (rather than mere resolvability) keeps auto-detected 'package' output portable across pnpm/isolated installs, where an undeclared transitive @amritk/helpers is not reachable at runtime.<br><strong>Allowed:</strong> <code>"package"</code>, <code>"embedded"</code></td>
576
- </tr>
577
- <tr>
578
- <td>🏷️ <code>typeSuffix</code></td>
579
- <td><code>--type-suffix &lt;suffix&gt;</code></td>
580
- <td><code>string</code></td>
581
- <td align="center"><code>""</code></td>
582
- </tr>
583
- <tr>
584
- <td colspan="4">Suffix appended to every generated type name derived from a $ref (e.g. 'Object' turns Contact into ContactObject). Defaults to no suffix. The root type name is used verbatim and is unaffected.</td>
585
- </tr>
586
- <tr>
587
- <td>🪧 <code>banner</code></td>
588
- <td><code>--banner [text]</code></td>
589
- <td><code>boolean | string</code></td>
590
- <td align="center"><code>false</code></td>
591
- </tr>
592
- <tr>
593
- <td colspan="4">Prepend a comment header to every generated file (excluding _helpers/). true uses the default message ('This file was auto-generated by @amritk/mjst…'); a string uses that text as the message body, wrapped in a JSDoc block; false or omitted emits no header. On the CLI, --banner alone enables the default message and --banner &lt;text&gt; sets a custom one.</td>
594
- </tr>
595
- <tr>
596
- <td>🔗 <code>importExt</code></td>
597
- <td><code>--import-ext &lt;ext&gt;</code></td>
598
- <td><code>string</code></td>
599
- <td align="center"><code>"ts"</code></td>
600
- </tr>
601
- <tr>
602
- <td colspan="4">Extension emitted on every relative import specifier in the generated output (cross-file $ref imports, the index barrel, and embedded-helper imports). 'ts' (default) emits the literal on-disk paths so the generated .ts sources load directly under Bun, Node's type stripping (Node 22.6+ with --experimental-strip-types, unflagged from 22.18/23), and tsc when the consumer sets allowImportingTsExtensions — no build step required. 'js' is the standard TS NodeNext form ('./x.js' resolving to a sibling x.ts) for output you compile; it is selected automatically under 'build' since tsc refuses to emit from .ts specifiers. Passing --import-ext ts together with --build is an error.<br><strong>Allowed:</strong> <code>"js"</code>, <code>"ts"</code></td>
603
- </tr>
604
- <tr>
605
- <td>🌱 <code>rootType</code></td>
606
- <td><code>--root-type &lt;name&gt;</code></td>
607
- <td><code>string</code></td>
608
- <td align="center"></td>
609
- </tr>
610
- <tr>
611
- <td colspan="4">Name for the root type of a single --schema run (e.g. 'Program' yields parseProgram / validateProgram). When omitted, the name is derived from the schema's title, falling back to the schema filename in PascalCase (spec-plan.json → SpecPlan) and then to 'Document'. Not supported with --schema-dir, where each schema derives its own root type from its filename.<br><strong>Examples:</strong> <code>"Program"</code></td>
612
- </tr>
613
- <tr>
614
- <td>🌐 <code>resolveRemote</code></td>
615
- <td><code>--resolve-remote</code></td>
616
- <td><code>boolean</code></td>
617
- <td align="center"><code>false</code></td>
618
- </tr>
619
- <tr>
620
- <td colspan="4">Allow fetching http(s) $refs while dereferencing a schema that contains cross-file or remote references. Off by default, so generation stays offline unless asked: a schema with a remote $ref fails rather than making a network call. Local cross-file $refs are always resolved and do not need this flag. A non-empty allowedHosts implies this.</td>
621
- </tr>
622
- <tr>
623
- <td>🛡️ <code>allowedHosts</code></td>
624
- <td><code>--allowed-hosts &lt;hosts&gt;</code></td>
625
- <td><code>array</code></td>
626
- <td align="center"></td>
627
- </tr>
628
- <tr>
629
- <td colspan="4">Restrict remote $ref fetches to these hosts (e.g. api.example.com). Accepts a comma-separated list or the flag repeated. Providing an allow-list is itself an opt-in to remote fetching (it implies resolveRemote), and each listed host bypasses the private-host guard.<br><strong>Examples:</strong> <code>["schemas.example.com"]</code></td>
630
- </tr>
631
- <tr>
632
- <td>🔓 <code>allowPrivateHosts</code></td>
633
- <td><code>--allow-private-hosts</code></td>
634
- <td><code>boolean</code></td>
635
- <td align="center"><code>false</code></td>
636
- </tr>
637
- <tr>
638
- <td colspan="4">Permit remote $refs to private, loopback, and link-local hosts. Off by default: such targets are refused as a best-effort SSRF guard (notably the 169.254.169.254 cloud-metadata endpoint). An explicit allowedHosts entry always bypasses this guard.</td>
639
- </tr>
640
- <tr>
641
- <td>📂 <code>allowedRoots</code></td>
642
- <td><code>--allowed-roots &lt;dirs&gt;</code></td>
643
- <td><code>array</code></td>
644
- <td align="center"></td>
645
- </tr>
646
- <tr>
647
- <td colspan="4">Extra directories a local (cross-file) $ref may resolve into. By default a local $ref is confined to the schema's own directory, so '{"$ref": "../../../secrets.env"}' (or an absolute path) reads nothing. List a root here for the ordinary split-spec layout where v1/api.json refers to a shared common/user.json one level up. The schema's own directory is always allowed, so these roots widen the default rather than replacing it, and a $ref that still lands outside every root is refused. Accepts a comma-separated list or the flag repeated; relative entries resolve against the current working directory, from a config file as well as from the flag.<br><strong>Examples:</strong> <code>["./specs"]</code></td>
648
- </tr>
649
- <tr>
650
- <td>⚙️ <code>config</code></td>
651
- <td><code>--config &lt;path&gt;</code></td>
652
- <td><code>string</code></td>
653
- <td align="center"></td>
654
- </tr>
655
- <tr>
656
- <td colspan="4">Path to a JSON config file. Keys match the option names in this schema (schema, schemaDir, input, export, outDir, outFile, typesOnly, validators, examples, build, force, logWarnings, strict, stripUnknown, caseInsensitive, readonly, unknownKeys, helpers, typeSuffix, banner, importExt, rootType, resolveRemote, allowedHosts, allowPrivateHosts, allowedRoots) and are validated: an unknown key or a wrong value type fails the run instead of being ignored. CLI flags take precedence over config file values.<br><strong>Examples:</strong> <code>"./mjst.config.json"</code></td>
657
- </tr>
658
- </tbody>
659
- </table>
660
- <!-- config-table-end -->` is replaced; a file that exists without both markers
661
- is left untouched and the run fails, rather than clobbering hand-written prose.
662
- The prose pages have no such deal — the generator owns them and overwrites them
663
- wholesale. The table and page flags are mutually exclusive: passing a page flag
664
- with `--table` is a usage error rather than a silently ignored option.
665
-
666
- The exit code is `0` on success, `1` when generation fails (malformed schema, a
667
- readme without markers, a page declaration the schema contradicts), and `2` on a
668
- usage error. Run `mjst markdown --help` for details.
669
-
670
- ---
671
-
672
- ## Configuration reference
673
-
674
- <!-- config-table-start -->
675
- <table>
676
- <thead>
677
- <tr>
678
- <th>Property</th>
679
- <th>CLI Flag</th>
680
- <th>Type</th>
681
- <th align="center">Default</th>
682
- </tr>
683
- </thead>
684
- <tbody>
685
- <tr>
686
- <td>📄 <code>schema</code></td>
687
- <td><code>--schema &lt;path&gt;</code></td>
688
- <td><code>string</code></td>
689
- <td align="center"></td>
690
- </tr>
691
- <tr>
692
- <td colspan="4">Path to the schema to process. With the default 'json' input this is a JSON Schema file that is read and parsed. With any other input format it is a JS/TS module that exports a schema, which is loaded and converted to JSON Schema via the matching adapter. Either 'schema' or 'schemaDir' is required.<br><strong>Examples:</strong> <code>"./schema.json"</code></td>
693
- </tr>
694
- <tr>
695
- <td>🗂️ <code>schemaDir</code></td>
696
- <td><code>--schema-dir &lt;dir&gt;</code></td>
697
- <td><code>string</code></td>
698
- <td align="center"></td>
699
- </tr>
700
- <tr>
701
- <td colspan="4">Path to a directory of JSON Schema files. When set, the CLI walks the directory recursively, generates parsers for every '*.json' schema it finds, and mirrors the directory layout under outDir (each schema lands in its own subdirectory). The runtime helpers are emitted once into a shared outDir/_helpers/ that every nested parser imports from. Mutually exclusive with 'schema'; when both are present 'schemaDir' wins. Only JSON Schema input is supported in this mode.<br><strong>Examples:</strong> <code>"./schemas"</code></td>
702
- </tr>
703
- <tr>
704
- <td>🔌 <code>input</code></td>
705
- <td><code>--input &lt;format&gt;</code></td>
706
- <td><code>string</code></td>
707
- <td align="center"><code>"json"</code></td>
708
- </tr>
709
- <tr>
710
- <td colspan="4">Source format of the schema. 'json' (default) reads a JSON Schema file directly. 'avro' reads an Apache Avro '.avsc' JSON document and converts it, needing no extra library. 'asyncapi' reads an AsyncAPI 2.x/3.0 document (JSON or YAML) and generates from every message payload/headers schema it declares. Any other format loads 'schema' as a module and converts it to JSON Schema with the matching adapter. Supported: 'typebox', 'zod' (zod v4+), 'valibot' (with @valibot/to-json-schema), and 'effect' — each requires the corresponding library installed in your project.<br><strong>Allowed:</strong> <code>"json"</code>, <code>"typebox"</code>, <code>"zod"</code>, <code>"valibot"</code>, <code>"effect"</code>, <code>"avro"</code>, <code>"asyncapi"</code></td>
711
- </tr>
712
- <tr>
713
- <td>📦 <code>export</code></td>
714
- <td><code>--export &lt;name&gt;</code></td>
715
- <td><code>string</code></td>
716
- <td align="center"></td>
717
- </tr>
718
- <tr>
719
- <td colspan="4">Which export of the schema module to use when 'input' names a module format (anything but 'json', 'avro', and 'asyncapi', which are read as data). Defaults to the default export, or the sole named export when the module has exactly one.</td>
720
- </tr>
721
- <tr>
722
- <td>📁 <code>outDir</code></td>
723
- <td><code>--out-dir &lt;dir&gt;</code></td>
724
- <td><code>string</code></td>
725
- <td align="center"></td>
726
- </tr>
727
- <tr>
728
- <td colspan="4">Output directory for generated TypeScript files. The directory is created automatically if it does not exist. Subdirectories are created as needed when a generated file includes a nested path. Mutually exclusive with 'outFile'.<br><strong>Examples:</strong> <code>"./generated"</code></td>
729
- </tr>
730
- <tr>
731
- <td>📄 <code>outFile</code></td>
732
- <td><code>--out-file &lt;file&gt;</code></td>
733
- <td><code>string</code></td>
734
- <td align="center"></td>
735
- </tr>
736
- <tr>
737
- <td colspan="4">Output everything to a single TypeScript file instead of a directory. Every generated definition is concatenated into one self-contained file and the cross-file imports are dropped. Mutually exclusive with 'outDir'. Currently supported only together with 'typesOnly'.<br><strong>Examples:</strong> <code>"./generated/schema.ts"</code></td>
738
- </tr>
739
- <tr>
740
- <td>🏷️ <code>typesOnly</code></td>
741
- <td><code>--types-only</code></td>
742
- <td><code>boolean</code></td>
743
- <td align="center"><code>false</code></td>
744
- </tr>
745
- <tr>
746
- <td colspan="4">Generate only TypeScript type definitions without parser functions. Useful when you only need the type shapes and do not need runtime validation.</td>
747
- </tr>
748
- <tr>
749
- <td>✅ <code>validators</code></td>
750
- <td><code>--validators</code></td>
751
- <td><code>boolean</code></td>
752
- <td align="center"><code>false</code></td>
753
- </tr>
754
- <tr>
755
- <td colspan="4">Also emit validation functions alongside the parsers. For every generated type X the CLI writes a validateX (returning a rich ValidationResult with JSON-Pointer error paths) and an isX boolean type guard. They share one directory and one declaration of X with the parser: the type and the validators land in x.ts, and the parser moves to x.parse.ts beside them, importing the type from there. Works with both schema and schemaDir. Incompatible with typesOnly and outFile, which produce no runtime code.</td>
493
+ <td colspan="4">Explain a failing anyOf/oneOf with the errors of the branch it meant, instead of the bare "must match a schema in anyOf" that names no field and no reason. The branch that rejected the value's kind is dropped first, so a string-or-object union is left with the one branch that was talking about this value; where several remain, a discriminator breaks the tie; where every branch rejected the value's kind, the kinds they accept are named instead ("must be object or boolean"); otherwise, where none stands out, nothing extra is reported. Off by default and off costs nothing — the generated code is exactly what it would be without the option. On, a combinator that passes costs what it costs with the option off, since its branches are tested by the same functions; only an anyOf/oneOf that has already failed asks its branches again for what each one complained about, so the price is paid on invalid input alone. Requires validators.</td>
756
494
  </tr>
757
495
  <tr>
758
496
  <td>🎲 <code>examples</code></td>
@@ -887,7 +625,7 @@ usage error. Run `mjst markdown --help` for details.
887
625
  <td align="center"><code>false</code></td>
888
626
  </tr>
889
627
  <tr>
890
- <td colspan="4">Prepend a comment header to every generated file (excluding _helpers/). true uses the default message ('This file was auto-generated by @amritk/mjst…'); a string uses that text as the message body, wrapped in a JSDoc block; false or omitted emits no header. On the CLI, --banner alone enables the default message and --banner &lt;text&gt; sets a custom one.</td>
628
+ <td colspan="4">Prepend a comment header to every generated file (excluding _helpers/). true uses the default message ('This file was auto-generated by @amritk/mjst…'); a string uses that text as the message body, wrapped in a JSDoc block, unless every line of it is a // comment — then it is emitted as written, which is how to add a directive such as // @ts-nocheck that TypeScript only honors as a line comment; false or omitted emits no header. On the CLI, --banner alone enables the default message and --banner &lt;text&gt; sets a custom one.</td>
891
629
  </tr>
892
630
  <tr>
893
631
  <td>🔗 <code>importExt</code></td>
@@ -112,10 +112,12 @@ export type CliConfig = {
112
112
  * branch listed before a `const: false` one.
113
113
  *
114
114
  * A document that is already valid is answered by `isX` alone where that is a
115
- * standalone guard, and handed back as the very same object. Against Ajv
116
- * cloning its input first — which it must to leave the caller's document
117
- * alone — `coerceX` runs 5–36× faster on valid input and 1.4–2.1× faster on
118
- * input that needs coercing (`bench:validators:coerce`).
115
+ * standalone guard, and handed back as the very same object. Where the caller
116
+ * cannot let Ajv mutate its input, so Ajv has to clone it first, `coerceX` runs
117
+ * 5–36× faster on valid input and 1.4–2.1× faster on input that needs coercing
118
+ * (`bench:validators:coerce`). Where the caller owns the document and lets Ajv
119
+ * coerce it in place, there is no clone to save, and on a large document Ajv
120
+ * can come out modestly ahead.
119
121
  *
120
122
  * Requires `validators`. `validateX` and `isX` are unchanged either way.
121
123
  */
@@ -135,6 +137,12 @@ export type CliConfig = {
135
137
  * comes back invalid carrying both the repairs applied and the errors still
136
138
  * outstanding.
137
139
  *
140
+ * Repair is an autofix tool, not a stricter validator: it accepts documents
141
+ * `validateX` rejects, by repairing them. Accepting only `valid` with an empty
142
+ * `repairs` gives exactly the verdicts `coerceX` gives, so a config loader that
143
+ * must reject a typo wants `coerceX`, and `repairX` is for producing a fixed
144
+ * document.
145
+ *
138
146
  * Implies `coerce` — repairing runs after coercion, so a value merely written
139
147
  * in the wrong type is right before the validator sees it and never counts as
140
148
  * a repair. Requires `validators`.
@@ -146,11 +154,11 @@ export type CliConfig = {
146
154
  * in anyOf" that names no field and no reason.
147
155
  *
148
156
  * Off by default, and off costs nothing — the generated code is exactly what
149
- * it would be without the option. On, each branch keeps what it complained
150
- * about, which is a push per *failing* branch and one lazily-created array per
151
- * combinator that had one. A valid instance fails no branch and allocates
152
- * nothing, but the branches are still handed a collector, so measure before
153
- * turning it on in a hot path.
157
+ * it would be without the option. On, a combinator that passes costs what it
158
+ * costs with the option off: its branches are tested by the same functions.
159
+ * Only an `anyOf` / `oneOf` that has already failed asks its branches again,
160
+ * this time for what each one complained about, so the price is paid on
161
+ * invalid input alone.
154
162
  *
155
163
  * Requires `validators`.
156
164
  */
package/dist/cli.js CHANGED
@@ -14,6 +14,7 @@ import { loadConfig } from "./load-config.js";
14
14
  import { parseCliArgs } from "./parse-cli-args.js";
15
15
  import { parseMetaRequest } from "./parse-meta-request.js";
16
16
  import { readVersion } from "./read-version.js";
17
+ import { resolveBanner } from "./resolve-banner.js";
17
18
  const ROOT_TYPE_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
18
19
  const DISCRIMINATOR_PATTERN = /^[A-Za-z_$][\w$-]*$/;
19
20
  const schemaBaseName = (schemaPath) => basename(schemaPath).replace(/\.[^.]+$/, "");
@@ -41,17 +42,6 @@ const extractConfigPath = (args) => {
41
42
  }
42
43
  return void 0;
43
44
  };
44
- const DEFAULT_BANNER_TEXT = "This file was auto-generated by @amritk/mjst.\n * Do not edit it manually \u2014 your changes will be overwritten on the next generation.";
45
- const resolveBanner = (banner) => {
46
- if (!banner)
47
- return "";
48
- const text = banner === true ? DEFAULT_BANNER_TEXT : banner;
49
- return `/**
50
- * ${text}
51
- */
52
-
53
- `;
54
- };
55
45
  const commitOrDiscard = async (writer, stageAll) => {
56
46
  try {
57
47
  await stageAll();
@@ -4,4 +4,4 @@
4
4
  * documents these flags (config.schema.json) is not shipped in the published
5
5
  * package; the help-text test cross-checks that every flag is listed.
6
6
  */
7
- export declare const HELP_TEXT = "mjst \u2014 generate TypeScript types, validators and parsers from JSON Schemas\n\nUsage:\n mjst --schema <path> --out-dir <dir> [options]\n mjst --schema-dir <dir> --out-dir <dir> [options]\n mjst --schema <path> --out-file <file> --types-only [options]\n\nSubcommands (each with its own flags and --help):\n mjst lint <files> Lint JSON/YAML documents against a ruleset\n mjst compile-api <module> --out <file> Compile @amritk/api route contracts into a fetch-handler module\n mjst markdown <schema> --out-dir <dir> Generate markdown documentation from a JSON Schema\n\nInput:\n --schema <path> Schema to process: a JSON Schema file, or a module when --input is set\n --schema-dir <dir> Directory of JSON Schemas, processed recursively (instead of --schema)\n --input <format> Schema source format: json (default), typebox, zod, valibot, effect, avro,\n or asyncapi (an AsyncAPI 2.x/3.0 document, JSON or YAML)\n --export <name> Which export of the schema module to use when --input names a module format\n\nOutput:\n --out-dir <dir> Output directory for the generated files\n --out-file <file> Single-file output instead of a directory (requires --types-only)\n --types-only Generate type definitions only, without parser functions\n --validators Also emit validateX/isX validators beside the parsers, over one\n shared declaration of each generated type\n --validators-only Emit the validator half and no parser: the type, isX, validateX and\n whichever of checkX/coerceX/repairX were asked for (implies\n --validators; the mirror of --types-only)\n --check Also emit checkX, the same result as validateX but stopped at the\n first violation (requires --validators)\n --coerce Also emit coerceX, which coerces scalars the way Ajv's coerceTypes\n does and then validates (requires --validators)\n --repair Also emit repairX, which coerces, validates, then repairs each\n rejected position to a schema-supplied value and reports the\n errors it repaired (implies --coerce; requires --validators)\n --branch-errors Explain a failing anyOf/oneOf with the errors of the branch it\n meant (requires --validators; costs a little on unions)\n --examples Also emit fast-check arbitraries + example values under examples/\n --message-contracts Also emit @amritk/api channel contracts under contracts/ (--input asyncapi only)\n --discriminator <p> Property naming which message a frame is, for --message-contracts (default: type)\n --build Compile the generated files to .js/.d.ts (implies --import-ext js)\n --force Deprecated; ignored (generated files always overwrite)\n --import-ext <ext> Extension on generated relative imports: ts (default) or js\n --helpers <mode> Runtime helpers: package or embedded (default: auto-detect from package.json)\n --root-type <name> Root type name for a single --schema run (default: schema title or filename)\n --type-suffix <s> Suffix appended to every $ref-derived type name\n --banner [text] Prepend a header comment to every generated file\n --readonly Emit deeply readonly type definitions\n\nValidation:\n --strict Throw on type/shape mismatches instead of coercing to defaults\n --strip-unknown Silently drop undeclared input keys at every nesting level\n --case-insensitive Normalize mis-cased enum/const strings to their exact casing\n --log-warnings console.warn on input keys not declared in the schema\n --unknown-keys <s> How closed objects are proven free of undeclared keys:\n count-keys (default, fastest on Bun) or count-enumerable (fastest on Node)\n --formats <f> String formats the generated validators enforce: \"all\", or a\n comma-separated list (e.g. uuid,date-time,email). Off by default,\n which leaves \"format\" an annotation as JSON Schema reads it.\n\nReference resolution:\n --resolve-remote Fetch http(s) $refs while resolving cross-file/remote refs (off by default)\n --allowed-hosts <h> Restrict remote $ref fetches to these hosts (comma-separated; implies --resolve-remote)\n --allow-private-hosts Permit remote $refs to private/loopback hosts (SSRF guard, off by default)\n --allowed-roots <d> Extra directories a local $ref may resolve into, on top of the schema's own\n (comma-separated; relative to the current directory)\n\nMisc:\n --config <path> JSON config file with the same keys; CLI flags take precedence\n --version, -v Print the CLI version\n --help, -h Print this help\n\nDocs: https://github.com/amritk/mjst/tree/main/packages/cli#readme\n";
7
+ export declare const HELP_TEXT = "mjst \u2014 generate TypeScript types, validators and parsers from JSON Schemas\n\nUsage:\n mjst --schema <path> --out-dir <dir> [options]\n mjst --schema-dir <dir> --out-dir <dir> [options]\n mjst --schema <path> --out-file <file> --types-only [options]\n\nSubcommands (each with its own flags and --help):\n mjst lint <files> Lint JSON/YAML documents against a ruleset\n mjst compile-api <module> --out <file> Compile @amritk/api route contracts into a fetch-handler module\n mjst markdown <schema> --out-dir <dir> Generate markdown documentation from a JSON Schema\n\nInput:\n --schema <path> Schema to process: a JSON Schema file, or a module when --input is set\n --schema-dir <dir> Directory of JSON Schemas, processed recursively (instead of --schema)\n --input <format> Schema source format: json (default), typebox, zod, valibot, effect, avro,\n or asyncapi (an AsyncAPI 2.x/3.0 document, JSON or YAML)\n --export <name> Which export of the schema module to use when --input names a module format\n\nOutput:\n --out-dir <dir> Output directory for the generated files\n --out-file <file> Single-file output instead of a directory (requires --types-only)\n --types-only Generate type definitions only, without parser functions\n --validators Also emit validateX/isX validators beside the parsers, over one\n shared declaration of each generated type\n --validators-only Emit the validator half and no parser: the type, isX, validateX and\n whichever of checkX/coerceX/repairX were asked for (implies\n --validators; the mirror of --types-only)\n --check Also emit checkX, the same result as validateX but stopped at the\n first violation (requires --validators)\n --coerce Also emit coerceX, which coerces scalars the way Ajv's coerceTypes\n does and then validates (requires --validators)\n --repair Also emit repairX, which coerces, validates, then repairs each\n rejected position to a schema-supplied value and reports the\n errors it repaired (implies --coerce; requires --validators)\n --branch-errors Explain a failing anyOf/oneOf with the errors of the branch it\n meant (requires --validators; costs a little on unions)\n --examples Also emit fast-check arbitraries + example values under examples/\n --message-contracts Also emit @amritk/api channel contracts under contracts/ (--input asyncapi only)\n --discriminator <p> Property naming which message a frame is, for --message-contracts (default: type)\n --build Compile the generated files to .js/.d.ts (implies --import-ext js)\n --force Deprecated; ignored (generated files always overwrite)\n --import-ext <ext> Extension on generated relative imports: ts (default) or js\n --helpers <mode> Runtime helpers: package or embedded (default: auto-detect from package.json)\n --root-type <name> Root type name for a single --schema run (default: schema title or filename)\n --type-suffix <s> Suffix appended to every $ref-derived type name\n --banner [text] Prepend a header comment to every generated file (text made of\n // lines is emitted as written, e.g. \"// @ts-nocheck\")\n --readonly Emit deeply readonly type definitions\n\nValidation:\n --strict Throw on type/shape mismatches instead of coercing to defaults\n --strip-unknown Silently drop undeclared input keys at every nesting level\n --case-insensitive Normalize mis-cased enum/const strings to their exact casing\n --log-warnings console.warn on input keys not declared in the schema\n --unknown-keys <s> How closed objects are proven free of undeclared keys:\n count-keys (default, fastest on Bun) or count-enumerable (fastest on Node)\n --formats <f> String formats the generated validators enforce: \"all\", or a\n comma-separated list (e.g. uuid,date-time,email). Off by default,\n which leaves \"format\" an annotation as JSON Schema reads it.\n\nReference resolution:\n --resolve-remote Fetch http(s) $refs while resolving cross-file/remote refs (off by default)\n --allowed-hosts <h> Restrict remote $ref fetches to these hosts (comma-separated; implies --resolve-remote)\n --allow-private-hosts Permit remote $refs to private/loopback hosts (SSRF guard, off by default)\n --allowed-roots <d> Extra directories a local $ref may resolve into, on top of the schema's own\n (comma-separated; relative to the current directory)\n\nMisc:\n --config <path> JSON config file with the same keys; CLI flags take precedence\n --version, -v Print the CLI version\n --help, -h Print this help\n\nDocs: https://github.com/amritk/mjst/tree/main/packages/cli#readme\n";
package/dist/help-text.js CHANGED
@@ -44,7 +44,8 @@ Output:
44
44
  --helpers <mode> Runtime helpers: package or embedded (default: auto-detect from package.json)
45
45
  --root-type <name> Root type name for a single --schema run (default: schema title or filename)
46
46
  --type-suffix <s> Suffix appended to every $ref-derived type name
47
- --banner [text] Prepend a header comment to every generated file
47
+ --banner [text] Prepend a header comment to every generated file (text made of
48
+ // lines is emitted as written, e.g. "// @ts-nocheck")
48
49
  --readonly Emit deeply readonly type definitions
49
50
 
50
51
  Validation:
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Turns the `banner` option into the header prepended to each generated file.
3
+ *
4
+ * A message is wrapped in a JSDoc block, which reads well and is what most
5
+ * headers want. Text made only of `//` lines is emitted as written,
6
+ * because some headers are directives rather than prose, and only the
7
+ * line-comment form counts as one: TypeScript ignores a `@ts-nocheck` inside
8
+ * a block comment, so `--banner "// @ts-nocheck"` was the one header a strict
9
+ * project needed and the one the wrapping made impossible.
10
+ */
11
+ export declare const resolveBanner: (banner: boolean | string | undefined) => string;
@@ -0,0 +1,22 @@
1
+ const DEFAULT_BANNER_TEXT = "This file was auto-generated by @amritk/mjst.\n * Do not edit it manually \u2014 your changes will be overwritten on the next generation.";
2
+ const isLineComments = (text) => {
3
+ const lines = text.split("\n").filter((line) => line.trim() !== "");
4
+ return lines.length > 0 && lines.every((line) => line.trimStart().startsWith("//"));
5
+ };
6
+ const resolveBanner = (banner) => {
7
+ if (!banner)
8
+ return "";
9
+ const text = banner === true ? DEFAULT_BANNER_TEXT : banner;
10
+ if (isLineComments(text))
11
+ return `${text.trim()}
12
+
13
+ `;
14
+ return `/**
15
+ * ${text}
16
+ */
17
+
18
+ `;
19
+ };
20
+ export {
21
+ resolveBanner
22
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amritk/mjst",
3
- "version": "0.26.1",
3
+ "version": "0.27.0",
4
4
  "description": "Generate TypeScript parsers and type definitions from JSON Schemas.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -49,14 +49,14 @@
49
49
  "./package.json": "./package.json"
50
50
  },
51
51
  "dependencies": {
52
- "@amritk/adapters": "^0.6.8",
53
- "@amritk/api": "^0.16.6",
54
- "@amritk/asyncapi": "^0.3.6",
55
- "@amritk/generate-examples": "^0.8.10",
52
+ "@amritk/adapters": "^0.6.9",
53
+ "@amritk/api": "^0.16.7",
54
+ "@amritk/asyncapi": "^0.3.7",
55
+ "@amritk/generate-examples": "^0.8.11",
56
56
  "@amritk/generate-markdown": "^0.12.0",
57
- "@amritk/helpers": "^0.24.0",
58
- "@amritk/lint": "^0.7.0",
59
- "@amritk/validation": "^0.4.0",
57
+ "@amritk/helpers": "^0.25.0",
58
+ "@amritk/lint": "^0.7.1",
59
+ "@amritk/validation": "^0.5.0",
60
60
  "@amritk/resolve-refs": "^0.9.0",
61
61
  "@amritk/yaml": "^0.8.0",
62
62
  "fast-glob": "^3.3.2",