@leemour/cli-core 0.7.0 → 0.9.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 +73 -11
- 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/dist/logger.d.ts +1 -1
- package/dist/release/index.d.ts +37 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +90 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/markdown.d.ts +35 -0
- package/dist/release/markdown.d.ts.map +1 -0
- package/dist/release/markdown.js +150 -0
- package/dist/release/markdown.js.map +1 -0
- package/package.json +32 -13
package/README.md
CHANGED
|
@@ -7,8 +7,9 @@ keyring behind a testable seam, and injectable clocks.
|
|
|
7
7
|
Extracted from [`brazecli`](https://github.com/leemour/brazecli), where each piece earned its
|
|
8
8
|
shape, and shared with [`max-cli`](https://github.com/leemour/max-cli).
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
Published on npm and used by `max-cli`, `cli-messaging`, `tg-cli` and `brazecli`. What changed in
|
|
11
|
+
each version is in [`CHANGELOG.md`](CHANGELOG.md); how the package is put together and released is in
|
|
12
|
+
[`docs/dev/`](docs/dev/ARCHITECTURE.md).
|
|
12
13
|
|
|
13
14
|
## The rule this package exists to keep
|
|
14
15
|
|
|
@@ -46,6 +47,8 @@ streams.stderr // []
|
|
|
46
47
|
| `/commands` | the command registry: `describeProgram`, `annotate`, `flatten` — see below |
|
|
47
48
|
| `/completion` | shell completion over the registry: `suggest`, `formatSuggestions` — see below |
|
|
48
49
|
| `/update` | keeping an install current: `installerOf`, `updateCommand`, `latestVersion`, `mayNotify`, `updateNotice`, `runUpdate` — see below |
|
|
50
|
+
| `/codegen` | build time: an official API description → types, Valibot schemas, an operation manifest and a coverage page — see below |
|
|
51
|
+
| `/release` | release time: `releaseCheck` and the checks it runs — changelog shape, links, package contents, version in step — see below |
|
|
49
52
|
|
|
50
53
|
**Nothing in the root export is HTTP.** Status classification, `Retry-After` parsing and the fetch
|
|
51
54
|
seam live in `@leemour/cli-core/http`, so a CLI that speaks a socket never depends on a stack it
|
|
@@ -95,9 +98,40 @@ a throwaway config directory silently overwrites the real secret unless you pass
|
|
|
95
98
|
And a secret should never be handed to a logger in the first place — redaction by field name is the
|
|
96
99
|
second line of defence, not the first.
|
|
97
100
|
|
|
98
|
-
**Everything the environment knows
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
**Everything the environment knows can be passed in**: the clock, the sleep, the keyring, `env`,
|
|
102
|
+
`fetch` and the streams. The real ones are only defaults — `Credentials` without a `keyring` uses the
|
|
103
|
+
system keychain, `resolvePaths` without `env` reads `process.env`. Passing them is what makes a
|
|
104
|
+
timeout test finish instantly and a keyring test incapable of reaching a real keychain.
|
|
105
|
+
|
|
106
|
+
**Generating an API catalog is `@leemour/cli-core/codegen`**, a build-time tool. It reads a
|
|
107
|
+
format-neutral `ApiModel` — operations with a transport binding (`http` method and path, or `rpc`
|
|
108
|
+
name), an `effect` (`read`, `write`, `destructive`) and how far the source can be trusted
|
|
109
|
+
(`contract`, `example`, `inferred`, `override`) — and writes committed files. It parses no file
|
|
110
|
+
format: the adapter from OpenAPI, Postman or anything else lives in the CLI that has that source,
|
|
111
|
+
so this adds no dependency. Generation stops, naming the problem, when two operations collide, an
|
|
112
|
+
operation is not classified as a read or a write, an override matches nothing, a reference points
|
|
113
|
+
nowhere or a construct cannot be expressed; it never drops an operation or falls back to `any`.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { generate, manifestGenerator, typesGenerator, valibotGenerator, writeArtifacts } from "@leemour/cli-core/codegen"
|
|
117
|
+
|
|
118
|
+
const artifacts = generate(model, [typesGenerator({ path }), valibotGenerator({ path, typesImport }), manifestGenerator({ path })], {
|
|
119
|
+
overrides: { answerOnCallback: { effect: "write", reason: "a POST that edits a message" } },
|
|
120
|
+
banner: ["Source: spec/bot/schema.yaml", "Run: pnpm bot:generate"],
|
|
121
|
+
})
|
|
122
|
+
const stale = writeArtifacts(artifacts, { root, check: process.argv.includes("--check") })
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The generated schemas import `@leemour/cli-core/codegen/runtime` at run time — a few number
|
|
126
|
+
helpers, not the generator. Numbers are expected from a lossless JSON parser (`lossless-json`): a
|
|
127
|
+
64-bit integer comes out as its exact decimal string, and any other integer that does not fit a JS
|
|
128
|
+
number fails instead of rounding. Objects are loose, so a field the API added later passes through.
|
|
129
|
+
Enums and discriminated unions are **strict**: a value or subtype the snapshot does not know fails,
|
|
130
|
+
so decode a live stream (updates, webhooks) only where that is what you want.
|
|
131
|
+
|
|
132
|
+
**The schemas decode; they do not encode.** Their output carries an `int64` as a string, so sending
|
|
133
|
+
it back would put a string where the API expects a number. Validate a request with the schema, then
|
|
134
|
+
send the original lossless value.
|
|
101
135
|
|
|
102
136
|
**Keeping an install current is `@leemour/cli-core/update`.** `installerOf(realpath(script))` says
|
|
103
137
|
which package manager put the CLI there — pnpm, npm or bun, measured on real installs — and
|
|
@@ -110,6 +144,30 @@ sentence or `undefined` — it never throws. `runUpdate` starts the package mana
|
|
|
110
144
|
stderr (`spawnPlan` is the Windows `.cmd` rule). Nothing here updates or prints by itself — a CLI
|
|
111
145
|
holding somebody's credentials must not change itself unasked.
|
|
112
146
|
|
|
147
|
+
**The release checks are `@leemour/cli-core/release`** — everything about a release that a program
|
|
148
|
+
can decide. A check is `{ name, run }`, and `run` returns the problems it found, one line each; an
|
|
149
|
+
empty list is a pass. `releaseCheck(checks, { version, log })` runs them all, even after a failure,
|
|
150
|
+
prints `ok` or `FAIL` per check and returns how many failed — the caller exits. The checks every CLI
|
|
151
|
+
shares: `command(root, "pnpm", "lint")` for anything that passes by exiting 0, `notOnNpm`,
|
|
152
|
+
`packContents` against a list of what may ship, `changelogProblems` for the fixed headings and the
|
|
153
|
+
dated top section, `docsProblems` for dead links and anchors and the rules of the pages a user reads,
|
|
154
|
+
and `versionScript` — the whole of a `version:check` / `version:sync` script. Each CLI passes its
|
|
155
|
+
own headings, id prefixes and pages; the checks that belong to one messenger stay in that CLI.
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { command, notOnNpm, packageVersion, releaseCheck } from "@leemour/cli-core/release"
|
|
159
|
+
|
|
160
|
+
const version = packageVersion(root)
|
|
161
|
+
const failed = releaseCheck(
|
|
162
|
+
[
|
|
163
|
+
{ name: "version not on npm", run: notOnNpm(root, "@leemour/tg-cli", version) },
|
|
164
|
+
{ name: "lint", run: command(root, "pnpm", "lint") },
|
|
165
|
+
],
|
|
166
|
+
{ version, log: console.log },
|
|
167
|
+
)
|
|
168
|
+
process.exit(failed === 0 ? 0 : 1)
|
|
169
|
+
```
|
|
170
|
+
|
|
113
171
|
## Where secrets actually go, per platform
|
|
114
172
|
|
|
115
173
|
The keyring is real on every desktop and absent on most servers, so the fallback is not an edge
|
|
@@ -149,19 +207,23 @@ pnpm typecheck
|
|
|
149
207
|
pnpm build
|
|
150
208
|
```
|
|
151
209
|
|
|
210
|
+
The rest of the checks, and what each is for, are in [`docs/dev/TESTING.md`](docs/dev/TESTING.md).
|
|
211
|
+
|
|
152
212
|
## Releasing
|
|
153
213
|
|
|
154
|
-
Raise `version` in `package.json`
|
|
214
|
+
Raise `version` in `package.json` and date the `## Unreleased` section of
|
|
215
|
+
[`CHANGELOG.md`](CHANGELOG.md) as that version, through a pull request; merge it, then on `main`:
|
|
155
216
|
|
|
156
217
|
```sh
|
|
157
218
|
bin/release
|
|
158
219
|
```
|
|
159
220
|
|
|
160
|
-
It refuses a dirty tree, a branch other than `main
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
[
|
|
164
|
-
|
|
221
|
+
It refuses a dirty tree, a branch other than `main` and a `main` that is not pushed. When npm already
|
|
222
|
+
has the version, or a higher one, it commits the next free version to `main` — the next minor for
|
|
223
|
+
`x.y.0`, the next patch otherwise — renames the changelog heading to match, and publishes that. Then it starts
|
|
224
|
+
[`release.yml`](.github/workflows/release.yml) and follows it. The workflow runs every check,
|
|
225
|
+
publishes through npm's [trusted publishing](https://docs.npmjs.com/trusted-publishers/) — no npm
|
|
226
|
+
token in GitHub, and npm attaches provenance — and tags `v<version>` only once npm shows the new version.
|
|
165
227
|
|
|
166
228
|
npm trusts the workflow **by file name**: the package's Trusted Publisher settings on npmjs.com name
|
|
167
229
|
`leemour` / `cli-core` / `release.yml`. Rename the file and publishing stops until they are updated.
|
|
@@ -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"}
|