@leemour/cli-core 0.7.0 → 0.8.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/README.md +31 -0
- package/dist/codegen/index.d.ts +12 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +11 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/manifest.d.ts +41 -0
- package/dist/codegen/manifest.d.ts.map +1 -0
- package/dist/codegen/manifest.js +59 -0
- package/dist/codegen/manifest.js.map +1 -0
- package/dist/codegen/model.d.ts +139 -0
- package/dist/codegen/model.d.ts.map +1 -0
- package/dist/codegen/model.js +7 -0
- package/dist/codegen/model.js.map +1 -0
- package/dist/codegen/names.d.ts +4 -0
- package/dist/codegen/names.d.ts.map +1 -0
- package/dist/codegen/names.js +46 -0
- package/dist/codegen/names.js.map +1 -0
- package/dist/codegen/pipeline.d.ts +24 -0
- package/dist/codegen/pipeline.d.ts.map +1 -0
- package/dist/codegen/pipeline.js +134 -0
- package/dist/codegen/pipeline.js.map +1 -0
- package/dist/codegen/runtime.d.ts +24 -0
- package/dist/codegen/runtime.d.ts.map +1 -0
- package/dist/codegen/runtime.js +38 -0
- package/dist/codegen/runtime.js.map +1 -0
- package/dist/codegen/tree.d.ts +29 -0
- package/dist/codegen/tree.d.ts.map +1 -0
- package/dist/codegen/tree.js +87 -0
- package/dist/codegen/tree.js.map +1 -0
- package/dist/codegen/typescript.d.ts +6 -0
- package/dist/codegen/typescript.d.ts.map +1 -0
- package/dist/codegen/typescript.js +76 -0
- package/dist/codegen/typescript.js.map +1 -0
- package/dist/codegen/valibot.d.ts +10 -0
- package/dist/codegen/valibot.d.ts.map +1 -0
- package/dist/codegen/valibot.js +121 -0
- package/dist/codegen/valibot.js.map +1 -0
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ streams.stderr // []
|
|
|
46
46
|
| `/commands` | the command registry: `describeProgram`, `annotate`, `flatten` — see below |
|
|
47
47
|
| `/completion` | shell completion over the registry: `suggest`, `formatSuggestions` — see below |
|
|
48
48
|
| `/update` | keeping an install current: `installerOf`, `updateCommand`, `latestVersion`, `mayNotify`, `updateNotice`, `runUpdate` — see below |
|
|
49
|
+
| `/codegen` | build time: an official API description → types, Valibot schemas, an operation manifest and a coverage page — see below |
|
|
49
50
|
|
|
50
51
|
**Nothing in the root export is HTTP.** Status classification, `Retry-After` parsing and the fetch
|
|
51
52
|
seam live in `@leemour/cli-core/http`, so a CLI that speaks a socket never depends on a stack it
|
|
@@ -99,6 +100,36 @@ second line of defence, not the first.
|
|
|
99
100
|
no ambient clock. That is what makes a timeout test finish instantly and a keyring test incapable
|
|
100
101
|
of reaching a real keychain.
|
|
101
102
|
|
|
103
|
+
**Generating an API catalog is `@leemour/cli-core/codegen`**, a build-time tool. It reads a
|
|
104
|
+
format-neutral `ApiModel` — operations with a transport binding (`http` method and path, or `rpc`
|
|
105
|
+
name), an `effect` (`read`, `write`, `destructive`) and how far the source can be trusted
|
|
106
|
+
(`contract`, `example`, `inferred`, `override`) — and writes committed files. It parses no file
|
|
107
|
+
format: the adapter from OpenAPI, Postman or anything else lives in the CLI that has that source,
|
|
108
|
+
so this adds no dependency. Generation stops, naming the problem, when two operations collide, an
|
|
109
|
+
operation is not classified as a read or a write, an override matches nothing, a reference points
|
|
110
|
+
nowhere or a construct cannot be expressed; it never drops an operation or falls back to `any`.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { generate, manifestGenerator, typesGenerator, valibotGenerator, writeArtifacts } from "@leemour/cli-core/codegen"
|
|
114
|
+
|
|
115
|
+
const artifacts = generate(model, [typesGenerator({ path }), valibotGenerator({ path, typesImport }), manifestGenerator({ path })], {
|
|
116
|
+
overrides: { answerOnCallback: { effect: "write", reason: "a POST that edits a message" } },
|
|
117
|
+
banner: ["Source: spec/bot/schema.yaml", "Run: pnpm bot:generate"],
|
|
118
|
+
})
|
|
119
|
+
const stale = writeArtifacts(artifacts, { root, check: process.argv.includes("--check") })
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The generated schemas import `@leemour/cli-core/codegen/runtime` at run time — a few number
|
|
123
|
+
helpers, not the generator. Numbers are expected from a lossless JSON parser (`lossless-json`): a
|
|
124
|
+
64-bit integer comes out as its exact decimal string, and any other integer that does not fit a JS
|
|
125
|
+
number fails instead of rounding. Objects are loose, so a field the API added later passes through.
|
|
126
|
+
Enums and discriminated unions are **strict**: a value or subtype the snapshot does not know fails,
|
|
127
|
+
so decode a live stream (updates, webhooks) only where that is what you want.
|
|
128
|
+
|
|
129
|
+
**The schemas decode; they do not encode.** Their output carries an `int64` as a string, so sending
|
|
130
|
+
it back would put a string where the API expects a number. Validate a request with the schema, then
|
|
131
|
+
send the original lossless value.
|
|
132
|
+
|
|
102
133
|
**Keeping an install current is `@leemour/cli-core/update`.** `installerOf(realpath(script))` says
|
|
103
134
|
which package manager put the CLI there — pnpm, npm or bun, measured on real installs — and
|
|
104
135
|
`updateCommand` gives the argv that updates it; a checkout or `npx` gets none. `latestVersion` asks
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns an official API description into committed code: types, Valibot schemas, an operation
|
|
3
|
+
* manifest and a coverage page. Build-time only, and format-neutral: it parses no file format and
|
|
4
|
+
* adds no dependency. The adapter from OpenAPI, Postman or anything else lives in the consumer.
|
|
5
|
+
*/
|
|
6
|
+
export { type CoverageOptions, coverageGenerator, type ManifestOperation, manifestGenerator } from "./manifest.js";
|
|
7
|
+
export type { ApiBody, ApiModel, ApiOperation, ApiParameter, ApiSchema, Binding, CodeGenerator, Confidence, Discriminator, Effect, GeneratedArtifact, HttpBinding, HttpMethod, Override, RpcBinding, SchemaNode, SourceInfo, SourceReference, } from "./model.js";
|
|
8
|
+
export { identifier, kebab } from "./names.js";
|
|
9
|
+
export { applyOverrides, CodegenError, type GenerateOptions, generate, validateModel, type WriteOptions, writeArtifacts, } from "./pipeline.js";
|
|
10
|
+
export { typesGenerator } from "./typescript.js";
|
|
11
|
+
export { type ValibotOptions, valibotGenerator } from "./valibot.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/codegen/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,eAAe,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAClH,YAAY,EACV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,OAAO,EACP,aAAa,EACb,UAAU,EACV,aAAa,EACb,MAAM,EACN,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EACL,cAAc,EACd,YAAY,EACZ,KAAK,eAAe,EACpB,QAAQ,EACR,aAAa,EACb,KAAK,YAAY,EACjB,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,KAAK,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns an official API description into committed code: types, Valibot schemas, an operation
|
|
3
|
+
* manifest and a coverage page. Build-time only, and format-neutral: it parses no file format and
|
|
4
|
+
* adds no dependency. The adapter from OpenAPI, Postman or anything else lives in the consumer.
|
|
5
|
+
*/
|
|
6
|
+
export { coverageGenerator, manifestGenerator } from "./manifest.js";
|
|
7
|
+
export { identifier, kebab } from "./names.js";
|
|
8
|
+
export { applyOverrides, CodegenError, generate, validateModel, writeArtifacts, } from "./pipeline.js";
|
|
9
|
+
export { typesGenerator } from "./typescript.js";
|
|
10
|
+
export { valibotGenerator } from "./valibot.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/codegen/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAwB,iBAAiB,EAA0B,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAqBlH,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EACL,cAAc,EACd,YAAY,EAEZ,QAAQ,EACR,aAAa,EAEb,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAuB,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Binding, CodeGenerator, Confidence, Effect, SchemaNode } from "./model.js";
|
|
2
|
+
/** One operation as a CLI reads it at run time: enough to build a command, validate input and guard a write. */
|
|
3
|
+
export interface ManifestOperation {
|
|
4
|
+
id: string;
|
|
5
|
+
command: string;
|
|
6
|
+
binding: Binding;
|
|
7
|
+
effect: Effect;
|
|
8
|
+
summary?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
tags: readonly string[];
|
|
11
|
+
deprecated?: boolean;
|
|
12
|
+
parameters: readonly {
|
|
13
|
+
name: string;
|
|
14
|
+
in: "path" | "query" | "header";
|
|
15
|
+
required: boolean;
|
|
16
|
+
description?: string;
|
|
17
|
+
schema: SchemaNode;
|
|
18
|
+
}[];
|
|
19
|
+
request?: {
|
|
20
|
+
required: boolean;
|
|
21
|
+
confidence: Confidence;
|
|
22
|
+
schema?: string;
|
|
23
|
+
};
|
|
24
|
+
response?: {
|
|
25
|
+
confidence: Confidence;
|
|
26
|
+
schema?: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare const manifestGenerator: (options: {
|
|
30
|
+
path: string;
|
|
31
|
+
coreImport?: string;
|
|
32
|
+
}) => CodeGenerator;
|
|
33
|
+
export interface CoverageOptions {
|
|
34
|
+
path: string;
|
|
35
|
+
title: string;
|
|
36
|
+
/** How a user reaches the operation, e.g. `max bot api get-my-info`. */
|
|
37
|
+
command: (operation: ManifestOperation) => string;
|
|
38
|
+
}
|
|
39
|
+
/** Every operation the source has, and how it is reached — the page a reviewer diffs after a sync. */
|
|
40
|
+
export declare const coverageGenerator: (options: CoverageOptions) => CodeGenerator;
|
|
41
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/codegen/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAIhH,gHAAgH;AAChH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,EAAE,SAAS;QACnB,IAAI,EAAE,MAAM,CAAA;QACZ,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;QAC/B,QAAQ,EAAE,OAAO,CAAA;QACjB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,MAAM,EAAE,UAAU,CAAA;KACnB,EAAE,CAAA;IACH,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,UAAU,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxE,QAAQ,CAAC,EAAE;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACvD;AA4BD,eAAO,MAAM,iBAAiB,YAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,aAWjD,CAAA;AAIH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,wEAAwE;IACxE,OAAO,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,MAAM,CAAA;CAClD;AAED,sGAAsG;AACtG,eAAO,MAAM,iBAAiB,YAClB,eAAe,KAAG,aAwB3B,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { kebab } from "./names.js";
|
|
2
|
+
import { SchemaTree } from "./tree.js";
|
|
3
|
+
const withoutUndefined = (value) => Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined));
|
|
4
|
+
const toManifest = (operation, tree) => withoutUndefined({
|
|
5
|
+
id: operation.id,
|
|
6
|
+
command: kebab(operation.id),
|
|
7
|
+
binding: operation.binding,
|
|
8
|
+
effect: operation.effect,
|
|
9
|
+
summary: operation.summary,
|
|
10
|
+
description: operation.description,
|
|
11
|
+
tags: operation.tags,
|
|
12
|
+
deprecated: operation.deprecated,
|
|
13
|
+
parameters: operation.parameters.map((parameter) => withoutUndefined({ ...parameter })),
|
|
14
|
+
request: operation.requestBody
|
|
15
|
+
? withoutUndefined({
|
|
16
|
+
required: operation.requestBody.required,
|
|
17
|
+
confidence: operation.requestBody.confidence,
|
|
18
|
+
schema: tree.requestName(operation.id),
|
|
19
|
+
})
|
|
20
|
+
: undefined,
|
|
21
|
+
response: operation.response
|
|
22
|
+
? withoutUndefined({ confidence: operation.response.confidence, schema: tree.responseName(operation.id) })
|
|
23
|
+
: undefined,
|
|
24
|
+
});
|
|
25
|
+
export const manifestGenerator = (options) => (model) => {
|
|
26
|
+
const tree = new SchemaTree(model);
|
|
27
|
+
const operations = model.operations.map((operation) => toManifest(operation, tree));
|
|
28
|
+
const content = [
|
|
29
|
+
`import type { ManifestOperation } from "${options.coreImport ?? "@leemour/cli-core/codegen"}"`,
|
|
30
|
+
"",
|
|
31
|
+
`export const operations: readonly ManifestOperation[] = ${JSON.stringify(operations, null, 2)}`,
|
|
32
|
+
"",
|
|
33
|
+
].join("\n");
|
|
34
|
+
return [{ path: options.path, content }];
|
|
35
|
+
};
|
|
36
|
+
const cell = (text) => (text ?? "").replace(/\s+/g, " ").replace(/\|/g, "\\|").trim();
|
|
37
|
+
/** Every operation the source has, and how it is reached — the page a reviewer diffs after a sync. */
|
|
38
|
+
export const coverageGenerator = (options) => (model) => {
|
|
39
|
+
const tree = new SchemaTree(model);
|
|
40
|
+
const rows = model.operations.map((operation) => {
|
|
41
|
+
const entry = toManifest(operation, tree);
|
|
42
|
+
const binding = entry.binding.kind === "http" ? `${entry.binding.method} ${entry.binding.path}` : entry.binding.name;
|
|
43
|
+
const status = entry.deprecated ? "deprecated" : "generated";
|
|
44
|
+
return `| \`${entry.id}\` | \`${binding}\` | \`${options.command(entry)}\` | ${entry.effect} | ${entry.request?.confidence ?? "—"} | ${status} | ${cell(entry.summary)} |`;
|
|
45
|
+
});
|
|
46
|
+
const version = model.source.version ? ` ${model.source.version}` : "";
|
|
47
|
+
const content = [
|
|
48
|
+
`# ${options.title}`,
|
|
49
|
+
"",
|
|
50
|
+
`${model.operations.length} operations from ${model.source.kind}${version}.`,
|
|
51
|
+
"",
|
|
52
|
+
"| Operation | Call | Command | Effect | Request source | Status | Summary |",
|
|
53
|
+
"|---|---|---|---|---|---|---|",
|
|
54
|
+
...rows,
|
|
55
|
+
"",
|
|
56
|
+
].join("\n");
|
|
57
|
+
return [{ path: options.path, content }];
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/codegen/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The model every generator reads, whatever the source was: an OpenAPI file, a Postman collection,
|
|
3
|
+
* a scraped reference page. A source adapter lives in the consumer and produces this; nothing here
|
|
4
|
+
* parses a file format.
|
|
5
|
+
*/
|
|
6
|
+
export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD";
|
|
7
|
+
/** How much the source promises. A Postman example is not a contract and must never become one. */
|
|
8
|
+
export type Confidence = "contract" | "example" | "inferred" | "override";
|
|
9
|
+
/**
|
|
10
|
+
* `undefined` in an adapter's output means "the source did not say". Generation refuses to run
|
|
11
|
+
* until an override classifies it — a write mistaken for a read is the expensive mistake.
|
|
12
|
+
*/
|
|
13
|
+
export type Effect = "read" | "write" | "destructive";
|
|
14
|
+
export interface HttpBinding {
|
|
15
|
+
kind: "http";
|
|
16
|
+
method: HttpMethod;
|
|
17
|
+
path: string;
|
|
18
|
+
}
|
|
19
|
+
/** Every call is the same HTTP shape and only the name differs, as in the Telegram Bot API. */
|
|
20
|
+
export interface RpcBinding {
|
|
21
|
+
kind: "rpc";
|
|
22
|
+
name: string;
|
|
23
|
+
}
|
|
24
|
+
export type Binding = HttpBinding | RpcBinding;
|
|
25
|
+
interface SchemaCommon {
|
|
26
|
+
description?: string;
|
|
27
|
+
nullable?: boolean;
|
|
28
|
+
deprecated?: boolean;
|
|
29
|
+
default?: unknown;
|
|
30
|
+
}
|
|
31
|
+
export type SchemaNode = SchemaCommon & ({
|
|
32
|
+
type: "ref";
|
|
33
|
+
ref: string;
|
|
34
|
+
} | {
|
|
35
|
+
type: "string";
|
|
36
|
+
enum?: readonly string[];
|
|
37
|
+
minLength?: number;
|
|
38
|
+
maxLength?: number;
|
|
39
|
+
pattern?: string;
|
|
40
|
+
} | {
|
|
41
|
+
type: "integer";
|
|
42
|
+
format?: "int32" | "int64";
|
|
43
|
+
minimum?: number;
|
|
44
|
+
maximum?: number;
|
|
45
|
+
enum?: readonly number[];
|
|
46
|
+
} | {
|
|
47
|
+
type: "number";
|
|
48
|
+
minimum?: number;
|
|
49
|
+
maximum?: number;
|
|
50
|
+
} | {
|
|
51
|
+
type: "boolean";
|
|
52
|
+
} | {
|
|
53
|
+
type: "array";
|
|
54
|
+
items: SchemaNode;
|
|
55
|
+
minItems?: number;
|
|
56
|
+
maxItems?: number;
|
|
57
|
+
uniqueItems?: boolean;
|
|
58
|
+
} | {
|
|
59
|
+
type: "object";
|
|
60
|
+
properties: Readonly<Record<string, SchemaNode>>;
|
|
61
|
+
required: readonly string[];
|
|
62
|
+
additionalProperties?: SchemaNode;
|
|
63
|
+
}
|
|
64
|
+
/** Inheritance: every member must resolve to an object, and the fields are merged. */
|
|
65
|
+
| {
|
|
66
|
+
type: "allOf";
|
|
67
|
+
of: readonly SchemaNode[];
|
|
68
|
+
}
|
|
69
|
+
/** Only where the source itself says "anything". An adapter never falls back to this. */
|
|
70
|
+
| {
|
|
71
|
+
type: "unknown";
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* A base type with subtypes chosen by one property, OpenAPI's `discriminator`. Referenced from
|
|
75
|
+
* inside an `allOf` it means the base's own fields; referenced anywhere else, one of the subtypes.
|
|
76
|
+
*/
|
|
77
|
+
export interface Discriminator {
|
|
78
|
+
property: string;
|
|
79
|
+
mapping: Readonly<Record<string, string>>;
|
|
80
|
+
}
|
|
81
|
+
export interface ApiSchema {
|
|
82
|
+
id: string;
|
|
83
|
+
schema: SchemaNode;
|
|
84
|
+
discriminator?: Discriminator;
|
|
85
|
+
}
|
|
86
|
+
export interface ApiParameter {
|
|
87
|
+
name: string;
|
|
88
|
+
in: "path" | "query" | "header";
|
|
89
|
+
required: boolean;
|
|
90
|
+
description?: string;
|
|
91
|
+
schema: SchemaNode;
|
|
92
|
+
}
|
|
93
|
+
export interface ApiBody {
|
|
94
|
+
confidence: Confidence;
|
|
95
|
+
required: boolean;
|
|
96
|
+
schema?: SchemaNode;
|
|
97
|
+
example?: unknown;
|
|
98
|
+
}
|
|
99
|
+
export interface SourceReference {
|
|
100
|
+
/** Where in the source this came from, for a reviewer: a JSON pointer, a folder path. */
|
|
101
|
+
location: string;
|
|
102
|
+
}
|
|
103
|
+
export interface ApiOperation {
|
|
104
|
+
/** The source's own id where it has one. Never re-derived when it does. */
|
|
105
|
+
id: string;
|
|
106
|
+
binding: Binding;
|
|
107
|
+
summary?: string;
|
|
108
|
+
description?: string;
|
|
109
|
+
tags: readonly string[];
|
|
110
|
+
parameters: readonly ApiParameter[];
|
|
111
|
+
requestBody?: ApiBody;
|
|
112
|
+
response?: ApiBody;
|
|
113
|
+
effect?: Effect;
|
|
114
|
+
deprecated?: boolean;
|
|
115
|
+
source: SourceReference;
|
|
116
|
+
}
|
|
117
|
+
export interface SourceInfo {
|
|
118
|
+
kind: "openapi" | "postman" | "other";
|
|
119
|
+
version?: string;
|
|
120
|
+
sourceUrl?: string;
|
|
121
|
+
sourceRevision?: string;
|
|
122
|
+
}
|
|
123
|
+
export interface ApiModel {
|
|
124
|
+
source: SourceInfo;
|
|
125
|
+
operations: readonly ApiOperation[];
|
|
126
|
+
schemas: readonly ApiSchema[];
|
|
127
|
+
}
|
|
128
|
+
export interface Override {
|
|
129
|
+
effect?: Effect;
|
|
130
|
+
/** Required: an override nobody can explain is one nobody dares remove. */
|
|
131
|
+
reason: string;
|
|
132
|
+
}
|
|
133
|
+
export interface GeneratedArtifact {
|
|
134
|
+
path: string;
|
|
135
|
+
content: string;
|
|
136
|
+
}
|
|
137
|
+
export type CodeGenerator = (model: ApiModel) => GeneratedArtifact[];
|
|
138
|
+
export {};
|
|
139
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/codegen/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The model every generator reads, whatever the source was: an OpenAPI file, a Postman collection,
|
|
3
|
+
* a scraped reference page. A source adapter lives in the consumer and produces this; nothing here
|
|
4
|
+
* parses a file format.
|
|
5
|
+
*/
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/codegen/model.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../src/codegen/names.ts"],"names":[],"mappings":"AAoCA,eAAO,MAAM,UAAU,OAAQ,MAAM,KAAG,MAIvC,CAAA;AAED,mCAAmC;AACnC,eAAO,MAAM,KAAK,OAAQ,MAAM,KAAG,MAKjB,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const pascal = (text) => text
|
|
2
|
+
.split(/[^A-Za-z0-9]+/)
|
|
3
|
+
.filter(Boolean)
|
|
4
|
+
.map((word) => word[0]?.toUpperCase() + word.slice(1))
|
|
5
|
+
.join("");
|
|
6
|
+
// A generated `export const Error` compiles, and then every `new Error()` in that module builds a schema.
|
|
7
|
+
const GLOBALS = new Set([
|
|
8
|
+
"Array",
|
|
9
|
+
"BigInt",
|
|
10
|
+
"Boolean",
|
|
11
|
+
"Date",
|
|
12
|
+
"Error",
|
|
13
|
+
"Function",
|
|
14
|
+
"Intl",
|
|
15
|
+
"JSON",
|
|
16
|
+
"Map",
|
|
17
|
+
"Math",
|
|
18
|
+
"Number",
|
|
19
|
+
"Object",
|
|
20
|
+
"Partial",
|
|
21
|
+
"Promise",
|
|
22
|
+
"Proxy",
|
|
23
|
+
"Record",
|
|
24
|
+
"Reflect",
|
|
25
|
+
"RegExp",
|
|
26
|
+
"Required",
|
|
27
|
+
"Set",
|
|
28
|
+
"String",
|
|
29
|
+
"Symbol",
|
|
30
|
+
"URL",
|
|
31
|
+
"WeakMap",
|
|
32
|
+
"WeakSet",
|
|
33
|
+
]);
|
|
34
|
+
export const identifier = (id) => {
|
|
35
|
+
const name = pascal(id);
|
|
36
|
+
if (!/^[A-Za-z]/.test(name))
|
|
37
|
+
return `Schema${name}`;
|
|
38
|
+
return GLOBALS.has(name) ? `Api${name}` : name;
|
|
39
|
+
};
|
|
40
|
+
/** `getMyInfo` → `get-my-info`. */
|
|
41
|
+
export const kebab = (id) => id
|
|
42
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
43
|
+
.replace(/[^A-Za-z0-9]+/g, "-")
|
|
44
|
+
.replace(/^-|-$/g, "")
|
|
45
|
+
.toLowerCase();
|
|
46
|
+
//# sourceMappingURL=names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/codegen/names.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,CAAC,IAAY,EAAU,EAAE,CACtC,IAAI;KACD,KAAK,CAAC,eAAe,CAAC;KACtB,MAAM,CAAC,OAAO,CAAC;KACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACrD,IAAI,CAAC,EAAE,CAAC,CAAA;AAEb,0GAA0G;AAC1G,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC;IACtB,OAAO;IACP,QAAQ;IACR,SAAS;IACT,MAAM;IACN,OAAO;IACP,UAAU;IACV,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,SAAS;IACT,OAAO;IACP,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,UAAU;IACV,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,SAAS;IACT,SAAS;CACV,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAU,EAAU,EAAE;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAA;IACvB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,IAAI,EAAE,CAAA;IACnD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AAChD,CAAC,CAAA;AAED,mCAAmC;AACnC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAU,EAAE,CAC1C,EAAE;KACC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;KACtC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;KAC9B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;KACrB,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ApiModel, CodeGenerator, GeneratedArtifact, Override } from "./model.js";
|
|
2
|
+
export declare class CodegenError extends Error {
|
|
3
|
+
readonly problems: readonly string[];
|
|
4
|
+
constructor(problems: readonly string[]);
|
|
5
|
+
}
|
|
6
|
+
export declare const applyOverrides: (model: ApiModel, overrides: Readonly<Record<string, Override>>) => ApiModel;
|
|
7
|
+
/** Everything that would otherwise make an operation vanish or turn into a guess. */
|
|
8
|
+
export declare const validateModel: (model: ApiModel) => void;
|
|
9
|
+
export interface GenerateOptions {
|
|
10
|
+
overrides?: Readonly<Record<string, Override>>;
|
|
11
|
+
/** Lines under "GENERATED. DO NOT EDIT." — the source and the command. Nothing that changes by itself. */
|
|
12
|
+
banner: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
export declare const generate: (model: ApiModel, generators: readonly CodeGenerator[], options: GenerateOptions) => GeneratedArtifact[];
|
|
15
|
+
export interface WriteOptions {
|
|
16
|
+
root: string;
|
|
17
|
+
/** Compare only: report what is out of date and write nothing. */
|
|
18
|
+
check?: boolean;
|
|
19
|
+
/** The consumer's formatter, so a check compares what would actually be committed. */
|
|
20
|
+
format?: (path: string, content: string) => string;
|
|
21
|
+
}
|
|
22
|
+
/** Paths whose committed content differs from what was generated — written, or with `check`, only reported. */
|
|
23
|
+
export declare const writeArtifacts: (artifacts: readonly GeneratedArtifact[], options: WriteOptions) => string[];
|
|
24
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/codegen/pipeline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAgB,aAAa,EAAE,iBAAiB,EAAE,QAAQ,EAAc,MAAM,YAAY,CAAA;AAGhH,qBAAa,YAAa,SAAQ,KAAK;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE;IAAhD,YAAqB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAG/C;CACF;AAED,eAAO,MAAM,cAAc,UAAW,QAAQ,aAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAG,QAc/F,CAAA;AA6BD,qFAAqF;AACrF,eAAO,MAAM,aAAa,UAAW,QAAQ,KAAG,IAyC/C,CAAA;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC9C,0GAA0G;IAC1G,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B;AAOD,eAAO,MAAM,QAAQ,UACZ,QAAQ,cACH,SAAS,aAAa,EAAE,WAC3B,eAAe,KACvB,iBAAiB,EAQnB,CAAA;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,sFAAsF;IACtF,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;CACnD;AAED,+GAA+G;AAC/G,eAAO,MAAM,cAAc,cAAe,SAAS,iBAAiB,EAAE,WAAW,YAAY,KAAG,MAAM,EAarG,CAAA"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, extname, join } from "node:path";
|
|
3
|
+
import { identifier, kebab } from "./names.js";
|
|
4
|
+
export class CodegenError extends Error {
|
|
5
|
+
problems;
|
|
6
|
+
constructor(problems) {
|
|
7
|
+
super(`generation stopped:\n${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
8
|
+
this.problems = problems;
|
|
9
|
+
this.name = "CodegenError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const applyOverrides = (model, overrides) => {
|
|
13
|
+
const known = new Set(model.operations.map((operation) => operation.id));
|
|
14
|
+
const stale = Object.keys(overrides).filter((id) => !known.has(id));
|
|
15
|
+
if (stale.length > 0) {
|
|
16
|
+
// A correction that matches nothing any more has silently stopped being applied.
|
|
17
|
+
throw new CodegenError(stale.map((id) => `override "${id}" matches no operation — stale, or the id changed`));
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
...model,
|
|
21
|
+
operations: model.operations.map((operation) => {
|
|
22
|
+
const override = overrides[operation.id];
|
|
23
|
+
return override?.effect ? { ...operation, effect: override.effect } : operation;
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
const bindingKey = (operation) => operation.binding.kind === "http"
|
|
28
|
+
? `${operation.binding.method} ${operation.binding.path}`
|
|
29
|
+
: `rpc ${operation.binding.name}`;
|
|
30
|
+
const duplicates = (values) => [...new Set(values.filter((value, index) => values.indexOf(value) !== index))].sort();
|
|
31
|
+
const refsIn = (node, found = []) => {
|
|
32
|
+
switch (node.type) {
|
|
33
|
+
case "ref":
|
|
34
|
+
found.push(node.ref);
|
|
35
|
+
break;
|
|
36
|
+
case "array":
|
|
37
|
+
refsIn(node.items, found);
|
|
38
|
+
break;
|
|
39
|
+
case "object":
|
|
40
|
+
for (const property of Object.values(node.properties))
|
|
41
|
+
refsIn(property, found);
|
|
42
|
+
if (node.additionalProperties)
|
|
43
|
+
refsIn(node.additionalProperties, found);
|
|
44
|
+
break;
|
|
45
|
+
case "allOf":
|
|
46
|
+
for (const member of node.of)
|
|
47
|
+
refsIn(member, found);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
return found;
|
|
51
|
+
};
|
|
52
|
+
/** Everything that would otherwise make an operation vanish or turn into a guess. */
|
|
53
|
+
export const validateModel = (model) => {
|
|
54
|
+
const problems = [];
|
|
55
|
+
for (const id of duplicates(model.operations.map((operation) => operation.id))) {
|
|
56
|
+
problems.push(`two operations share the id "${id}"`);
|
|
57
|
+
}
|
|
58
|
+
for (const key of duplicates(model.operations.map(bindingKey)))
|
|
59
|
+
problems.push(`two operations are both ${key}`);
|
|
60
|
+
for (const id of duplicates(model.schemas.map((schema) => schema.id))) {
|
|
61
|
+
problems.push(`two schemas share the id "${id}"`);
|
|
62
|
+
}
|
|
63
|
+
for (const command of duplicates(model.operations.map((operation) => kebab(operation.id)))) {
|
|
64
|
+
problems.push(`two operations both become the command "${command}"`);
|
|
65
|
+
}
|
|
66
|
+
for (const name of duplicates(model.schemas.map((schema) => identifier(schema.id)))) {
|
|
67
|
+
problems.push(`two schemas both become the name "${name}"`);
|
|
68
|
+
}
|
|
69
|
+
for (const operation of model.operations) {
|
|
70
|
+
for (const name of duplicates(operation.parameters.map((parameter) => parameter.name))) {
|
|
71
|
+
problems.push(`operation "${operation.id}" has two parameters named "${name}"`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const operation of model.operations) {
|
|
75
|
+
if (!operation.effect)
|
|
76
|
+
problems.push(`operation "${operation.id}" is not classified as read, write or destructive`);
|
|
77
|
+
}
|
|
78
|
+
const schemaIds = new Set(model.schemas.map((schema) => schema.id));
|
|
79
|
+
const unresolved = (where, node) => {
|
|
80
|
+
if (!node)
|
|
81
|
+
return;
|
|
82
|
+
for (const ref of refsIn(node))
|
|
83
|
+
if (!schemaIds.has(ref))
|
|
84
|
+
problems.push(`${where} refers to unknown schema "${ref}"`);
|
|
85
|
+
};
|
|
86
|
+
for (const schema of model.schemas) {
|
|
87
|
+
unresolved(`schema "${schema.id}"`, schema.schema);
|
|
88
|
+
for (const [value, target] of Object.entries(schema.discriminator?.mapping ?? {})) {
|
|
89
|
+
if (!schemaIds.has(target))
|
|
90
|
+
problems.push(`schema "${schema.id}" maps "${value}" to unknown schema "${target}"`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const operation of model.operations) {
|
|
94
|
+
for (const parameter of operation.parameters)
|
|
95
|
+
unresolved(`operation "${operation.id}"`, parameter.schema);
|
|
96
|
+
unresolved(`operation "${operation.id}" request`, operation.requestBody?.schema);
|
|
97
|
+
unresolved(`operation "${operation.id}" response`, operation.response?.schema);
|
|
98
|
+
}
|
|
99
|
+
if (problems.length > 0)
|
|
100
|
+
throw new CodegenError(problems);
|
|
101
|
+
};
|
|
102
|
+
const commentFor = (path, lines) => {
|
|
103
|
+
if (extname(path) === ".md")
|
|
104
|
+
return `<!--\n${lines.join("\n")}\n-->\n\n`;
|
|
105
|
+
return `${lines.map((line) => `// ${line}`).join("\n")}\n\n`;
|
|
106
|
+
};
|
|
107
|
+
export const generate = (model, generators, options) => {
|
|
108
|
+
const prepared = applyOverrides(model, options.overrides ?? {});
|
|
109
|
+
validateModel(prepared);
|
|
110
|
+
const artifacts = generators.flatMap((generator) => generator(prepared));
|
|
111
|
+
const clashing = duplicates(artifacts.map((artifact) => artifact.path));
|
|
112
|
+
if (clashing.length > 0)
|
|
113
|
+
throw new CodegenError(clashing.map((path) => `two generators both write ${path}`));
|
|
114
|
+
const banner = ["GENERATED. DO NOT EDIT.", ...options.banner];
|
|
115
|
+
return artifacts.map((artifact) => ({ ...artifact, content: commentFor(artifact.path, banner) + artifact.content }));
|
|
116
|
+
};
|
|
117
|
+
/** Paths whose committed content differs from what was generated — written, or with `check`, only reported. */
|
|
118
|
+
export const writeArtifacts = (artifacts, options) => {
|
|
119
|
+
const stale = [];
|
|
120
|
+
for (const artifact of artifacts) {
|
|
121
|
+
const target = join(options.root, artifact.path);
|
|
122
|
+
const content = options.format ? options.format(artifact.path, artifact.content) : artifact.content;
|
|
123
|
+
const current = existsSync(target) ? readFileSync(target, "utf8") : undefined;
|
|
124
|
+
if (current === content)
|
|
125
|
+
continue;
|
|
126
|
+
stale.push(artifact.path);
|
|
127
|
+
if (options.check)
|
|
128
|
+
continue;
|
|
129
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
130
|
+
writeFileSync(target, content);
|
|
131
|
+
}
|
|
132
|
+
return stale;
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/codegen/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What generated Valibot schemas call at run time. Kept apart from the generator so a CLI loads
|
|
3
|
+
* these few functions, not the code that writes code.
|
|
4
|
+
*
|
|
5
|
+
* Numbers arrive from a lossless JSON parser (`lossless-json` or anything shaped like its
|
|
6
|
+
* `LosslessNumber`), because a 64-bit id read as a JS number is silently a different id.
|
|
7
|
+
*/
|
|
8
|
+
import * as v from "valibot";
|
|
9
|
+
interface LosslessLike {
|
|
10
|
+
isLosslessNumber: true;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
interface Range {
|
|
14
|
+
minimum?: number;
|
|
15
|
+
maximum?: number;
|
|
16
|
+
}
|
|
17
|
+
/** A 64-bit integer, handed on as its exact decimal string. */
|
|
18
|
+
export declare const int64: (range?: Range) => v.SchemaWithPipe<readonly [v.CustomSchema<number | bigint | LosslessLike, v.ErrorMessage<v.CustomIssue> | undefined>, v.TransformAction<number | bigint | LosslessLike, string>, v.CheckAction<string, "integer out of range">]>;
|
|
19
|
+
/** An integer that must fit a JS number exactly; one that does not fails instead of rounding. */
|
|
20
|
+
export declare const integer: (range?: Range) => v.SchemaWithPipe<readonly [v.CustomSchema<number | bigint | LosslessLike, v.ErrorMessage<v.CustomIssue> | undefined>, v.TransformAction<number | bigint | LosslessLike, number>, v.CheckAction<number, "integer out of range">]>;
|
|
21
|
+
export declare const number: (range?: Range) => v.SchemaWithPipe<readonly [v.CustomSchema<number | LosslessLike, v.ErrorMessage<v.CustomIssue> | undefined>, v.TransformAction<number | LosslessLike, number>, v.CheckAction<number, "number out of range">]>;
|
|
22
|
+
export declare const unique: (items: readonly unknown[]) => boolean;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/codegen/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAE5B,UAAU,YAAY;IACpB,gBAAgB,EAAE,IAAI,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;CACd;AAmBD,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAKD,+DAA+D;AAC/D,eAAO,MAAM,KAAK,WAAW,KAAK,qOAQ/B,CAAA;AAEH,iGAAiG;AACjG,eAAO,MAAM,OAAO,WAAW,KAAK,qOAQjC,CAAA;AAEH,eAAO,MAAM,MAAM,WAAW,KAAK,kNAQhC,CAAA;AAEH,eAAO,MAAM,MAAM,UAAW,SAAS,OAAO,EAAE,KAAG,OACuB,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What generated Valibot schemas call at run time. Kept apart from the generator so a CLI loads
|
|
3
|
+
* these few functions, not the code that writes code.
|
|
4
|
+
*
|
|
5
|
+
* Numbers arrive from a lossless JSON parser (`lossless-json` or anything shaped like its
|
|
6
|
+
* `LosslessNumber`), because a 64-bit id read as a JS number is silently a different id.
|
|
7
|
+
*/
|
|
8
|
+
import * as v from "valibot";
|
|
9
|
+
const isLossless = (input) => typeof input === "object" &&
|
|
10
|
+
input !== null &&
|
|
11
|
+
input.isLosslessNumber === true &&
|
|
12
|
+
typeof input.value === "string";
|
|
13
|
+
const INTEGER = /^-?\d+$/;
|
|
14
|
+
const INT64_MIN = -(2n ** 63n);
|
|
15
|
+
const INT64_MAX = 2n ** 63n - 1n;
|
|
16
|
+
const digitsOf = (input) => {
|
|
17
|
+
if (isLossless(input))
|
|
18
|
+
return INTEGER.test(input.value) ? input.value : undefined;
|
|
19
|
+
if (typeof input === "bigint")
|
|
20
|
+
return input.toString();
|
|
21
|
+
if (typeof input === "number" && Number.isSafeInteger(input))
|
|
22
|
+
return String(input);
|
|
23
|
+
return undefined;
|
|
24
|
+
};
|
|
25
|
+
const inRange = (value, { minimum, maximum }) => (minimum === undefined || value >= minimum) && (maximum === undefined || value <= maximum);
|
|
26
|
+
/** A 64-bit integer, handed on as its exact decimal string. */
|
|
27
|
+
export const int64 = (range = {}) => v.pipe(v.custom((input) => digitsOf(input) !== undefined, "expected an integer"), v.transform((input) => digitsOf(input)), v.check((digits) => {
|
|
28
|
+
const value = BigInt(digits);
|
|
29
|
+
return value >= INT64_MIN && value <= INT64_MAX && inRange(value, range);
|
|
30
|
+
}, "integer out of range"));
|
|
31
|
+
/** An integer that must fit a JS number exactly; one that does not fails instead of rounding. */
|
|
32
|
+
export const integer = (range = {}) => v.pipe(v.custom((input) => {
|
|
33
|
+
const digits = digitsOf(input);
|
|
34
|
+
return digits !== undefined && Number.isSafeInteger(Number(digits));
|
|
35
|
+
}, "expected an integer within ±2^53"), v.transform((input) => Number(digitsOf(input))), v.check((value) => inRange(value, range), "integer out of range"));
|
|
36
|
+
export const number = (range = {}) => v.pipe(v.custom((input) => (isLossless(input) ? Number.isFinite(Number(input.value)) : Number.isFinite(input)), "expected a number"), v.transform((input) => (isLossless(input) ? Number(input.value) : input)), v.check((value) => inRange(value, range), "number out of range"));
|
|
37
|
+
export const unique = (items) => new Set(items.map((item) => JSON.stringify(item))).size === items.length;
|
|
38
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/codegen/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ApiModel, ApiSchema, SchemaNode } from "./model.js";
|
|
2
|
+
type ObjectNode = Extract<SchemaNode, {
|
|
3
|
+
type: "object";
|
|
4
|
+
}>;
|
|
5
|
+
export interface NamedSchema {
|
|
6
|
+
name: string;
|
|
7
|
+
schema: ApiSchema;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The schema index generators share: named components, inline request and response bodies given a
|
|
11
|
+
* name of their own, and which subtype each discriminator value selects.
|
|
12
|
+
*/
|
|
13
|
+
export declare class SchemaTree {
|
|
14
|
+
#private;
|
|
15
|
+
readonly named: NamedSchema[];
|
|
16
|
+
constructor(model: ApiModel);
|
|
17
|
+
schema(id: string): ApiSchema;
|
|
18
|
+
requestName(operationId: string): string | undefined;
|
|
19
|
+
responseName(operationId: string): string | undefined;
|
|
20
|
+
/** The value a subtype's discriminator property must hold, if the schema is a subtype. */
|
|
21
|
+
literalFor(id: string): {
|
|
22
|
+
property: string;
|
|
23
|
+
value: string;
|
|
24
|
+
} | undefined;
|
|
25
|
+
/** Merges inheritance into one object. A member that is not an object stops generation. */
|
|
26
|
+
flatten(node: SchemaNode, where: string): ObjectNode;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/codegen/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAIjE,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAA;AAEzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,SAAS,CAAA;CAClB;AAED;;;GAGG;AACH,qBAAa,UAAU;;IACrB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,CAAA;IAM7B,YAAY,KAAK,EAAE,QAAQ,EA8B1B;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAI5B;IAED,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnD;IAED,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEpD;IAED,0FAA0F;IAC1F,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAEtE;IAED,2FAA2F;IAC3F,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAiBnD;CACF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { identifier } from "./names.js";
|
|
2
|
+
import { CodegenError } from "./pipeline.js";
|
|
3
|
+
/**
|
|
4
|
+
* The schema index generators share: named components, inline request and response bodies given a
|
|
5
|
+
* name of their own, and which subtype each discriminator value selects.
|
|
6
|
+
*/
|
|
7
|
+
export class SchemaTree {
|
|
8
|
+
named;
|
|
9
|
+
#byId;
|
|
10
|
+
#literals = new Map();
|
|
11
|
+
#requests = new Map();
|
|
12
|
+
#responses = new Map();
|
|
13
|
+
constructor(model) {
|
|
14
|
+
this.#byId = new Map(model.schemas.map((schema) => [schema.id, schema]));
|
|
15
|
+
this.named = model.schemas.map((schema) => ({ name: identifier(schema.id), schema }));
|
|
16
|
+
const taken = new Set(this.named.map((entry) => entry.name));
|
|
17
|
+
const nameInline = (operationId, suffix, node) => {
|
|
18
|
+
if (!node)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (node.type === "ref")
|
|
21
|
+
return identifier(node.ref);
|
|
22
|
+
const name = identifier(`${operationId} ${suffix}`);
|
|
23
|
+
if (taken.has(name))
|
|
24
|
+
throw new CodegenError([`inline ${suffix.toLowerCase()} of "${operationId}" collides with ${name}`]);
|
|
25
|
+
taken.add(name);
|
|
26
|
+
this.named.push({ name, schema: { id: name, schema: node } });
|
|
27
|
+
return name;
|
|
28
|
+
};
|
|
29
|
+
for (const operation of model.operations) {
|
|
30
|
+
const request = nameInline(operation.id, "Request", operation.requestBody?.schema);
|
|
31
|
+
const response = nameInline(operation.id, "Response", operation.response?.schema);
|
|
32
|
+
if (request)
|
|
33
|
+
this.#requests.set(operation.id, request);
|
|
34
|
+
if (response)
|
|
35
|
+
this.#responses.set(operation.id, response);
|
|
36
|
+
}
|
|
37
|
+
for (const schema of model.schemas) {
|
|
38
|
+
for (const [value, target] of Object.entries(schema.discriminator?.mapping ?? {})) {
|
|
39
|
+
if (this.#literals.has(target)) {
|
|
40
|
+
throw new CodegenError([`schema "${target}" is a subtype of two discriminated schemas`]);
|
|
41
|
+
}
|
|
42
|
+
this.#literals.set(target, { property: schema.discriminator?.property ?? "", value });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
schema(id) {
|
|
47
|
+
const schema = this.#byId.get(id);
|
|
48
|
+
if (!schema)
|
|
49
|
+
throw new CodegenError([`unknown schema "${id}"`]);
|
|
50
|
+
return schema;
|
|
51
|
+
}
|
|
52
|
+
requestName(operationId) {
|
|
53
|
+
return this.#requests.get(operationId);
|
|
54
|
+
}
|
|
55
|
+
responseName(operationId) {
|
|
56
|
+
return this.#responses.get(operationId);
|
|
57
|
+
}
|
|
58
|
+
/** The value a subtype's discriminator property must hold, if the schema is a subtype. */
|
|
59
|
+
literalFor(id) {
|
|
60
|
+
return this.#literals.get(id);
|
|
61
|
+
}
|
|
62
|
+
/** Merges inheritance into one object. A member that is not an object stops generation. */
|
|
63
|
+
flatten(node, where) {
|
|
64
|
+
if (node.type === "object")
|
|
65
|
+
return node;
|
|
66
|
+
if (node.type === "ref")
|
|
67
|
+
return this.flatten(this.schema(node.ref).schema, `${where} → ${node.ref}`);
|
|
68
|
+
if (node.type !== "allOf") {
|
|
69
|
+
throw new CodegenError([`${where}: allOf member of type "${node.type}" cannot be merged into an object`]);
|
|
70
|
+
}
|
|
71
|
+
const merged = {
|
|
72
|
+
properties: {},
|
|
73
|
+
required: [],
|
|
74
|
+
};
|
|
75
|
+
for (const member of node.of) {
|
|
76
|
+
const part = this.flatten(member, where);
|
|
77
|
+
Object.assign(merged.properties, part.properties);
|
|
78
|
+
for (const name of part.required)
|
|
79
|
+
if (!merged.required.includes(name))
|
|
80
|
+
merged.required.push(name);
|
|
81
|
+
if (part.additionalProperties)
|
|
82
|
+
merged.additionalProperties = part.additionalProperties;
|
|
83
|
+
}
|
|
84
|
+
return { type: "object", description: node.description, nullable: node.nullable, ...merged };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/codegen/tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CodeGenerator } from "./model.js";
|
|
2
|
+
/** TypeScript types for every schema: what a caller holds after the response has been validated. */
|
|
3
|
+
export declare const typesGenerator: (options: {
|
|
4
|
+
path: string;
|
|
5
|
+
}) => CodeGenerator;
|
|
6
|
+
//# sourceMappingURL=typescript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/codegen/typescript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,aAAa,EAAc,MAAM,YAAY,CAAA;AAmErE,oGAAoG;AACpG,eAAO,MAAM,cAAc,YACf;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,KAAG,aAY5B,CAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { identifier } from "./names.js";
|
|
2
|
+
import { SchemaTree } from "./tree.js";
|
|
3
|
+
const doc = (text, indent) => {
|
|
4
|
+
const line = text?.replace(/\s+/g, " ").replace(/\*\//g, "*\\/").trim();
|
|
5
|
+
return line ? `${indent}/** ${line} */\n` : "";
|
|
6
|
+
};
|
|
7
|
+
const key = (name) => (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name));
|
|
8
|
+
class TypeWriter {
|
|
9
|
+
tree;
|
|
10
|
+
constructor(tree) {
|
|
11
|
+
this.tree = tree;
|
|
12
|
+
}
|
|
13
|
+
node(node, where, literal) {
|
|
14
|
+
const base = this.#bare(node, where, literal);
|
|
15
|
+
return node.nullable ? `${base} | null` : base;
|
|
16
|
+
}
|
|
17
|
+
#bare(node, where, literal) {
|
|
18
|
+
switch (node.type) {
|
|
19
|
+
case "ref":
|
|
20
|
+
return identifier(node.ref);
|
|
21
|
+
case "string":
|
|
22
|
+
return node.enum ? node.enum.map((value) => JSON.stringify(value)).join(" | ") : "string";
|
|
23
|
+
case "integer":
|
|
24
|
+
if (node.format === "int64")
|
|
25
|
+
return "string";
|
|
26
|
+
return node.enum ? node.enum.map(String).join(" | ") : "number";
|
|
27
|
+
case "number":
|
|
28
|
+
return "number";
|
|
29
|
+
case "boolean":
|
|
30
|
+
return "boolean";
|
|
31
|
+
case "unknown":
|
|
32
|
+
return "unknown";
|
|
33
|
+
case "array": {
|
|
34
|
+
return `Array<${this.node(node.items, `${where}[]`)}>`;
|
|
35
|
+
}
|
|
36
|
+
case "allOf":
|
|
37
|
+
if (node.of.length === 1 && node.of[0] && !literal)
|
|
38
|
+
return this.#bare(node.of[0], where);
|
|
39
|
+
return this.#object(this.tree.flatten(node, where), where, literal);
|
|
40
|
+
case "object":
|
|
41
|
+
return this.#object(node, where, literal);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
#object(node, where, literal) {
|
|
45
|
+
const names = Object.keys(node.properties);
|
|
46
|
+
if (literal && !names.includes(literal.property))
|
|
47
|
+
names.unshift(literal.property);
|
|
48
|
+
const rest = node.additionalProperties
|
|
49
|
+
? `Record<string, ${this.node(node.additionalProperties, where)}>`
|
|
50
|
+
: undefined;
|
|
51
|
+
if (names.length === 0)
|
|
52
|
+
return rest ?? "Record<string, unknown>";
|
|
53
|
+
const fields = names.map((name) => {
|
|
54
|
+
const property = node.properties[name] ?? { type: "string" };
|
|
55
|
+
const optional = node.required.includes(name) || literal?.property === name ? "" : "?";
|
|
56
|
+
const type = literal?.property === name ? JSON.stringify(literal.value) : this.node(property, `${where}.${name}`);
|
|
57
|
+
return `${doc(property.description, " ")} ${key(name)}${optional}: ${type}`;
|
|
58
|
+
});
|
|
59
|
+
const body = `{\n${fields.join("\n")}\n}`;
|
|
60
|
+
return rest ? `${body} & ${rest}` : body;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** TypeScript types for every schema: what a caller holds after the response has been validated. */
|
|
64
|
+
export const typesGenerator = (options) => (model) => {
|
|
65
|
+
const tree = new SchemaTree(model);
|
|
66
|
+
const writer = new TypeWriter(tree);
|
|
67
|
+
const declarations = tree.named.map(({ name, schema }) => {
|
|
68
|
+
const union = schema.discriminator
|
|
69
|
+
? Object.values(schema.discriminator.mapping).map(identifier).join(" | ")
|
|
70
|
+
: undefined;
|
|
71
|
+
const type = union ?? writer.node(schema.schema, schema.id, tree.literalFor(schema.id));
|
|
72
|
+
return `${doc(schema.schema.description, "")}export type ${name} = ${type}\n`;
|
|
73
|
+
});
|
|
74
|
+
return [{ path: options.path, content: declarations.join("\n") }];
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=typescript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../src/codegen/typescript.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CodeGenerator } from "./model.js";
|
|
2
|
+
export interface ValibotOptions {
|
|
3
|
+
path: string;
|
|
4
|
+
/** Module the types come from, relative to `path`. */
|
|
5
|
+
typesImport: string;
|
|
6
|
+
runtimeImport?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Valibot schemas that keep the source's constraints at run time, which plain generated types lose. */
|
|
9
|
+
export declare const valibotGenerator: (options: ValibotOptions) => CodeGenerator;
|
|
10
|
+
//# sourceMappingURL=valibot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"valibot.d.ts","sourceRoot":"","sources":["../../src/codegen/valibot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,aAAa,EAAc,MAAM,YAAY,CAAA;AA8FrE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wGAAwG;AACxG,eAAO,MAAM,gBAAgB,YACjB,cAAc,KAAG,aAqB1B,CAAA"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { identifier } from "./names.js";
|
|
2
|
+
import { CodegenError } from "./pipeline.js";
|
|
3
|
+
import { SchemaTree } from "./tree.js";
|
|
4
|
+
const key = (name) => (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name));
|
|
5
|
+
const piped = (base, actions) => actions.length === 0 ? base : `v.pipe(${base}, ${actions.join(", ")})`;
|
|
6
|
+
const range = (node) => {
|
|
7
|
+
const parts = [];
|
|
8
|
+
if (node.minimum !== undefined)
|
|
9
|
+
parts.push(`minimum: ${node.minimum}`);
|
|
10
|
+
if (node.maximum !== undefined)
|
|
11
|
+
parts.push(`maximum: ${node.maximum}`);
|
|
12
|
+
return parts.length === 0 ? "" : `{ ${parts.join(", ")} }`;
|
|
13
|
+
};
|
|
14
|
+
class SchemaWriter {
|
|
15
|
+
tree;
|
|
16
|
+
helpers = new Set();
|
|
17
|
+
constructor(tree) {
|
|
18
|
+
this.tree = tree;
|
|
19
|
+
}
|
|
20
|
+
node(node, where, literal) {
|
|
21
|
+
const base = this.#bare(node, where, literal);
|
|
22
|
+
return node.nullable ? `v.nullable(${base})` : base;
|
|
23
|
+
}
|
|
24
|
+
#bare(node, where, literal) {
|
|
25
|
+
switch (node.type) {
|
|
26
|
+
case "ref":
|
|
27
|
+
return `v.lazy(() => ${identifier(node.ref)})`;
|
|
28
|
+
case "string": {
|
|
29
|
+
if (node.enum)
|
|
30
|
+
return `v.picklist(${JSON.stringify(node.enum)})`;
|
|
31
|
+
const actions = [];
|
|
32
|
+
if (node.minLength !== undefined)
|
|
33
|
+
actions.push(`v.minLength(${node.minLength})`);
|
|
34
|
+
if (node.maxLength !== undefined)
|
|
35
|
+
actions.push(`v.maxLength(${node.maxLength})`);
|
|
36
|
+
if (node.pattern !== undefined) {
|
|
37
|
+
try {
|
|
38
|
+
new RegExp(node.pattern);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
throw new CodegenError([`${where}: pattern ${JSON.stringify(node.pattern)} is not a JS regular expression`]);
|
|
42
|
+
}
|
|
43
|
+
actions.push(`v.regex(new RegExp(${JSON.stringify(node.pattern)}))`);
|
|
44
|
+
}
|
|
45
|
+
return piped("v.string()", actions);
|
|
46
|
+
}
|
|
47
|
+
case "integer": {
|
|
48
|
+
const helper = node.format === "int64" ? "int64" : "integer";
|
|
49
|
+
this.helpers.add(helper);
|
|
50
|
+
const call = `${helper}(${range(node)})`;
|
|
51
|
+
return node.enum ? piped(call, [`v.picklist(${JSON.stringify(node.enum)})`]) : call;
|
|
52
|
+
}
|
|
53
|
+
case "number":
|
|
54
|
+
this.helpers.add("number");
|
|
55
|
+
return `number(${range(node)})`;
|
|
56
|
+
case "boolean":
|
|
57
|
+
return "v.boolean()";
|
|
58
|
+
case "unknown":
|
|
59
|
+
return "v.unknown()";
|
|
60
|
+
case "array": {
|
|
61
|
+
const actions = [];
|
|
62
|
+
if (node.minItems !== undefined)
|
|
63
|
+
actions.push(`v.minLength(${node.minItems})`);
|
|
64
|
+
if (node.maxItems !== undefined)
|
|
65
|
+
actions.push(`v.maxLength(${node.maxItems})`);
|
|
66
|
+
if (node.uniqueItems)
|
|
67
|
+
this.helpers.add("unique");
|
|
68
|
+
if (node.uniqueItems)
|
|
69
|
+
actions.push(`v.check((items) => unique(items), "items must be unique")`);
|
|
70
|
+
return piped(`v.array(${this.node(node.items, `${where}[]`)})`, actions);
|
|
71
|
+
}
|
|
72
|
+
case "allOf":
|
|
73
|
+
if (node.of.length === 1 && node.of[0] && !literal)
|
|
74
|
+
return this.#bare(node.of[0], where);
|
|
75
|
+
return this.#object(this.tree.flatten(node, where), where, literal);
|
|
76
|
+
case "object":
|
|
77
|
+
return this.#object(node, where, literal);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Loose on purpose: MAX adds fields, and a response with a field we have never seen is still valid.
|
|
81
|
+
#object(node, where, literal) {
|
|
82
|
+
const names = Object.keys(node.properties);
|
|
83
|
+
if (literal && !names.includes(literal.property))
|
|
84
|
+
names.unshift(literal.property);
|
|
85
|
+
const rest = node.additionalProperties ? this.node(node.additionalProperties, where) : undefined;
|
|
86
|
+
if (names.length === 0)
|
|
87
|
+
return rest ? `v.record(v.string(), ${rest})` : "v.looseObject({})";
|
|
88
|
+
const entries = names.map((name) => {
|
|
89
|
+
if (literal?.property === name)
|
|
90
|
+
return ` ${key(name)}: v.literal(${JSON.stringify(literal.value)}),`;
|
|
91
|
+
const property = node.properties[name];
|
|
92
|
+
const schema = this.node(property, `${where}.${name}`);
|
|
93
|
+
return ` ${key(name)}: ${node.required.includes(name) ? schema : `v.optional(${schema})`},`;
|
|
94
|
+
});
|
|
95
|
+
const body = `{\n${entries.join("\n")}\n}`;
|
|
96
|
+
return rest ? `v.objectWithRest(${body}, ${rest})` : `v.looseObject(${body})`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Valibot schemas that keep the source's constraints at run time, which plain generated types lose. */
|
|
100
|
+
export const valibotGenerator = (options) => (model) => {
|
|
101
|
+
const tree = new SchemaTree(model);
|
|
102
|
+
const writer = new SchemaWriter(tree);
|
|
103
|
+
const declarations = tree.named.map(({ name, schema }) => {
|
|
104
|
+
const expression = schema.discriminator
|
|
105
|
+
? `v.union([${Object.values(schema.discriminator.mapping)
|
|
106
|
+
.map((target) => `v.lazy(() => ${identifier(target)})`)
|
|
107
|
+
.join(", ")}])`
|
|
108
|
+
: writer.node(schema.schema, schema.id, tree.literalFor(schema.id));
|
|
109
|
+
return `export const ${name}: v.GenericSchema<unknown, T.${name}> = ${expression}\n`;
|
|
110
|
+
});
|
|
111
|
+
const helpers = [...writer.helpers].sort();
|
|
112
|
+
const runtime = options.runtimeImport ?? "@leemour/cli-core/codegen/runtime";
|
|
113
|
+
const packages = [
|
|
114
|
+
`import * as v from "valibot"`,
|
|
115
|
+
...(helpers.length > 0 ? [`import { ${helpers.join(", ")} } from "${runtime}"`] : []),
|
|
116
|
+
].sort((a, b) => (a.split(" from ")[1] ?? "").localeCompare(b.split(" from ")[1] ?? ""));
|
|
117
|
+
const header = [...packages, `import type * as T from "${options.typesImport}"`, ""];
|
|
118
|
+
const registry = `export const schemas = {\n${tree.named.map(({ name }) => ` ${name},`).join("\n")}\n} as const\n`;
|
|
119
|
+
return [{ path: options.path, content: `${header.join("\n")}\n${declarations.join("\n")}\n${registry}` }];
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=valibot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"valibot.js","sourceRoot":"","sources":["../../src/codegen/valibot.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leemour/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
|
@@ -41,6 +41,14 @@
|
|
|
41
41
|
"./update": {
|
|
42
42
|
"types": "./dist/update/index.d.ts",
|
|
43
43
|
"default": "./dist/update/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./codegen": {
|
|
46
|
+
"types": "./dist/codegen/index.d.ts",
|
|
47
|
+
"default": "./dist/codegen/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./codegen/runtime": {
|
|
50
|
+
"types": "./dist/codegen/runtime.d.ts",
|
|
51
|
+
"default": "./dist/codegen/runtime.js"
|
|
44
52
|
}
|
|
45
53
|
},
|
|
46
54
|
"dependencies": {
|