@goast/core 0.5.2 → 0.6.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +67 -67
- package/esm/src/parse/parser.js +2 -1
- package/package.json +1 -1
- package/script/src/parse/parser.js +2 -1
- package/src/_dnt.shims.ts +0 -69
- package/src/mod.ts +0 -35
- package/src/src/ast/node.ts +0 -46
- package/src/src/codegen/config.ts +0 -41
- package/src/src/codegen/endpoints-generator.ts +0 -72
- package/src/src/codegen/generator.ts +0 -192
- package/src/src/codegen/internal-utils.ts +0 -6
- package/src/src/codegen/schemas-generator.ts +0 -87
- package/src/src/codegen/services-generator.ts +0 -77
- package/src/src/codegen/types.ts +0 -37
- package/src/src/collect/collector.ts +0 -142
- package/src/src/collect/helpers.ts +0 -36
- package/src/src/collect/types.ts +0 -21
- package/src/src/internal-utils.ts +0 -5
- package/src/src/parse/deref-proxy.ts +0 -70
- package/src/src/parse/openapi-types.ts +0 -949
- package/src/src/parse/parser.ts +0 -206
- package/src/src/parse/types.ts +0 -28
- package/src/src/transform/api-types.ts +0 -245
- package/src/src/transform/helpers.ts +0 -218
- package/src/src/transform/transform-document.ts +0 -35
- package/src/src/transform/transform-endpoint.ts +0 -331
- package/src/src/transform/transform-schema.ts +0 -217
- package/src/src/transform/transformer.ts +0 -53
- package/src/src/transform/types.ts +0 -52
- package/src/src/utils/action-provider.ts +0 -58
- package/src/src/utils/api-data.utils.ts +0 -48
- package/src/src/utils/array.utils.ts +0 -7
- package/src/src/utils/asset-manager.ts +0 -51
- package/src/src/utils/class.utils.ts +0 -40
- package/src/src/utils/common.utils.ts +0 -86
- package/src/src/utils/condition.ts +0 -7
- package/src/src/utils/endpoint.utils.ts +0 -10
- package/src/src/utils/error.utils.ts +0 -3
- package/src/src/utils/factory.ts +0 -42
- package/src/src/utils/file-system.utils.ts +0 -61
- package/src/src/utils/generator.utils.ts +0 -6
- package/src/src/utils/object.utils.ts +0 -32
- package/src/src/utils/schema.utils.ts +0 -148
- package/src/src/utils/source-builder.ts +0 -597
- package/src/src/utils/string-builder/options.ts +0 -19
- package/src/src/utils/string-builder/string-builder.ts +0 -165
- package/src/src/utils/string-builder/utils.ts +0 -69
- package/src/src/utils/string.utils.ts +0 -369
- package/src/src/utils/string.utils.types.ts +0 -179
- package/src/src/utils/type.utils.ts +0 -93
- package/src/src/utils/yaml-info.ts +0 -48
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import fs from 'fs-extra';
|
|
5
|
-
|
|
6
|
-
import { OpenApiParser } from '../parse/parser.js';
|
|
7
|
-
import type { ApiData } from '../transform/api-types.js';
|
|
8
|
-
import { ActionProvider } from '../utils/action-provider.js';
|
|
9
|
-
import { type DirectoryScanOptions, getFiles } from '../utils/file-system.utils.js';
|
|
10
|
-
import type { EmptyConstructor, Merge } from '../utils/type.utils.js';
|
|
11
|
-
import { defaultOpenApiGeneratorConfig, type OpenApiGeneratorConfig } from './config.js';
|
|
12
|
-
import type {
|
|
13
|
-
AnyConfig,
|
|
14
|
-
OpenApiGenerationProvider,
|
|
15
|
-
OpenApiGenerationProviderContext,
|
|
16
|
-
OpenApiGenerationProviderFn,
|
|
17
|
-
OpenApiGeneratorContext,
|
|
18
|
-
OpenApiGeneratorInput,
|
|
19
|
-
OpenApiGeneratorOutput,
|
|
20
|
-
} from './types.js';
|
|
21
|
-
|
|
22
|
-
type OpenApiGenerationProviders = {
|
|
23
|
-
provider: ActionProvider<OpenApiGenerationProviderFn>;
|
|
24
|
-
config: AnyConfig | undefined;
|
|
25
|
-
}[];
|
|
26
|
-
|
|
27
|
-
type VInput<TActual, TExpected> = TExpected extends TActual ? TActual
|
|
28
|
-
: { __error: 'The current output of the generator does not satisfy the input of this generator.' };
|
|
29
|
-
|
|
30
|
-
class _OpenApiGenerator<TOutput extends OpenApiGeneratorInput> {
|
|
31
|
-
private readonly _providers: OpenApiGenerationProviders;
|
|
32
|
-
private readonly _config: OpenApiGeneratorConfig;
|
|
33
|
-
private readonly _parser: OpenApiParser;
|
|
34
|
-
|
|
35
|
-
constructor(config: OpenApiGeneratorConfig, providers: OpenApiGenerationProviders, parser: OpenApiParser) {
|
|
36
|
-
this._providers = providers;
|
|
37
|
-
this._config = config;
|
|
38
|
-
this._parser = parser;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public use<PInput extends OpenApiGeneratorInput, POutput extends OpenApiGeneratorOutput, PConfig extends AnyConfig>(
|
|
42
|
-
provider: ActionProvider<OpenApiGenerationProviderFn<VInput<PInput, TOutput>, POutput, PConfig>>,
|
|
43
|
-
config?: Partial<PConfig>,
|
|
44
|
-
): _OpenApiGenerator<Merge<[TOutput, POutput]>> {
|
|
45
|
-
// deno-lint-ignore no-explicit-any
|
|
46
|
-
this._providers.push({ provider: provider as any, config });
|
|
47
|
-
return new _OpenApiGenerator<Merge<[TOutput, POutput]>>(this._config, [...this._providers], this._parser);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public useType<
|
|
51
|
-
PInput extends OpenApiGeneratorInput,
|
|
52
|
-
POutput extends OpenApiGeneratorOutput,
|
|
53
|
-
PConfig extends AnyConfig,
|
|
54
|
-
>(
|
|
55
|
-
type: EmptyConstructor<OpenApiGenerationProvider<VInput<PInput, TOutput>, POutput, PConfig>>,
|
|
56
|
-
config?: Partial<PConfig>,
|
|
57
|
-
): _OpenApiGenerator<Merge<[TOutput, POutput]>> {
|
|
58
|
-
return this.use(ActionProvider.fromType(type, 'generate'), config);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public useFn<PInput extends TOutput, POutput extends OpenApiGeneratorOutput, PConfig extends AnyConfig>(
|
|
62
|
-
fn: OpenApiGenerationProviderFn<VInput<PInput, TOutput>, POutput, PConfig>,
|
|
63
|
-
config?: Partial<PConfig>,
|
|
64
|
-
): _OpenApiGenerator<Merge<[TOutput, POutput]>> {
|
|
65
|
-
return this.use(ActionProvider.fromFn(fn), config);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
public useValue<PInput extends TOutput, POutput extends OpenApiGeneratorOutput, PConfig extends AnyConfig>(
|
|
69
|
-
value: OpenApiGenerationProvider<VInput<PInput, TOutput>, POutput, PConfig>,
|
|
70
|
-
config?: Partial<PConfig>,
|
|
71
|
-
): _OpenApiGenerator<Merge<[TOutput, POutput]>> {
|
|
72
|
-
return this.use(ActionProvider.fromValue(value, 'generate'), config);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public async generate<T extends ApiData>(data: T): Promise<TOutput> {
|
|
76
|
-
const absOutputPath = resolve(this._config.outputDir);
|
|
77
|
-
if (this._config.clearOutputDir) {
|
|
78
|
-
await fs.emptyDir(absOutputPath);
|
|
79
|
-
} else {
|
|
80
|
-
await fs.ensureDir(absOutputPath);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
this._providers.forEach(({ config }) => {
|
|
84
|
-
if (config && 'outputDir' in config && config.outputDir && typeof config.outputDir === 'string') {
|
|
85
|
-
const providerOutputDir = resolve(config.outputDir);
|
|
86
|
-
if (this._config.clearOutputDir) {
|
|
87
|
-
fs.emptyDirSync(providerOutputDir);
|
|
88
|
-
} else {
|
|
89
|
-
fs.ensureDirSync(providerOutputDir);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
let input = {} as TOutput;
|
|
95
|
-
for (const generator of this._providers) {
|
|
96
|
-
const context = {
|
|
97
|
-
data,
|
|
98
|
-
input,
|
|
99
|
-
config: this._config,
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const result = await generator.provider.run(context, generator.config);
|
|
103
|
-
if (result) {
|
|
104
|
-
input = mergeDeep(input, result);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return input;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
public async parseAndGenerate(...fileNames: (string | string[])[]): Promise<TOutput> {
|
|
112
|
-
const data = await this._parser.parseApisAndTransform(...fileNames);
|
|
113
|
-
return await this.generate(data);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
public async parseAndGenerateFromDir(dir: string, options?: Partial<DirectoryScanOptions>): Promise<TOutput> {
|
|
117
|
-
const filter = (file: string) =>
|
|
118
|
-
(file.endsWith('.yml') || file.endsWith('.yaml') || file.endsWith('.json')) && (options?.filter?.(file) ?? true);
|
|
119
|
-
return this.parseAndGenerate(...(await getFiles(dir, { ...options, filter })));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// deno-lint-ignore ban-types
|
|
124
|
-
export class OpenApiGenerator extends _OpenApiGenerator<{}> {
|
|
125
|
-
constructor(config?: Partial<OpenApiGeneratorConfig>) {
|
|
126
|
-
super(
|
|
127
|
-
{ ...defaultOpenApiGeneratorConfig, ...config },
|
|
128
|
-
[],
|
|
129
|
-
new OpenApiParser({ ...defaultOpenApiGeneratorConfig, ...config }),
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function mergeDeep<T extends Record<string, unknown>, U extends Record<string, unknown>[]>(
|
|
135
|
-
target: T,
|
|
136
|
-
...sources: U
|
|
137
|
-
): T & U[number] {
|
|
138
|
-
if (!sources.length) return target;
|
|
139
|
-
const source = sources.shift();
|
|
140
|
-
|
|
141
|
-
for (const key in source) {
|
|
142
|
-
const value = source[key];
|
|
143
|
-
if (value && typeof value === 'object') {
|
|
144
|
-
if (!target[key]) Object.assign(target, { [key]: value });
|
|
145
|
-
else mergeDeep(target[key] as Record<string, unknown>, value as Record<string, unknown>);
|
|
146
|
-
} else if (Array.isArray(value)) {
|
|
147
|
-
if (!target[key]) Object.assign(target, { [key]: value });
|
|
148
|
-
else Object.assign(target, { [key]: [...(target[key] as Iterable<unknown>), ...value] });
|
|
149
|
-
} else {
|
|
150
|
-
Object.assign(target, { [key]: value });
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return mergeDeep(target, ...sources);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export type DefaultGenerationProviderConfig<T extends AnyConfig> =
|
|
158
|
-
& Omit<T, keyof OpenApiGeneratorConfig>
|
|
159
|
-
& Partial<Pick<T, keyof OpenApiGeneratorConfig>>;
|
|
160
|
-
|
|
161
|
-
export abstract class OpenApiGenerationProviderBase<
|
|
162
|
-
TInput extends OpenApiGeneratorInput,
|
|
163
|
-
TOutput extends OpenApiGeneratorOutput,
|
|
164
|
-
TConfig extends AnyConfig,
|
|
165
|
-
TContext extends OpenApiGenerationProviderContext<TInput, TConfig>,
|
|
166
|
-
> implements OpenApiGenerationProvider<TInput, TOutput, TConfig> {
|
|
167
|
-
public async generate(
|
|
168
|
-
context: OpenApiGeneratorContext<TInput>,
|
|
169
|
-
config?: Partial<TConfig> | undefined,
|
|
170
|
-
): Promise<TOutput> {
|
|
171
|
-
const ctx = await this.buildContext(context, config);
|
|
172
|
-
return await this.onGenerate(ctx);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
protected getProviderContext(
|
|
176
|
-
context: OpenApiGeneratorContext<TInput>,
|
|
177
|
-
config: Partial<TConfig> | undefined,
|
|
178
|
-
defaultConfig: DefaultGenerationProviderConfig<TConfig>,
|
|
179
|
-
): OpenApiGenerationProviderContext<TInput, TConfig> {
|
|
180
|
-
const c = { ...context.config, ...defaultConfig, ...config } as unknown as OpenApiGeneratorConfig & TConfig;
|
|
181
|
-
return Object.assign(context, {
|
|
182
|
-
config: c,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
protected abstract buildContext(
|
|
187
|
-
context: OpenApiGeneratorContext<TInput>,
|
|
188
|
-
config?: Partial<TConfig> | undefined,
|
|
189
|
-
): TContext | Promise<TContext>;
|
|
190
|
-
|
|
191
|
-
protected abstract onGenerate(ctx: TContext): TOutput | Promise<TOutput>;
|
|
192
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { ApiSchema } from '../transform/api-types.js';
|
|
2
|
-
import { getSchemaReference } from '../utils/schema.utils.js';
|
|
3
|
-
import type { MaybePromise } from '../utils/type.utils.js';
|
|
4
|
-
import { type DefaultGenerationProviderConfig, OpenApiGenerationProviderBase } from './generator.js';
|
|
5
|
-
import { addSourceIfTest } from './internal-utils.js';
|
|
6
|
-
import type {
|
|
7
|
-
AnyConfig,
|
|
8
|
-
OpenApiGenerationProviderContext,
|
|
9
|
-
OpenApiGeneratorContext,
|
|
10
|
-
OpenApiGeneratorInput,
|
|
11
|
-
OpenApiGeneratorOutput,
|
|
12
|
-
} from './types.js';
|
|
13
|
-
|
|
14
|
-
export type OpenApiSchemasGenerationProviderContext<
|
|
15
|
-
TInput extends OpenApiGeneratorInput,
|
|
16
|
-
TOutput extends OpenApiGeneratorOutput,
|
|
17
|
-
TConfig extends AnyConfig,
|
|
18
|
-
TSchemaOutput extends OpenApiGeneratorOutput,
|
|
19
|
-
> = OpenApiGenerationProviderContext<TInput, TConfig> & {
|
|
20
|
-
existingSchemaResults: Map<string, TSchemaOutput>;
|
|
21
|
-
output: TOutput;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export abstract class OpenApiSchemasGenerationProviderBase<
|
|
25
|
-
TInput extends OpenApiGeneratorInput,
|
|
26
|
-
TOutput extends OpenApiGeneratorOutput,
|
|
27
|
-
TConfig extends AnyConfig,
|
|
28
|
-
TSchemaOutput extends OpenApiGeneratorOutput,
|
|
29
|
-
TContext extends OpenApiSchemasGenerationProviderContext<TInput, TOutput, TConfig, TSchemaOutput>,
|
|
30
|
-
> extends OpenApiGenerationProviderBase<TInput, TOutput, TConfig, TContext> {
|
|
31
|
-
protected override getProviderContext(
|
|
32
|
-
context: OpenApiGeneratorContext<TInput>,
|
|
33
|
-
config: Partial<TConfig> | undefined,
|
|
34
|
-
defaultConfig: DefaultGenerationProviderConfig<TConfig>,
|
|
35
|
-
): OpenApiSchemasGenerationProviderContext<TInput, TOutput, TConfig, TSchemaOutput> {
|
|
36
|
-
const ctx = super.getProviderContext(context, config, defaultConfig);
|
|
37
|
-
return Object.assign(ctx, {
|
|
38
|
-
existingSchemaResults: new Map<string, TSchemaOutput>(),
|
|
39
|
-
output: this.initResult(ctx),
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
protected override async onGenerate(ctx: TContext): Promise<TOutput> {
|
|
44
|
-
for (const schema of ctx.data.schemas) {
|
|
45
|
-
await this.getSchemaResult(ctx, schema);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
await this.generateAdditionalFiles(ctx);
|
|
49
|
-
|
|
50
|
-
return ctx.output;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public async getSchemaResult(ctx: TContext, schema: ApiSchema): Promise<TSchemaOutput> {
|
|
54
|
-
const existingResult = ctx.existingSchemaResults.get(schema.id);
|
|
55
|
-
if (existingResult) return existingResult;
|
|
56
|
-
|
|
57
|
-
let result: TSchemaOutput;
|
|
58
|
-
const reference = this.getSchemaReference(ctx, schema);
|
|
59
|
-
if (reference) {
|
|
60
|
-
result = await this.getSchemaResult(ctx, reference);
|
|
61
|
-
} else {
|
|
62
|
-
result = await this.generateSchema(ctx, schema);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
addSourceIfTest(ctx.config, result, () => `${schema.$src.file}#${schema.$src.path}`);
|
|
66
|
-
ctx.existingSchemaResults.set(schema.id, result);
|
|
67
|
-
this.addSchemaResult(ctx, schema, result);
|
|
68
|
-
return result;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// deno-lint-ignore no-unused-vars
|
|
72
|
-
protected getSchemaReference(ctx: TContext, schema: ApiSchema): ApiSchema | undefined {
|
|
73
|
-
const ref = getSchemaReference(schema, ['description']);
|
|
74
|
-
return ref.id !== schema.id ? ref : undefined;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
protected abstract initResult(ctx: OpenApiGenerationProviderContext<TInput, TConfig>): TOutput;
|
|
78
|
-
|
|
79
|
-
protected abstract generateSchema(ctx: TContext, schema: ApiSchema): MaybePromise<TSchemaOutput>;
|
|
80
|
-
|
|
81
|
-
protected abstract addSchemaResult(ctx: TContext, schema: ApiSchema, result: TSchemaOutput): void;
|
|
82
|
-
|
|
83
|
-
// deno-lint-ignore no-unused-vars
|
|
84
|
-
protected generateAdditionalFiles(ctx: TContext): MaybePromise<void> {
|
|
85
|
-
// Override if needed
|
|
86
|
-
}
|
|
87
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import type { ApiService } from '../transform/api-types.js';
|
|
2
|
-
import type { MaybePromise } from '../utils/type.utils.js';
|
|
3
|
-
import { type DefaultGenerationProviderConfig, OpenApiGenerationProviderBase } from './generator.js';
|
|
4
|
-
import { addSourceIfTest } from './internal-utils.js';
|
|
5
|
-
import type {
|
|
6
|
-
AnyConfig,
|
|
7
|
-
OpenApiGenerationProviderContext,
|
|
8
|
-
OpenApiGeneratorContext,
|
|
9
|
-
OpenApiGeneratorInput,
|
|
10
|
-
OpenApiGeneratorOutput,
|
|
11
|
-
} from './types.js';
|
|
12
|
-
|
|
13
|
-
export type OpenApiServicesGenerationProviderContext<
|
|
14
|
-
TInput extends OpenApiGeneratorInput,
|
|
15
|
-
TOutput extends OpenApiGeneratorOutput,
|
|
16
|
-
TConfig extends AnyConfig,
|
|
17
|
-
TServiceOutput extends OpenApiGeneratorOutput,
|
|
18
|
-
> = OpenApiGenerationProviderContext<TInput, TConfig> & {
|
|
19
|
-
existingServiceResults: Map<string, TServiceOutput>;
|
|
20
|
-
output: TOutput;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export abstract class OpenApiServicesGenerationProviderBase<
|
|
24
|
-
TInput extends OpenApiGeneratorInput,
|
|
25
|
-
TOutput extends OpenApiGeneratorOutput,
|
|
26
|
-
TConfig extends AnyConfig,
|
|
27
|
-
TServiceOutput extends OpenApiGeneratorOutput,
|
|
28
|
-
TContext extends OpenApiServicesGenerationProviderContext<TInput, TOutput, TConfig, TServiceOutput>,
|
|
29
|
-
> extends OpenApiGenerationProviderBase<TInput, TOutput, TConfig, TContext> {
|
|
30
|
-
protected override getProviderContext(
|
|
31
|
-
context: OpenApiGeneratorContext<TInput>,
|
|
32
|
-
config: Partial<TConfig> | undefined,
|
|
33
|
-
defaultConfig: DefaultGenerationProviderConfig<TConfig>,
|
|
34
|
-
): OpenApiServicesGenerationProviderContext<TInput, TOutput, TConfig, TServiceOutput> {
|
|
35
|
-
const ctx = super.getProviderContext(context, config, defaultConfig);
|
|
36
|
-
return Object.assign(ctx, {
|
|
37
|
-
existingServiceResults: new Map<string, TServiceOutput>(),
|
|
38
|
-
output: this.initResult(ctx),
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
protected override async onGenerate(ctx: TContext): Promise<TOutput> {
|
|
43
|
-
for (const service of ctx.data.services) {
|
|
44
|
-
await this.getServiceResult(ctx, service);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
await this.generateAdditionalFiles(ctx);
|
|
48
|
-
|
|
49
|
-
return ctx.output;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
protected async getServiceResult(ctx: TContext, service: ApiService): Promise<TServiceOutput> {
|
|
53
|
-
const existingResult = ctx.existingServiceResults.get(service.id);
|
|
54
|
-
if (existingResult) return existingResult;
|
|
55
|
-
|
|
56
|
-
const result = await this.generateService(ctx, service);
|
|
57
|
-
|
|
58
|
-
addSourceIfTest(
|
|
59
|
-
ctx.config,
|
|
60
|
-
result,
|
|
61
|
-
() => service.$src ? `${service.$src.file}#${service.$src.path}` : `tag:${service.name}`,
|
|
62
|
-
);
|
|
63
|
-
this.addServiceResult(ctx, service, result);
|
|
64
|
-
return result;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
protected abstract initResult(ctx: OpenApiGenerationProviderContext<TInput, TConfig>): TOutput;
|
|
68
|
-
|
|
69
|
-
protected abstract generateService(ctx: TContext, service: ApiService): MaybePromise<TServiceOutput>;
|
|
70
|
-
|
|
71
|
-
protected abstract addServiceResult(ctx: TContext, service: ApiService, result: TServiceOutput): void;
|
|
72
|
-
|
|
73
|
-
// deno-lint-ignore no-unused-vars
|
|
74
|
-
protected generateAdditionalFiles(ctx: TContext): MaybePromise<void> {
|
|
75
|
-
// Override if needed
|
|
76
|
-
}
|
|
77
|
-
}
|
package/src/src/codegen/types.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { ApiData } from '../transform/api-types.js';
|
|
2
|
-
import type { MaybePromise } from '../utils/type.utils.js';
|
|
3
|
-
import type { OpenApiGeneratorConfig } from './config.js';
|
|
4
|
-
|
|
5
|
-
export type AnyConfig = Readonly<Record<string, unknown>>;
|
|
6
|
-
export type OpenApiGeneratorInput = Record<string, unknown>;
|
|
7
|
-
export type OpenApiGeneratorOutput = Record<string, unknown> | undefined;
|
|
8
|
-
export type OpenApiGeneratorContext<TInput extends OpenApiGeneratorInput = OpenApiGeneratorInput> = {
|
|
9
|
-
data: ApiData;
|
|
10
|
-
input: TInput;
|
|
11
|
-
config: OpenApiGeneratorConfig;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export type OpenApiGenerationProviderContext<TInput extends OpenApiGeneratorInput, TConfig extends AnyConfig> =
|
|
15
|
-
& Omit<
|
|
16
|
-
OpenApiGeneratorContext<TInput>,
|
|
17
|
-
'config'
|
|
18
|
-
>
|
|
19
|
-
& {
|
|
20
|
-
config: OpenApiGeneratorConfig & TConfig;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export interface OpenApiGenerationProvider<
|
|
24
|
-
TInput extends OpenApiGeneratorInput = OpenApiGeneratorInput,
|
|
25
|
-
TOutput extends OpenApiGeneratorOutput = OpenApiGeneratorOutput,
|
|
26
|
-
TConfig extends AnyConfig = AnyConfig,
|
|
27
|
-
> {
|
|
28
|
-
generate(
|
|
29
|
-
...args: Parameters<OpenApiGenerationProviderFn<TInput, TOutput, TConfig>>
|
|
30
|
-
): ReturnType<OpenApiGenerationProviderFn<TInput, TOutput, TConfig>>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type OpenApiGenerationProviderFn<
|
|
34
|
-
TInput extends OpenApiGeneratorInput = OpenApiGeneratorInput,
|
|
35
|
-
TOutput extends OpenApiGeneratorOutput = OpenApiGeneratorOutput,
|
|
36
|
-
TConfig extends AnyConfig = AnyConfig,
|
|
37
|
-
> = (context: OpenApiGeneratorContext<TInput>, config?: Partial<TConfig>) => MaybePromise<TOutput>;
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenApiDocument,
|
|
3
|
-
OpenApiHeader,
|
|
4
|
-
OpenApiMediaType,
|
|
5
|
-
OpenApiParameter,
|
|
6
|
-
OpenApiPathItem,
|
|
7
|
-
OpenApiRequestBody,
|
|
8
|
-
OpenApiResponse,
|
|
9
|
-
OpenApiSchema,
|
|
10
|
-
} from '../parse/openapi-types.js';
|
|
11
|
-
import type { Deref } from '../parse/types.js';
|
|
12
|
-
import { collect, collectRecord } from './helpers.js';
|
|
13
|
-
import type { OpenApiCollectorData } from './types.js';
|
|
14
|
-
|
|
15
|
-
type Collect<T> = Deref<T> | Deref<T>[] | undefined;
|
|
16
|
-
|
|
17
|
-
export function collectOpenApi(apis: Deref<OpenApiDocument>[]): OpenApiCollectorData {
|
|
18
|
-
const data: OpenApiCollectorData = {
|
|
19
|
-
documents: [],
|
|
20
|
-
schemas: new Map(),
|
|
21
|
-
endpoints: new Map(),
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
collectDocument(data, apis);
|
|
25
|
-
|
|
26
|
-
return data;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const jsonSchemaProperties = ['$id', 'allOf', 'anyOf', 'oneOf', 'enum', 'not', 'properties', 'title', 'type'];
|
|
30
|
-
|
|
31
|
-
function collectDocument(data: OpenApiCollectorData, documents: Collect<OpenApiDocument>) {
|
|
32
|
-
collect(data, documents, (data, document) => {
|
|
33
|
-
data.documents.push(document);
|
|
34
|
-
collectPaths(data, document.paths);
|
|
35
|
-
collectRecord<Deref<OpenApiSchema>>(data, document.components?.schemas, collectSchema);
|
|
36
|
-
collectRecord<Deref<OpenApiSchema>>(data, document.definitions, collectSchema);
|
|
37
|
-
collectRecord<Deref<OpenApiParameter>>(data, document.components?.parameters, collectParameter);
|
|
38
|
-
collectRecord<Deref<OpenApiParameter>>(data, document.parameters, collectParameter);
|
|
39
|
-
collectRecord<Deref<OpenApiRequestBody>>(data, document.components?.requestBodies, collectRequestBody);
|
|
40
|
-
collectRecord<Deref<OpenApiResponse>>(data, document.components?.responses, collectResponse);
|
|
41
|
-
collectRecord<Deref<OpenApiResponse>>(data, document.responses, collectResponse);
|
|
42
|
-
collectRecord<Deref<OpenApiHeader>>(data, document.components?.headers, collectHeader);
|
|
43
|
-
|
|
44
|
-
if (Object.keys(document).some((key) => jsonSchemaProperties.includes(key))) {
|
|
45
|
-
collectSchema(data, document as Deref<OpenApiSchema>);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function collectPaths(data: OpenApiCollectorData, paths: Collect<Record<string, OpenApiPathItem>>) {
|
|
51
|
-
collect(data, paths, (data, path) => {
|
|
52
|
-
collectRecord<Deref<OpenApiPathItem>>(data, path, collectPathItem);
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function collectPathItem(data: OpenApiCollectorData, pathItems: Collect<OpenApiPathItem>, path: string) {
|
|
57
|
-
collect(data, pathItems, (data, pathItem) => {
|
|
58
|
-
collectParameter(data, pathItem.parameters);
|
|
59
|
-
for (const m of ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'] as const) {
|
|
60
|
-
const operation = pathItem[m];
|
|
61
|
-
if (!operation) continue;
|
|
62
|
-
const key = `${operation.$src.file}#${operation.$src.path}`;
|
|
63
|
-
if (data.endpoints.has(key)) continue;
|
|
64
|
-
data.endpoints.set(key, {
|
|
65
|
-
path,
|
|
66
|
-
method: m,
|
|
67
|
-
pathItem,
|
|
68
|
-
operation,
|
|
69
|
-
});
|
|
70
|
-
collectParameter(data, operation.parameters);
|
|
71
|
-
collectRequestBody(data, operation.requestBody);
|
|
72
|
-
collectRecord<Deref<OpenApiResponse>>(data, operation.responses, collectResponse);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function collectSchema(data: OpenApiCollectorData, schemas: Collect<OpenApiSchema>) {
|
|
78
|
-
collect(data, schemas, (data, schema) => {
|
|
79
|
-
const key = `${schema.$src.file}#${schema.$src.path}`;
|
|
80
|
-
if (data.schemas.has(key)) return;
|
|
81
|
-
data.schemas.set(key, schema);
|
|
82
|
-
collectSchema(data, schema.allOf);
|
|
83
|
-
collectSchema(data, schema.anyOf);
|
|
84
|
-
collectSchema(data, schema.oneOf);
|
|
85
|
-
collectSchema(data, schema.items);
|
|
86
|
-
collectSchema(data, schema.not);
|
|
87
|
-
collectRecord<Deref<OpenApiSchema>>(data, schema.properties, collectSchema);
|
|
88
|
-
collectRecord<Deref<OpenApiSchema>>(data, schema.patternProperties, collectSchema);
|
|
89
|
-
collectRecord<Deref<OpenApiSchema>>(data, schema.dependencies, collectSchema);
|
|
90
|
-
collectRecord<Deref<OpenApiSchema>>(data, schema.definitions, collectSchema);
|
|
91
|
-
if (typeof schema.additionalProperties === 'object') {
|
|
92
|
-
collectSchema(data, schema.additionalProperties);
|
|
93
|
-
}
|
|
94
|
-
if (typeof schema.additionalItems === 'object') {
|
|
95
|
-
collectSchema(data, schema.additionalItems);
|
|
96
|
-
}
|
|
97
|
-
if (typeof schema.discriminator === 'object') {
|
|
98
|
-
collectRecord<Deref<OpenApiSchema>>(data, schema.discriminator?.mapping, collectSchema);
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function collectParameter(data: OpenApiCollectorData, parameters: Collect<OpenApiParameter>) {
|
|
104
|
-
collect(data, parameters, (data, parameter) => {
|
|
105
|
-
collectSchema(data, parameter.schema);
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function collectMediaType(data: OpenApiCollectorData, mediaTypes: Collect<OpenApiMediaType>) {
|
|
110
|
-
collect(data, mediaTypes, (data, mediaType) => {
|
|
111
|
-
collectSchema(data, mediaType.schema);
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function collectRequestBody(data: OpenApiCollectorData, requestBody: Collect<OpenApiRequestBody>) {
|
|
116
|
-
collect(data, requestBody, (data, requestBody) => {
|
|
117
|
-
collectRecord<Deref<OpenApiMediaType>>(data, requestBody.content, collectMediaType);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function isSchema(obj: Record<string, unknown>): obj is Deref<OpenApiSchema> {
|
|
122
|
-
return obj && typeof obj === 'object' && obj['type'] !== undefined;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function collectResponse(data: OpenApiCollectorData, responses: Collect<OpenApiResponse>) {
|
|
126
|
-
collect(data, responses, (data, responses) => {
|
|
127
|
-
collectRecord<Deref<OpenApiMediaType>>(data, responses.content, collectMediaType);
|
|
128
|
-
collect(data, responses.headers, (data, header) => {
|
|
129
|
-
if (isSchema(header)) {
|
|
130
|
-
collectSchema(data, header);
|
|
131
|
-
} else {
|
|
132
|
-
collectHeader(data, header);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function collectHeader(data: OpenApiCollectorData, headers: Collect<OpenApiHeader>) {
|
|
139
|
-
collect(data, headers, (data, headers) => {
|
|
140
|
-
collectSchema(data, headers.schema);
|
|
141
|
-
});
|
|
142
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { isOpenApiObjectProperty } from '../internal-utils.js';
|
|
2
|
-
import type { Nullable } from '../utils/type.utils.js';
|
|
3
|
-
import type { OpenApiCollectorData } from './types.js';
|
|
4
|
-
|
|
5
|
-
export function collect<T extends Record<`x-${string}`, unknown>>(
|
|
6
|
-
data: OpenApiCollectorData,
|
|
7
|
-
obj: Nullable<T | Nullable<T>[]>,
|
|
8
|
-
func: (data: OpenApiCollectorData, obj: NonNullable<T>) => void,
|
|
9
|
-
) {
|
|
10
|
-
if (!obj) return;
|
|
11
|
-
if (Array.isArray(obj)) {
|
|
12
|
-
for (const o of obj) {
|
|
13
|
-
if (!o) continue;
|
|
14
|
-
if (o['x-ignore']) continue;
|
|
15
|
-
func(data, o);
|
|
16
|
-
}
|
|
17
|
-
} else {
|
|
18
|
-
if (obj['x-ignore']) return;
|
|
19
|
-
func(data, obj);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function collectRecord<T extends Record<`x-${string}`, unknown>>(
|
|
24
|
-
data: OpenApiCollectorData,
|
|
25
|
-
obj: Nullable<Record<string, Nullable<T>>>,
|
|
26
|
-
func: (data: OpenApiCollectorData, obj: NonNullable<T>, key: string) => void,
|
|
27
|
-
) {
|
|
28
|
-
if (!obj) return;
|
|
29
|
-
for (const key in obj) {
|
|
30
|
-
if (!isOpenApiObjectProperty(key)) continue;
|
|
31
|
-
const value = obj[key];
|
|
32
|
-
if (!value) continue;
|
|
33
|
-
if (value['x-ignore']) continue;
|
|
34
|
-
func(data, value, key);
|
|
35
|
-
}
|
|
36
|
-
}
|
package/src/src/collect/types.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenApiDocument,
|
|
3
|
-
OpenApiHttpMethod,
|
|
4
|
-
OpenApiOperation,
|
|
5
|
-
OpenApiPathItem,
|
|
6
|
-
OpenApiSchema,
|
|
7
|
-
} from '../parse/openapi-types.js';
|
|
8
|
-
import type { Deref } from '../parse/types.js';
|
|
9
|
-
|
|
10
|
-
export type OpenApiCollectorEndpointInfo = {
|
|
11
|
-
path: string;
|
|
12
|
-
method: OpenApiHttpMethod;
|
|
13
|
-
pathItem: Deref<OpenApiPathItem>;
|
|
14
|
-
operation: Deref<OpenApiOperation>;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type OpenApiCollectorData = {
|
|
18
|
-
documents: Deref<OpenApiDocument>[];
|
|
19
|
-
schemas: Map<string, Deref<OpenApiSchema>>;
|
|
20
|
-
endpoints: Map<string, OpenApiCollectorEndpointInfo>;
|
|
21
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { isNullish } from '../utils/common.utils.js';
|
|
2
|
-
import type { OpenApiObject } from './openapi-types.js';
|
|
3
|
-
import type { Deref, DerefSource } from './types.js';
|
|
4
|
-
|
|
5
|
-
export function createDerefProxy<T extends OpenApiObject<string>>(
|
|
6
|
-
obj: T,
|
|
7
|
-
source: DerefSource<T>,
|
|
8
|
-
ref?: Deref<T>,
|
|
9
|
-
): Deref<T> {
|
|
10
|
-
return new Proxy(obj, new DerefProxyHandler(source, ref)) as Deref<T>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const propertiesNotDerivedFromRef: PropertyKey[] = ['title'];
|
|
14
|
-
|
|
15
|
-
class DerefProxyHandler<T extends OpenApiObject<string>> implements ProxyHandler<T> {
|
|
16
|
-
private readonly _overwrittenValues: Record<PropertyKey, unknown> = {};
|
|
17
|
-
|
|
18
|
-
constructor(
|
|
19
|
-
private readonly _source: DerefSource<T>,
|
|
20
|
-
private _ref?: Deref<T>,
|
|
21
|
-
) {}
|
|
22
|
-
|
|
23
|
-
public get(target: T, prop: PropertyKey): unknown {
|
|
24
|
-
if (prop === '$ref') {
|
|
25
|
-
return this._ref;
|
|
26
|
-
} else if (prop === '$src') {
|
|
27
|
-
return this._source;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (this._overwrittenValues[prop] !== undefined) {
|
|
31
|
-
return this._overwrittenValues[prop];
|
|
32
|
-
}
|
|
33
|
-
if ((target as Record<PropertyKey, unknown>)[prop] !== undefined) {
|
|
34
|
-
return (target as Record<PropertyKey, unknown>)[prop];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return propertiesNotDerivedFromRef.includes(prop)
|
|
38
|
-
? undefined
|
|
39
|
-
: (this._ref as Record<PropertyKey, unknown> | undefined)?.[prop];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public set(_target: T, prop: PropertyKey, value: unknown): boolean {
|
|
43
|
-
if (prop === '$ref' && (typeof value === 'object' || typeof value === 'undefined')) {
|
|
44
|
-
this._ref = !value ? undefined : (value as Deref<T>);
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
if (prop === '$src') {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
this._overwrittenValues[prop] = value;
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public has(target: T, prop: PropertyKey): boolean {
|
|
56
|
-
return prop in target || (!isNullish(this._ref) && prop in this._ref);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
public ownKeys(target: T): ArrayLike<string | symbol> {
|
|
60
|
-
return Array.from(
|
|
61
|
-
new Set([
|
|
62
|
-
...Object.getOwnPropertyNames(target),
|
|
63
|
-
...Object.getOwnPropertySymbols(target),
|
|
64
|
-
...(!isNullish(this._ref) ? Object.keys(this._ref) : []),
|
|
65
|
-
'$ref',
|
|
66
|
-
'$src',
|
|
67
|
-
]),
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
}
|