nestjs-openapi 0.1.1 → 0.1.3
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/dist/cli.mjs +4 -4
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +4 -4
- package/dist/internal.d.mts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.mjs +1 -1
- package/dist/shared/{nestjs-openapi.CCvQ3RSW.mjs → nestjs-openapi.D2c4bMP5.mjs} +378 -47
- package/dist/shared/{nestjs-openapi.CzNt1duF.mjs → nestjs-openapi.DRcy130f.mjs} +45 -4
- package/dist/shared/{nestjs-openapi.BYUrTaMo.d.mts → nestjs-openapi.t3iwzrrT.d.mts} +93 -12
- package/dist/shared/{nestjs-openapi.BYUrTaMo.d.ts → nestjs-openapi.t3iwzrrT.d.ts} +93 -12
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import 'tsx';
|
|
3
|
-
import { g as generate, e as formatValidationResult } from './shared/nestjs-openapi.
|
|
3
|
+
import { g as generate, e as formatValidationResult } from './shared/nestjs-openapi.D2c4bMP5.mjs';
|
|
4
4
|
import minimist from 'minimist';
|
|
5
5
|
import { relative } from 'node:path';
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
7
|
import 'effect';
|
|
8
8
|
import 'node:fs';
|
|
9
|
+
import 'node:crypto';
|
|
9
10
|
import 'ts-morph';
|
|
10
11
|
import 'glob';
|
|
11
12
|
import 'js-yaml';
|
|
12
|
-
import './shared/nestjs-openapi.
|
|
13
|
+
import './shared/nestjs-openapi.DRcy130f.mjs';
|
|
13
14
|
import 'ts-json-schema-generator';
|
|
14
|
-
import 'node:crypto';
|
|
15
15
|
import 'node:url';
|
|
16
16
|
import 'child_process';
|
|
17
17
|
|
|
@@ -117,7 +117,7 @@ const main = async () => {
|
|
|
117
117
|
console.log(` ${formatValidationResult(result.validation)}`);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
process.exit(0);
|
|
120
|
+
process.exit(result.validation.valid ? 0 : 1);
|
|
121
121
|
} catch (err) {
|
|
122
122
|
const duration = performance.now() - startTime;
|
|
123
123
|
const message = err instanceof Error ? err.message : String(err);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Context, Layer, Option } from 'effect';
|
|
2
|
-
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.
|
|
3
|
-
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.
|
|
2
|
+
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.t3iwzrrT.mjs';
|
|
3
|
+
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.t3iwzrrT.mjs';
|
|
4
4
|
import { DynamicModule } from '@nestjs/common';
|
|
5
5
|
import { Project, SourceFile, ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
|
|
6
6
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Context, Layer, Option } from 'effect';
|
|
2
|
-
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.
|
|
3
|
-
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.
|
|
2
|
+
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.t3iwzrrT.js';
|
|
3
|
+
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.t3iwzrrT.js';
|
|
4
4
|
import { DynamicModule } from '@nestjs/common';
|
|
5
5
|
import { Project, SourceFile, ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
|
|
6
6
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
export { c as categorizeBrokenRefs, d as defineConfig, f as findConfigFile, e as formatValidationResult, g as generate, b as loadAndResolveConfig, a as loadConfig, l as loadConfigFromFile, r as resolveConfig, v as validateSpec } from './shared/nestjs-openapi.
|
|
1
|
+
export { c as categorizeBrokenRefs, d as defineConfig, f as findConfigFile, e as formatValidationResult, g as generate, b as loadAndResolveConfig, a as loadConfig, l as loadConfigFromFile, r as resolveConfig, v as validateSpec } from './shared/nestjs-openapi.D2c4bMP5.mjs';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { Module } from '@nestjs/common';
|
|
5
5
|
export { generateAsync, generate as generateEffect } from './internal.mjs';
|
|
6
|
-
import { P as ProjectInitError, E as EntryNotFoundError } from './shared/nestjs-openapi.
|
|
7
|
-
export { a as ConfigLoadError, C as ConfigNotFoundError, b as ConfigValidationError, I as InvalidMethodError, c as getAllControllers, q as getArrayInitializer, o as getControllerMethodInfos, e as getControllerName, d as getControllerPrefix, j as getControllerTags, h as getDecoratorName, k as getHttpDecorator, f as getHttpMethods, m as getMethodInfo, w as getModuleDecoratorArg, z as getModuleMetadata, g as getModules, s as getStringLiteralValue, u as getSymbolFromIdentifier, l as isHttpDecorator, i as isHttpMethod, v as isModuleClass, n as normalizePath, y as resolveArrayOfClasses, x as resolveClassFromExpression, r as resolveClassFromSymbol, t as transformMethod, p as transformMethods } from './shared/nestjs-openapi.
|
|
6
|
+
import { P as ProjectInitError, E as EntryNotFoundError } from './shared/nestjs-openapi.DRcy130f.mjs';
|
|
7
|
+
export { a as ConfigLoadError, C as ConfigNotFoundError, b as ConfigValidationError, I as InvalidMethodError, c as getAllControllers, q as getArrayInitializer, o as getControllerMethodInfos, e as getControllerName, d as getControllerPrefix, j as getControllerTags, h as getDecoratorName, k as getHttpDecorator, f as getHttpMethods, m as getMethodInfo, w as getModuleDecoratorArg, z as getModuleMetadata, g as getModules, s as getStringLiteralValue, u as getSymbolFromIdentifier, l as isHttpDecorator, i as isHttpMethod, v as isModuleClass, n as normalizePath, y as resolveArrayOfClasses, x as resolveClassFromExpression, r as resolveClassFromSymbol, t as transformMethod, p as transformMethods } from './shared/nestjs-openapi.DRcy130f.mjs';
|
|
8
8
|
import { Context, Effect, Layer } from 'effect';
|
|
9
9
|
import { Project } from 'ts-morph';
|
|
10
|
+
import 'node:crypto';
|
|
10
11
|
import 'glob';
|
|
11
12
|
import 'js-yaml';
|
|
12
13
|
import 'ts-json-schema-generator';
|
|
13
|
-
import 'node:crypto';
|
|
14
14
|
import 'node:url';
|
|
15
15
|
import 'child_process';
|
|
16
16
|
|
package/dist/internal.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import 'effect';
|
|
2
|
-
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.
|
|
2
|
+
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.t3iwzrrT.mjs';
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import 'effect';
|
|
2
|
-
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.
|
|
2
|
+
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.t3iwzrrT.js';
|
package/dist/internal.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
import { Project } from 'ts-morph';
|
|
3
|
-
import { E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos, p as transformMethods } from './shared/nestjs-openapi.
|
|
3
|
+
import { E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos, p as transformMethods } from './shared/nestjs-openapi.DRcy130f.mjs';
|
|
4
4
|
|
|
5
5
|
const generate = (options) => Effect.gen(function* () {
|
|
6
6
|
yield* Effect.logInfo("Starting OpenAPI generation").pipe(
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Schema, Effect, Logger, Layer, LogLevel } from 'effect';
|
|
2
2
|
import { readFileSync, writeFileSync, existsSync, unlinkSync, mkdirSync } from 'node:fs';
|
|
3
|
-
import { join, dirname, resolve } from 'node:path';
|
|
3
|
+
import { join, dirname, resolve, relative } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
4
5
|
import { Project } from 'ts-morph';
|
|
5
6
|
import { globSync, glob } from 'glob';
|
|
6
7
|
import yaml from 'js-yaml';
|
|
7
|
-
import { C as ConfigNotFoundError, a as ConfigLoadError, b as ConfigValidationError, p as transformMethods, A as extractClassConstraints, B as getRequiredProperties, D as mergeValidationConstraints, E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos } from './nestjs-openapi.
|
|
8
|
+
import { C as ConfigNotFoundError, a as ConfigLoadError, b as ConfigValidationError, p as transformMethods, A as extractClassConstraints, B as getRequiredProperties, D as mergeValidationConstraints, E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos } from './nestjs-openapi.DRcy130f.mjs';
|
|
8
9
|
import { createGenerator } from 'ts-json-schema-generator';
|
|
9
|
-
import { randomUUID } from 'node:crypto';
|
|
10
10
|
import { pathToFileURL } from 'node:url';
|
|
11
11
|
import { execSync } from 'child_process';
|
|
12
12
|
|
|
@@ -466,6 +466,12 @@ const extractReferencedSchemas = (paths) => {
|
|
|
466
466
|
if (schema.oneOf) {
|
|
467
467
|
schema.oneOf.forEach(extractFromSchema);
|
|
468
468
|
}
|
|
469
|
+
if (schema.allOf) {
|
|
470
|
+
schema.allOf.forEach(extractFromSchema);
|
|
471
|
+
}
|
|
472
|
+
if (schema.anyOf) {
|
|
473
|
+
schema.anyOf.forEach(extractFromSchema);
|
|
474
|
+
}
|
|
469
475
|
if (schema.properties) {
|
|
470
476
|
Object.values(schema.properties).forEach(extractFromSchema);
|
|
471
477
|
}
|
|
@@ -529,7 +535,14 @@ const extractNestedReferences = (schemas, knownSchemas) => {
|
|
|
529
535
|
};
|
|
530
536
|
const convertToOpenApiSchema = (schema) => {
|
|
531
537
|
const result = {};
|
|
532
|
-
if (schema.type)
|
|
538
|
+
if (Array.isArray(schema.type)) {
|
|
539
|
+
const nonNull = schema.type.filter((t) => t !== "null");
|
|
540
|
+
const isNullable = nonNull.length < schema.type.length;
|
|
541
|
+
result["type"] = nonNull.length === 1 ? nonNull[0] : schema.type;
|
|
542
|
+
if (isNullable && nonNull.length === 1) result["nullable"] = true;
|
|
543
|
+
} else if (schema.type) {
|
|
544
|
+
result["type"] = schema.type;
|
|
545
|
+
}
|
|
533
546
|
if (schema.format) result["format"] = schema.format;
|
|
534
547
|
if (schema.$ref) {
|
|
535
548
|
result["$ref"] = schema.$ref.replace(
|
|
@@ -633,7 +646,11 @@ const createPathFilter = (pathFilter) => {
|
|
|
633
646
|
if (typeof pathFilter === "function") {
|
|
634
647
|
return (method) => pathFilter(method.path);
|
|
635
648
|
}
|
|
636
|
-
|
|
649
|
+
const pattern = new RegExp(pathFilter.source, pathFilter.flags);
|
|
650
|
+
return (method) => {
|
|
651
|
+
pattern.lastIndex = 0;
|
|
652
|
+
return pattern.test(method.path);
|
|
653
|
+
};
|
|
637
654
|
};
|
|
638
655
|
const combineFilters = (filters) => {
|
|
639
656
|
if (filters.length === 0) {
|
|
@@ -665,6 +682,11 @@ const filterMethods = (methods, options) => {
|
|
|
665
682
|
return methods.filter(filter);
|
|
666
683
|
};
|
|
667
684
|
|
|
685
|
+
const NULL_SCHEMA = { type: "null" };
|
|
686
|
+
const schemaIncludesNull = (schema) => {
|
|
687
|
+
if (schema.type === "null") return true;
|
|
688
|
+
return Array.isArray(schema.type) && schema.type.includes("null");
|
|
689
|
+
};
|
|
668
690
|
const transformSchemaToV31 = (schema) => {
|
|
669
691
|
const transformedOneOf = schema.oneOf?.map(transformSchemaToV31);
|
|
670
692
|
const transformedAnyOf = schema.anyOf?.map(transformSchemaToV31);
|
|
@@ -676,19 +698,36 @@ const transformSchemaToV31 = (schema) => {
|
|
|
676
698
|
transformSchemaToV31(value)
|
|
677
699
|
])
|
|
678
700
|
) : void 0;
|
|
679
|
-
const
|
|
680
|
-
const transformedType =
|
|
681
|
-
const
|
|
682
|
-
return {
|
|
701
|
+
const { nullable, ...restWithoutNullable } = schema;
|
|
702
|
+
const transformedType = nullable && typeof schema.type === "string" ? [schema.type, "null"] : schema.type;
|
|
703
|
+
const transformedSchema = {
|
|
683
704
|
...restWithoutNullable,
|
|
684
|
-
type: transformedType,
|
|
705
|
+
...transformedType !== void 0 && { type: transformedType },
|
|
685
706
|
...transformedOneOf && { oneOf: transformedOneOf },
|
|
686
707
|
...transformedAnyOf && { anyOf: transformedAnyOf },
|
|
687
708
|
...transformedAllOf && { allOf: transformedAllOf },
|
|
688
709
|
...transformedItems && { items: transformedItems },
|
|
689
710
|
...transformedProperties && { properties: transformedProperties }
|
|
690
711
|
};
|
|
712
|
+
if (!nullable) return transformedSchema;
|
|
713
|
+
if (schema.type && typeof schema.type === "string") {
|
|
714
|
+
return transformedSchema;
|
|
715
|
+
}
|
|
716
|
+
if (transformedSchema.oneOf) {
|
|
717
|
+
return {
|
|
718
|
+
...transformedSchema,
|
|
719
|
+
oneOf: schemaIncludesNullInVariants(transformedSchema.oneOf) ? transformedSchema.oneOf : [...transformedSchema.oneOf, NULL_SCHEMA]
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
if (transformedSchema.anyOf) {
|
|
723
|
+
return {
|
|
724
|
+
...transformedSchema,
|
|
725
|
+
anyOf: schemaIncludesNullInVariants(transformedSchema.anyOf) ? transformedSchema.anyOf : [...transformedSchema.anyOf, NULL_SCHEMA]
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
return { anyOf: [transformedSchema, NULL_SCHEMA] };
|
|
691
729
|
};
|
|
730
|
+
const schemaIncludesNullInVariants = (variants) => variants.some(schemaIncludesNull);
|
|
692
731
|
const transformSchemasForVersion = (schemas, version) => {
|
|
693
732
|
if (version === "3.0.3") {
|
|
694
733
|
return schemas;
|
|
@@ -700,14 +739,81 @@ const transformSchemasForVersion = (schemas, version) => {
|
|
|
700
739
|
])
|
|
701
740
|
);
|
|
702
741
|
};
|
|
742
|
+
const transformOperationToV31 = (operation) => {
|
|
743
|
+
const parameters = operation.parameters?.map((param) => ({
|
|
744
|
+
...param,
|
|
745
|
+
schema: transformSchemaToV31(param.schema)
|
|
746
|
+
}));
|
|
747
|
+
const requestBody = operation.requestBody ? {
|
|
748
|
+
...operation.requestBody,
|
|
749
|
+
content: Object.fromEntries(
|
|
750
|
+
Object.entries(operation.requestBody.content).map(
|
|
751
|
+
([contentType, mediaType]) => [
|
|
752
|
+
contentType,
|
|
753
|
+
{ ...mediaType, schema: transformSchemaToV31(mediaType.schema) }
|
|
754
|
+
]
|
|
755
|
+
)
|
|
756
|
+
)
|
|
757
|
+
} : void 0;
|
|
758
|
+
const responses = Object.fromEntries(
|
|
759
|
+
Object.entries(operation.responses).map(([code, response]) => [
|
|
760
|
+
code,
|
|
761
|
+
response.content ? {
|
|
762
|
+
...response,
|
|
763
|
+
content: Object.fromEntries(
|
|
764
|
+
Object.entries(response.content).map(
|
|
765
|
+
([contentType, mediaType]) => [
|
|
766
|
+
contentType,
|
|
767
|
+
{
|
|
768
|
+
...mediaType,
|
|
769
|
+
schema: transformSchemaToV31(mediaType.schema)
|
|
770
|
+
}
|
|
771
|
+
]
|
|
772
|
+
)
|
|
773
|
+
)
|
|
774
|
+
} : response
|
|
775
|
+
])
|
|
776
|
+
);
|
|
777
|
+
return {
|
|
778
|
+
...operation,
|
|
779
|
+
...parameters && { parameters },
|
|
780
|
+
...requestBody && { requestBody },
|
|
781
|
+
responses
|
|
782
|
+
};
|
|
783
|
+
};
|
|
784
|
+
const HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
785
|
+
"get",
|
|
786
|
+
"put",
|
|
787
|
+
"post",
|
|
788
|
+
"delete",
|
|
789
|
+
"options",
|
|
790
|
+
"head",
|
|
791
|
+
"patch",
|
|
792
|
+
"trace"
|
|
793
|
+
]);
|
|
794
|
+
const transformPathsForVersion = (paths, version) => {
|
|
795
|
+
if (version === "3.0.3") return paths;
|
|
796
|
+
return Object.fromEntries(
|
|
797
|
+
Object.entries(paths).map(([path, pathItem]) => [
|
|
798
|
+
path,
|
|
799
|
+
Object.fromEntries(
|
|
800
|
+
Object.entries(pathItem).map(
|
|
801
|
+
([key, value]) => HTTP_METHODS.has(key) ? [key, transformOperationToV31(value)] : [key, value]
|
|
802
|
+
)
|
|
803
|
+
)
|
|
804
|
+
])
|
|
805
|
+
);
|
|
806
|
+
};
|
|
703
807
|
const transformSpecForVersion = (spec, version) => {
|
|
704
808
|
if (version === "3.0.3") {
|
|
705
809
|
return { ...spec, openapi: version };
|
|
706
810
|
}
|
|
707
811
|
const transformedSchemas = spec.components?.schemas ? transformSchemasForVersion(spec.components.schemas, version) : void 0;
|
|
812
|
+
const transformedPaths = transformPathsForVersion(spec.paths, version);
|
|
708
813
|
return {
|
|
709
814
|
...spec,
|
|
710
815
|
openapi: version,
|
|
816
|
+
paths: transformedPaths,
|
|
711
817
|
...transformedSchemas && {
|
|
712
818
|
components: {
|
|
713
819
|
...spec.components,
|
|
@@ -886,22 +992,59 @@ const OpenApiTagConfig = Schema.Struct({
|
|
|
886
992
|
name: Schema.String,
|
|
887
993
|
description: Schema.optional(Schema.String)
|
|
888
994
|
});
|
|
889
|
-
|
|
995
|
+
Schema.Literal(
|
|
890
996
|
"apiKey",
|
|
891
997
|
"http",
|
|
892
998
|
"oauth2",
|
|
893
999
|
"openIdConnect"
|
|
894
1000
|
);
|
|
895
1001
|
const SecuritySchemeIn = Schema.Literal("query", "header", "cookie");
|
|
896
|
-
const
|
|
1002
|
+
const OAuth2FlowConfig = Schema.Struct({
|
|
1003
|
+
authorizationUrl: Schema.optional(Schema.String),
|
|
1004
|
+
tokenUrl: Schema.optional(Schema.String),
|
|
1005
|
+
refreshUrl: Schema.optional(Schema.String),
|
|
1006
|
+
scopes: Schema.optional(
|
|
1007
|
+
Schema.Record({ key: Schema.String, value: Schema.String })
|
|
1008
|
+
)
|
|
1009
|
+
});
|
|
1010
|
+
const OAuth2FlowsConfig = Schema.Struct({
|
|
1011
|
+
implicit: Schema.optional(OAuth2FlowConfig),
|
|
1012
|
+
password: Schema.optional(OAuth2FlowConfig),
|
|
1013
|
+
clientCredentials: Schema.optional(OAuth2FlowConfig),
|
|
1014
|
+
authorizationCode: Schema.optional(OAuth2FlowConfig)
|
|
1015
|
+
});
|
|
1016
|
+
const HttpSecuritySchemeConfig = Schema.Struct({
|
|
897
1017
|
name: Schema.String,
|
|
898
|
-
type:
|
|
899
|
-
scheme: Schema.
|
|
1018
|
+
type: Schema.Literal("http"),
|
|
1019
|
+
scheme: Schema.String,
|
|
900
1020
|
bearerFormat: Schema.optional(Schema.String),
|
|
901
|
-
in: Schema.optional(SecuritySchemeIn),
|
|
902
|
-
parameterName: Schema.optional(Schema.String),
|
|
903
1021
|
description: Schema.optional(Schema.String)
|
|
904
1022
|
});
|
|
1023
|
+
const ApiKeySecuritySchemeConfig = Schema.Struct({
|
|
1024
|
+
name: Schema.String,
|
|
1025
|
+
type: Schema.Literal("apiKey"),
|
|
1026
|
+
in: SecuritySchemeIn,
|
|
1027
|
+
parameterName: Schema.String,
|
|
1028
|
+
description: Schema.optional(Schema.String)
|
|
1029
|
+
});
|
|
1030
|
+
const OAuth2SecuritySchemeConfig = Schema.Struct({
|
|
1031
|
+
name: Schema.String,
|
|
1032
|
+
type: Schema.Literal("oauth2"),
|
|
1033
|
+
flows: OAuth2FlowsConfig,
|
|
1034
|
+
description: Schema.optional(Schema.String)
|
|
1035
|
+
});
|
|
1036
|
+
const OpenIdConnectSecuritySchemeConfig = Schema.Struct({
|
|
1037
|
+
name: Schema.String,
|
|
1038
|
+
type: Schema.Literal("openIdConnect"),
|
|
1039
|
+
openIdConnectUrl: Schema.String,
|
|
1040
|
+
description: Schema.optional(Schema.String)
|
|
1041
|
+
});
|
|
1042
|
+
const SecuritySchemeConfig = Schema.Union(
|
|
1043
|
+
HttpSecuritySchemeConfig,
|
|
1044
|
+
ApiKeySecuritySchemeConfig,
|
|
1045
|
+
OAuth2SecuritySchemeConfig,
|
|
1046
|
+
OpenIdConnectSecuritySchemeConfig
|
|
1047
|
+
);
|
|
905
1048
|
const SecurityRequirement = Schema.Record({
|
|
906
1049
|
key: Schema.String,
|
|
907
1050
|
value: Schema.Array(Schema.String)
|
|
@@ -1008,7 +1151,7 @@ const CONFIG_FILE_NAMES = [
|
|
|
1008
1151
|
"openapi.config.cjs"
|
|
1009
1152
|
];
|
|
1010
1153
|
const DEFAULT_ENTRY$1 = "src/app.module.ts";
|
|
1011
|
-
const DEFAULT_DTO_GLOB = [
|
|
1154
|
+
const DEFAULT_DTO_GLOB$1 = [
|
|
1012
1155
|
"**/*.dto.ts",
|
|
1013
1156
|
"**/*.entity.ts",
|
|
1014
1157
|
"**/*.model.ts",
|
|
@@ -1035,8 +1178,7 @@ const DEFAULT_CONFIG = {
|
|
|
1035
1178
|
};
|
|
1036
1179
|
const findConfigFile = (startDir = process.cwd()) => Effect.gen(function* () {
|
|
1037
1180
|
let currentDir = resolve(startDir);
|
|
1038
|
-
|
|
1039
|
-
while (currentDir !== root) {
|
|
1181
|
+
while (true) {
|
|
1040
1182
|
for (const fileName of CONFIG_FILE_NAMES) {
|
|
1041
1183
|
const configPath = resolve(currentDir, fileName);
|
|
1042
1184
|
if (existsSync(configPath)) {
|
|
@@ -1125,7 +1267,7 @@ const resolveConfig = (config) => {
|
|
|
1125
1267
|
const rawEntry = files.entry ?? DEFAULT_ENTRY$1;
|
|
1126
1268
|
const entry = Array.isArray(rawEntry) ? rawEntry : [rawEntry];
|
|
1127
1269
|
const rawDtoGlob = files.dtoGlob;
|
|
1128
|
-
const dtoGlob = rawDtoGlob ? Array.isArray(rawDtoGlob) ? rawDtoGlob : [rawDtoGlob] : [...DEFAULT_DTO_GLOB];
|
|
1270
|
+
const dtoGlob = rawDtoGlob ? Array.isArray(rawDtoGlob) ? rawDtoGlob : [rawDtoGlob] : [...DEFAULT_DTO_GLOB$1];
|
|
1129
1271
|
const tsconfig = files.tsconfig;
|
|
1130
1272
|
if (!tsconfig) {
|
|
1131
1273
|
throw new Error("tsconfig is required in files configuration");
|
|
@@ -1404,6 +1546,22 @@ function resolveTypeLocationsFast(baseDir, missingTypes) {
|
|
|
1404
1546
|
}
|
|
1405
1547
|
|
|
1406
1548
|
const DEFAULT_ENTRY = "src/app.module.ts";
|
|
1549
|
+
const DEFAULT_DTO_GLOB = [
|
|
1550
|
+
"**/*.dto.ts",
|
|
1551
|
+
"**/*.entity.ts",
|
|
1552
|
+
"**/*.model.ts",
|
|
1553
|
+
"**/*.schema.ts"
|
|
1554
|
+
];
|
|
1555
|
+
const mergeSingleSecurityRequirement = (left, right) => {
|
|
1556
|
+
const merged = {};
|
|
1557
|
+
for (const requirement of [left, right]) {
|
|
1558
|
+
for (const [scheme, scopes] of Object.entries(requirement)) {
|
|
1559
|
+
const existingScopes = merged[scheme] ?? [];
|
|
1560
|
+
merged[scheme] = [.../* @__PURE__ */ new Set([...existingScopes, ...scopes])];
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
return merged;
|
|
1564
|
+
};
|
|
1407
1565
|
const mergeSecurityWithGlobal = (paths, globalSecurity) => {
|
|
1408
1566
|
if (!globalSecurity || globalSecurity.length === 0) {
|
|
1409
1567
|
return paths;
|
|
@@ -1413,23 +1571,17 @@ const mergeSecurityWithGlobal = (paths, globalSecurity) => {
|
|
|
1413
1571
|
const mergedMethods = {};
|
|
1414
1572
|
for (const [method, operation] of Object.entries(methods)) {
|
|
1415
1573
|
if (operation.security && operation.security.length > 0) {
|
|
1416
|
-
const
|
|
1574
|
+
const mergedSecurity = [];
|
|
1417
1575
|
for (const globalReq of globalSecurity) {
|
|
1418
|
-
for (const
|
|
1419
|
-
|
|
1576
|
+
for (const operationReq of operation.security) {
|
|
1577
|
+
mergedSecurity.push(
|
|
1578
|
+
mergeSingleSecurityRequirement(globalReq, operationReq)
|
|
1579
|
+
);
|
|
1420
1580
|
}
|
|
1421
1581
|
}
|
|
1422
|
-
for (const decoratorReq of operation.security) {
|
|
1423
|
-
for (const [scheme, scopes] of Object.entries(decoratorReq)) {
|
|
1424
|
-
merged[scheme] = [...merged[scheme] ?? [], ...scopes];
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
for (const scheme of Object.keys(merged)) {
|
|
1428
|
-
merged[scheme] = [...new Set(merged[scheme])];
|
|
1429
|
-
}
|
|
1430
1582
|
mergedMethods[method] = {
|
|
1431
1583
|
...operation,
|
|
1432
|
-
security:
|
|
1584
|
+
security: mergedSecurity
|
|
1433
1585
|
};
|
|
1434
1586
|
} else {
|
|
1435
1587
|
mergedMethods[method] = operation;
|
|
@@ -1493,6 +1645,131 @@ const findMissingSchemaRefs = (paths, schemas) => {
|
|
|
1493
1645
|
findRefs(paths);
|
|
1494
1646
|
return missing;
|
|
1495
1647
|
};
|
|
1648
|
+
const isGenericSchemaRef = (name) => name.includes("<") && name.endsWith(">");
|
|
1649
|
+
const NON_IMPORTABLE_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
1650
|
+
"string",
|
|
1651
|
+
"number",
|
|
1652
|
+
"boolean",
|
|
1653
|
+
"null",
|
|
1654
|
+
"undefined",
|
|
1655
|
+
"void",
|
|
1656
|
+
"unknown",
|
|
1657
|
+
"any",
|
|
1658
|
+
"never",
|
|
1659
|
+
"object",
|
|
1660
|
+
"true",
|
|
1661
|
+
"false",
|
|
1662
|
+
"Array",
|
|
1663
|
+
"ReadonlyArray",
|
|
1664
|
+
"Record",
|
|
1665
|
+
"Promise",
|
|
1666
|
+
"Partial",
|
|
1667
|
+
"Required",
|
|
1668
|
+
"Pick",
|
|
1669
|
+
"Omit",
|
|
1670
|
+
"Exclude",
|
|
1671
|
+
"Extract",
|
|
1672
|
+
"Readonly",
|
|
1673
|
+
"keyof",
|
|
1674
|
+
"infer",
|
|
1675
|
+
"extends"
|
|
1676
|
+
]);
|
|
1677
|
+
const extractTypeIdentifiers = (typeRef) => {
|
|
1678
|
+
const withoutStringLiterals = typeRef.replace(
|
|
1679
|
+
/'[^']*'|"[^"]*"|`[^`]*`/g,
|
|
1680
|
+
""
|
|
1681
|
+
);
|
|
1682
|
+
const matches = withoutStringLiterals.match(/\b[A-Za-z_$][A-Za-z0-9_$]*\b/g) ?? [];
|
|
1683
|
+
return new Set(
|
|
1684
|
+
matches.filter((name) => !NON_IMPORTABLE_TYPE_NAMES.has(name))
|
|
1685
|
+
);
|
|
1686
|
+
};
|
|
1687
|
+
const toModuleImportPath = (fromDir, filePath) => {
|
|
1688
|
+
const importPath = relative(fromDir, filePath).replace(/\\/g, "/");
|
|
1689
|
+
return importPath.startsWith(".") ? importPath : `./${importPath}`;
|
|
1690
|
+
};
|
|
1691
|
+
const resolveSymbolLocations = (tsconfig, symbolNames) => {
|
|
1692
|
+
if (symbolNames.size === 0) {
|
|
1693
|
+
return /* @__PURE__ */ new Map();
|
|
1694
|
+
}
|
|
1695
|
+
const tsconfigDir = dirname(tsconfig);
|
|
1696
|
+
const resolved = resolveTypeLocationsFast(tsconfigDir, symbolNames);
|
|
1697
|
+
const unresolved = new Set(
|
|
1698
|
+
[...symbolNames].filter((name) => !resolved.has(name))
|
|
1699
|
+
);
|
|
1700
|
+
if (unresolved.size > 0) {
|
|
1701
|
+
const project = createTypeResolverProject(tsconfig);
|
|
1702
|
+
const morphResolved = resolveTypeLocations(project, unresolved);
|
|
1703
|
+
for (const [name, filePath] of morphResolved) {
|
|
1704
|
+
resolved.set(name, filePath);
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
return resolved;
|
|
1708
|
+
};
|
|
1709
|
+
const generateMissingGenericSchemas = async (genericRefs, tsconfig, symbolLocations, runEffect) => {
|
|
1710
|
+
if (genericRefs.length === 0) {
|
|
1711
|
+
return { definitions: {} };
|
|
1712
|
+
}
|
|
1713
|
+
const importGroups = /* @__PURE__ */ new Map();
|
|
1714
|
+
const aliases = [];
|
|
1715
|
+
const aliasLines = [];
|
|
1716
|
+
for (const [index, genericRef] of genericRefs.entries()) {
|
|
1717
|
+
const identifiers = [...extractTypeIdentifiers(genericRef)];
|
|
1718
|
+
if (identifiers.length === 0) {
|
|
1719
|
+
continue;
|
|
1720
|
+
}
|
|
1721
|
+
const unresolved = identifiers.filter((name) => !symbolLocations.has(name));
|
|
1722
|
+
if (unresolved.length > 0) {
|
|
1723
|
+
continue;
|
|
1724
|
+
}
|
|
1725
|
+
for (const identifier of identifiers) {
|
|
1726
|
+
const filePath = symbolLocations.get(identifier);
|
|
1727
|
+
if (!filePath) continue;
|
|
1728
|
+
const existing = importGroups.get(filePath) ?? /* @__PURE__ */ new Set();
|
|
1729
|
+
existing.add(identifier);
|
|
1730
|
+
importGroups.set(filePath, existing);
|
|
1731
|
+
}
|
|
1732
|
+
const aliasName = `__MissingGenericRef${index}`;
|
|
1733
|
+
aliases.push({ aliasName, schemaName: genericRef });
|
|
1734
|
+
aliasLines.push(`export type ${aliasName} = ${genericRef};`);
|
|
1735
|
+
}
|
|
1736
|
+
if (aliases.length === 0) {
|
|
1737
|
+
return { definitions: {} };
|
|
1738
|
+
}
|
|
1739
|
+
const tempDir = dirname(tsconfig);
|
|
1740
|
+
const tempFilePath = join(
|
|
1741
|
+
tempDir,
|
|
1742
|
+
`.openapi.missing-generic.${randomUUID()}.ts`
|
|
1743
|
+
);
|
|
1744
|
+
const importLines = [...importGroups.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([filePath, symbols]) => {
|
|
1745
|
+
const importPath = toModuleImportPath(tempDir, filePath);
|
|
1746
|
+
const names = [...symbols].sort().join(", ");
|
|
1747
|
+
return `import type { ${names} } from '${importPath}';`;
|
|
1748
|
+
});
|
|
1749
|
+
writeFileSync(
|
|
1750
|
+
tempFilePath,
|
|
1751
|
+
[...importLines, "", ...aliasLines, ""].join("\n"),
|
|
1752
|
+
"utf-8"
|
|
1753
|
+
);
|
|
1754
|
+
try {
|
|
1755
|
+
const generated = await runEffect(
|
|
1756
|
+
generateSchemasFromFiles([tempFilePath], tsconfig)
|
|
1757
|
+
);
|
|
1758
|
+
const definitions = { ...generated.definitions };
|
|
1759
|
+
for (const { aliasName, schemaName } of aliases) {
|
|
1760
|
+
const resolvedSchema = definitions[schemaName] ?? definitions[aliasName] ?? void 0;
|
|
1761
|
+
if (resolvedSchema) {
|
|
1762
|
+
definitions[schemaName] = resolvedSchema;
|
|
1763
|
+
}
|
|
1764
|
+
delete definitions[aliasName];
|
|
1765
|
+
}
|
|
1766
|
+
return { definitions };
|
|
1767
|
+
} finally {
|
|
1768
|
+
if (existsSync(tempFilePath)) {
|
|
1769
|
+
unlinkSync(tempFilePath);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1496
1773
|
const extractValidationConstraints = async (dtoGlobPatterns, basePath, tsconfig, schemas) => {
|
|
1497
1774
|
const absolutePatterns = dtoGlobPatterns.map(
|
|
1498
1775
|
(pattern) => pattern.startsWith("/") ? pattern : join(basePath, pattern)
|
|
@@ -1539,8 +1816,7 @@ const extractValidationConstraints = async (dtoGlobPatterns, basePath, tsconfig,
|
|
|
1539
1816
|
};
|
|
1540
1817
|
const findTsConfig = (startDir) => {
|
|
1541
1818
|
let currentDir = resolve(startDir);
|
|
1542
|
-
|
|
1543
|
-
while (currentDir !== root) {
|
|
1819
|
+
while (true) {
|
|
1544
1820
|
const tsconfigPath = join(currentDir, "tsconfig.json");
|
|
1545
1821
|
if (existsSync(tsconfigPath)) {
|
|
1546
1822
|
return tsconfigPath;
|
|
@@ -1635,19 +1911,30 @@ const generate = async (configPath, overrides) => {
|
|
|
1635
1911
|
(e) => resolve(configDir, e)
|
|
1636
1912
|
);
|
|
1637
1913
|
const output = resolve(configDir, config.output);
|
|
1638
|
-
const tsconfig =
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1914
|
+
const tsconfig = await runEffect(
|
|
1915
|
+
Effect.gen(function* () {
|
|
1916
|
+
const discoveredTsconfig = files.tsconfig ? resolve(configDir, files.tsconfig) : findTsConfig(dirname(entries[0]));
|
|
1917
|
+
if (!discoveredTsconfig) {
|
|
1918
|
+
return yield* Effect.fail(
|
|
1919
|
+
ConfigValidationError.fromIssues(absoluteConfigPath, [
|
|
1920
|
+
"Could not find tsconfig.json. Please specify files.tsconfig in your config file."
|
|
1921
|
+
])
|
|
1922
|
+
);
|
|
1923
|
+
}
|
|
1924
|
+
if (!existsSync(discoveredTsconfig)) {
|
|
1925
|
+
return yield* Effect.fail(
|
|
1926
|
+
ConfigValidationError.fromIssues(absoluteConfigPath, [
|
|
1927
|
+
`tsconfig.json not found at: ${discoveredTsconfig}`
|
|
1928
|
+
])
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
return discoveredTsconfig;
|
|
1932
|
+
}).pipe(Effect.mapError((error) => new Error(error.message)))
|
|
1933
|
+
);
|
|
1647
1934
|
const extractOptions = {
|
|
1648
1935
|
query: options.query
|
|
1649
1936
|
};
|
|
1650
|
-
const dtoGlobArray = files.dtoGlob ? Array.isArray(files.dtoGlob) ? files.dtoGlob : [files.dtoGlob]
|
|
1937
|
+
const dtoGlobArray = files.dtoGlob === void 0 ? [...DEFAULT_DTO_GLOB] : Array.isArray(files.dtoGlob) ? files.dtoGlob : [files.dtoGlob];
|
|
1651
1938
|
const [extractedMethodInfos, initialSchemas] = await Promise.all([
|
|
1652
1939
|
runEffect(
|
|
1653
1940
|
extractMethodInfosEffect(tsconfig, entries, extractOptions).pipe(
|
|
@@ -1659,7 +1946,7 @@ const generate = async (configPath, overrides) => {
|
|
|
1659
1946
|
Effect.mapError((error) => new Error(error.message))
|
|
1660
1947
|
)
|
|
1661
1948
|
),
|
|
1662
|
-
|
|
1949
|
+
runEffect(
|
|
1663
1950
|
generateSchemas({
|
|
1664
1951
|
dtoGlob: dtoGlobArray,
|
|
1665
1952
|
tsconfig,
|
|
@@ -1675,7 +1962,7 @@ const generate = async (configPath, overrides) => {
|
|
|
1675
1962
|
),
|
|
1676
1963
|
Effect.mapError((error) => new Error(error.message))
|
|
1677
1964
|
)
|
|
1678
|
-
)
|
|
1965
|
+
)
|
|
1679
1966
|
]);
|
|
1680
1967
|
const filteredMethodInfos = filterMethods(extractedMethodInfos, {
|
|
1681
1968
|
excludeDecorators: options.excludeDecorators,
|
|
@@ -1696,7 +1983,7 @@ const generate = async (configPath, overrides) => {
|
|
|
1696
1983
|
security.global
|
|
1697
1984
|
);
|
|
1698
1985
|
let schemas = {};
|
|
1699
|
-
if (initialSchemas
|
|
1986
|
+
if (initialSchemas) {
|
|
1700
1987
|
let generatedSchemas = initialSchemas;
|
|
1701
1988
|
const shouldExtractValidation = options.extractValidation !== false;
|
|
1702
1989
|
if (shouldExtractValidation) {
|
|
@@ -1748,6 +2035,50 @@ const generate = async (configPath, overrides) => {
|
|
|
1748
2035
|
...normalizedAdditional.definitions
|
|
1749
2036
|
}
|
|
1750
2037
|
};
|
|
2038
|
+
generatedSchemas = combinedSchemas;
|
|
2039
|
+
mergeResult = mergeSchemas(
|
|
2040
|
+
paths,
|
|
2041
|
+
combinedSchemas
|
|
2042
|
+
);
|
|
2043
|
+
schemas = mergeResult.schemas;
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
const unresolvedAfterFileResolution = findMissingSchemaRefs(
|
|
2047
|
+
paths,
|
|
2048
|
+
schemas
|
|
2049
|
+
);
|
|
2050
|
+
const unresolvedGenericRefs = [...unresolvedAfterFileResolution].filter(
|
|
2051
|
+
isGenericSchemaRef
|
|
2052
|
+
);
|
|
2053
|
+
if (unresolvedGenericRefs.length > 0) {
|
|
2054
|
+
const genericSymbols = /* @__PURE__ */ new Set();
|
|
2055
|
+
for (const ref of unresolvedGenericRefs) {
|
|
2056
|
+
for (const symbol of extractTypeIdentifiers(ref)) {
|
|
2057
|
+
genericSymbols.add(symbol);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
const resolvedGenericSymbols = resolveSymbolLocations(
|
|
2061
|
+
tsconfig,
|
|
2062
|
+
genericSymbols
|
|
2063
|
+
);
|
|
2064
|
+
for (const [name, filePath] of resolvedLocations) {
|
|
2065
|
+
resolvedGenericSymbols.set(name, filePath);
|
|
2066
|
+
}
|
|
2067
|
+
const genericSchemas = await generateMissingGenericSchemas(
|
|
2068
|
+
unresolvedGenericRefs,
|
|
2069
|
+
tsconfig,
|
|
2070
|
+
resolvedGenericSymbols,
|
|
2071
|
+
runEffect
|
|
2072
|
+
);
|
|
2073
|
+
if (Object.keys(genericSchemas.definitions).length > 0) {
|
|
2074
|
+
const normalizedGeneric = normalizeStructureRefs(genericSchemas);
|
|
2075
|
+
const combinedSchemas = {
|
|
2076
|
+
definitions: {
|
|
2077
|
+
...generatedSchemas.definitions,
|
|
2078
|
+
...normalizedGeneric.definitions
|
|
2079
|
+
}
|
|
2080
|
+
};
|
|
2081
|
+
generatedSchemas = combinedSchemas;
|
|
1751
2082
|
mergeResult = mergeSchemas(
|
|
1752
2083
|
paths,
|
|
1753
2084
|
combinedSchemas
|
|
@@ -703,6 +703,22 @@ const parseTypeText = (text) => {
|
|
|
703
703
|
const trimmed = text.trim();
|
|
704
704
|
return trimmed.startsWith("{") && trimmed.endsWith("}") ? { type: Option.none(), inline: Option.some(trimmed) } : { type: Option.some(trimmed), inline: Option.none() };
|
|
705
705
|
};
|
|
706
|
+
const getGenericBaseType = (text) => {
|
|
707
|
+
const genericStart = text.indexOf("<");
|
|
708
|
+
return genericStart === -1 ? null : text.slice(0, genericStart).trim();
|
|
709
|
+
};
|
|
710
|
+
const hasAliasedImportCollision = (method, exportedName) => {
|
|
711
|
+
const localNames = /* @__PURE__ */ new Set();
|
|
712
|
+
for (const importDecl of method.getSourceFile().getImportDeclarations()) {
|
|
713
|
+
for (const namedImport of importDecl.getNamedImports()) {
|
|
714
|
+
const aliasNode = namedImport.getAliasNode();
|
|
715
|
+
if (!aliasNode) continue;
|
|
716
|
+
if (namedImport.getName() !== exportedName) continue;
|
|
717
|
+
localNames.add(aliasNode.getText());
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return localNames.size > 1;
|
|
721
|
+
};
|
|
706
722
|
const getReturnTypeInfo = (method) => {
|
|
707
723
|
const returnType = method.getReturnType();
|
|
708
724
|
const awaited = returnType.getAwaitedType?.() ?? returnType;
|
|
@@ -717,6 +733,25 @@ const getReturnTypeInfo = (method) => {
|
|
|
717
733
|
return null;
|
|
718
734
|
};
|
|
719
735
|
let text = getOriginalTypeName() ?? awaited.getText(method);
|
|
736
|
+
const compilerType = awaited.compilerType;
|
|
737
|
+
const aliasName = compilerType.aliasSymbol?.escapedName?.toString();
|
|
738
|
+
if (aliasName && !aliasName.startsWith("__")) {
|
|
739
|
+
const genericBase = getGenericBaseType(text);
|
|
740
|
+
const shouldPreserveLocalAlias = genericBase !== null && genericBase !== aliasName && hasAliasedImportCollision(method, aliasName);
|
|
741
|
+
if (!shouldPreserveLocalAlias) {
|
|
742
|
+
text = genericBase === null ? aliasName : `${aliasName}${text.slice(text.indexOf("<"))}`;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
const symbolName = symbol?.getName();
|
|
746
|
+
if (symbolName && !symbolName.startsWith("__")) {
|
|
747
|
+
const genericBase = getGenericBaseType(text);
|
|
748
|
+
if (genericBase !== null) {
|
|
749
|
+
const shouldPreserveLocalAlias = genericBase !== symbolName && hasAliasedImportCollision(method, symbolName);
|
|
750
|
+
if (!shouldPreserveLocalAlias) {
|
|
751
|
+
text = `${symbolName}${text.slice(text.indexOf("<"))}`;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
720
755
|
const promiseMatch = text.match(/^Promise<(.+)>$/);
|
|
721
756
|
if (promiseMatch) text = promiseMatch[1].trim();
|
|
722
757
|
text = text.replace(/\bimport\([^)]*\)\./g, "");
|
|
@@ -1306,10 +1341,16 @@ const tsTypeToOpenApiSchema = (tsType) => {
|
|
|
1306
1341
|
}
|
|
1307
1342
|
}
|
|
1308
1343
|
if (trimmed.includes(" | ")) {
|
|
1309
|
-
const
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
};
|
|
1344
|
+
const allMembers = trimmed.split(" | ").map((t) => t.trim());
|
|
1345
|
+
const hasNull = allMembers.includes("null");
|
|
1346
|
+
const types = allMembers.filter((t) => t !== "undefined" && t !== "null");
|
|
1347
|
+
if (types.length === 0) return { type: "object" };
|
|
1348
|
+
const schema = types.length === 1 ? tsTypeToOpenApiSchema(types[0]) : { oneOf: types.map((type) => tsTypeToOpenApiSchema(type)) };
|
|
1349
|
+
if (!hasNull) return schema;
|
|
1350
|
+
if (schema.$ref) {
|
|
1351
|
+
return { allOf: [{ $ref: schema.$ref }], nullable: true };
|
|
1352
|
+
}
|
|
1353
|
+
return { ...schema, nullable: true };
|
|
1313
1354
|
}
|
|
1314
1355
|
switch (trimmed.toLowerCase()) {
|
|
1315
1356
|
case "string":
|
|
@@ -173,9 +173,12 @@ interface OpenApiSchema {
|
|
|
173
173
|
readonly format?: string;
|
|
174
174
|
readonly $ref?: string;
|
|
175
175
|
readonly oneOf?: readonly OpenApiSchema[];
|
|
176
|
+
readonly allOf?: readonly OpenApiSchema[];
|
|
176
177
|
readonly items?: OpenApiSchema;
|
|
177
178
|
readonly properties?: Record<string, OpenApiSchema>;
|
|
178
179
|
readonly required?: readonly string[];
|
|
180
|
+
/** OpenAPI 3.0 nullable flag */
|
|
181
|
+
readonly nullable?: boolean;
|
|
179
182
|
}
|
|
180
183
|
declare const OpenApiOperation: Schema.Struct<{
|
|
181
184
|
operationId: typeof Schema.String;
|
|
@@ -249,15 +252,54 @@ declare const OpenApiGeneratorConfig: Schema.Struct<{
|
|
|
249
252
|
description: Schema.optional<typeof Schema.String>;
|
|
250
253
|
}>>>;
|
|
251
254
|
security: Schema.optional<Schema.Struct<{
|
|
252
|
-
schemes: Schema.optional<Schema.Array$<Schema.Struct<{
|
|
255
|
+
schemes: Schema.optional<Schema.Array$<Schema.Union<[Schema.Struct<{
|
|
253
256
|
name: typeof Schema.String;
|
|
254
|
-
type: Schema.Literal<["
|
|
255
|
-
scheme:
|
|
257
|
+
type: Schema.Literal<["http"]>;
|
|
258
|
+
scheme: typeof Schema.String;
|
|
256
259
|
bearerFormat: Schema.optional<typeof Schema.String>;
|
|
257
|
-
in: Schema.optional<Schema.Literal<["query", "header", "cookie"]>>;
|
|
258
|
-
parameterName: Schema.optional<typeof Schema.String>;
|
|
259
260
|
description: Schema.optional<typeof Schema.String>;
|
|
260
|
-
}
|
|
261
|
+
}>, Schema.Struct<{
|
|
262
|
+
name: typeof Schema.String;
|
|
263
|
+
type: Schema.Literal<["apiKey"]>;
|
|
264
|
+
in: Schema.Literal<["query", "header", "cookie"]>;
|
|
265
|
+
parameterName: typeof Schema.String;
|
|
266
|
+
description: Schema.optional<typeof Schema.String>;
|
|
267
|
+
}>, Schema.Struct<{
|
|
268
|
+
name: typeof Schema.String;
|
|
269
|
+
type: Schema.Literal<["oauth2"]>;
|
|
270
|
+
flows: Schema.Struct<{
|
|
271
|
+
implicit: Schema.optional<Schema.Struct<{
|
|
272
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
273
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
274
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
275
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
276
|
+
}>>;
|
|
277
|
+
password: Schema.optional<Schema.Struct<{
|
|
278
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
279
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
280
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
281
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
282
|
+
}>>;
|
|
283
|
+
clientCredentials: Schema.optional<Schema.Struct<{
|
|
284
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
285
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
286
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
287
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
288
|
+
}>>;
|
|
289
|
+
authorizationCode: Schema.optional<Schema.Struct<{
|
|
290
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
291
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
292
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
293
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
294
|
+
}>>;
|
|
295
|
+
}>;
|
|
296
|
+
description: Schema.optional<typeof Schema.String>;
|
|
297
|
+
}>, Schema.Struct<{
|
|
298
|
+
name: typeof Schema.String;
|
|
299
|
+
type: Schema.Literal<["openIdConnect"]>;
|
|
300
|
+
openIdConnectUrl: typeof Schema.String;
|
|
301
|
+
description: Schema.optional<typeof Schema.String>;
|
|
302
|
+
}>]>>>;
|
|
261
303
|
global: Schema.optional<Schema.Array$<Schema.Record$<typeof Schema.String, Schema.Array$<typeof Schema.String>>>>;
|
|
262
304
|
}>>;
|
|
263
305
|
}>;
|
|
@@ -301,15 +343,54 @@ declare const ResolvedConfig: Schema.Struct<{
|
|
|
301
343
|
url: typeof Schema.String;
|
|
302
344
|
description: Schema.optional<typeof Schema.String>;
|
|
303
345
|
}>>;
|
|
304
|
-
securitySchemes: Schema.Array$<Schema.Struct<{
|
|
346
|
+
securitySchemes: Schema.Array$<Schema.Union<[Schema.Struct<{
|
|
305
347
|
name: typeof Schema.String;
|
|
306
|
-
type: Schema.Literal<["
|
|
307
|
-
scheme:
|
|
348
|
+
type: Schema.Literal<["http"]>;
|
|
349
|
+
scheme: typeof Schema.String;
|
|
308
350
|
bearerFormat: Schema.optional<typeof Schema.String>;
|
|
309
|
-
in: Schema.optional<Schema.Literal<["query", "header", "cookie"]>>;
|
|
310
|
-
parameterName: Schema.optional<typeof Schema.String>;
|
|
311
351
|
description: Schema.optional<typeof Schema.String>;
|
|
312
|
-
}
|
|
352
|
+
}>, Schema.Struct<{
|
|
353
|
+
name: typeof Schema.String;
|
|
354
|
+
type: Schema.Literal<["apiKey"]>;
|
|
355
|
+
in: Schema.Literal<["query", "header", "cookie"]>;
|
|
356
|
+
parameterName: typeof Schema.String;
|
|
357
|
+
description: Schema.optional<typeof Schema.String>;
|
|
358
|
+
}>, Schema.Struct<{
|
|
359
|
+
name: typeof Schema.String;
|
|
360
|
+
type: Schema.Literal<["oauth2"]>;
|
|
361
|
+
flows: Schema.Struct<{
|
|
362
|
+
implicit: Schema.optional<Schema.Struct<{
|
|
363
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
364
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
365
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
366
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
367
|
+
}>>;
|
|
368
|
+
password: Schema.optional<Schema.Struct<{
|
|
369
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
370
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
371
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
372
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
373
|
+
}>>;
|
|
374
|
+
clientCredentials: Schema.optional<Schema.Struct<{
|
|
375
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
376
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
377
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
378
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
379
|
+
}>>;
|
|
380
|
+
authorizationCode: Schema.optional<Schema.Struct<{
|
|
381
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
382
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
383
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
384
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
385
|
+
}>>;
|
|
386
|
+
}>;
|
|
387
|
+
description: Schema.optional<typeof Schema.String>;
|
|
388
|
+
}>, Schema.Struct<{
|
|
389
|
+
name: typeof Schema.String;
|
|
390
|
+
type: Schema.Literal<["openIdConnect"]>;
|
|
391
|
+
openIdConnectUrl: typeof Schema.String;
|
|
392
|
+
description: Schema.optional<typeof Schema.String>;
|
|
393
|
+
}>]>>;
|
|
313
394
|
securityRequirements: Schema.Array$<Schema.Record$<typeof Schema.String, Schema.Array$<typeof Schema.String>>>;
|
|
314
395
|
tags: Schema.Array$<Schema.Struct<{
|
|
315
396
|
name: typeof Schema.String;
|
|
@@ -173,9 +173,12 @@ interface OpenApiSchema {
|
|
|
173
173
|
readonly format?: string;
|
|
174
174
|
readonly $ref?: string;
|
|
175
175
|
readonly oneOf?: readonly OpenApiSchema[];
|
|
176
|
+
readonly allOf?: readonly OpenApiSchema[];
|
|
176
177
|
readonly items?: OpenApiSchema;
|
|
177
178
|
readonly properties?: Record<string, OpenApiSchema>;
|
|
178
179
|
readonly required?: readonly string[];
|
|
180
|
+
/** OpenAPI 3.0 nullable flag */
|
|
181
|
+
readonly nullable?: boolean;
|
|
179
182
|
}
|
|
180
183
|
declare const OpenApiOperation: Schema.Struct<{
|
|
181
184
|
operationId: typeof Schema.String;
|
|
@@ -249,15 +252,54 @@ declare const OpenApiGeneratorConfig: Schema.Struct<{
|
|
|
249
252
|
description: Schema.optional<typeof Schema.String>;
|
|
250
253
|
}>>>;
|
|
251
254
|
security: Schema.optional<Schema.Struct<{
|
|
252
|
-
schemes: Schema.optional<Schema.Array$<Schema.Struct<{
|
|
255
|
+
schemes: Schema.optional<Schema.Array$<Schema.Union<[Schema.Struct<{
|
|
253
256
|
name: typeof Schema.String;
|
|
254
|
-
type: Schema.Literal<["
|
|
255
|
-
scheme:
|
|
257
|
+
type: Schema.Literal<["http"]>;
|
|
258
|
+
scheme: typeof Schema.String;
|
|
256
259
|
bearerFormat: Schema.optional<typeof Schema.String>;
|
|
257
|
-
in: Schema.optional<Schema.Literal<["query", "header", "cookie"]>>;
|
|
258
|
-
parameterName: Schema.optional<typeof Schema.String>;
|
|
259
260
|
description: Schema.optional<typeof Schema.String>;
|
|
260
|
-
}
|
|
261
|
+
}>, Schema.Struct<{
|
|
262
|
+
name: typeof Schema.String;
|
|
263
|
+
type: Schema.Literal<["apiKey"]>;
|
|
264
|
+
in: Schema.Literal<["query", "header", "cookie"]>;
|
|
265
|
+
parameterName: typeof Schema.String;
|
|
266
|
+
description: Schema.optional<typeof Schema.String>;
|
|
267
|
+
}>, Schema.Struct<{
|
|
268
|
+
name: typeof Schema.String;
|
|
269
|
+
type: Schema.Literal<["oauth2"]>;
|
|
270
|
+
flows: Schema.Struct<{
|
|
271
|
+
implicit: Schema.optional<Schema.Struct<{
|
|
272
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
273
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
274
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
275
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
276
|
+
}>>;
|
|
277
|
+
password: Schema.optional<Schema.Struct<{
|
|
278
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
279
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
280
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
281
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
282
|
+
}>>;
|
|
283
|
+
clientCredentials: Schema.optional<Schema.Struct<{
|
|
284
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
285
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
286
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
287
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
288
|
+
}>>;
|
|
289
|
+
authorizationCode: Schema.optional<Schema.Struct<{
|
|
290
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
291
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
292
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
293
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
294
|
+
}>>;
|
|
295
|
+
}>;
|
|
296
|
+
description: Schema.optional<typeof Schema.String>;
|
|
297
|
+
}>, Schema.Struct<{
|
|
298
|
+
name: typeof Schema.String;
|
|
299
|
+
type: Schema.Literal<["openIdConnect"]>;
|
|
300
|
+
openIdConnectUrl: typeof Schema.String;
|
|
301
|
+
description: Schema.optional<typeof Schema.String>;
|
|
302
|
+
}>]>>>;
|
|
261
303
|
global: Schema.optional<Schema.Array$<Schema.Record$<typeof Schema.String, Schema.Array$<typeof Schema.String>>>>;
|
|
262
304
|
}>>;
|
|
263
305
|
}>;
|
|
@@ -301,15 +343,54 @@ declare const ResolvedConfig: Schema.Struct<{
|
|
|
301
343
|
url: typeof Schema.String;
|
|
302
344
|
description: Schema.optional<typeof Schema.String>;
|
|
303
345
|
}>>;
|
|
304
|
-
securitySchemes: Schema.Array$<Schema.Struct<{
|
|
346
|
+
securitySchemes: Schema.Array$<Schema.Union<[Schema.Struct<{
|
|
305
347
|
name: typeof Schema.String;
|
|
306
|
-
type: Schema.Literal<["
|
|
307
|
-
scheme:
|
|
348
|
+
type: Schema.Literal<["http"]>;
|
|
349
|
+
scheme: typeof Schema.String;
|
|
308
350
|
bearerFormat: Schema.optional<typeof Schema.String>;
|
|
309
|
-
in: Schema.optional<Schema.Literal<["query", "header", "cookie"]>>;
|
|
310
|
-
parameterName: Schema.optional<typeof Schema.String>;
|
|
311
351
|
description: Schema.optional<typeof Schema.String>;
|
|
312
|
-
}
|
|
352
|
+
}>, Schema.Struct<{
|
|
353
|
+
name: typeof Schema.String;
|
|
354
|
+
type: Schema.Literal<["apiKey"]>;
|
|
355
|
+
in: Schema.Literal<["query", "header", "cookie"]>;
|
|
356
|
+
parameterName: typeof Schema.String;
|
|
357
|
+
description: Schema.optional<typeof Schema.String>;
|
|
358
|
+
}>, Schema.Struct<{
|
|
359
|
+
name: typeof Schema.String;
|
|
360
|
+
type: Schema.Literal<["oauth2"]>;
|
|
361
|
+
flows: Schema.Struct<{
|
|
362
|
+
implicit: Schema.optional<Schema.Struct<{
|
|
363
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
364
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
365
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
366
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
367
|
+
}>>;
|
|
368
|
+
password: Schema.optional<Schema.Struct<{
|
|
369
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
370
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
371
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
372
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
373
|
+
}>>;
|
|
374
|
+
clientCredentials: Schema.optional<Schema.Struct<{
|
|
375
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
376
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
377
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
378
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
379
|
+
}>>;
|
|
380
|
+
authorizationCode: Schema.optional<Schema.Struct<{
|
|
381
|
+
authorizationUrl: Schema.optional<typeof Schema.String>;
|
|
382
|
+
tokenUrl: Schema.optional<typeof Schema.String>;
|
|
383
|
+
refreshUrl: Schema.optional<typeof Schema.String>;
|
|
384
|
+
scopes: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
385
|
+
}>>;
|
|
386
|
+
}>;
|
|
387
|
+
description: Schema.optional<typeof Schema.String>;
|
|
388
|
+
}>, Schema.Struct<{
|
|
389
|
+
name: typeof Schema.String;
|
|
390
|
+
type: Schema.Literal<["openIdConnect"]>;
|
|
391
|
+
openIdConnectUrl: typeof Schema.String;
|
|
392
|
+
description: Schema.optional<typeof Schema.String>;
|
|
393
|
+
}>]>>;
|
|
313
394
|
securityRequirements: Schema.Array$<Schema.Record$<typeof Schema.String, Schema.Array$<typeof Schema.String>>>;
|
|
314
395
|
tags: Schema.Array$<Schema.Struct<{
|
|
315
396
|
name: typeof Schema.String;
|
package/package.json
CHANGED