@octalmesh/seagull-core 0.0.2

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.
@@ -0,0 +1,270 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * The seagull config *schema* version - not the npm package's own version.
5
+ * Bumped only when the shape of `seagull.yaml` changes in a breaking way, so
6
+ * older configs fail with a clear "this config targets schema vN, seagull
7
+ * expects vM" error instead of a confusing validation failure on some
8
+ * unrelated field once the schema moves on.
9
+ */
10
+ export const CONFIG_SCHEMA_VERSION = 1;
11
+
12
+ /**
13
+ * A free-form tree of leaf values, used for the `vars:` block in the CLI config.
14
+ * Nest however deep is useful - every leaf becomes addressable as
15
+ * `{vars.<dot.path>}` in templated fields.
16
+ */
17
+ export interface VarsTree {
18
+ [key: string]: string | number | boolean | VarsTree;
19
+ }
20
+
21
+ export const varsTreeSchema: z.ZodType<VarsTree> = z.lazy(() =>
22
+ z.record(
23
+ z.string(),
24
+ z.union([z.string(), z.number(), z.boolean(), varsTreeSchema]),
25
+ ),
26
+ );
27
+
28
+ export const githubSchema = z.object({
29
+ owner: z.string().min(1),
30
+ repo: z.string().min(1),
31
+ });
32
+
33
+ export const pathsSchema = z.object({
34
+ dist: z.string().min(1).default("dist"),
35
+ specs: z.string().min(1).optional(),
36
+ docs: z.string().min(1).optional(),
37
+ sdk: z.string().min(1).optional(),
38
+ });
39
+
40
+ export const docsSchema = z.object({
41
+ server: z.object({
42
+ host: z.string().min(1),
43
+ port: z.number().int().positive(),
44
+ }),
45
+ metadata: z.object({
46
+ title: z.string().min(1),
47
+ description: z.string().min(1),
48
+ favicon: z.string().min(1),
49
+ baseServerUrl: z.string().min(1),
50
+ }),
51
+ });
52
+
53
+ export const sdkToolSchema = z.enum([
54
+ "openapi-generator",
55
+ "openapi-typescript",
56
+ ]);
57
+ export const sdkLangSchema = z.enum(["typescript", "go", "java"]);
58
+ export const sdkKindSchema = z.enum(["client", "server"]);
59
+
60
+ /**
61
+ * `-g`/`--additional-properties` values: openapi-generator accepts strings,
62
+ * numbers and booleans, all rendered as `key=value` on the CLI.
63
+ */
64
+ export const additionalPropertiesSchema = z
65
+ .record(z.string(), z.union([z.string(), z.number(), z.boolean()]))
66
+ .default({});
67
+
68
+ export const mavenCoordsSchema = z.object({
69
+ groupId: z.string().min(1),
70
+ artifactId: z.string().min(1),
71
+ });
72
+
73
+ /**
74
+ * Publishing conventions - git branch/tag naming, and where registry-backed
75
+ * artifacts (npm, Maven) get pushed. Every field is a template supporting the
76
+ * usual `{...}` placeholders (`{service}`, `{id}`, `{github.*}`, `{vars.*}`,
77
+ * and for `tag` only, also `{version}`).
78
+ *
79
+ * Required at the root level - seagull has no built-in opinion on branch/tag
80
+ * naming or which registry to use, so this has to come from the config, not
81
+ * from a hardcoded convention baked into the tool. Per-generator
82
+ * (`generators.<id>.publishing`) and per-contract-artifact
83
+ * (`artifacts[].overrides.publishing`) blocks only need to override the
84
+ * fields that differ for that generator/artifact - see
85
+ * {@link publishingOverrideSchema}.
86
+ */
87
+ export const publishingSchema = z.object({
88
+ /**
89
+ * Git branch artifacts publish to. Resolved once, at config-load time -
90
+ * no `{version}` available here, e.g. `"sdk/svc-{service}/{id}"`.
91
+ */
92
+ branch: z.string().min(1),
93
+ /**
94
+ * Git tag artifacts are tagged with on publish. Resolved at publish time,
95
+ * once the version is known, e.g. `"svc-{service}-{id}-v{version}"`.
96
+ */
97
+ tag: z.string().min(1),
98
+ /**
99
+ * Template for the `repository.url` field written into generated
100
+ * `package.json` (and shown in default README templates), e.g.
101
+ * `"https://github.com/{github.owner}/{github.repo}"`.
102
+ */
103
+ repositoryUrl: z.string().min(1),
104
+ npm: z.object({
105
+ registry: z.string().min(1),
106
+ access: z.enum(["public", "restricted"]),
107
+ }),
108
+ maven: z.object({
109
+ repositoryId: z.string().min(1),
110
+ repositoryUrl: z.string().min(1),
111
+ }),
112
+ });
113
+
114
+ export type PublishingInput = z.infer<typeof publishingSchema>;
115
+
116
+ /**
117
+ * The generator-level / per-artifact-override form of {@link publishingSchema} -
118
+ * every field optional, since it only needs to override whichever fields
119
+ * differ from the root-level `publishing:` (which is guaranteed complete).
120
+ */
121
+ export const publishingOverrideSchema = z.object({
122
+ branch: z.string().min(1).optional(),
123
+ tag: z.string().min(1).optional(),
124
+ repositoryUrl: z.string().min(1).optional(),
125
+ npm: z
126
+ .object({
127
+ registry: z.string().min(1).optional(),
128
+ access: z.enum(["public", "restricted"]).optional(),
129
+ })
130
+ .optional(),
131
+ maven: z
132
+ .object({
133
+ repositoryId: z.string().min(1).optional(),
134
+ repositoryUrl: z.string().min(1).optional(),
135
+ })
136
+ .optional(),
137
+ });
138
+
139
+ export type PublishingOverrideInput = z.infer<typeof publishingOverrideSchema>;
140
+
141
+ /**
142
+ * The shape of a generator "recipe", without the cross-field checks below -
143
+ * kept separate so {@link artifactRefSchema}'s `overrides:` can `.partial()`
144
+ * it (zod rejects `.partial()` on a schema with `.check()` refinements
145
+ * attached).
146
+ */
147
+ const generatorDefBaseSchema = z.object({
148
+ tool: sdkToolSchema,
149
+ lang: sdkLangSchema,
150
+ kind: sdkKindSchema,
151
+ /**
152
+ * `openapi-generator -g <generator>` value. Required when `tool` is
153
+ * `openapi-generator`.
154
+ */
155
+ generator: z.string().min(1).optional(),
156
+ /** npm package name template, e.g. `"@{vars.org}/{service}-client"`. */
157
+ package: z.string().min(1).optional(),
158
+ goModule: z.string().min(1).optional(),
159
+ goPackageName: z.string().min(1).optional(),
160
+ maven: mavenCoordsSchema.optional(),
161
+ additionalProperties: additionalPropertiesSchema,
162
+ /**
163
+ * Optional path (relative to the config file's directory) to a custom README
164
+ * template for this artifact - supports the same `{...}` placeholders as
165
+ * naming templates, plus `{version}`, `{title}`, and `{artifact.*}`. If
166
+ * omitted, a built-in default template for the artifact's language/kind is
167
+ * used instead.
168
+ */
169
+ readme: z.string().min(1).optional(),
170
+ /**
171
+ * Publishing conventions (branch/tag naming, registry URLs) for this
172
+ * generator specifically - overrides whichever fields differ from the
173
+ * root-level `publishing:` (required, see {@link publishingSchema}).
174
+ */
175
+ publishing: publishingOverrideSchema.optional(),
176
+ });
177
+
178
+ /**
179
+ * A single generator "recipe": which tool to invoke and how. Referenced by id
180
+ * from one or more contracts' `artifacts:` list.
181
+ */
182
+ export const generatorDefSchema = generatorDefBaseSchema.check((ctx) => {
183
+ const value = ctx.value;
184
+
185
+ if (value.tool === "openapi-generator" && !value.generator) {
186
+ ctx.issues.push({
187
+ code: "custom",
188
+ message: '"generator" is required when tool is "openapi-generator"',
189
+ input: value,
190
+ });
191
+ }
192
+
193
+ if (value.lang === "go" && !value.goModule) {
194
+ ctx.issues.push({
195
+ code: "custom",
196
+ message: '"goModule" is required for lang "go"',
197
+ input: value,
198
+ });
199
+ }
200
+
201
+ if (value.lang === "java" && !value.maven) {
202
+ ctx.issues.push({
203
+ code: "custom",
204
+ message: '"maven" ({ groupId, artifactId }) is required for lang "java"',
205
+ input: value,
206
+ });
207
+ }
208
+
209
+ if (value.lang === "typescript" && !value.package) {
210
+ ctx.issues.push({
211
+ code: "custom",
212
+ message: '"package" is required for lang "typescript"',
213
+ input: value,
214
+ });
215
+ }
216
+ });
217
+
218
+ export type GeneratorDefInput = z.infer<typeof generatorDefSchema>;
219
+
220
+ export const generatorsSchema = z.record(z.string(), generatorDefSchema);
221
+
222
+ /**
223
+ * A contract's reference to a generator by id. The plain-string form just runs
224
+ * that generator as-is; the object form lets one contract tweak a shared
225
+ * generator (extra/overridden `additionalProperties`, a different
226
+ * `maven`/`package`/`readme`/... value) without duplicating the whole recipe
227
+ * under a new id, and `as` renames the artifact's own id (output
228
+ * folder / branch / tag segment) if a contract needs two variants of the same
229
+ * base generator.
230
+ */
231
+ export const artifactRefSchema = z.union([
232
+ z.string().min(1),
233
+ z.object({
234
+ generator: z.string().min(1),
235
+ as: z.string().min(1).optional(),
236
+ overrides: generatorDefBaseSchema.partial().optional(),
237
+ }),
238
+ ]);
239
+
240
+ export const contractSchema = z.object({
241
+ name: z.string().min(1),
242
+ title: z.string().min(1),
243
+ entrypoint: z.string().min(1),
244
+ artifacts: z.array(artifactRefSchema).min(1),
245
+ });
246
+
247
+ export const rootConfigSchema = z.object({
248
+ /**
249
+ * The config schema version this file targets. Currently must be `1`
250
+ * (the only version that exists) - see {@link CONFIG_SCHEMA_VERSION}.
251
+ */
252
+ configVersion: z.literal(CONFIG_SCHEMA_VERSION),
253
+ github: githubSchema,
254
+ vars: varsTreeSchema.default({}),
255
+ paths: pathsSchema.default({ dist: "dist" }),
256
+ docs: docsSchema,
257
+ /**
258
+ * Publishing conventions (branch/tag naming, registry URLs), applied to
259
+ * every artifact unless overridden per-generator or
260
+ * per-contract-artifact. Required - seagull has no built-in default here,
261
+ * see {@link publishingSchema}.
262
+ */
263
+ publishing: publishingSchema,
264
+ generators: generatorsSchema,
265
+ contracts: z.array(contractSchema).min(1),
266
+ });
267
+
268
+ export type RootConfigInput = z.infer<typeof rootConfigSchema>;
269
+ export type ArtifactRefInput = z.infer<typeof artifactRefSchema>;
270
+ export type ContractInput = z.infer<typeof contractSchema>;
@@ -0,0 +1,113 @@
1
+ const PLACEHOLDER = /\{([a-zA-Z0-9_.]+)}/g;
2
+
3
+ export type TemplateScope = Record<string, unknown>;
4
+ export type TemplateContext = Readonly<Record<string, string>>;
5
+
6
+ /**
7
+ * Replaces every `{dot.path}` placeholder in `template` with its value from
8
+ * `context`, throwing a descriptive error if a placeholder has no match -
9
+ * a typo'd `{vars.org}` should fail loudly at config-load time, not silently
10
+ * produce a package named literally `@{vars.org}/...`.
11
+ *
12
+ * @param template - The template string, e.g. `"@{vars.org}/{service}-client"`.
13
+ * @param context - The flattened context to resolve placeholders against.
14
+ * @returns The interpolated string.
15
+ */
16
+ export function interpolate(
17
+ template: string,
18
+ context: TemplateContext,
19
+ ): string {
20
+ return template.replace(PLACEHOLDER, (_match, key: string) => {
21
+ const value = context[key];
22
+
23
+ if (value === undefined) {
24
+ const available = Object.keys(context).sort().join(", ");
25
+
26
+ throw new Error(
27
+ `Unknown template placeholder "{${key}}" in "${template}" (available: ${available})`,
28
+ );
29
+ }
30
+
31
+ return value;
32
+ });
33
+ }
34
+
35
+ /**
36
+ * Recursively interpolates every string value in `value` (walking through plain
37
+ * objects), leaving non-string leaves untouched. Used to resolve
38
+ * `additionalProperties` maps, which may mix templated strings with plain
39
+ * booleans/numbers.
40
+ *
41
+ * @param value - The value (string, object, or primitive) to interpolate.
42
+ * @param context - The flattened context to resolve placeholders against.
43
+ * @returns A deep copy of `value` with every string interpolated.
44
+ */
45
+ export function interpolateDeep<T>(value: T, context: TemplateContext): T {
46
+ // Every `as T` below asserts a value back into the exact shape it was
47
+ // destructured from - `T` is unconstrained here (it's whatever shape the
48
+ // caller's config value happens to be), which is the shape-preserving
49
+ // contract this function promises, not an actual type hole in practice.
50
+ /* eslint-disable @typescript-eslint/no-unsafe-return */
51
+ if (typeof value === "string") {
52
+ const interpolated: string = interpolate(value, context);
53
+
54
+ return interpolated as T;
55
+ }
56
+
57
+ if (Array.isArray(value)) {
58
+ return value.map((item) => interpolateDeep(item, context)) as T;
59
+ }
60
+
61
+ if (value !== null && typeof value === "object") {
62
+ return Object.fromEntries(
63
+ Object.entries(value as Record<string, unknown>).map(([key, child]) => [
64
+ key,
65
+ interpolateDeep(child, context),
66
+ ]),
67
+ ) as T;
68
+ }
69
+
70
+ /* eslint-enable @typescript-eslint/no-unsafe-return */
71
+ return value;
72
+ }
73
+
74
+ /**
75
+ * Flattens a nested scope object (e.g. `{ service: "auth", vars: { org: "x" } }`)
76
+ * into dot-path lookup keys (`{ service: "auth", "vars.org": "x" }`) for use
77
+ * with {@link interpolate}.
78
+ *
79
+ * @param scope - The nested scope to flatten.
80
+ * @returns A flat dot-path -> string map.
81
+ */
82
+ export function buildTemplateContext(scope: TemplateScope): TemplateContext {
83
+ const out: Record<string, string> = {};
84
+
85
+ flatten(scope, "", out);
86
+
87
+ return out;
88
+ }
89
+
90
+ function flatten(
91
+ value: unknown,
92
+ prefix: string,
93
+ out: Record<string, string>,
94
+ ): void {
95
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
96
+ for (const [key, child] of Object.entries(
97
+ value as Record<string, unknown>,
98
+ )) {
99
+ flatten(child, prefix ? `${prefix}.${key}` : key, out);
100
+ }
101
+
102
+ return;
103
+ }
104
+
105
+ if (value === undefined) {
106
+ return;
107
+ }
108
+
109
+ // Leaf values from parsed YAML/JSON config are always string/number/boolean
110
+ // (VarsTree's own type guarantees this) - String() is safe here.
111
+ /* eslint-disable-next-line @typescript-eslint/no-base-to-string */
112
+ out[prefix] = String(value);
113
+ }
@@ -0,0 +1,139 @@
1
+ import type { VarsTree } from "./schema";
2
+
3
+ export type { VarsTree } from "./schema";
4
+ export type SdkTool = "openapi-generator" | "openapi-typescript";
5
+ export type SdkLang = "typescript" | "go" | "java";
6
+ export type SdkKind = "client" | "server";
7
+
8
+ /**
9
+ * Fully resolved publishing conventions for one artifact.
10
+ */
11
+ export interface ResolvedPublishing {
12
+ /** Fully resolved git branch name (no runtime-only placeholders left). */
13
+ branch: string;
14
+ /**
15
+ * Raw tag template - still contains `{version}`, resolved at publish
16
+ * time via `renderArtifactTag()` in `config/publishing.ts`.
17
+ */
18
+ tagTemplate: string;
19
+ /** Resolved `repository.url` for generated package.json / README examples. */
20
+ repositoryUrl: string;
21
+ npmRegistry: string;
22
+ npmAccess: "public" | "restricted";
23
+ mavenRepositoryId: string;
24
+ mavenRepositoryUrl: string;
25
+ }
26
+
27
+ /**
28
+ * A single artifact a contract generates: a generator recipe from the CLI
29
+ * config, fully resolved (templates interpolated, overrides merged, paths made
30
+ * absolute) for one specific contract.
31
+ */
32
+ export interface ResolvedArtifact {
33
+ /**
34
+ * The id this artifact is known by for this contract - the key under
35
+ * `generators:` it was resolved from, or its `as` override. Used as the
36
+ * output folder segment, and to derive the publish branch/tag.
37
+ */
38
+ id: string;
39
+
40
+ tool: SdkTool;
41
+ lang: SdkLang;
42
+ kind: SdkKind;
43
+
44
+ /** `openapi-generator -g` value. Set only when `tool` is `openapi-generator`. */
45
+ generator?: string;
46
+
47
+ /** Absolute output directory: `<sdkDir>/<contract>/<id>`. */
48
+ outputDir: string;
49
+
50
+ /**
51
+ * Fully resolved git branch name - convenience alias for
52
+ * `publishing.branch`.
53
+ */
54
+ branch: string;
55
+
56
+ /**
57
+ * Publishing conventions (branch/tag/registry) for this artifact - see
58
+ * {@link ResolvedPublishing}.
59
+ */
60
+ publishing: ResolvedPublishing;
61
+
62
+ additionalProperties: Record<string, string | number | boolean>;
63
+
64
+ package?: string;
65
+ goModule?: string;
66
+ goPackageName?: string;
67
+ maven?: { groupId: string; artifactId: string };
68
+
69
+ /**
70
+ * Absolute path to a custom README template, if `readme:` was set for this
71
+ * generator/artifact. Falls back to a built-in default template when unset -
72
+ * see `core/readme/readme-renderer.ts`.
73
+ */
74
+ readmeTemplate?: string;
75
+ }
76
+
77
+ export interface ResolvedContract {
78
+ name: string;
79
+ title: string;
80
+ /** Absolute path to the source `openapi.yaml`. */
81
+ entrypoint: string;
82
+ /**
83
+ * Path to the source `openapi.yaml`, relative to `rootDir` - what
84
+ * `redocly.yaml`'s `apis:` section wants.
85
+ */
86
+ entrypointRelative: string;
87
+ artifacts: ResolvedArtifact[];
88
+ }
89
+
90
+ /**
91
+ * One (contract, artifact) pair - the flattened unit of work most commands
92
+ * actually iterate over.
93
+ */
94
+ export interface ResolvedArtifactEntry {
95
+ contract: ResolvedContract;
96
+ artifact: ResolvedArtifact;
97
+ }
98
+
99
+ export interface ResolvedConfig {
100
+ /**
101
+ * The config schema version this file targets - see `CONFIG_SCHEMA_VERSION`
102
+ * in `config/schema.ts`.
103
+ */
104
+ configVersion: number;
105
+
106
+ /**
107
+ * Directory containing the config file - every relative path in the config
108
+ * (entrypoints, `paths.*`, `readme` templates, ...) resolves against this.
109
+ */
110
+ rootDir: string;
111
+
112
+ paths: {
113
+ dist: string;
114
+ specs: string;
115
+ docs: string;
116
+ sdk: string;
117
+ };
118
+
119
+ github: { owner: string; repo: string };
120
+ vars: VarsTree;
121
+
122
+ docs: {
123
+ server: { host: string; port: number };
124
+ metadata: {
125
+ title: string;
126
+ description: string;
127
+ favicon: string;
128
+ baseServerUrl: string;
129
+ };
130
+ };
131
+
132
+ contracts: ResolvedContract[];
133
+
134
+ /**
135
+ * Every (contract, artifact) pair across every contract, in config order -
136
+ * the flat list most commands iterate over.
137
+ */
138
+ allArtifacts: ResolvedArtifactEntry[];
139
+ }
@@ -0,0 +1,33 @@
1
+ import type { SdkTool } from "../config/types";
2
+ import type { GenerateContext, PrepareContext } from "./types";
3
+
4
+ /**
5
+ * The root primitive every concrete SDK generator implements.
6
+ *
7
+ * One instance per underlying tool (`openapi-generator-cli`,
8
+ * `openapi-typescript`, ...) - not one per language, since a single tool
9
+ * invocation (e.g. `openapi-generator-cli -g java`/`-g go`) already covers
10
+ * every language it supports. Language-specific behaviour (patching `go.mod`,
11
+ * `package.json`, `pom.xml`, ...) is composed in via patchers rather than
12
+ * living in per-language subclasses.
13
+ */
14
+ export abstract class Generator {
15
+ abstract readonly tool: SdkTool;
16
+
17
+ /**
18
+ * Optional one-time setup step, run once per tool before any of that tool's
19
+ * {@link generate} calls - for tools like `openapi-typescript` that generate
20
+ * every contract's output in a single global invocation instead of one call
21
+ * per artifact.
22
+ *
23
+ * @param ctx - Every (contract, artifact) pair using this generator's tool.
24
+ */
25
+ prepare?(ctx: PrepareContext): Promise<void>;
26
+
27
+ /**
28
+ * Generates a single artifact.
29
+ *
30
+ * @param ctx - The contract, artifact, and resolved version to generate for.
31
+ */
32
+ abstract generate(ctx: GenerateContext): Promise<void>;
33
+ }
@@ -0,0 +1,51 @@
1
+ import type { SdkTool } from "../config/types";
2
+ import type { Generator } from "./generator";
3
+
4
+ /**
5
+ * Looks up the concrete {@link Generator} implementation for a given tool name.
6
+ */
7
+ export class GeneratorRegistry {
8
+ private readonly generators = new Map<SdkTool, Generator>();
9
+
10
+ /**
11
+ * Registers a generator implementation under its own {@link Generator.tool}.
12
+ *
13
+ * @param generator - The generator instance to register.
14
+ * @returns `this`, for chaining.
15
+ */
16
+ register(generator: Generator): this {
17
+ this.generators.set(generator.tool, generator);
18
+
19
+ return this;
20
+ }
21
+
22
+ /**
23
+ * Resolves the generator implementation for a given tool name.
24
+ *
25
+ * @param tool - The tool name, e.g. `"openapi-generator"`.
26
+ * @returns The registered generator.
27
+ * @throws Error if no generator is registered for that tool.
28
+ */
29
+ resolve(tool: SdkTool): Generator {
30
+ const generator = this.generators.get(tool);
31
+
32
+ if (!generator) {
33
+ const available = [...this.generators.keys()].join(", ");
34
+
35
+ throw new Error(
36
+ `No generator implementation registered for tool "${tool}" (available: ${available})`,
37
+ );
38
+ }
39
+
40
+ return generator;
41
+ }
42
+
43
+ /**
44
+ * All distinct tools currently registered.
45
+ *
46
+ * @returns The registered tool names.
47
+ */
48
+ tools(): SdkTool[] {
49
+ return [...this.generators.keys()];
50
+ }
51
+ }
@@ -0,0 +1,38 @@
1
+ import type {
2
+ ResolvedArtifact,
3
+ ResolvedArtifactEntry,
4
+ ResolvedContract,
5
+ SdkTool,
6
+ } from "../config/types";
7
+
8
+ export type {
9
+ ResolvedArtifact,
10
+ ResolvedArtifactEntry,
11
+ ResolvedContract,
12
+ SdkTool,
13
+ };
14
+
15
+ /** Passed once per tool to {@link Generator.prepare}, before any of that
16
+ * tool's {@link Generator.generate} calls run. */
17
+ export interface PrepareContext {
18
+ rootDir: string;
19
+ /**
20
+ * Every (contract, artifact) pair that uses this generator's `tool`, across
21
+ * all contracts.
22
+ */
23
+ entries: ResolvedArtifactEntry[];
24
+ }
25
+
26
+ /** Passed once per artifact to {@link Generator.generate}. */
27
+ export interface GenerateContext {
28
+ rootDir: string;
29
+ contract: ResolvedContract;
30
+ artifact: ResolvedArtifact;
31
+ version: string;
32
+ github: { owner: string; repo: string };
33
+ /**
34
+ * Absolute path to the contract's bundled JSON spec
35
+ * (`<specsDir>/<contract>.json`).
36
+ */
37
+ specInputPath: string;
38
+ }
@@ -0,0 +1 @@
1
+ export { OpenApiGeneratorCli } from "./openapi-generator-cli.generator";