@redocly/client-generator 0.0.0-snapshot.1786868116 → 0.0.0-snapshot.1787063344
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 +22 -30
- package/eject-assets/AGENTS.md +130 -0
- package/eject-assets/generators/cli.mjs +700 -0
- package/eject-assets/generators/go.mjs +856 -0
- package/eject-assets/generators/mock.mjs +689 -0
- package/eject-assets/generators/php.mjs +830 -0
- package/eject-assets/generators/python.mjs +742 -0
- package/eject-assets/generators/swr.mjs +267 -0
- package/eject-assets/generators/tanstack-query.mjs +632 -0
- package/eject-assets/generators/transformers.mjs +403 -0
- package/eject-assets/generators/typescript.mjs +1819 -0
- package/eject-assets/generators/zod.mjs +520 -0
- package/eject-assets/skills/cli-generator/SKILL.md +112 -0
- package/eject-assets/skills/client-generators/SKILL.md +135 -0
- package/eject-assets/skills/go-generator/SKILL.md +89 -0
- package/eject-assets/skills/mock-generator/SKILL.md +45 -0
- package/eject-assets/skills/php-generator/SKILL.md +105 -0
- package/eject-assets/skills/python-generator/SKILL.md +93 -0
- package/eject-assets/skills/swr-generator/SKILL.md +44 -0
- package/eject-assets/skills/tanstack-query-generator/SKILL.md +48 -0
- package/eject-assets/skills/transformers-generator/SKILL.md +43 -0
- package/eject-assets/skills/typescript-generator/SKILL.md +73 -0
- package/eject-assets/skills/zod-generator/SKILL.md +49 -0
- package/lib/authoring/index.d.ts +10 -0
- package/lib/authoring/index.d.ts.map +1 -0
- package/lib/authoring/index.js +33 -0
- package/lib/authoring/index.js.map +1 -0
- package/lib/authoring/naming.d.ts +19 -0
- package/lib/authoring/naming.d.ts.map +1 -0
- package/lib/authoring/naming.js +80 -0
- package/lib/authoring/naming.js.map +1 -0
- package/lib/authoring/options.d.ts +9 -0
- package/lib/authoring/options.d.ts.map +1 -0
- package/lib/authoring/options.js +5 -0
- package/lib/authoring/options.js.map +1 -0
- package/lib/authoring/pagination.d.ts +19 -0
- package/lib/authoring/pagination.d.ts.map +1 -0
- package/lib/authoring/pagination.js +45 -0
- package/lib/authoring/pagination.js.map +1 -0
- package/lib/authoring/printer.d.ts +16 -0
- package/lib/authoring/printer.d.ts.map +1 -0
- package/lib/authoring/printer.js +36 -0
- package/lib/authoring/printer.js.map +1 -0
- package/lib/authoring/reference-page.d.ts +29 -0
- package/lib/authoring/reference-page.d.ts.map +1 -0
- package/lib/authoring/reference-page.js +157 -0
- package/lib/authoring/reference-page.js.map +1 -0
- package/lib/authoring/schema.d.ts +49 -0
- package/lib/authoring/schema.d.ts.map +1 -0
- package/lib/authoring/schema.js +185 -0
- package/lib/authoring/schema.js.map +1 -0
- package/lib/emitters/cli-docs.d.ts +17 -0
- package/lib/emitters/cli-docs.d.ts.map +1 -0
- package/lib/emitters/cli-docs.js +186 -0
- package/lib/emitters/cli-docs.js.map +1 -0
- package/lib/emitters/cli.d.ts +38 -0
- package/lib/emitters/cli.d.ts.map +1 -0
- package/lib/emitters/cli.js +230 -0
- package/lib/emitters/cli.js.map +1 -0
- package/lib/emitters/client-assembly.d.ts.map +1 -1
- package/lib/emitters/client-assembly.js +45 -172
- package/lib/emitters/client-assembly.js.map +1 -1
- package/lib/emitters/descriptor.d.ts +4 -13
- package/lib/emitters/descriptor.d.ts.map +1 -1
- package/lib/emitters/descriptor.js +34 -123
- package/lib/emitters/descriptor.js.map +1 -1
- package/lib/emitters/emit-options.d.ts +22 -1
- package/lib/emitters/emit-options.d.ts.map +1 -1
- package/lib/emitters/emit-options.js +1 -1
- package/lib/emitters/emit-options.js.map +1 -1
- package/lib/emitters/faker.d.ts +3 -3
- package/lib/emitters/faker.d.ts.map +1 -1
- package/lib/emitters/faker.js +66 -107
- package/lib/emitters/faker.js.map +1 -1
- package/lib/emitters/go-runtime-sources.d.ts +2 -0
- package/lib/emitters/go-runtime-sources.d.ts.map +1 -0
- package/lib/emitters/go-runtime-sources.js +3 -0
- package/lib/emitters/go-runtime-sources.js.map +1 -0
- package/lib/emitters/identifier.d.ts.map +1 -1
- package/lib/emitters/identifier.js +10 -0
- package/lib/emitters/identifier.js.map +1 -1
- package/lib/emitters/inline-runtime.d.ts +2 -0
- package/lib/emitters/inline-runtime.d.ts.map +1 -1
- package/lib/emitters/inline-runtime.js +14 -45
- package/lib/emitters/inline-runtime.js.map +1 -1
- package/lib/emitters/jsdoc.d.ts +2 -0
- package/lib/emitters/jsdoc.d.ts.map +1 -1
- package/lib/emitters/jsdoc.js +4 -1
- package/lib/emitters/jsdoc.js.map +1 -1
- package/lib/emitters/mock-value.d.ts +33 -0
- package/lib/emitters/mock-value.d.ts.map +1 -0
- package/lib/emitters/mock-value.js +47 -0
- package/lib/emitters/mock-value.js.map +1 -0
- package/lib/emitters/mock.d.ts.map +1 -1
- package/lib/emitters/mock.js +88 -123
- package/lib/emitters/mock.js.map +1 -1
- package/lib/emitters/operation-types.d.ts +1 -24
- package/lib/emitters/operation-types.d.ts.map +1 -1
- package/lib/emitters/operation-types.js +1 -107
- package/lib/emitters/operation-types.js.map +1 -1
- package/lib/emitters/operations.d.ts +2 -10
- package/lib/emitters/operations.d.ts.map +1 -1
- package/lib/emitters/operations.js +1 -34
- package/lib/emitters/operations.js.map +1 -1
- package/lib/emitters/pagination.d.ts +6 -13
- package/lib/emitters/pagination.d.ts.map +1 -1
- package/lib/emitters/pagination.js +11 -49
- package/lib/emitters/pagination.js.map +1 -1
- package/lib/emitters/php-runtime-sources.d.ts +2 -0
- package/lib/emitters/php-runtime-sources.d.ts.map +1 -0
- package/lib/emitters/php-runtime-sources.js +3 -0
- package/lib/emitters/php-runtime-sources.js.map +1 -0
- package/lib/emitters/python-runtime-sources.d.ts +12 -0
- package/lib/emitters/python-runtime-sources.d.ts.map +1 -0
- package/lib/emitters/python-runtime-sources.js +12 -0
- package/lib/emitters/python-runtime-sources.js.map +1 -0
- package/lib/emitters/render-client.d.ts +31 -0
- package/lib/emitters/render-client.d.ts.map +1 -0
- package/lib/emitters/render-client.js +346 -0
- package/lib/emitters/render-client.js.map +1 -0
- package/lib/emitters/reserved-names.d.ts +4 -1
- package/lib/emitters/reserved-names.d.ts.map +1 -1
- package/lib/emitters/reserved-names.js +16 -27
- package/lib/emitters/reserved-names.js.map +1 -1
- package/lib/emitters/response-headers.d.ts +5 -6
- package/lib/emitters/response-headers.d.ts.map +1 -1
- package/lib/emitters/response-headers.js +13 -63
- package/lib/emitters/response-headers.js.map +1 -1
- package/lib/emitters/runtime-sources.d.ts +20 -0
- package/lib/emitters/runtime-sources.d.ts.map +1 -1
- package/lib/emitters/runtime-sources.js +130 -0
- package/lib/emitters/runtime-sources.js.map +1 -1
- package/lib/emitters/setup-bake.d.ts.map +1 -1
- package/lib/emitters/setup-bake.js +10 -1
- package/lib/emitters/setup-bake.js.map +1 -1
- package/lib/emitters/sse.d.ts +3 -5
- package/lib/emitters/sse.d.ts.map +1 -1
- package/lib/emitters/sse.js +1 -11
- package/lib/emitters/sse.js.map +1 -1
- package/lib/emitters/swr.d.ts.map +1 -1
- package/lib/emitters/swr.js +34 -65
- package/lib/emitters/swr.js.map +1 -1
- package/lib/emitters/tanstack-query.d.ts.map +1 -1
- package/lib/emitters/tanstack-query.js +3 -5
- package/lib/emitters/tanstack-query.js.map +1 -1
- package/lib/emitters/transformers.d.ts.map +1 -1
- package/lib/emitters/transformers.js +123 -162
- package/lib/emitters/transformers.js.map +1 -1
- package/lib/emitters/ts-literal.d.ts +5 -0
- package/lib/emitters/ts-literal.d.ts.map +1 -0
- package/lib/emitters/ts-literal.js +35 -0
- package/lib/emitters/ts-literal.js.map +1 -0
- package/lib/emitters/ts-type.d.ts +9 -0
- package/lib/emitters/ts-type.d.ts.map +1 -0
- package/lib/emitters/ts-type.js +133 -0
- package/lib/emitters/ts-type.js.map +1 -0
- package/lib/emitters/type-guards.d.ts +2 -19
- package/lib/emitters/type-guards.d.ts.map +1 -1
- package/lib/emitters/type-guards.js +18 -52
- package/lib/emitters/type-guards.js.map +1 -1
- package/lib/emitters/types.d.ts +1 -14
- package/lib/emitters/types.d.ts.map +1 -1
- package/lib/emitters/types.js +4 -124
- package/lib/emitters/types.js.map +1 -1
- package/lib/emitters/wrapper-support.d.ts +10 -23
- package/lib/emitters/wrapper-support.d.ts.map +1 -1
- package/lib/emitters/wrapper-support.js +23 -53
- package/lib/emitters/wrapper-support.js.map +1 -1
- package/lib/emitters/zod.d.ts +2 -3
- package/lib/emitters/zod.d.ts.map +1 -1
- package/lib/emitters/zod.js +115 -148
- package/lib/emitters/zod.js.map +1 -1
- package/lib/generate.d.ts +5 -4
- package/lib/generate.d.ts.map +1 -1
- package/lib/generate.js +22 -103
- package/lib/generate.js.map +1 -1
- package/lib/generators/cli/index.d.ts +13 -0
- package/lib/generators/cli/index.d.ts.map +1 -0
- package/lib/generators/cli/index.js +67 -0
- package/lib/generators/cli/index.js.map +1 -0
- package/lib/generators/compatibility.d.ts +10 -0
- package/lib/generators/compatibility.d.ts.map +1 -0
- package/lib/generators/compatibility.js +45 -0
- package/lib/generators/compatibility.js.map +1 -0
- package/lib/generators/go/index.d.ts +18 -0
- package/lib/generators/go/index.d.ts.map +1 -0
- package/lib/generators/go/index.js +838 -0
- package/lib/generators/go/index.js.map +1 -0
- package/lib/generators/index.d.ts +2 -2
- package/lib/generators/index.d.ts.map +1 -1
- package/lib/generators/index.js +31 -53
- package/lib/generators/index.js.map +1 -1
- package/lib/generators/meta.d.ts +14 -0
- package/lib/generators/meta.d.ts.map +1 -0
- package/lib/generators/meta.js +168 -0
- package/lib/generators/meta.js.map +1 -0
- package/lib/generators/{mock.d.ts → mock/index.d.ts} +2 -2
- package/lib/generators/mock/index.d.ts.map +1 -0
- package/lib/generators/{mock.js → mock/index.js} +4 -4
- package/lib/generators/mock/index.js.map +1 -0
- package/lib/generators/options.d.ts +7 -0
- package/lib/generators/options.d.ts.map +1 -0
- package/lib/generators/options.js +74 -0
- package/lib/generators/options.js.map +1 -0
- package/lib/generators/php/index.d.ts +18 -0
- package/lib/generators/php/index.d.ts.map +1 -0
- package/lib/generators/php/index.js +812 -0
- package/lib/generators/php/index.js.map +1 -0
- package/lib/generators/python/index.d.ts +21 -0
- package/lib/generators/python/index.d.ts.map +1 -0
- package/lib/generators/python/index.js +725 -0
- package/lib/generators/python/index.js.map +1 -0
- package/lib/generators/resolve.d.ts.map +1 -1
- package/lib/generators/resolve.js +73 -11
- package/lib/generators/resolve.js.map +1 -1
- package/lib/generators/{swr.d.ts → swr/index.d.ts} +3 -3
- package/lib/generators/swr/index.d.ts.map +1 -0
- package/lib/generators/{swr.js → swr/index.js} +5 -5
- package/lib/generators/swr/index.js.map +1 -0
- package/lib/generators/{tanstack-query.d.ts → tanstack-query/index.d.ts} +3 -3
- package/lib/generators/tanstack-query/index.d.ts.map +1 -0
- package/lib/generators/{tanstack-query.js → tanstack-query/index.js} +5 -5
- package/lib/generators/{tanstack-query.js.map → tanstack-query/index.js.map} +1 -1
- package/lib/generators/{transformers.d.ts → transformers/index.d.ts} +2 -2
- package/lib/generators/transformers/index.d.ts.map +1 -0
- package/lib/generators/{transformers.js → transformers/index.js} +4 -4
- package/lib/generators/transformers/index.js.map +1 -0
- package/lib/generators/types.d.ts +82 -4
- package/lib/generators/types.d.ts.map +1 -1
- package/lib/generators/typescript/index.d.ts +21 -0
- package/lib/generators/typescript/index.d.ts.map +1 -0
- package/lib/generators/typescript/index.js +80 -0
- package/lib/generators/typescript/index.js.map +1 -0
- package/lib/generators/{zod.d.ts → zod/index.d.ts} +2 -2
- package/lib/generators/zod/index.d.ts.map +1 -0
- package/lib/generators/{zod.js → zod/index.js} +4 -4
- package/lib/generators/zod/index.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -2
- package/lib/index.js.map +1 -1
- package/lib/intermediate-representation/build.d.ts.map +1 -1
- package/lib/intermediate-representation/build.js +31 -2
- package/lib/intermediate-representation/build.js.map +1 -1
- package/lib/intermediate-representation/model.d.ts +13 -1
- package/lib/intermediate-representation/model.d.ts.map +1 -1
- package/lib/intermediate-representation/model.js.map +1 -1
- package/lib/intermediate-representation/sanitize-identifiers.d.ts.map +1 -1
- package/lib/intermediate-representation/sanitize-identifiers.js +35 -13
- package/lib/intermediate-representation/sanitize-identifiers.js.map +1 -1
- package/lib/pipeline.d.ts +20 -0
- package/lib/pipeline.d.ts.map +1 -0
- package/lib/pipeline.js +199 -0
- package/lib/pipeline.js.map +1 -0
- package/lib/plugin.d.ts +1 -0
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +8 -7
- package/lib/plugin.js.map +1 -1
- package/lib/runtime/cli.d.ts +135 -0
- package/lib/runtime/cli.d.ts.map +1 -0
- package/lib/runtime/cli.js +558 -0
- package/lib/runtime/cli.js.map +1 -0
- package/lib/runtime-sources.d.ts +4 -0
- package/lib/runtime-sources.d.ts.map +1 -0
- package/lib/runtime-sources.js +9 -0
- package/lib/runtime-sources.js.map +1 -0
- package/lib/types.d.ts +35 -3
- package/lib/types.d.ts.map +1 -1
- package/package.json +10 -4
- package/lib/emitters/auth.d.ts +0 -14
- package/lib/emitters/auth.d.ts.map +0 -1
- package/lib/emitters/auth.js +0 -30
- package/lib/emitters/auth.js.map +0 -1
- package/lib/emitters/operation-aliases.d.ts +0 -27
- package/lib/emitters/operation-aliases.d.ts.map +0 -1
- package/lib/emitters/operation-aliases.js +0 -150
- package/lib/emitters/operation-aliases.js.map +0 -1
- package/lib/emitters/ts.d.ts +0 -42
- package/lib/emitters/ts.d.ts.map +0 -1
- package/lib/emitters/ts.js +0 -116
- package/lib/emitters/ts.js.map +0 -1
- package/lib/generators/mock.d.ts.map +0 -1
- package/lib/generators/mock.js.map +0 -1
- package/lib/generators/sdk.d.ts +0 -12
- package/lib/generators/sdk.d.ts.map +0 -1
- package/lib/generators/sdk.js +0 -26
- package/lib/generators/sdk.js.map +0 -1
- package/lib/generators/swr.d.ts.map +0 -1
- package/lib/generators/swr.js.map +0 -1
- package/lib/generators/tanstack-query.d.ts.map +0 -1
- package/lib/generators/transformers.d.ts.map +0 -1
- package/lib/generators/transformers.js.map +0 -1
- package/lib/generators/zod.d.ts.map +0 -1
- package/lib/generators/zod.js.map +0 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ import { generateClient } from '@redocly/client-generator';
|
|
|
27
27
|
const result = await generateClient({
|
|
28
28
|
api: './openapi.yaml', // file path or URL; OpenAPI 3.0/3.1/3.2 or Swagger 2.0
|
|
29
29
|
output: './src/api/client.ts',
|
|
30
|
-
generators: ['
|
|
30
|
+
generators: ['typescript', 'zod'],
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
console.log(`Wrote ${result.files.length} file(s), ${result.bytes} bytes.`);
|
|
@@ -55,43 +55,32 @@ With `runtime: 'package'` the generated client also imports its whole engine fro
|
|
|
55
55
|
### Write a custom generator
|
|
56
56
|
|
|
57
57
|
A custom generator reads the same API model the built-ins consume, runs in the same pass, and returns files.
|
|
58
|
-
|
|
58
|
+
Emitters print text: `Printer` handles indentation, and `tsType` is the same schema→type renderer the built-in sdk uses, so the mapping (refs, arrays, unions, formats, parenthesization) matches the generated client exactly:
|
|
59
59
|
|
|
60
60
|
```ts
|
|
61
61
|
// response-map-generator.ts
|
|
62
|
-
import { defineGenerator } from '@redocly/client-generator';
|
|
63
|
-
import {
|
|
64
|
-
|
|
65
|
-
const { factory } = ts;
|
|
62
|
+
import { defineGenerator, Printer } from '@redocly/client-generator';
|
|
63
|
+
import { tsType } from '@redocly/client-generator/generate';
|
|
66
64
|
|
|
67
65
|
export default defineGenerator({
|
|
68
66
|
name: 'response-map',
|
|
69
|
-
requires: ['
|
|
67
|
+
requires: ['typescript'],
|
|
70
68
|
run({ model, outputPath }) {
|
|
69
|
+
const printer = new Printer();
|
|
71
70
|
// One `ResponseShapes` entry per operation with a JSON success body.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
),
|
|
84
|
-
];
|
|
85
|
-
});
|
|
86
|
-
const alias = factory.createTypeAliasDeclaration(
|
|
87
|
-
[factory.createModifier(ts.SyntaxKind.ExportKeyword)],
|
|
88
|
-
'ResponseShapes',
|
|
89
|
-
undefined,
|
|
90
|
-
factory.createTypeLiteralNode(members)
|
|
71
|
+
printer.block(
|
|
72
|
+
'export type ResponseShapes = {',
|
|
73
|
+
() => {
|
|
74
|
+
for (const service of model.services) {
|
|
75
|
+
for (const op of service.operations) {
|
|
76
|
+
const success = op.successResponses.find((r) => r.contentType.includes('json'));
|
|
77
|
+
if (success) printer.line(`${op.name}: ${tsType(success.schema)};`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
'};'
|
|
91
82
|
);
|
|
92
|
-
return [
|
|
93
|
-
{ path: outputPath.replace(/\.ts$/, '.responses.ts'), content: printStatements([alias]) },
|
|
94
|
-
];
|
|
83
|
+
return [{ path: outputPath.replace(/\.ts$/, '.responses.ts'), content: printer.toString() }];
|
|
95
84
|
},
|
|
96
85
|
});
|
|
97
86
|
```
|
|
@@ -150,7 +139,10 @@ Authors a custom generator (`{ name, run }` plus optional `requires`/`errorModes
|
|
|
150
139
|
function defineGenerator(generator: CustomGenerator): CustomGenerator;
|
|
151
140
|
```
|
|
152
141
|
|
|
153
|
-
The `@redocly/client-generator/generate` entry also exports the
|
|
142
|
+
The `@redocly/client-generator/generate` entry also exports the TypeScript renderers the built-ins use (`tsType`, `tsJsdoc`, `codeLiteral`, `operationSignature`, `pascalCase`, `safeIdent`).
|
|
143
|
+
The package root exports the IR types plus the language-neutral toolkit.
|
|
144
|
+
A custom generator emits TypeScript exactly as the first-party ones do.
|
|
145
|
+
See the [`typescript-types-generator` example](https://github.com/Redocly/redocly-cli/tree/main/tests/e2e/generate-client/examples/typescript-types-generator).
|
|
154
146
|
|
|
155
147
|
### `defineClientSetup`
|
|
156
148
|
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Writing custom client generators
|
|
2
|
+
|
|
3
|
+
A generator is a plain module: `(input) => GeneratedFile[]`. It receives the
|
|
4
|
+
language-agnostic API model and returns files — in ANY output language. It runs
|
|
5
|
+
in the same pass as the built-ins; select it by path in `redocly.yaml`:
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
client:
|
|
9
|
+
generators: [typescript, ./generators/my-generator.mjs]
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## The contract
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
/** @type {import('@redocly/client-generator').CustomGenerator} */
|
|
16
|
+
export default {
|
|
17
|
+
name: 'my-generator',
|
|
18
|
+
run({ model, outputPath, outputMode, emit }) {
|
|
19
|
+
return [{ path: outputPath.replace(/\.ts$/, '.mine.txt'), content: '…' }];
|
|
20
|
+
},
|
|
21
|
+
// Optional: one idiomatic call snippet per operation for docs (x-codeSamples),
|
|
22
|
+
// collected into an overlay file when `client.codeSamples: true` is set.
|
|
23
|
+
sample(operation, { model, emit }) {
|
|
24
|
+
return { lang: 'python', source: '…' };
|
|
25
|
+
},
|
|
26
|
+
// Optional: the reference page for what `run` emits, written when `client.docs` (or
|
|
27
|
+
// --docs) is on. Same `{ path, content }` shape as `run`; `renderReferencePage` gives
|
|
28
|
+
// the standard layout and takes `sample` for its snippets. A generator documents itself.
|
|
29
|
+
docs({ model, outputPath, emit }) {
|
|
30
|
+
return [{ path: outputPath.replace(/\.ts$/, '.mine.md'), content: '…' }];
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Declaring options
|
|
36
|
+
|
|
37
|
+
A generator that needs configuration declares it as a schema; `run` then receives
|
|
38
|
+
`options` already validated, with defaults applied:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
export default {
|
|
42
|
+
name: 'permissions-matrix',
|
|
43
|
+
options: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: { groupBy: { enum: ['tag', 'path'], default: 'tag' } },
|
|
46
|
+
additionalProperties: false,
|
|
47
|
+
},
|
|
48
|
+
run({ model, outputPath, options }) {
|
|
49
|
+
return [
|
|
50
|
+
{ path: outputPath.replace(/\.ts$/, '.permissions.md'), content: render(options.groupBy) },
|
|
51
|
+
];
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Users set them per generator name:
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
client:
|
|
60
|
+
generators: [typescript, ./generators/permissions-matrix.mjs]
|
|
61
|
+
options:
|
|
62
|
+
permissions-matrix:
|
|
63
|
+
groupBy: path
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The supported subset is a top-level `type: 'object'` with `properties`, `required`, and
|
|
67
|
+
`additionalProperties`; each property is a scalar (`string`/`number`/`boolean`), an
|
|
68
|
+
`enum`, or an array of scalars, and may carry a `default` and a `description`. Don't
|
|
69
|
+
validate options inside `run` — an unknown key, a wrong type, a value outside an `enum`,
|
|
70
|
+
or a missing `required` key already fails generation before `run` is called.
|
|
71
|
+
|
|
72
|
+
Rules: output is deterministic (same description → same bytes); never add
|
|
73
|
+
dependencies to the generated client; **never hand-edit generated output** —
|
|
74
|
+
edit this generator and regenerate. Emitted file paths must stay inside the
|
|
75
|
+
`--output` directory (subdirectories are fine) — escapes are rejected.
|
|
76
|
+
Optionally declare `requiresGenerator` — the `@redocly/client-generator` version
|
|
77
|
+
range you wrote this against (`'^1.2.0'`, `'~1.2.0'`, `'>=1.2.0'`, or an exact
|
|
78
|
+
version). A CLI outside the range then fails with the fix path instead of feeding
|
|
79
|
+
your generator an unexpected model shape. Ejected generators carry it
|
|
80
|
+
automatically; hand-written ones without it are taken as current.
|
|
81
|
+
|
|
82
|
+
## The model (IR)
|
|
83
|
+
|
|
84
|
+
`model.services[].operations[]` — each operation carries `name`, `specName`,
|
|
85
|
+
`method`, `path`, `tags`, `pathParams`/`queryParams`/`headerParams`/`cookieParams`,
|
|
86
|
+
`requestBody`, `successResponses`/`errorResponses` (each with a `schema`), and
|
|
87
|
+
`security`. `model.schemas` holds the named schemas. Every schema is a
|
|
88
|
+
discriminated union on `kind`: `scalar`, `array`, `object`, `record`, `ref`,
|
|
89
|
+
`literal`, `enum`, `union` (optionally with a discriminator), `intersection`
|
|
90
|
+
(allOf), `null`, `unknown`, `omit`.
|
|
91
|
+
|
|
92
|
+
## Helpers (import from '@redocly/client-generator')
|
|
93
|
+
|
|
94
|
+
| Helper | Use |
|
|
95
|
+
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
96
|
+
| `flattenAllOf(schema, model)` | The merged property view of allOf compositions — languages without intersection types render this. |
|
|
97
|
+
| `discriminatorCases(schema, model)` | `{ property, cases }` dispatch table for discriminated unions. |
|
|
98
|
+
| `isNullable(schema)` / `unwrapNullable(schema)` | Detect and strip `null` union members (`Optional[T]`, pointers, `Option<T>`). |
|
|
99
|
+
| `enumValues(schema)` | Values plus SCREAMING_SNAKE member-name suggestions. |
|
|
100
|
+
| `headerCoerceType(schema, model)` | Response-header coerce hint (`integer`/`number`/`boolean`/`string`) through refs, nullables, and allOf wrappers. |
|
|
101
|
+
| `casing` / `identifierFor(name, { style, reserved })` | camel/pascal/snake/screaming; keyword-safe identifiers (`RESERVED_WORDS.python/go/typescript` shipped). |
|
|
102
|
+
| `Printer` | Indentation-aware text builder — no manual whitespace bookkeeping. |
|
|
103
|
+
| `docText(description)` | Description as trimmed lines for any comment syntax. |
|
|
104
|
+
| `schemaAtPointer(schema, pointer, model)` | Resolve an RFC 6901 JSON pointer over a schema (through refs and allOf) — e.g. a pagination `items` pointer to its element type. |
|
|
105
|
+
| `paginationRuleFor(op, config)` | The pagination rule that applies to an operation (per-op config > extension > fitting convention), normalized. |
|
|
106
|
+
| `renderReferencePage(model, options)` | The Markdown reference page a generator's `docs` hook returns — your `sample` hook supplies its call snippets. |
|
|
107
|
+
| `NotSupportedError` | Throw it to reject an option the generator can't honor — the CLI prints the message as a user error, not a crash. |
|
|
108
|
+
| `AUTHORING_HELPER_NAMES` | The list of the above (introspection). |
|
|
109
|
+
|
|
110
|
+
Worked example: the built-in `python` generator
|
|
111
|
+
(`packages/client-generator/src/generators/python/index.ts` in the Redocly CLI repo) is
|
|
112
|
+
authored with exactly this toolkit and nothing else — models via `flattenAllOf`/
|
|
113
|
+
`enumValues`/`discriminatorCases`, all code through `Printer`, every name through
|
|
114
|
+
`identifierFor(..., RESERVED_WORDS.python)`.
|
|
115
|
+
|
|
116
|
+
A generator that emits TypeScript may additionally use the source-text renderers from
|
|
117
|
+
`@redocly/client-generator/generate` — `tsType` (schema → type), `tsJsdoc`, `codeLiteral`,
|
|
118
|
+
`operationSignature`, `pascalCase`, `safeIdent`. There is no AST toolkit and no
|
|
119
|
+
`typescript` dependency: every generator prints text through `Printer`.
|
|
120
|
+
|
|
121
|
+
## The loop
|
|
122
|
+
|
|
123
|
+
1. Edit the generator.
|
|
124
|
+
2. Run `redocly generate-client`.
|
|
125
|
+
3. Inspect `git diff` of the generated output.
|
|
126
|
+
4. Repeat. Generated files are never hand-edited.
|
|
127
|
+
|
|
128
|
+
If you had to work around a **missing helper** or a wrong default, tell the user
|
|
129
|
+
and suggest filing an issue at https://github.com/Redocly/redocly-cli/issues —
|
|
130
|
+
include the generator snippet and the helper you expected to exist.
|