@goast/core 0.5.0-beta.5 → 0.5.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/LICENSE +21 -21
- package/esm/src/utils/api-data.utils.d.ts +2 -2
- package/esm/src/utils/api-data.utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/script/src/utils/api-data.utils.d.ts +2 -2
- package/script/src/utils/api-data.utils.d.ts.map +1 -1
- package/src/_dnt.shims.ts +69 -0
- package/src/mod.ts +35 -0
- package/src/src/ast/node.ts +46 -0
- package/src/src/codegen/config.ts +41 -0
- package/src/src/codegen/endpoints-generator.ts +72 -0
- package/src/src/codegen/generator.ts +192 -0
- package/src/src/codegen/internal-utils.ts +6 -0
- package/src/src/codegen/schemas-generator.ts +87 -0
- package/src/src/codegen/services-generator.ts +77 -0
- package/src/src/codegen/types.ts +37 -0
- package/src/src/collect/collector.ts +142 -0
- package/src/src/collect/helpers.ts +36 -0
- package/src/src/collect/types.ts +21 -0
- package/src/src/internal-utils.ts +5 -0
- package/src/src/parse/deref-proxy.ts +64 -0
- package/src/src/parse/openapi-types.ts +949 -0
- package/src/src/parse/parser.ts +226 -0
- package/src/src/parse/types.ts +27 -0
- package/src/src/transform/api-types.ts +245 -0
- package/src/src/transform/helpers.ts +217 -0
- package/src/src/transform/transform-document.ts +35 -0
- package/src/src/transform/transform-endpoint.ts +331 -0
- package/src/src/transform/transform-schema.ts +217 -0
- package/src/src/transform/transformer.ts +53 -0
- package/src/src/transform/types.ts +52 -0
- package/src/src/utils/action-provider.ts +58 -0
- package/src/src/utils/api-data.utils.ts +48 -0
- package/src/src/utils/array.utils.ts +7 -0
- package/src/src/utils/asset-manager.ts +51 -0
- package/src/src/utils/class.utils.ts +40 -0
- package/src/src/utils/common.utils.ts +86 -0
- package/src/src/utils/condition.ts +7 -0
- package/src/src/utils/endpoint.utils.ts +10 -0
- package/src/src/utils/error.utils.ts +3 -0
- package/src/src/utils/factory.ts +42 -0
- package/src/src/utils/file-system.utils.ts +61 -0
- package/src/src/utils/generator.utils.ts +6 -0
- package/src/src/utils/object.utils.ts +32 -0
- package/src/src/utils/schema.utils.ts +148 -0
- package/src/src/utils/source-builder.ts +597 -0
- package/src/src/utils/string-builder/options.ts +19 -0
- package/src/src/utils/string-builder/string-builder.ts +165 -0
- package/src/src/utils/string-builder/utils.ts +69 -0
- package/src/src/utils/string.utils.ts +369 -0
- package/src/src/utils/string.utils.types.ts +179 -0
- package/src/src/utils/type.utils.ts +93 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
|
|
6
|
+
import type { OpenApiGeneratorConfig } from '../codegen/config.js';
|
|
7
|
+
import type { Nullable } from './type.utils.js';
|
|
8
|
+
|
|
9
|
+
export type DirectoryScanOptions = {
|
|
10
|
+
recursive: boolean;
|
|
11
|
+
maxDepth: Nullable<number>;
|
|
12
|
+
filter?: (file: string) => boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const defaultDirectoryScanOptions: DirectoryScanOptions = {
|
|
16
|
+
recursive: false,
|
|
17
|
+
maxDepth: 5,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export async function getFiles(dir: string, options?: Partial<DirectoryScanOptions>): Promise<string[]> {
|
|
21
|
+
const opts = { ...defaultDirectoryScanOptions, ...options };
|
|
22
|
+
const files: string[] = [];
|
|
23
|
+
await getFilesImpl(dir, opts, files, 0);
|
|
24
|
+
return files;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function getFilesImpl(
|
|
28
|
+
dir: string,
|
|
29
|
+
options: DirectoryScanOptions,
|
|
30
|
+
files: string[],
|
|
31
|
+
currentDepth: number,
|
|
32
|
+
): Promise<void> {
|
|
33
|
+
const dirFiles = await fs.readdir(dir);
|
|
34
|
+
for (const file of dirFiles) {
|
|
35
|
+
const filePath = resolve(dir, file);
|
|
36
|
+
const stat = await fs.lstat(filePath);
|
|
37
|
+
if (stat.isDirectory()) {
|
|
38
|
+
if (options.recursive) {
|
|
39
|
+
if (options.maxDepth && options.maxDepth > currentDepth) {
|
|
40
|
+
await getFilesImpl(filePath, options, files, currentDepth + 1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
if (!options.filter || options.filter(file)) {
|
|
45
|
+
files.push(filePath);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function writeGeneratedFile(config: OpenApiGeneratorConfig, filePath: string, content: string): void {
|
|
52
|
+
if (config.existingFileBehavior !== 'override' && fs.existsSync(filePath)) {
|
|
53
|
+
if (config.existingFileBehavior === 'error') {
|
|
54
|
+
throw new Error(`File already exists: ${filePath}`);
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fs.ensureDirSync(dirname(filePath));
|
|
60
|
+
fs.writeFileSync(filePath, content);
|
|
61
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export function createOverwriteProxy<T extends object>(target: T, values?: Partial<T>): T {
|
|
2
|
+
const proxy = new Proxy(target, new OverwriteProxyHandler());
|
|
3
|
+
if (values) {
|
|
4
|
+
Object.assign(proxy, values);
|
|
5
|
+
}
|
|
6
|
+
return proxy;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getDeepProperty(obj: object, path: string[]): unknown {
|
|
10
|
+
let current = obj;
|
|
11
|
+
for (const key of path) {
|
|
12
|
+
if (!current || typeof current !== 'object') {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
// deno-lint-ignore no-explicit-any
|
|
16
|
+
current = (current as any)[key];
|
|
17
|
+
}
|
|
18
|
+
return current;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class OverwriteProxyHandler<T extends object> implements ProxyHandler<T> {
|
|
22
|
+
private readonly _overwrittenValues: Record<PropertyKey, unknown> = {};
|
|
23
|
+
|
|
24
|
+
public get(target: T, prop: PropertyKey): unknown {
|
|
25
|
+
return this._overwrittenValues[prop] ?? (target as Record<PropertyKey, unknown>)[prop];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public set(_target: T, prop: PropertyKey, value: unknown): boolean {
|
|
29
|
+
this._overwrittenValues[prop] = value;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { isOpenApiObjectProperty } from '../internal-utils.js';
|
|
2
|
+
import type { OpenApiSchema } from '../parse/openapi-types.js';
|
|
3
|
+
import type { ApiSchema, ApiSchemaProperty, ObjectLikeApiSchema } from '../transform/api-types.js';
|
|
4
|
+
|
|
5
|
+
export function resolveAnyOfAndAllOf(
|
|
6
|
+
schema: ApiSchema<'combined' | 'object'>,
|
|
7
|
+
ignoreNonObjectParts: boolean,
|
|
8
|
+
): ApiSchema<'object'> | undefined {
|
|
9
|
+
if (!ignoreNonObjectParts && (hasInvalidSubSchema(schema.anyOf) || hasInvalidSubSchema(schema.allOf))) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const required = new Set(schema.required);
|
|
14
|
+
const properties = new Map<string, ApiSchemaProperty>();
|
|
15
|
+
if ('properties' in schema) {
|
|
16
|
+
schema.properties.forEach((prop) => properties.set(prop.name, prop));
|
|
17
|
+
}
|
|
18
|
+
collectSubSchemaProperties(schema.allOf, properties, required, false);
|
|
19
|
+
collectSubSchemaProperties(schema.anyOf, properties, required, true);
|
|
20
|
+
|
|
21
|
+
const initialAdditionalProperties = schema.kind === 'object' ? schema.additionalProperties : undefined;
|
|
22
|
+
let additionalProperties = initialAdditionalProperties;
|
|
23
|
+
additionalProperties = combineAdditionalProperties(schema.allOf, additionalProperties);
|
|
24
|
+
additionalProperties = combineAdditionalProperties(schema.anyOf, additionalProperties);
|
|
25
|
+
|
|
26
|
+
if (properties.size === 0 && initialAdditionalProperties === additionalProperties) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
...schema,
|
|
32
|
+
kind: 'object',
|
|
33
|
+
type: 'object',
|
|
34
|
+
anyOf: [],
|
|
35
|
+
allOf: [],
|
|
36
|
+
properties: properties,
|
|
37
|
+
required: required,
|
|
38
|
+
additionalProperties,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function collectSubSchemaProperties(
|
|
43
|
+
subSchemas: ApiSchema[],
|
|
44
|
+
properties: Map<string, ApiSchemaProperty>,
|
|
45
|
+
required: Set<string>,
|
|
46
|
+
optional: boolean,
|
|
47
|
+
) {
|
|
48
|
+
for (const subSchema of subSchemas) {
|
|
49
|
+
if (subSchema.kind === 'object') {
|
|
50
|
+
for (const prop of subSchema.properties.values()) {
|
|
51
|
+
if (!properties.has(prop.name)) {
|
|
52
|
+
properties.set(prop.name, prop);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!optional) {
|
|
56
|
+
for (const prop of subSchema.required) {
|
|
57
|
+
required.add(prop);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (subSchema.kind === 'object' || subSchema.kind === 'combined') {
|
|
63
|
+
collectSubSchemaProperties(subSchema.allOf, properties, required, optional);
|
|
64
|
+
collectSubSchemaProperties(subSchema.anyOf, properties, required, true);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function combineAdditionalProperties(
|
|
70
|
+
subSchemas: ApiSchema[],
|
|
71
|
+
current: ObjectLikeApiSchema['additionalProperties'],
|
|
72
|
+
): ObjectLikeApiSchema['additionalProperties'] {
|
|
73
|
+
if (current === true) return true;
|
|
74
|
+
|
|
75
|
+
for (const subSchema of subSchemas) {
|
|
76
|
+
if (subSchema.kind === 'object' && subSchema.additionalProperties) {
|
|
77
|
+
if (subSchema.additionalProperties === true) return true;
|
|
78
|
+
if (!current) {
|
|
79
|
+
current = subSchema.additionalProperties;
|
|
80
|
+
} else if (current && current.id !== subSchema.additionalProperties.id) {
|
|
81
|
+
if (current.kind === 'oneOf') {
|
|
82
|
+
current.oneOf.push(subSchema.additionalProperties);
|
|
83
|
+
} else {
|
|
84
|
+
const id = `schema-${Math.random().toString(36).substring(2)}`;
|
|
85
|
+
current = {
|
|
86
|
+
$ref: undefined,
|
|
87
|
+
$src: current.$src,
|
|
88
|
+
id,
|
|
89
|
+
kind: 'oneOf',
|
|
90
|
+
name: id,
|
|
91
|
+
isNameGenerated: true,
|
|
92
|
+
description: undefined,
|
|
93
|
+
deprecated: false,
|
|
94
|
+
accessibility: 'all',
|
|
95
|
+
enum: undefined,
|
|
96
|
+
const: undefined,
|
|
97
|
+
default: undefined,
|
|
98
|
+
example: undefined,
|
|
99
|
+
nullable: false,
|
|
100
|
+
required: new Set(),
|
|
101
|
+
custom: {},
|
|
102
|
+
not: undefined,
|
|
103
|
+
discriminator: undefined,
|
|
104
|
+
inheritedSchemas: [],
|
|
105
|
+
oneOf: [current, subSchema.additionalProperties],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (subSchema.kind === 'object' || subSchema.kind === 'combined') {
|
|
112
|
+
current = combineAdditionalProperties(subSchema.allOf, current);
|
|
113
|
+
current = combineAdditionalProperties(subSchema.anyOf, current);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (current === true) return true;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return current;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function hasInvalidSubSchema(subSchemas: ApiSchema[]): boolean {
|
|
123
|
+
return subSchemas.some(
|
|
124
|
+
(x) =>
|
|
125
|
+
x.kind !== 'object' &&
|
|
126
|
+
(x.kind !== 'combined' || (!hasInvalidSubSchema(x.allOf) && !hasInvalidSubSchema(x.anyOf))),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export const DEFAULT_IGNORED_SCHEMA_PROPERTIES: (keyof OpenApiSchema)[] = [
|
|
131
|
+
'description',
|
|
132
|
+
'example',
|
|
133
|
+
'deprecated',
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Retrieves the first schema reference and the reference chain of a given schema that
|
|
138
|
+
* defines some schema properties. (e.g. schemas with just "$ref" are skipped)
|
|
139
|
+
* @param schema The schema to retrieve the reference from.
|
|
140
|
+
* @param propertiesToIgnore The properties to ignore when checking for a schema definition.
|
|
141
|
+
*/
|
|
142
|
+
export function getSchemaReference(schema: ApiSchema, propertiesToIgnore: (keyof OpenApiSchema)[]): ApiSchema {
|
|
143
|
+
if (!schema.$ref) return schema;
|
|
144
|
+
const hasPropertiesDefined = Object.keys(schema.$src.originalComponent).some(
|
|
145
|
+
(key) => isOpenApiObjectProperty(key) && !propertiesToIgnore.includes(key as keyof OpenApiSchema),
|
|
146
|
+
);
|
|
147
|
+
return hasPropertiesDefined ? schema : getSchemaReference(schema.$ref, propertiesToIgnore);
|
|
148
|
+
}
|