@goast/core 0.5.3 → 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/package.json +1 -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,58 +0,0 @@
|
|
|
1
|
-
// deno-lint-ignore-file
|
|
2
|
-
import type { EmptyConstructor, FunctionNames } from './type.utils.js';
|
|
3
|
-
|
|
4
|
-
type MatchingFunctionNames<T, TAction> = {
|
|
5
|
-
[K in keyof T]: T[K] extends TAction ? K : never;
|
|
6
|
-
}[keyof T];
|
|
7
|
-
|
|
8
|
-
type CtorActionRunner<T, TAction> = {
|
|
9
|
-
kind: 'ctor';
|
|
10
|
-
factory: EmptyConstructor<T>;
|
|
11
|
-
functionName: MatchingFunctionNames<T, TAction>;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
type FnActionRunner<TAction> = {
|
|
15
|
-
kind: 'fn';
|
|
16
|
-
action: TAction;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
type ValueActionRunner<T, TAction> = {
|
|
20
|
-
kind: 'value';
|
|
21
|
-
value: T;
|
|
22
|
-
functionName: MatchingFunctionNames<T, TAction>;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
type ActionRunner<TAction> = CtorActionRunner<any, TAction> | FnActionRunner<TAction> | ValueActionRunner<any, TAction>;
|
|
26
|
-
|
|
27
|
-
export class ActionProvider<TAction extends (...args: any[]) => any> {
|
|
28
|
-
constructor(private readonly _runner: ActionRunner<TAction>) {}
|
|
29
|
-
|
|
30
|
-
public run(...args: Parameters<TAction>): ReturnType<TAction> {
|
|
31
|
-
switch (this._runner.kind) {
|
|
32
|
-
case 'ctor':
|
|
33
|
-
return new this._runner.factory()[this._runner.functionName as any](...args);
|
|
34
|
-
case 'fn':
|
|
35
|
-
return this._runner.action(...args);
|
|
36
|
-
case 'value':
|
|
37
|
-
return this._runner.value[this._runner.functionName as any](...args);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public static fromType<T, TName extends FunctionNames<T>>(
|
|
42
|
-
type: EmptyConstructor<T>,
|
|
43
|
-
functionName: TName,
|
|
44
|
-
): ActionProvider<T[TName] extends (...args: any[]) => any ? T[TName] : never> {
|
|
45
|
-
return new ActionProvider({ kind: 'ctor', factory: type, functionName: functionName as any });
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
public static fromFn<TAction extends (...args: any[]) => any>(fn: TAction): ActionProvider<TAction> {
|
|
49
|
-
return new ActionProvider({ kind: 'fn', action: fn });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
public static fromValue<T, TName extends FunctionNames<T>>(
|
|
53
|
-
value: T,
|
|
54
|
-
functionName: TName,
|
|
55
|
-
): ActionProvider<T[TName] extends (...args: any[]) => any ? T[TName] : never> {
|
|
56
|
-
return new ActionProvider({ kind: 'value', value, functionName: functionName as any });
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { dirname, relative } from 'node:path';
|
|
2
|
-
import process from 'node:process';
|
|
3
|
-
import type { ApiComponent, ApiData } from '../transform/api-types.js';
|
|
4
|
-
|
|
5
|
-
const DOCUMENTS_BASE_PATH = Symbol('documentsBasePath');
|
|
6
|
-
|
|
7
|
-
type ApiDataWithBasePath = ApiData & {
|
|
8
|
-
[DOCUMENTS_BASE_PATH]?: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export function getSourceDisplayName<T>(data: ApiData, component: ApiComponent<T>): string {
|
|
12
|
-
let basePath: string | undefined = (data as ApiDataWithBasePath)[DOCUMENTS_BASE_PATH];
|
|
13
|
-
if (basePath === undefined) {
|
|
14
|
-
const allPaths = data.documents.map((doc) => doc.$src.file);
|
|
15
|
-
basePath = getCommonBasePath(allPaths);
|
|
16
|
-
(data as ApiDataWithBasePath)[DOCUMENTS_BASE_PATH] = basePath;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const relativePath = relative(basePath, component.$src.file);
|
|
20
|
-
return `${relativePath}#${component.$src.path}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function getCommonBasePath(paths: string[]): string {
|
|
24
|
-
if (paths.length === 0) return '';
|
|
25
|
-
if (paths.length === 1) return dirname(paths[0]);
|
|
26
|
-
|
|
27
|
-
const splitPaths = paths.map((p) => normalizePath(p).split('/'));
|
|
28
|
-
const minLength = Math.min(...splitPaths.map((parts) => parts.length));
|
|
29
|
-
const commonParts: string[] = [];
|
|
30
|
-
|
|
31
|
-
for (let i = 0; i < minLength; i++) {
|
|
32
|
-
const part = splitPaths[0][i];
|
|
33
|
-
if (splitPaths.every((parts) => parts[i] === part)) {
|
|
34
|
-
commonParts.push(part);
|
|
35
|
-
} else {
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return commonParts.join('/');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function normalizePath(path: string): string {
|
|
44
|
-
if (process.platform === 'win32') {
|
|
45
|
-
return path.replace(/\\/g, '/');
|
|
46
|
-
}
|
|
47
|
-
return path;
|
|
48
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
-
import { basename, resolve } from 'node:path';
|
|
3
|
-
import { fileURLToPath, URL } from 'node:url';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import fs from 'fs-extra';
|
|
7
|
-
|
|
8
|
-
export class AssetManager {
|
|
9
|
-
private readonly _assetsBaseUrl: URL;
|
|
10
|
-
|
|
11
|
-
constructor(assetsBaseUrl: URL) {
|
|
12
|
-
this._assetsBaseUrl = assetsBaseUrl;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
public async getAssetFileContent(relativePath: string): Promise<string> {
|
|
16
|
-
if (this._assetsBaseUrl.protocol === 'file:') {
|
|
17
|
-
return await fs.readFile(resolve(fileURLToPath(this._assetsBaseUrl), relativePath), 'utf8');
|
|
18
|
-
} else {
|
|
19
|
-
return await this.fetchAssetFile(relativePath);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public async copyAssetFile(relativePath: string, destDir: string, logName?: string): Promise<void> {
|
|
24
|
-
const targetPath = resolve(destDir, basename(relativePath));
|
|
25
|
-
if (logName !== undefined) {
|
|
26
|
-
if (logName) {
|
|
27
|
-
console.log(`Copying ${logName} to "${targetPath}"`);
|
|
28
|
-
} else {
|
|
29
|
-
console.log(`Copying asset file "${relativePath}" to "${targetPath}"`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (this._assetsBaseUrl.protocol === 'file:') {
|
|
33
|
-
const srcPath = resolve(fileURLToPath(this._assetsBaseUrl), relativePath);
|
|
34
|
-
await fs.copyFile(srcPath, targetPath);
|
|
35
|
-
} else {
|
|
36
|
-
const fileContent = await this.fetchAssetFile(relativePath);
|
|
37
|
-
await fs.outputFile(targetPath, fileContent);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private async fetchAssetFile(relativePath: string): Promise<string> {
|
|
42
|
-
const url = new URL(relativePath, this._assetsBaseUrl);
|
|
43
|
-
const response = await dntShim.fetch(url);
|
|
44
|
-
if (!response.ok) {
|
|
45
|
-
throw new Error(
|
|
46
|
-
`Failed to fetch asset file "${relativePath}" from "${url.href}": ${response.statusText} (${response.status})`,
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
return await response.text();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// deno-lint-ignore-file no-explicit-any
|
|
2
|
-
export function classifyArray<TItem, TClassification extends Record<string, abstract new (...args: any[]) => any>>(
|
|
3
|
-
items: Iterable<TItem>,
|
|
4
|
-
classification: TClassification,
|
|
5
|
-
): { [P in keyof TClassification]: InstanceType<TClassification[P]>[] } & {
|
|
6
|
-
rest: Exclude<TItem, InstanceType<TClassification[string]>>[];
|
|
7
|
-
} {
|
|
8
|
-
const result = { rest: [] } as { [P in keyof TClassification]: InstanceType<TClassification[P]>[] } & {
|
|
9
|
-
rest: Exclude<TItem, InstanceType<TClassification[string]>>[];
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
for (const key in classification) {
|
|
13
|
-
(result as any)[key] = [];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
for (const item of items) {
|
|
17
|
-
let classified = false;
|
|
18
|
-
for (const key in classification) {
|
|
19
|
-
const type = classification[key];
|
|
20
|
-
if (item instanceof type) {
|
|
21
|
-
result[key].push(item as any);
|
|
22
|
-
classified = true;
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (!classified) {
|
|
27
|
-
result.rest.push(item as any);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return result;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function isInstanceOf<T>(item: unknown, type: abstract new (...args: any[]) => T): item is T {
|
|
35
|
-
return item instanceof type;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function getIsInstanceOf<T>(type: abstract new (...args: any[]) => T): (item: unknown) => item is T {
|
|
39
|
-
return (item): item is T => item instanceof type;
|
|
40
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type { SingleOrMultiple } from './type.utils.js';
|
|
2
|
-
|
|
3
|
-
export function isNullish(value: unknown): value is null | undefined {
|
|
4
|
-
return value === null || value === undefined;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function notNullish<T>(value: T): value is NonNullable<T> {
|
|
8
|
-
return !isNullish(value);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function concatSingleOrMultiple<T>(...values: SingleOrMultiple<T>[]): SingleOrMultiple<T> {
|
|
12
|
-
if (values.length === 1) {
|
|
13
|
-
return values[0];
|
|
14
|
-
}
|
|
15
|
-
const result: T[] = [];
|
|
16
|
-
for (const value of values) {
|
|
17
|
-
if (Array.isArray(value)) {
|
|
18
|
-
result.push(...value);
|
|
19
|
-
} else {
|
|
20
|
-
result.push(value);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return result;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function isIterable(value: unknown): value is Iterable<unknown> {
|
|
27
|
-
return typeof value === 'object' && value !== null && Symbol.iterator in value;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function toArray<T>(value: T | T[] | Iterable<T>): T[] {
|
|
31
|
-
if (Array.isArray(value)) {
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
if (isIterable(value)) {
|
|
35
|
-
return Array.from(value);
|
|
36
|
-
}
|
|
37
|
-
return [value];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function modify<T>(value: T, callback: (value: NonNullable<T>) => void): T {
|
|
41
|
-
if (notNullish(value)) {
|
|
42
|
-
callback(value);
|
|
43
|
-
}
|
|
44
|
-
return value;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function run<T>(value: T, callback: (value: T) => void): T {
|
|
48
|
-
callback(value);
|
|
49
|
-
return value;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function transform<T, U>(value: T, callback: (value: T) => U): U {
|
|
53
|
-
return callback(value);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
type IterableItem<T> = T extends Iterable<infer U> ? U : never;
|
|
57
|
-
export function modifyEach<T extends Iterable<unknown>>(
|
|
58
|
-
values: T,
|
|
59
|
-
callback: (value: NonNullable<IterableItem<T>>) => void,
|
|
60
|
-
): T {
|
|
61
|
-
for (const value of values) {
|
|
62
|
-
if (notNullish(value)) {
|
|
63
|
-
callback(value as NonNullable<IterableItem<T>>);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return values;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function runEach<T extends Iterable<unknown>>(values: T, callback: (value: IterableItem<T>) => void): T {
|
|
70
|
-
for (const value of values) {
|
|
71
|
-
callback(value as IterableItem<T>);
|
|
72
|
-
}
|
|
73
|
-
return values;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function transformEach<T, U>(values: Iterable<T>, callback: (value: T) => U): U[] {
|
|
77
|
-
const result: U[] = [];
|
|
78
|
-
for (const value of values) {
|
|
79
|
-
result.push(callback(value));
|
|
80
|
-
}
|
|
81
|
-
return result;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function asVoid(_: unknown): void {
|
|
85
|
-
// Do nothing
|
|
86
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export type Condition<T = never> = boolean | ([T] extends [never] ? () => boolean : (ctx: T) => boolean);
|
|
2
|
-
export function evalCondition(condition: Condition<never>): boolean;
|
|
3
|
-
export function evalCondition<T>(condition: Condition<T>, ctx: T): boolean;
|
|
4
|
-
export function evalCondition<T>(condition: Condition<T>, ctx?: T): boolean {
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
6
|
-
return typeof condition === 'function' ? condition(ctx!) : condition;
|
|
7
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { ApiEndpoint } from '../transform/api-types.js';
|
|
2
|
-
|
|
3
|
-
export function getEndpointUrlPreview(endpoint: ApiEndpoint): string {
|
|
4
|
-
let url = endpoint.path;
|
|
5
|
-
const queryParams = endpoint.parameters.filter((p) => p.target === 'query');
|
|
6
|
-
if (queryParams.length > 0) {
|
|
7
|
-
url += '?' + queryParams.map((p) => (p.required ? `${p.name}={${p.name}}` : `[${p.name}={${p.name}}]`)).join('&');
|
|
8
|
-
}
|
|
9
|
-
return url;
|
|
10
|
-
}
|
package/src/src/utils/factory.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { Constructor } from './type.utils.js';
|
|
2
|
-
|
|
3
|
-
type FactoryProvider<T, TArgs extends unknown[]> =
|
|
4
|
-
| {
|
|
5
|
-
kind: 'ctor';
|
|
6
|
-
factory: Constructor<T, TArgs>;
|
|
7
|
-
}
|
|
8
|
-
| {
|
|
9
|
-
kind: 'fn';
|
|
10
|
-
factory: (...args: TArgs) => T;
|
|
11
|
-
}
|
|
12
|
-
| {
|
|
13
|
-
kind: 'value';
|
|
14
|
-
factory: T;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export class Factory<T, TArgs extends unknown[]> {
|
|
18
|
-
constructor(private readonly _provider: FactoryProvider<T, TArgs>) {}
|
|
19
|
-
|
|
20
|
-
public create(...args: TArgs): T {
|
|
21
|
-
switch (this._provider.kind) {
|
|
22
|
-
case 'ctor':
|
|
23
|
-
return new this._provider.factory(...args);
|
|
24
|
-
case 'fn':
|
|
25
|
-
return this._provider.factory(...args);
|
|
26
|
-
case 'value':
|
|
27
|
-
return this._provider.factory;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public static fromType<T, TArgs extends unknown[]>(type: Constructor<T, TArgs>): Factory<T, TArgs> {
|
|
32
|
-
return new Factory({ kind: 'ctor', factory: type });
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public static fromFn<T, TArgs extends unknown[]>(fn: (...args: TArgs) => T): Factory<T, TArgs> {
|
|
36
|
-
return new Factory({ kind: 'fn', factory: fn });
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public static fromValue<T>(value: T): Factory<T, []> {
|
|
40
|
-
return new Factory({ kind: 'value', factory: value });
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
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
|
-
}
|