@amritk/mjst 0.24.0 → 0.25.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.
- package/README.md +3 -3
- package/dist/cli.js +20 -11
- package/dist/markdown/help-text.d.ts +1 -1
- package/dist/markdown/help-text.js +7 -5
- package/dist/markdown/parse-markdown-args.d.ts +4 -1
- package/dist/markdown/parse-markdown-args.js +3 -2
- package/dist/markdown/run.js +1 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -304,7 +304,7 @@ its own flags (and its own `--help`), independent of the generation flags above.
|
|
|
304
304
|
|
|
305
305
|
```bash
|
|
306
306
|
# The prose reference: a heading, a type, the description and an example per
|
|
307
|
-
# property, across as many pages as the schema's x-
|
|
307
|
+
# property, across as many pages as the schema's x-mjst keyword declares
|
|
308
308
|
npx mjst markdown ./config.schema.json --out-dir ./docs
|
|
309
309
|
|
|
310
310
|
# The other shape: one HTML table, spliced into an existing markdown file
|
|
@@ -315,7 +315,7 @@ npx mjst markdown ./config.schema.json --table --readme ./README.md
|
|
|
315
315
|
| --- | --- |
|
|
316
316
|
| `<schema>` | The JSON Schema to document (positional, required). |
|
|
317
317
|
| `--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-
|
|
318
|
+
| `--file` | Output path of the index page (default: the schema's `x-mjst.file`, then `index.md`). |
|
|
319
319
|
| `--title` | Page title (default: the schema's `title`). |
|
|
320
320
|
| `--language` | Fence language for derived examples and literals (default: `json`). |
|
|
321
321
|
| `--layout` | Default layout for nested properties: `headings` (default), `table`, or `none`. |
|
|
@@ -324,7 +324,7 @@ npx mjst markdown ./config.schema.json --table --readme ./README.md
|
|
|
324
324
|
| `--type-label` | Whether every property heading gets its **Type:** line: `auto` (default) or `never`. Under `never` an enum lists its **Allowed values:** instead, since the label was the only other place they appeared. |
|
|
325
325
|
| `--type-column` | When a property table renders its **Type** column: `auto` (default — only when a row fills it with something a reader could act on), `always`, or `never`. |
|
|
326
326
|
| `--default-column` | When a property table renders its **Default** column: `auto` (default), `always`, or `never`. |
|
|
327
|
-
| `--required-style` | How a property table says which properties are required: `
|
|
327
|
+
| `--required-style` | How a property table says which properties are required: `column` (default — a **Required** column), or any other text as a suffix right after a required name, as markdown or inline HTML — e.g. `"*"`, `" _required_"` or `"<br><sub><i>required</i></sub>"`. Appended exactly as written, so include a leading space if you want one. |
|
|
328
328
|
| `--required-first` | List the required properties at the top of every table, the rest under them. |
|
|
329
329
|
| `--table` | Render the HTML config table instead of the prose pages. |
|
|
330
330
|
| `--readme` | Markdown file the table is spliced into (default: `README.md`). Requires `--table`. |
|
package/dist/cli.js
CHANGED
|
@@ -3,21 +3,14 @@ import { execFile } from "node:child_process";
|
|
|
3
3
|
import { readdir, unlink, writeFile } from "node:fs/promises";
|
|
4
4
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
|
-
import { extractAsyncApi, listMessageSchemas } from "@amritk/asyncapi";
|
|
7
6
|
import { deriveRootTypeName } from "@amritk/helpers/derive-root-type-name";
|
|
8
7
|
const execFileAsync = promisify(execFile);
|
|
9
|
-
import { combineGeneratedFiles } from "./combine-files.js";
|
|
10
8
|
import { createOutputWriter } from "./create-output-writer.js";
|
|
11
9
|
import { detectHelpersMode } from "./detect-helpers-mode.js";
|
|
12
|
-
import { emitExamples } from "./emit-examples.js";
|
|
13
|
-
import { CONTRACTS_DIR, CONTRACTS_PEER, emitMessageContracts } from "./emit-message-contracts.js";
|
|
14
10
|
import { ensureOutputDir } from "./ensure-output-dir.js";
|
|
15
|
-
import { generateFiles } from "./generate-files.js";
|
|
16
11
|
import { HELP_TEXT } from "./help-text.js";
|
|
17
12
|
import { isDependencyDeclared } from "./is-dependency-declared.js";
|
|
18
|
-
import { loadAsyncApiDocument } from "./load-asyncapi-document.js";
|
|
19
13
|
import { loadConfig } from "./load-config.js";
|
|
20
|
-
import { loadSchema } from "./load-schema.js";
|
|
21
14
|
import { parseCliArgs } from "./parse-cli-args.js";
|
|
22
15
|
import { parseMetaRequest } from "./parse-meta-request.js";
|
|
23
16
|
import { readVersion } from "./read-version.js";
|
|
@@ -32,6 +25,10 @@ const resolveHelpersMode = (config, outputDir) => {
|
|
|
32
25
|
}
|
|
33
26
|
return helpersMode;
|
|
34
27
|
};
|
|
28
|
+
const loadGenerationPipeline = async () => {
|
|
29
|
+
const [{ loadSchema }, { generateFiles }] = await Promise.all([import("./load-schema.js"), import("./generate-files.js")]);
|
|
30
|
+
return { loadSchema, generateFiles };
|
|
31
|
+
};
|
|
35
32
|
const extractConfigPath = (args) => {
|
|
36
33
|
for (let i = 0; i < args.length; i++) {
|
|
37
34
|
const arg = args[i];
|
|
@@ -65,6 +62,7 @@ const commitOrDiscard = async (writer, stageAll) => {
|
|
|
65
62
|
return writer.commit();
|
|
66
63
|
};
|
|
67
64
|
const runExamples = async (config, outputDir, tasks) => {
|
|
65
|
+
const { emitExamples } = await import("./emit-examples.js");
|
|
68
66
|
const writer = await createOutputWriter(outputDir);
|
|
69
67
|
const written = await commitOrDiscard(writer, async () => {
|
|
70
68
|
for (const task of tasks) {
|
|
@@ -137,6 +135,7 @@ const findJsonSchemas = async (dir) => {
|
|
|
137
135
|
return results;
|
|
138
136
|
};
|
|
139
137
|
const runSingle = async (config, schemaPath, outputDir) => {
|
|
138
|
+
const { loadSchema, generateFiles } = await loadGenerationPipeline();
|
|
140
139
|
const schema = await loadSchema(config, schemaPath);
|
|
141
140
|
await ensureOutputDir(outputDir);
|
|
142
141
|
const helpersMode = resolveHelpersMode(config, outputDir);
|
|
@@ -164,6 +163,8 @@ Total files generated: ${written.length}`);
|
|
|
164
163
|
}
|
|
165
164
|
};
|
|
166
165
|
const runSingleFile = async (config, schemaPath, outFilePath) => {
|
|
166
|
+
const { loadSchema, generateFiles } = await loadGenerationPipeline();
|
|
167
|
+
const { combineGeneratedFiles } = await import("./combine-files.js");
|
|
167
168
|
const schema = await loadSchema(config, schemaPath);
|
|
168
169
|
const outputDir = dirname(outFilePath);
|
|
169
170
|
await ensureOutputDir(outputDir);
|
|
@@ -194,6 +195,7 @@ const runRecursive = async (config, schemaDir, outputDir) => {
|
|
|
194
195
|
process.exit(1);
|
|
195
196
|
}
|
|
196
197
|
const schemaFiles = await findJsonSchemas(schemaDir);
|
|
198
|
+
const { loadSchema, generateFiles } = await loadGenerationPipeline();
|
|
197
199
|
if (schemaFiles.length === 0) {
|
|
198
200
|
console.error(`Error: no .json schema files found under ${schemaDir}.`);
|
|
199
201
|
process.exit(1);
|
|
@@ -245,12 +247,19 @@ ${relPath} \u2192 ${relNoExt}/ (root type: ${rootTypeName})`);
|
|
|
245
247
|
Total files generated: ${writtenTsFiles.length}`);
|
|
246
248
|
}
|
|
247
249
|
};
|
|
248
|
-
const reportContractsPeer = (outputDir) => {
|
|
249
|
-
if (isDependencyDeclared(outputDir,
|
|
250
|
+
const reportContractsPeer = (outputDir, peer) => {
|
|
251
|
+
if (isDependencyDeclared(outputDir, peer))
|
|
250
252
|
return;
|
|
251
|
-
console.log(`Tip: the generated contracts import ${
|
|
253
|
+
console.log(`Tip: the generated contracts import ${peer}, which is not a declared dependency of the project at ${outputDir}. Install it there (it is a peer of the generated code, not of the mjst CLI).`);
|
|
252
254
|
};
|
|
253
255
|
const runAsyncApi = async (config, documentPath, outputDir) => {
|
|
256
|
+
const [{ loadAsyncApiDocument }, { extractAsyncApi, listMessageSchemas }, { generateFiles }, contractsModule] = await Promise.all([
|
|
257
|
+
import("./load-asyncapi-document.js"),
|
|
258
|
+
import("@amritk/asyncapi"),
|
|
259
|
+
import("./generate-files.js"),
|
|
260
|
+
import("./emit-message-contracts.js")
|
|
261
|
+
]);
|
|
262
|
+
const { CONTRACTS_DIR, CONTRACTS_PEER, emitMessageContracts } = contractsModule;
|
|
254
263
|
const document = await loadAsyncApiDocument(config, documentPath);
|
|
255
264
|
const model = extractAsyncApi(document);
|
|
256
265
|
const schemas = listMessageSchemas(model);
|
|
@@ -323,7 +332,7 @@ ${subDir}/ (root type: ${rootTypeName})`);
|
|
|
323
332
|
if (config.messageContracts) {
|
|
324
333
|
console.log(`
|
|
325
334
|
Message contracts: ${contractMessageCount} message(s) across ${contractChannelCount} channel(s)`);
|
|
326
|
-
reportContractsPeer(outputDir);
|
|
335
|
+
reportContractsPeer(outputDir, CONTRACTS_PEER);
|
|
327
336
|
}
|
|
328
337
|
if (exampleTasks.length > 0) {
|
|
329
338
|
await runExamples(config, outputDir, exampleTasks);
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* HELP_TEXT: the flag list is small and stable, and the test cross-checks that
|
|
4
4
|
* every flag is listed.
|
|
5
5
|
*/
|
|
6
|
-
export declare const MARKDOWN_HELP_TEXT = "mjst markdown \u2014 generate markdown documentation from a JSON Schema\n\nUsage:\n mjst markdown <schema> --out-dir <dir> [options]\n mjst markdown <schema> --table --readme <file>\n\nTwo shapes come out of the same schema. By default it writes the prose\nreference \u2014 a heading, a type, the description and an example per property,\nacross as many pages as the schema's x-
|
|
6
|
+
export declare const MARKDOWN_HELP_TEXT = "mjst markdown \u2014 generate markdown documentation from a JSON Schema\n\nUsage:\n mjst markdown <schema> --out-dir <dir> [options]\n mjst markdown <schema> --table --readme <file>\n\nTwo shapes come out of the same schema. By default it writes the prose\nreference \u2014 a heading, a type, the description and an example per property,\nacross as many pages as the schema's x-mjst keyword declares. With --table it\nrenders one HTML table instead and splices it into an existing markdown file\nbetween <!-- config-table-start --> and <!-- config-table-end -->, leaving the\nrest of that file alone.\n\nProse reference options:\n --out-dir <dir> Directory the pages are written to (default: the current directory)\n --file <path> Output path of the index page (default: the schema's x-mjst.markdown.file, then index.md)\n --title <text> Page title (default: the schema's title)\n --language <lang> Fence language for derived examples and literals (default: json)\n --layout <mode> Default layout for nested properties: headings (default), table, or none\n --sort <order> Property order: schema (default) or alphabetical\n --heading-level <n> Heading level of the page title, 1-6 (default: 1)\n --type-label <when> Give every property heading its Type: line: auto (default) or\n never (an enum then lists its allowed values instead)\n\nProperty table options (the root x-mjst.markdown.table, for every table on every page):\n --type-column <when> Render the Type column: auto (default), always, or never\n --default-column <when> Render the Default column: auto (default), always, or never\n --required-style <how> Say which properties are required: column (default, a\n Required column), or any other text as a suffix right\n after a required name, as markdown or inline HTML: \"*\",\n \" _required_\", \"<br><sub>required</sub>\"\n --required-first List the required properties at the top of every table\n\nTable options:\n --table Render the HTML config table instead of the prose pages\n --readme <path> Markdown file the table is spliced into (default: README.md)\n\nMisc:\n --help, -h Print this help\n\nDocs: https://github.com/amritk/mjst/tree/main/packages/cli#readme\n";
|
|
@@ -6,14 +6,14 @@ Usage:
|
|
|
6
6
|
|
|
7
7
|
Two shapes come out of the same schema. By default it writes the prose
|
|
8
8
|
reference \u2014 a heading, a type, the description and an example per property,
|
|
9
|
-
across as many pages as the schema's x-
|
|
9
|
+
across as many pages as the schema's x-mjst keyword declares. With --table it
|
|
10
10
|
renders one HTML table instead and splices it into an existing markdown file
|
|
11
11
|
between <!-- config-table-start --> and <!-- config-table-end -->, leaving the
|
|
12
12
|
rest of that file alone.
|
|
13
13
|
|
|
14
14
|
Prose reference options:
|
|
15
15
|
--out-dir <dir> Directory the pages are written to (default: the current directory)
|
|
16
|
-
--file <path> Output path of the index page (default: the schema's x-
|
|
16
|
+
--file <path> Output path of the index page (default: the schema's x-mjst.markdown.file, then index.md)
|
|
17
17
|
--title <text> Page title (default: the schema's title)
|
|
18
18
|
--language <lang> Fence language for derived examples and literals (default: json)
|
|
19
19
|
--layout <mode> Default layout for nested properties: headings (default), table, or none
|
|
@@ -22,11 +22,13 @@ Prose reference options:
|
|
|
22
22
|
--type-label <when> Give every property heading its Type: line: auto (default) or
|
|
23
23
|
never (an enum then lists its allowed values instead)
|
|
24
24
|
|
|
25
|
-
Property table options (the root x-
|
|
25
|
+
Property table options (the root x-mjst.markdown.table, for every table on every page):
|
|
26
26
|
--type-column <when> Render the Type column: auto (default), always, or never
|
|
27
27
|
--default-column <when> Render the Default column: auto (default), always, or never
|
|
28
|
-
--required-style <how> Say which properties are required:
|
|
29
|
-
|
|
28
|
+
--required-style <how> Say which properties are required: column (default, a
|
|
29
|
+
Required column), or any other text as a suffix right
|
|
30
|
+
after a required name, as markdown or inline HTML: "*",
|
|
31
|
+
" _required_", "<br><sub>required</sub>"
|
|
30
32
|
--required-first List the required properties at the top of every table
|
|
31
33
|
|
|
32
34
|
Table options:
|
|
@@ -23,7 +23,10 @@ export type MarkdownArgs = {
|
|
|
23
23
|
typeColumn?: DocTableColumn;
|
|
24
24
|
/** When property tables render their Default column (`--default-column`). */
|
|
25
25
|
defaultColumn?: DocTableColumn;
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* How property tables say which properties are required (`--required-style`):
|
|
28
|
+
* `column`, or any other text as a suffix after a required name.
|
|
29
|
+
*/
|
|
27
30
|
requiredStyle?: DocTableRequired;
|
|
28
31
|
/** True when `--required-first` was passed: required properties head every table. */
|
|
29
32
|
requiredFirst?: boolean;
|
|
@@ -17,7 +17,6 @@ const LAYOUTS = ["headings", "table", "none"];
|
|
|
17
17
|
const SORTS = ["schema", "alphabetical"];
|
|
18
18
|
const HEADING_TYPES = ["auto", "never"];
|
|
19
19
|
const TABLE_COLUMNS = ["auto", "always", "never"];
|
|
20
|
-
const REQUIRED_STYLES = ["marker", "column"];
|
|
21
20
|
const toCamelCase = (key) => key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
22
21
|
const parseChoice = (flag, value, choices) => {
|
|
23
22
|
const match = choices.find((choice) => choice === value);
|
|
@@ -65,8 +64,10 @@ const assignValue = (args, key, value) => {
|
|
|
65
64
|
case "defaultColumn":
|
|
66
65
|
args.defaultColumn = parseChoice("default-column", value, TABLE_COLUMNS);
|
|
67
66
|
return;
|
|
67
|
+
// Free text on purpose: anything but `column` is the suffix itself, so
|
|
68
|
+
// there is no typo to catch — `*` is as valid as ` _required_`.
|
|
68
69
|
case "requiredStyle":
|
|
69
|
-
args.requiredStyle =
|
|
70
|
+
args.requiredStyle = value;
|
|
70
71
|
return;
|
|
71
72
|
case "readme":
|
|
72
73
|
args.readme = value;
|
package/dist/markdown/run.js
CHANGED
|
@@ -66,7 +66,7 @@ const run = async (argv) => {
|
|
|
66
66
|
sort: args.sort,
|
|
67
67
|
headingLevel: args.headingLevel,
|
|
68
68
|
// Always passed: every member is optional, so the schema's own
|
|
69
|
-
// `x-
|
|
69
|
+
// `x-mjst.markdown.table` still decides whatever the flags left alone.
|
|
70
70
|
table: {
|
|
71
71
|
type: args.typeColumn,
|
|
72
72
|
default: args.defaultColumn,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amritk/mjst",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Generate TypeScript parsers and type definitions from JSON Schemas.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -49,16 +49,16 @@
|
|
|
49
49
|
"./package.json": "./package.json"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@amritk/adapters": "^0.6.
|
|
53
|
-
"@amritk/api": "^0.16.
|
|
54
|
-
"@amritk/asyncapi": "^0.3.
|
|
55
|
-
"@amritk/generate-examples": "^0.8.
|
|
56
|
-
"@amritk/generate-markdown": "^0.
|
|
57
|
-
"@amritk/helpers": "^0.23.
|
|
58
|
-
"@amritk/lint": "^0.6.
|
|
59
|
-
"@amritk/validation": "^0.3.
|
|
60
|
-
"@amritk/resolve-refs": "^0.
|
|
61
|
-
"@amritk/yaml": "^0.7.
|
|
52
|
+
"@amritk/adapters": "^0.6.7",
|
|
53
|
+
"@amritk/api": "^0.16.6",
|
|
54
|
+
"@amritk/asyncapi": "^0.3.5",
|
|
55
|
+
"@amritk/generate-examples": "^0.8.9",
|
|
56
|
+
"@amritk/generate-markdown": "^0.11.0",
|
|
57
|
+
"@amritk/helpers": "^0.23.3",
|
|
58
|
+
"@amritk/lint": "^0.6.2",
|
|
59
|
+
"@amritk/validation": "^0.3.2",
|
|
60
|
+
"@amritk/resolve-refs": "^0.8.0",
|
|
61
|
+
"@amritk/yaml": "^0.7.3",
|
|
62
62
|
"fast-glob": "^3.3.2",
|
|
63
63
|
"json-schema-typed": "^8.0.1",
|
|
64
64
|
"yargs": "^17.7.2"
|