diff --git a/README.md b/README.md index 55ffcd79d..ad6bb43b1 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,6 @@ Options: --js generate js api module with declaration file (default: false) --module-name-index determines which path index should be used for routes separation (example: GET:/fruits/getFruit -> index:0 -> moduleName -> fruits) (default: 0) --module-name-first-tag splits routes based on the first tag (default: false) - --disableStrictSSL disabled strict SSL (default: false) - --disableProxy disabled proxy (default: false) --axios generate axios http client (default: false) --unwrap-response-data unwrap the data item from the response (default: false) --disable-throw-on-error Do not throw an error when response.ok is not true (default: false) @@ -403,7 +401,7 @@ type PrimitiveTypeStructValue = | string | (( schema: Record, - parser: import("./src/schema-parser/schema-parser").SchemaParser, + parser: import("./src/schema-parser/schema-parser").SchemaParser ) => string); type PrimitiveTypeStruct = Record< @@ -416,7 +414,7 @@ type PrimitiveTypeStruct = Record< >; declare const primitiveTypeConstructs: ( - struct: PrimitiveTypeStruct, + struct: PrimitiveTypeStruct ) => Partial; generateApi({ diff --git a/index.ts b/index.ts index 7ee5eb777..0605c1916 100644 --- a/index.ts +++ b/index.ts @@ -175,27 +175,17 @@ const generateCommand = defineCommand({ type: "string", description: "determines which path index should be used for routes separation (example: GET:/fruits/getFruit -> index:0 -> moduleName -> fruits)", - default: codeGenBaseConfig.moduleNameIndex, + default: codeGenBaseConfig.moduleNameIndex.toString(), }, "module-name-first-tag": { type: "boolean", description: "splits routes based on the first tag", default: codeGenBaseConfig.moduleNameFirstTag, }, - disableStrictSSL: { - type: "boolean", - description: "disabled strict SSL", - default: codeGenBaseConfig.disableStrictSSL, - }, - disableProxy: { - type: "boolean", - description: "disabled proxy", - default: codeGenBaseConfig.disableProxy, - }, axios: { type: "boolean", description: "generate axios http client", - default: codeGenBaseConfig.httpClientType === HTTP_CLIENT.AXIOS, + default: false, }, "unwrap-response-data": { type: "boolean", @@ -223,12 +213,12 @@ const generateCommand = defineCommand({ default: codeGenBaseConfig.defaultResponseType, }, "type-prefix": { - type: "boolean", + type: "string", description: "data contract name prefix", default: codeGenBaseConfig.typePrefix, }, "type-suffix": { - type: "boolean", + type: "string", description: "data contract name suffix", default: codeGenBaseConfig.typeSuffix, }, @@ -277,7 +267,6 @@ const generateCommand = defineCommand({ "custom-config": { type: "string", description: "custom config: primitiveTypeConstructs, hooks, ... ", - default: "", }, }, run: async ({ args }) => { @@ -306,8 +295,6 @@ const generateCommand = defineCommand({ debug: args.debug, defaultResponseAsSuccess: args["default-as-success"], defaultResponseType: args["default-response"], - disableProxy: args.disableProxy, - disableStrictSSL: args.disableStrictSSL, disableThrowOnError: args["disable-throw-on-error"], enumNamesAsValues: args["enum-names-as-values"], extractEnums: args["extract-enums"], @@ -325,11 +312,11 @@ const generateCommand = defineCommand({ args["http-client"] || args.axios ? HTTP_CLIENT.AXIOS : HTTP_CLIENT.FETCH, - input: path.resolve(process.cwd(), args.path), + input: path.resolve(process.cwd(), args.path as string), modular: args.modular, moduleNameFirstTag: args["module-name-first-tag"], moduleNameIndex: +args["module-name-index"] || 0, - output: path.resolve(process.cwd(), args.output || "."), + output: path.resolve(process.cwd(), (args.output as string) || "."), patch: args.patch, silent: args.silent, singleHttpClient: args["single-http-client"], diff --git a/src/code-formatter.js b/src/code-formatter.ts similarity index 71% rename from src/code-formatter.js rename to src/code-formatter.ts index 2b9106e85..7954512e7 100644 --- a/src/code-formatter.js +++ b/src/code-formatter.ts @@ -1,17 +1,15 @@ import * as prettier from "prettier"; import * as typescript from "typescript"; +import type { CodeGenConfig } from "./configuration.js"; -class CodeFormatter { - /** - * @type {CodeGenConfig} - */ - config; +export class CodeFormatter { + config: CodeGenConfig; - constructor({ config }) { + constructor(config: CodeGenConfig) { this.config = config; } - removeUnusedImports = (content) => { + removeUnusedImports = (content: string) => { const tempFileName = "file.ts"; const host = new TsLanguageServiceHost(tempFileName, content); @@ -20,6 +18,7 @@ class CodeFormatter { const fileTextChanges = languageService.organizeImports( { type: "file", fileName: tempFileName }, { newLineCharacter: typescript.sys.newLine }, + undefined, )[0]; if (fileTextChanges?.textChanges.length) { @@ -35,11 +34,7 @@ class CodeFormatter { return content; }; - /** - * @param content - * @returns {Promise} - */ - prettierFormat = async (content) => { + prettierFormat = async (content: string) => { const formatted = await prettier.format( content, this.config.prettierOptions, @@ -48,7 +43,7 @@ class CodeFormatter { }; formatCode = async ( - code, + code: string, { removeUnusedImports = true, prettierFormat = true } = {}, ) => { if (removeUnusedImports) { @@ -62,22 +57,24 @@ class CodeFormatter { } class TsLanguageServiceHost { - constructor(fileName, content) { + fileName: string; + content: string; + compilerOptions: typescript.CompilerOptions; + + constructor(fileName: string, content: string) { + this.fileName = fileName; + this.content = content; const tsconfig = typescript.findConfigFile( fileName, typescript.sys.fileExists, ); - - Object.assign(this, { - fileName, - content, - compilerOptions: tsconfig - ? typescript.convertCompilerOptionsFromJson( - typescript.readConfigFile(tsconfig, typescript.sys.readFile).config - .compilerOptions, - ).options - : typescript.getDefaultCompilerOptions(), - }); + this.compilerOptions = tsconfig + ? typescript.convertCompilerOptionsFromJson( + typescript.readConfigFile(tsconfig, typescript.sys.readFile).config + .compilerOptions, + "", + ).options + : typescript.getDefaultCompilerOptions(); } getNewLine() { @@ -101,16 +98,14 @@ class TsLanguageServiceHost { getScriptSnapshot() { return typescript.ScriptSnapshot.fromString(this.content); } - readFile(fileName, encoding) { + readFile(fileName: string, encoding: string) { if (fileName === this.fileName) { return this.content; } return typescript.sys.readFile(fileName, encoding); } - fileExists(path) { + fileExists(path: string) { return typescript.sys.fileExists(path); } } - -export { CodeFormatter }; diff --git a/src/code-gen-process.js b/src/code-gen-process.ts similarity index 85% rename from src/code-gen-process.js rename to src/code-gen-process.ts index d90ab3a26..a61f0e528 100644 --- a/src/code-gen-process.js +++ b/src/code-gen-process.ts @@ -1,6 +1,10 @@ import { consola } from "consola"; import lodash from "lodash"; import * as typescript from "typescript"; +import type { + GenerateApiConfiguration, + SchemaComponent, +} from "../types/index.js"; import { CodeFormatter } from "./code-formatter.js"; import { CodeGenConfig } from "./configuration.js"; import { SchemaComponentsMap } from "./schema-components-map.js"; @@ -10,6 +14,7 @@ import { SchemaWalker } from "./schema-walker.js"; import { SwaggerSchemaResolver } from "./swagger-schema-resolver.js"; import { TemplatesWorker } from "./templates-worker.js"; import { JavascriptTranslator } from "./translators/javascript.js"; +import type { TranslatorIO } from "./translators/translator.js"; import { TypeNameFormatter } from "./type-name-formatter.js"; import { FileSystem } from "./util/file-system.js"; import { internalCase } from "./util/internal-case.js"; @@ -29,46 +34,56 @@ const PATCHABLE_INSTANCES = [ "javascriptTranslator", ]; -class CodeGenProcess { - /** @type {CodeGenConfig} */ - config; - /** @type {SwaggerSchemaResolver} */ - swaggerSchemaResolver; - /** @type {SchemaComponentsMap} */ - schemaComponentsMap; - /** @type {TypeNameFormatter} */ - typeNameFormatter; - /** @type {SchemaParserFabric} */ - schemaParserFabric; - /** @type {SchemaRoutes} */ - schemaRoutes; - /** @type {FileSystem} */ - fileSystem; - /** @type {CodeFormatter} */ - codeFormatter; - /** type {TemplatesWorker} */ - templatesWorker; - /** @type {SchemaWalker} */ - schemaWalker; - /** @type {JavascriptTranslator} */ - javascriptTranslator; - - /** - * - * @param config {Partial} - */ - constructor(config) { +export class CodeGenProcess { + config: CodeGenConfig; + swaggerSchemaResolver: SwaggerSchemaResolver; + schemaComponentsMap: SchemaComponentsMap; + typeNameFormatter: TypeNameFormatter; + schemaParserFabric: SchemaParserFabric; + schemaRoutes: SchemaRoutes; + fileSystem: FileSystem; + codeFormatter: CodeFormatter; + templatesWorker: TemplatesWorker; + schemaWalker: SchemaWalker; + javascriptTranslator: JavascriptTranslator; + + constructor(config: Partial) { this.config = new CodeGenConfig(config); - this.fileSystem = new FileSystem(this); - this.schemaWalker = new SchemaWalker(this); - this.swaggerSchemaResolver = new SwaggerSchemaResolver(this); - this.schemaComponentsMap = new SchemaComponentsMap(this); - this.typeNameFormatter = new TypeNameFormatter(this); - this.templatesWorker = new TemplatesWorker(this); - this.codeFormatter = new CodeFormatter(this); - this.schemaParserFabric = new SchemaParserFabric(this); - this.schemaRoutes = new SchemaRoutes(this); - this.javascriptTranslator = new JavascriptTranslator(this); + this.fileSystem = new FileSystem(); + this.swaggerSchemaResolver = new SwaggerSchemaResolver( + this.config, + this.fileSystem, + ); + this.schemaWalker = new SchemaWalker( + this.config, + this.swaggerSchemaResolver, + ); + this.schemaComponentsMap = new SchemaComponentsMap(this.config); + this.typeNameFormatter = new TypeNameFormatter(this.config); + this.templatesWorker = new TemplatesWorker( + this.config, + this.fileSystem, + this.getRenderTemplateData, + ); + this.codeFormatter = new CodeFormatter(this.config); + this.schemaParserFabric = new SchemaParserFabric( + this.config, + this.templatesWorker, + this.schemaComponentsMap, + this.typeNameFormatter, + this.schemaWalker, + ); + this.schemaRoutes = new SchemaRoutes( + this.config, + this.schemaParserFabric, + this.schemaComponentsMap, + this.templatesWorker, + this.typeNameFormatter, + ); + this.javascriptTranslator = new JavascriptTranslator( + this.config, + this.codeFormatter, + ); } async start() { @@ -112,12 +127,13 @@ class CodeGenProcess { }), ); - /** - * @type {SchemaComponent[]} - */ - const componentsToParse = this.schemaComponentsMap.filter( - lodash.compact(["schemas", this.config.extractResponses && "responses"]), - ); + const componentsToParse: SchemaComponent[] = + this.schemaComponentsMap.filter( + lodash.compact([ + "schemas", + this.config.extractResponses && "responses", + ]), + ); const parsedSchemas = componentsToParse.map((schemaComponent) => { const parsed = this.schemaParserFabric.parseSchema( @@ -220,7 +236,7 @@ class CodeGenProcess { inlineExtraFormatters: this.schemaParserFabric.schemaFormatters.inline, formatters: this.schemaParserFabric.schemaFormatters.base, formatModelName: this.typeNameFormatter.format, - fmtToJSDocLine: function fmtToJSDocLine(line, { eol = true }) { + fmtToJSDocLine: (line: string, { eol = true }) => { return ` * ${line}${eol ? "\n" : ""}`; }, NameResolver: NameResolver, @@ -311,12 +327,7 @@ class CodeGenProcess { return preparedModelType; }; - /** - * - * @param configuration - * @returns {Promise} - */ - generateOutputFiles = async ({ configuration }) => { + generateOutputFiles = async ({ configuration }): Promise => { const { modular, templatesToRender } = this.config; const output = modular @@ -342,19 +353,14 @@ class CodeGenProcess { return output.filter((fileInfo) => !!fileInfo && !!fileInfo.fileContent); }; - /** - * @param templatesToRender - * @param configuration - * @returns {Promise} - */ - createMultipleFileInfos = async (templatesToRender, configuration) => { + createMultipleFileInfos = async ( + templatesToRender, + configuration, + ): Promise => { const { routes } = configuration; const { fileNames, generateRouteTypes, generateClient } = configuration.config; - /** - * @type {TranslatorIO[]} - */ - const modularApiFileInfos = []; + const modularApiFileInfos: TranslatorIO[] = []; if (routes.$outOfModule) { if (generateRouteTypes) { @@ -456,13 +462,10 @@ class CodeGenProcess { ]; }; - /** - * - * @param templatesToRender - * @param configuration - * @returns {Promise} - */ - createSingleFileInfo = async (templatesToRender, configuration) => { + createSingleFileInfo = async ( + templatesToRender, + configuration, + ): Promise => { const { generateRouteTypes, generateClient } = configuration.config; return await this.createOutputFileInfo( @@ -494,14 +497,11 @@ class CodeGenProcess { ); }; - /** - * - * @param configuration - * @param fileNameFull - * @param content - * @returns {Promise} - */ - createOutputFileInfo = async (configuration, fileNameFull, content) => { + createOutputFileInfo = async ( + configuration, + fileNameFull, + content, + ): Promise => { const fileName = this.fileSystem.cropExtension(fileNameFull); const fileExtension = typescript.Extension.Ts; @@ -568,5 +568,3 @@ class CodeGenProcess { } }; } - -export { CodeGenProcess }; diff --git a/src/commands/generate-templates/configuration.js b/src/commands/generate-templates/configuration.ts similarity index 57% rename from src/commands/generate-templates/configuration.js rename to src/commands/generate-templates/configuration.ts index 1c595e63a..ab69f9576 100644 --- a/src/commands/generate-templates/configuration.js +++ b/src/commands/generate-templates/configuration.ts @@ -1,10 +1,8 @@ +import type { GenerateTemplatesParams } from "../../../types/index.js"; import { HTTP_CLIENT, PROJECT_VERSION } from "../../constants.js"; import { objectAssign } from "../../util/object-assign.js"; -/** - * @type {GenerateTemplatesParams}} - */ -class TemplatesGenConfig { +export class TemplatesGenConfig { cleanOutput = false; output = undefined; httpClientType = HTTP_CLIENT.FETCH; @@ -13,19 +11,11 @@ class TemplatesGenConfig { version = PROJECT_VERSION; rewrite = false; - /** - * @param config {GenerateTemplatesParams} - */ - constructor(config) { + constructor(config: GenerateTemplatesParams) { this.update(config); } - /** - * @param update {Partial} - */ - update = (update) => { + update = (update: Partial) => { objectAssign(this, update); }; } - -export { TemplatesGenConfig }; diff --git a/src/commands/generate-templates/index.js b/src/commands/generate-templates/index.ts similarity index 71% rename from src/commands/generate-templates/index.js rename to src/commands/generate-templates/index.ts index fd6741931..28cd3f33f 100644 --- a/src/commands/generate-templates/index.js +++ b/src/commands/generate-templates/index.ts @@ -2,9 +2,7 @@ import { TemplatesGenProcess } from "./templates-gen-process.js"; -async function generateTemplates(config) { +export async function generateTemplates(config) { const codeGenProcess = new TemplatesGenProcess(config); return await codeGenProcess.start(); } - -export { generateTemplates }; diff --git a/src/commands/generate-templates/templates-gen-process.js b/src/commands/generate-templates/templates-gen-process.ts similarity index 94% rename from src/commands/generate-templates/templates-gen-process.js rename to src/commands/generate-templates/templates-gen-process.ts index 8c636d25e..988732260 100644 --- a/src/commands/generate-templates/templates-gen-process.js +++ b/src/commands/generate-templates/templates-gen-process.ts @@ -1,20 +1,15 @@ import path from "node:path"; import url from "node:url"; import { consola } from "consola"; +import type { GenerateTemplatesOutput } from "../../../types/index.js"; import { FileSystem } from "../../util/file-system.js"; import { TemplatesGenConfig } from "./configuration.js"; const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); -class TemplatesGenProcess { - /** - * @type {TemplatesGenConfig} - */ - config; - /** - * @type {FileSystem} - */ - fileSystem; +export class TemplatesGenProcess { + config: TemplatesGenConfig; + fileSystem: FileSystem; rootDir = path.resolve(__dirname, "../../../"); @@ -29,13 +24,10 @@ class TemplatesGenProcess { constructor(config) { this.config = new TemplatesGenConfig(config); - this.fileSystem = new FileSystem(this); + this.fileSystem = new FileSystem(); } - /** - * @return {Promise} - */ - async start() { + async start(): Promise { consola.info('start generating source templates ".ejs" for code generator'); const templates = this.getTemplates(); @@ -194,5 +186,3 @@ class TemplatesGenProcess { ); }; } - -export { TemplatesGenProcess }; diff --git a/src/component-type-name-resolver.js b/src/component-type-name-resolver.ts similarity index 83% rename from src/component-type-name-resolver.js rename to src/component-type-name-resolver.ts index b4d45c163..1ced36a9b 100644 --- a/src/component-type-name-resolver.js +++ b/src/component-type-name-resolver.ts @@ -1,17 +1,14 @@ import { consola } from "consola"; +import type { CodeGenConfig } from "./configuration.js"; import { NameResolver } from "./util/name-resolver.js"; import { getRandomInt } from "./util/random.js"; -class ComponentTypeNameResolver extends NameResolver { +export class ComponentTypeNameResolver extends NameResolver { counter = 1; fallbackNameCounter = 1; countersByVariant = new Map(); - /** - * @param {CodeGenConfig} config; - * @param {string[]} reservedNames - */ - constructor(config, reservedNames) { + constructor(config: CodeGenConfig, reservedNames: string[]) { super(config, reservedNames, (variants) => { const randomVariant = variants[getRandomInt(0, variants.length - 1)]; if (randomVariant) { @@ -38,5 +35,3 @@ class ComponentTypeNameResolver extends NameResolver { }); } } - -export { ComponentTypeNameResolver }; diff --git a/src/configuration.js b/src/configuration.ts similarity index 76% rename from src/configuration.js rename to src/configuration.ts index 504e74152..10631b6dd 100644 --- a/src/configuration.js +++ b/src/configuration.ts @@ -1,8 +1,14 @@ import * as cosmiconfig from "cosmiconfig"; import lodash from "lodash"; import * as typescript from "typescript"; +import type { + ExtractingOptions, + GenerateApiConfiguration, +} from "../types/index.js"; import { ComponentTypeNameResolver } from "./component-type-name-resolver.js"; import * as CONSTANTS from "./constants.js"; +import type { MonoSchemaParser } from "./schema-parser/mono-schema-parser.js"; +import type { SchemaParser } from "./schema-parser/schema-parser.js"; import { objectAssign } from "./util/object-assign.js"; const TsKeyword = { @@ -30,10 +36,7 @@ const TsCodeGenKeyword = { UtilRequiredKeys: "UtilRequiredKeys", }; -/** - * @type {GenerateApiConfiguration["config"]}} - */ -class CodeGenConfig { +export class CodeGenConfig { version = CONSTANTS.PROJECT_VERSION; /** CLI flag */ templates = ""; @@ -67,8 +70,6 @@ class CodeGenConfig { /** use the first tag for the module name */ moduleNameFirstTag = false; - disableStrictSSL = false; - disableProxy = false; extractRequestParams = false; extractRequestBody = false; extractResponseBody = false; @@ -84,19 +85,28 @@ class CodeGenConfig { routeNameDuplicatesMap = new Map(); prettierOptions = { ...CONSTANTS.PRETTIER_OPTIONS }; hooks = { - onPreBuildRoutePath: (routePath) => void 0, - onBuildRoutePath: (routeData) => void 0, - onInsertPathParam: (pathParam) => void 0, - onCreateComponent: (schema) => schema, - onPreParseSchema: (originalSchema, typeName, schemaType) => void 0, - onParseSchema: (originalSchema, parsedSchema) => parsedSchema, - onCreateRoute: (routeData) => routeData, - onInit: (config, codeGenProcess) => config, - onPrepareConfig: (apiConfig) => apiConfig, - onCreateRequestParams: (rawType) => {}, + onPreBuildRoutePath: (_routePath: unknown) => void 0, + onBuildRoutePath: (_routeData: unknown) => void 0, + onInsertPathParam: (_pathParam: unknown) => void 0, + onCreateComponent: (schema: unknown) => schema, + onPreParseSchema: ( + _originalSchema: unknown, + _typeName: unknown, + _schemaType: unknown, + ) => void 0, + onParseSchema: (_originalSchema: unknown, parsedSchema: unknown) => + parsedSchema, + onCreateRoute: (routeData: unknown) => routeData, + onInit: (config: unknown, _codeGenProcess: unknown) => config, + onPrepareConfig: (apiConfig: unknown) => apiConfig, + onCreateRequestParams: (_rawType: unknown) => {}, onCreateRouteName: () => {}, - onFormatTypeName: (typeName, rawTypeName, schemaType) => {}, - onFormatRouteName: (routeInfo, templateRouteName) => {}, + onFormatTypeName: ( + _typeName: unknown, + _rawTypeName: unknown, + _schemaType: unknown, + ) => {}, + onFormatRouteName: (_routeInfo: unknown, _templateRouteName: unknown) => {}, }; defaultResponseType; singleHttpClient = false; @@ -130,10 +140,7 @@ class CodeGenConfig { routeTypes: "", routeName: "", }; - /** - * @type {Record MonoSchemaParser>} - */ - schemaParsers = {}; + schemaParsers: Record MonoSchemaParser> = {}; toJS = false; silent = false; typePrefix = ""; @@ -141,8 +148,7 @@ class CodeGenConfig { enumKeyPrefix = ""; enumKeySuffix = ""; patch = false; - /** @type {ComponentTypeNameResolver} */ - componentTypeNameResolver; + componentTypeNameResolver: ComponentTypeNameResolver; /** name of the main exported class */ apiClassName = "Api"; debug = false; @@ -158,11 +164,11 @@ class CodeGenConfig { cleanOutput = false; spec = null; fileName = "Api.ts"; - authorizationToken = void 0; + authorizationToken: string | undefined; requestOptions = null; - jsPrimitiveTypes = []; - jsEmptyTypes = []; + jsPrimitiveTypes: string[] = []; + jsEmptyTypes: string[] = []; fixInvalidTypeNamePrefix = "Type"; fixInvalidEnumKeyPrefix = "Value"; @@ -172,8 +178,7 @@ class CodeGenConfig { successResponseStatusRange = [200, 299]; - /** @type {ExtractingOptions} */ - extractingOptions = { + extractingOptions: Partial = { requestBodySuffix: ["Payload", "Body", "Input"], requestParamsSuffix: ["Params"], responseBodySuffix: ["Data", "Result", "Output"], @@ -218,7 +223,7 @@ class CodeGenConfig { /** * $A[] or Array<$A> */ - ArrayType: (content) => { + ArrayType: (content: unknown) => { if (this.anotherArrayType) { return this.Ts.TypeWithGeneric(this.Ts.Keyword.Array, [content]); } @@ -228,75 +233,79 @@ class CodeGenConfig { /** * "$A" */ - StringValue: (content) => `"${content}"`, + StringValue: (content: unknown) => `"${content}"`, /** * $A */ - BooleanValue: (content) => `${content}`, + BooleanValue: (content: unknown) => `${content}`, /** * $A */ - NumberValue: (content) => `${content}`, + NumberValue: (content: unknown) => `${content}`, /** * $A */ - NullValue: (content) => "null", + NullValue: () => "null", /** * $A1 | $A2 */ - UnionType: (contents) => + UnionType: (contents: unknown[]) => lodash.join(lodash.uniq(contents), ` ${this.Ts.Keyword.Union} `), /** * ($A1) */ - ExpressionGroup: (content) => (content ? `(${content})` : ""), + ExpressionGroup: (content: unknown) => (content ? `(${content})` : ""), /** * $A1 & $A2 */ - IntersectionType: (contents) => + IntersectionType: (contents: unknown[]) => lodash.join(lodash.uniq(contents), ` ${this.Ts.Keyword.Intersection} `), /** * Record<$A1, $A2> */ - RecordType: (key, value) => + RecordType: (key: unknown, value: unknown) => this.Ts.TypeWithGeneric(this.Ts.Keyword.Record, [key, value]), /** * readonly $key?:$value */ - TypeField: ({ readonly, key, optional, value }) => + TypeField: ({ readonly, key, optional, value }: Record) => lodash .compact([readonly && "readonly ", key, optional && "?", ": ", value]) .join(""), /** * [key: $A1]: $A2 */ - InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`, + InterfaceDynamicField: (key: unknown, value: unknown) => + `[key: ${key}]: ${value}`, /** * EnumName.EnumKey */ - EnumUsageKey: (enumStruct, key) => `${enumStruct}.${key}`, + EnumUsageKey: (enumStruct: unknown, key: unknown) => `${enumStruct}.${key}`, /** * $A1 = $A2 */ - EnumField: (key, value) => `${key} = ${value}`, + EnumField: (key: unknown, value: unknown) => `${key} = ${value}`, /** * $A0.key = $A0.value, * $A1.key = $A1.value, * $AN.key = $AN.value, */ - EnumFieldsWrapper: (contents) => + EnumFieldsWrapper: (contents: Record[]) => lodash .map(contents, ({ key, value }) => ` ${this.Ts.EnumField(key, value)}`) .join(",\n"), /** * {\n $A \n} */ - ObjectWrapper: (content) => `{\n${content}\n}`, + ObjectWrapper: (content: unknown) => `{\n${content}\n}`, /** * /** $A *\/ */ - MultilineComment: (contents, formatFn) => + MultilineComment: ( + contents: unknown[], + formatFn: (arg: unknown) => unknown, + ) => [ ...(contents.length === 1 ? [`/** ${contents[0]} */`] @@ -305,7 +314,7 @@ class CodeGenConfig { /** * $A1<...$A2.join(,)> */ - TypeWithGeneric: (typeName, genericArgs) => { + TypeWithGeneric: (typeName: unknown, genericArgs: unknown[]) => { return `${typeName}${ genericArgs.length ? `<${genericArgs.join(",")}>` : "" }`; @@ -313,7 +322,7 @@ class CodeGenConfig { /** * [$A1, $A2, ...$AN] */ - Tuple: (values) => { + Tuple: (values: unknown[]) => { return `[${values.join(", ")}]`; }, }; @@ -321,16 +330,23 @@ class CodeGenConfig { /** * swagger schema type -> typescript type * https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times - * @type {Record string) | ({ $default: string } & Record string)>)>} */ - primitiveTypes = { + primitiveTypes: Record< + string, + | string + | ((schema: any, parser: SchemaParser) => string) + | ({ $default: string } & Record< + string, + string | ((schema: any, parser: SchemaParser) => string) + >) + > = { integer: () => this.Ts.Keyword.Number, number: () => this.Ts.Keyword.Number, boolean: () => this.Ts.Keyword.Boolean, object: () => this.Ts.Keyword.Object, file: () => this.Ts.Keyword.File, string: { - $default: () => this.Ts.Keyword.String, + $default: this.Ts.Keyword.String, /** formats */ binary: () => this.Ts.Keyword.File, @@ -369,9 +385,6 @@ class CodeGenConfig { templateExtensions = [".eta", ".ejs"]; - /** - * @param config {Partial} - */ constructor({ prettierOptions = getDefaultPrettierOptions(), codeGenConstructs, @@ -380,7 +393,7 @@ class CodeGenConfig { templateInfos, hooks, ...otherConfig - }) { + }: Partial) { objectAssign(this.Ts, codeGenConstructs); objectAssign(this.primitiveTypes, primitiveTypeConstructs); @@ -413,11 +426,7 @@ class CodeGenConfig { ); } - /** - * - * @param update {Partial} - */ - update = (update) => { + update = (update: Partial) => { objectAssign(this, update); }; } @@ -438,5 +447,3 @@ const getDefaultPrettierOptions = () => { return { ...CONSTANTS.PRETTIER_OPTIONS }; }; - -export { CodeGenConfig }; diff --git a/src/constants.js b/src/constants.ts similarity index 56% rename from src/constants.js rename to src/constants.ts index efce06144..515095f67 100644 --- a/src/constants.js +++ b/src/constants.ts @@ -1,8 +1,8 @@ import packageJson from "../package.json" with { type: "json" }; -const DEFAULT_BODY_ARG_NAME = "data"; +export const DEFAULT_BODY_ARG_NAME = "data"; -const FILE_PREFIX = `/* eslint-disable */ +export const FILE_PREFIX = `/* eslint-disable */ /* tslint:disable */ /* * --------------------------------------------------------------- @@ -15,36 +15,36 @@ const FILE_PREFIX = `/* eslint-disable */ `; -const HTTP_CLIENT = { +export const HTTP_CLIENT = { FETCH: "fetch", AXIOS: "axios", -}; +} as const; -const PRETTIER_OPTIONS = { +export const PRETTIER_OPTIONS = { printWidth: 120, tabWidth: 2, trailingComma: "all", parser: "typescript", -}; +} as const; -const PROJECT_VERSION = packageJson.version; +export const PROJECT_VERSION = packageJson.version; -const RESERVED_BODY_ARG_NAMES = ["data", "body", "reqBody"]; +export const RESERVED_BODY_ARG_NAMES = ["data", "body", "reqBody"]; -const RESERVED_HEADER_ARG_NAMES = ["headers", "headersParams"]; +export const RESERVED_HEADER_ARG_NAMES = ["headers", "headersParams"]; -const RESERVED_PATH_ARG_NAMES = ["path", "pathParams"]; +export const RESERVED_PATH_ARG_NAMES = ["path", "pathParams"]; -const RESERVED_QUERY_ARG_NAMES = ["query", "queryParams", "queryArg"]; +export const RESERVED_QUERY_ARG_NAMES = ["query", "queryParams", "queryArg"]; -const RESERVED_REQ_PARAMS_ARG_NAMES = [ +export const RESERVED_REQ_PARAMS_ARG_NAMES = [ "params", "requestParams", "reqParams", "httpParams", ]; -const SCHEMA_TYPES = { +export const SCHEMA_TYPES = { ARRAY: "array", OBJECT: "object", ENUM: "enum", @@ -57,18 +57,4 @@ const SCHEMA_TYPES = { COMPLEX_ALL_OF: "allOf", COMPLEX_NOT: "not", COMPLEX_UNKNOWN: "__unknown", -}; - -export { - DEFAULT_BODY_ARG_NAME, - FILE_PREFIX, - HTTP_CLIENT, - PRETTIER_OPTIONS, - PROJECT_VERSION, - RESERVED_BODY_ARG_NAMES, - RESERVED_HEADER_ARG_NAMES, - RESERVED_PATH_ARG_NAMES, - RESERVED_QUERY_ARG_NAMES, - RESERVED_REQ_PARAMS_ARG_NAMES, - SCHEMA_TYPES, -}; +} as const; diff --git a/src/index.js b/src/index.js deleted file mode 100644 index aa30ba836..000000000 --- a/src/index.js +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env node - -import { consola } from "consola"; -import { CodeGenProcess } from "./code-gen-process.js"; -import { generateTemplates } from "./commands/generate-templates/index.js"; -import * as constants from "./constants.js"; - -async function generateApi({ prettier, ...config }) { - if (config.debug) { - consola.level = Number.MAX_SAFE_INTEGER; - } - const codeGenProcess = new CodeGenProcess({ - ...config, - prettierOptions: prettier, - }); - return await codeGenProcess.start(); -} - -export { constants, generateApi, generateTemplates }; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 000000000..6ef76c068 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,16 @@ +import { consola } from "consola"; +import type { GenerateApiConfiguration } from "../types/index.js"; +import { CodeGenProcess } from "./code-gen-process.js"; + +export async function generateApi( + config: Partial, +) { + if (config.debug) { + consola.level = Number.MAX_SAFE_INTEGER; + } + const codeGenProcess = new CodeGenProcess(config); + return await codeGenProcess.start(); +} + +export * as constants from "./constants.js"; +export { generateTemplates } from "./commands/generate-templates/index.js"; diff --git a/src/schema-components-map.js b/src/schema-components-map.ts similarity index 70% rename from src/schema-components-map.js rename to src/schema-components-map.ts index 0229fa62f..7c9d13752 100644 --- a/src/schema-components-map.js +++ b/src/schema-components-map.ts @@ -1,10 +1,11 @@ -class SchemaComponentsMap { - /** @type {SchemaComponent[]} */ - _data = []; - /** @type {CodeGenConfig} */ - config; +import type { SchemaComponent } from "../types/index.js"; +import type { CodeGenConfig } from "./configuration.js"; - constructor({ config }) { +export class SchemaComponentsMap { + _data: SchemaComponent[] = []; + config: CodeGenConfig; + + constructor(config: CodeGenConfig) { this.config = config; } @@ -12,15 +13,15 @@ class SchemaComponentsMap { this._data = []; } - createRef = (paths) => { + createRef = (paths: string[]) => { return ["#", ...paths].join("/"); }; - parseRef = (ref) => { + parseRef = (ref: string) => { return ref.split("/"); }; - createComponent($ref, rawTypeData) { + createComponent($ref: string, rawTypeData: string) { const parsed = this.parseRef($ref); const typeName = parsed[parsed.length - 1]; const componentName = parsed[parsed.length - 2]; @@ -47,18 +48,11 @@ class SchemaComponentsMap { return usageComponent; } - /** - * @returns {SchemaComponent[]} - */ getComponents() { return this._data; } - /** - * @params {...string[]} componentNames - * @returns {SchemaComponent[]} - */ - filter(...componentNames) { + filter(...componentNames: string[]) { return this._data.filter((it) => componentNames.some((componentName) => it.$ref.startsWith(`#/components/${componentName}`), @@ -66,9 +60,7 @@ class SchemaComponentsMap { ); } - get($ref) { + get($ref: string) { return this._data.find((c) => c.$ref === $ref) || null; } } - -export { SchemaComponentsMap }; diff --git a/src/schema-parser/base-schema-parsers/array.js b/src/schema-parser/base-schema-parsers/array.ts similarity index 93% rename from src/schema-parser/base-schema-parsers/array.js rename to src/schema-parser/base-schema-parsers/array.ts index ef8081646..ae84eef7c 100644 --- a/src/schema-parser/base-schema-parsers/array.js +++ b/src/schema-parser/base-schema-parsers/array.ts @@ -1,8 +1,8 @@ import { SCHEMA_TYPES } from "../../constants.js"; import { MonoSchemaParser } from "../mono-schema-parser.js"; -class ArraySchemaParser extends MonoSchemaParser { - parse() { +export class ArraySchemaParser extends MonoSchemaParser { + override parse() { let contentType; const { type, description, items } = this.schema || {}; @@ -36,5 +36,3 @@ class ArraySchemaParser extends MonoSchemaParser { }; } } - -export { ArraySchemaParser }; diff --git a/src/schema-parser/base-schema-parsers/complex.js b/src/schema-parser/base-schema-parsers/complex.ts similarity index 94% rename from src/schema-parser/base-schema-parsers/complex.js rename to src/schema-parser/base-schema-parsers/complex.ts index 88873a8bd..67bce3639 100644 --- a/src/schema-parser/base-schema-parsers/complex.js +++ b/src/schema-parser/base-schema-parsers/complex.ts @@ -2,8 +2,8 @@ import lodash from "lodash"; import { SCHEMA_TYPES } from "../../constants.js"; import { MonoSchemaParser } from "../mono-schema-parser.js"; -class ComplexSchemaParser extends MonoSchemaParser { - parse() { +export class ComplexSchemaParser extends MonoSchemaParser { + override parse() { const complexType = this.schemaUtils.getComplexType(this.schema); const simpleSchema = lodash.omit( lodash.clone(this.schema), @@ -47,5 +47,3 @@ class ComplexSchemaParser extends MonoSchemaParser { }; } } - -export { ComplexSchemaParser }; diff --git a/src/schema-parser/base-schema-parsers/discriminator.js b/src/schema-parser/base-schema-parsers/discriminator.ts similarity index 98% rename from src/schema-parser/base-schema-parsers/discriminator.js rename to src/schema-parser/base-schema-parsers/discriminator.ts index bea3a333f..4fce9b174 100644 --- a/src/schema-parser/base-schema-parsers/discriminator.js +++ b/src/schema-parser/base-schema-parsers/discriminator.ts @@ -2,8 +2,8 @@ import lodash from "lodash"; import { SCHEMA_TYPES } from "../../constants.js"; import { MonoSchemaParser } from "../mono-schema-parser.js"; -class DiscriminatorSchemaParser extends MonoSchemaParser { - parse() { +export class DiscriminatorSchemaParser extends MonoSchemaParser { + override parse() { const ts = this.config.Ts; const { discriminator, ...noDiscriminatorSchema } = this.schema; @@ -307,5 +307,3 @@ class DiscriminatorSchemaParser extends MonoSchemaParser { }; }; } - -export { DiscriminatorSchemaParser }; diff --git a/src/schema-parser/base-schema-parsers/enum.js b/src/schema-parser/base-schema-parsers/enum.ts similarity index 91% rename from src/schema-parser/base-schema-parsers/enum.js rename to src/schema-parser/base-schema-parsers/enum.ts index c4f285f7a..5f53f6a58 100644 --- a/src/schema-parser/base-schema-parsers/enum.js +++ b/src/schema-parser/base-schema-parsers/enum.ts @@ -3,11 +3,11 @@ import { SCHEMA_TYPES } from "../../constants.js"; import { MonoSchemaParser } from "../mono-schema-parser.js"; import { EnumKeyResolver } from "../util/enum-key-resolver.js"; -class EnumSchemaParser extends MonoSchemaParser { - /** @type {EnumKeyResolver} */ - enumKeyResolver; +export class EnumSchemaParser extends MonoSchemaParser { + enumKeyResolver: EnumKeyResolver; constructor(...args) { + // @ts-expect-error TS(2556) FIXME: A spread argument must either have a tuple type or... Remove this comment to see the full error message super(...args); this.enumKeyResolver = new EnumKeyResolver(this.config, []); } @@ -30,7 +30,7 @@ class EnumSchemaParser extends MonoSchemaParser { return this.schemaParserFabric.parseSchema(customComponent); }; - parse() { + override parse() { const pathTypeName = this.buildTypeNameFromPath(); if (this.config.extractEnums && !this.typeName && pathTypeName != null) { @@ -108,6 +108,7 @@ class EnumSchemaParser extends MonoSchemaParser { } else { content = this.schema.enum.map((value) => { return { + // @ts-expect-error TS(2345) FIXME: Argument of type '{ value: any; }' is not assignab... Remove this comment to see the full error message key: this.formatEnumKey({ value }), type: keyType, value: formatValue(value), @@ -152,5 +153,3 @@ class EnumSchemaParser extends MonoSchemaParser { return this.enumKeyResolver.resolve([formatted]); }; } - -export { EnumSchemaParser }; diff --git a/src/schema-parser/base-schema-parsers/object.js b/src/schema-parser/base-schema-parsers/object.ts similarity index 96% rename from src/schema-parser/base-schema-parsers/object.js rename to src/schema-parser/base-schema-parsers/object.ts index 1d91fe803..cad7346a3 100644 --- a/src/schema-parser/base-schema-parsers/object.js +++ b/src/schema-parser/base-schema-parsers/object.ts @@ -2,8 +2,8 @@ import lodash from "lodash"; import { SCHEMA_TYPES } from "../../constants.js"; import { MonoSchemaParser } from "../mono-schema-parser.js"; -class ObjectSchemaParser extends MonoSchemaParser { - parse() { +export class ObjectSchemaParser extends MonoSchemaParser { + override parse() { const contentProperties = this.getObjectSchemaContent(this.schema); return { @@ -96,5 +96,3 @@ class ObjectSchemaParser extends MonoSchemaParser { return propertiesContent; }; } - -export { ObjectSchemaParser }; diff --git a/src/schema-parser/base-schema-parsers/primitive.js b/src/schema-parser/base-schema-parsers/primitive.ts similarity index 94% rename from src/schema-parser/base-schema-parsers/primitive.js rename to src/schema-parser/base-schema-parsers/primitive.ts index 5ee4677f3..4ed2c0e0a 100644 --- a/src/schema-parser/base-schema-parsers/primitive.js +++ b/src/schema-parser/base-schema-parsers/primitive.ts @@ -1,8 +1,8 @@ import { SCHEMA_TYPES } from "../../constants.js"; import { MonoSchemaParser } from "../mono-schema-parser.js"; -class PrimitiveSchemaParser extends MonoSchemaParser { - parse() { +export class PrimitiveSchemaParser extends MonoSchemaParser { + override parse() { let contentType = null; const { additionalProperties, type, description, items } = this.schema || {}; @@ -57,5 +57,3 @@ class PrimitiveSchemaParser extends MonoSchemaParser { }; } } - -export { PrimitiveSchemaParser }; diff --git a/src/schema-parser/complex-schema-parsers/all-of.js b/src/schema-parser/complex-schema-parsers/all-of.ts similarity index 87% rename from src/schema-parser/complex-schema-parsers/all-of.js rename to src/schema-parser/complex-schema-parsers/all-of.ts index 6e55f66c3..be98fe8d6 100644 --- a/src/schema-parser/complex-schema-parsers/all-of.js +++ b/src/schema-parser/complex-schema-parsers/all-of.ts @@ -1,8 +1,8 @@ import { MonoSchemaParser } from "../mono-schema-parser.js"; // T1 & T2 -class AllOfSchemaParser extends MonoSchemaParser { - parse() { +export class AllOfSchemaParser extends MonoSchemaParser { + override parse() { const ignoreTypes = [this.config.Ts.Keyword.Any]; const combined = this.schema.allOf.map((childSchema) => this.schemaParserFabric.getInlineParseContent( @@ -21,5 +21,3 @@ class AllOfSchemaParser extends MonoSchemaParser { return this.schemaUtils.safeAddNullToType(this.schema, type); } } - -export { AllOfSchemaParser }; diff --git a/src/schema-parser/complex-schema-parsers/any-of.js b/src/schema-parser/complex-schema-parsers/any-of.ts similarity index 87% rename from src/schema-parser/complex-schema-parsers/any-of.js rename to src/schema-parser/complex-schema-parsers/any-of.ts index b586575ee..8c32db6e7 100644 --- a/src/schema-parser/complex-schema-parsers/any-of.js +++ b/src/schema-parser/complex-schema-parsers/any-of.ts @@ -1,8 +1,8 @@ import { MonoSchemaParser } from "../mono-schema-parser.js"; // T1 | T2 -class AnyOfSchemaParser extends MonoSchemaParser { - parse() { +export class AnyOfSchemaParser extends MonoSchemaParser { + override parse() { const ignoreTypes = [this.config.Ts.Keyword.Any]; const combined = this.schema.anyOf.map((childSchema) => this.schemaParserFabric.getInlineParseContent( @@ -22,5 +22,3 @@ class AnyOfSchemaParser extends MonoSchemaParser { return this.schemaUtils.safeAddNullToType(this.schema, type); } } - -export { AnyOfSchemaParser }; diff --git a/src/schema-parser/complex-schema-parsers/not.js b/src/schema-parser/complex-schema-parsers/not.ts similarity index 54% rename from src/schema-parser/complex-schema-parsers/not.js rename to src/schema-parser/complex-schema-parsers/not.ts index 1fb94363e..acfe6fc74 100644 --- a/src/schema-parser/complex-schema-parsers/not.js +++ b/src/schema-parser/complex-schema-parsers/not.ts @@ -1,9 +1,7 @@ import { MonoSchemaParser } from "../mono-schema-parser.js"; -class NotSchemaParser extends MonoSchemaParser { - parse() { +export class NotSchemaParser extends MonoSchemaParser { + override parse() { return this.config.Ts.Keyword.Any; } } - -export { NotSchemaParser }; diff --git a/src/schema-parser/complex-schema-parsers/one-of.js b/src/schema-parser/complex-schema-parsers/one-of.ts similarity index 87% rename from src/schema-parser/complex-schema-parsers/one-of.js rename to src/schema-parser/complex-schema-parsers/one-of.ts index bb74060c4..e31945be6 100644 --- a/src/schema-parser/complex-schema-parsers/one-of.js +++ b/src/schema-parser/complex-schema-parsers/one-of.ts @@ -1,8 +1,8 @@ import { MonoSchemaParser } from "../mono-schema-parser.js"; // T1 | T2 -class OneOfSchemaParser extends MonoSchemaParser { - parse() { +export class OneOfSchemaParser extends MonoSchemaParser { + override parse() { const ignoreTypes = [this.config.Ts.Keyword.Any]; const combined = this.schema.oneOf.map((childSchema) => this.schemaParserFabric.getInlineParseContent( @@ -22,5 +22,3 @@ class OneOfSchemaParser extends MonoSchemaParser { return this.schemaUtils.safeAddNullToType(this.schema, type); } } - -export { OneOfSchemaParser }; diff --git a/src/schema-parser/mono-schema-parser.js b/src/schema-parser/mono-schema-parser.js deleted file mode 100644 index 9dc4ae420..000000000 --- a/src/schema-parser/mono-schema-parser.js +++ /dev/null @@ -1,43 +0,0 @@ -class MonoSchemaParser { - schema; - typeName; - schemaPath; - - /** @type {SchemaParser} */ - schemaParser; - /** @type {SchemaParserFabric} */ - schemaParserFabric; - /** @type {TypeNameFormatter} */ - typeNameFormatter; - /** @type {SchemaComponentsMap} */ - schemaComponentsMap; - /** @type {SchemaUtils} */ - schemaUtils; - /** @type {CodeGenConfig} */ - config; - /** @type {SchemaFormatters} */ - schemaFormatters; - - constructor(schemaParser, schema, typeName = null, schemaPath = []) { - this.schemaParser = schemaParser; - this.schemaParserFabric = schemaParser.schemaParserFabric; - this.schema = schema; - this.typeName = typeName; - this.typeNameFormatter = schemaParser.typeNameFormatter; - this.schemaPath = schemaPath; - this.schemaComponentsMap = this.schemaParser.schemaComponentsMap; - this.schemaUtils = this.schemaParser.schemaUtils; - this.config = this.schemaParser.config; - this.schemaFormatters = this.schemaParser.schemaFormatters; - } - - parse() { - throw new Error("not implemented"); - } - - buildTypeNameFromPath = () => { - return this.schemaUtils.buildTypeNameFromPath(this.schemaPath); - }; -} - -export { MonoSchemaParser }; diff --git a/src/schema-parser/mono-schema-parser.ts b/src/schema-parser/mono-schema-parser.ts new file mode 100644 index 000000000..c8745a21b --- /dev/null +++ b/src/schema-parser/mono-schema-parser.ts @@ -0,0 +1,47 @@ +import type { CodeGenConfig } from "../configuration.js"; +import type { SchemaComponentsMap } from "../schema-components-map.js"; +import type { TypeNameFormatter } from "../type-name-formatter.js"; +import type { SchemaFormatters } from "./schema-formatters.js"; +import type { SchemaParserFabric } from "./schema-parser-fabric.js"; +import type { SchemaParser } from "./schema-parser.js"; +import type { SchemaUtils } from "./schema-utils.js"; + +export class MonoSchemaParser { + schema; + typeName; + schemaPath; + + schemaParser: SchemaParser; + schemaParserFabric: SchemaParserFabric; + typeNameFormatter: TypeNameFormatter; + schemaComponentsMap: SchemaComponentsMap; + schemaUtils: SchemaUtils; + config: CodeGenConfig; + schemaFormatters: SchemaFormatters; + + constructor( + schemaParser: SchemaParser, + schema, + typeName = null, + schemaPath = [], + ) { + this.schemaParser = schemaParser; + this.schemaParserFabric = schemaParser.schemaParserFabric; + this.schema = schema; + this.typeName = typeName; + this.typeNameFormatter = schemaParser.typeNameFormatter; + this.schemaPath = schemaPath; + this.schemaComponentsMap = this.schemaParser.schemaComponentsMap; + this.schemaUtils = this.schemaParser.schemaUtils; + this.config = this.schemaParser.config; + this.schemaFormatters = this.schemaParser.schemaFormatters; + } + + parse() { + throw new Error("not implemented"); + } + + buildTypeNameFromPath = () => { + return this.schemaUtils.buildTypeNameFromPath(this.schemaPath); + }; +} diff --git a/src/schema-parser/schema-formatters.js b/src/schema-parser/schema-formatters.ts similarity index 79% rename from src/schema-parser/schema-formatters.js rename to src/schema-parser/schema-formatters.ts index 09571cc38..9e2a20ee8 100644 --- a/src/schema-parser/schema-formatters.js +++ b/src/schema-parser/schema-formatters.ts @@ -1,18 +1,17 @@ import lodash from "lodash"; +import type { CodeGenConfig } from "../configuration.js"; import { SCHEMA_TYPES } from "../constants.js"; +import type { TemplatesWorker } from "../templates-worker.js"; +import type { SchemaParserFabric } from "./schema-parser-fabric.js"; +import type { SchemaParser } from "./schema-parser.js"; +import type { SchemaUtils } from "./schema-utils.js"; -class SchemaFormatters { - /** @type {CodeGenConfig} */ - config; - /** @type {TemplatesWorker} */ - templatesWorker; - /** @type {SchemaUtils} */ - schemaUtils; - - /** - * @param schemaParser {SchemaParser | SchemaParserFabric} - */ - constructor(schemaParser) { +export class SchemaFormatters { + config: CodeGenConfig; + templatesWorker: TemplatesWorker; + schemaUtils: SchemaUtils; + + constructor(schemaParser: SchemaParser | SchemaParserFabric) { this.config = schemaParser.config; this.schemaUtils = schemaParser.schemaUtils; this.templatesWorker = schemaParser.templatesWorker; @@ -92,11 +91,10 @@ class SchemaFormatters { }, }; - /** - * @param parsedSchema {Record} - * @param formatType {"base" | "inline"} - */ - formatSchema = (parsedSchema, formatType = "base") => { + formatSchema = ( + parsedSchema: Record, + formatType: "base" | "inline" = "base", + ) => { const schemaType = lodash.get(parsedSchema, ["schemaType"]) || lodash.get(parsedSchema, ["$parsed", "schemaType"]); @@ -112,13 +110,16 @@ class SchemaFormatters { if (!hasMultipleLines) return description; if (inline) { - return lodash - ._(description) - .split(/\n/g) - .map((part) => part.trim()) - .compact() - .join(" ") - .valueOf(); + return ( + lodash + // @ts-expect-error TS(2339) FIXME: Property '_' does not exist on type 'LoDashStatic'... Remove this comment to see the full error message + ._(description) + .split(/\n/g) + .map((part) => part.trim()) + .compact() + .join(" ") + .valueOf() + ); } return description.replace(/\n$/g, ""); @@ -153,5 +154,3 @@ class SchemaFormatters { return fields.join(""); }; } - -export { SchemaFormatters }; diff --git a/src/schema-parser/schema-parser-fabric.js b/src/schema-parser/schema-parser-fabric.ts similarity index 55% rename from src/schema-parser/schema-parser-fabric.js rename to src/schema-parser/schema-parser-fabric.ts index e09e21121..bdf9ffc0a 100644 --- a/src/schema-parser/schema-parser-fabric.js +++ b/src/schema-parser/schema-parser-fabric.ts @@ -1,30 +1,34 @@ +import type { + ParsedSchema, + SchemaTypeEnumContent, + SchemaTypeObjectContent, + SchemaTypePrimitiveContent, +} from "../../types/index.js"; +import type { CodeGenConfig } from "../configuration.js"; +import type { SchemaComponentsMap } from "../schema-components-map.js"; +import type { SchemaWalker } from "../schema-walker.js"; +import type { TemplatesWorker } from "../templates-worker.js"; +import type { TypeNameFormatter } from "../type-name-formatter.js"; import { SchemaFormatters } from "./schema-formatters.js"; import { SchemaParser } from "./schema-parser.js"; import { SchemaUtils } from "./schema-utils.js"; -class SchemaParserFabric { - /** @type {CodeGenConfig} */ - config; - /** @type {SchemaComponentsMap} */ - schemaComponentsMap; - /** @type {TypeNameFormatter} */ - typeNameFormatter; - /** @type {SchemaFormatters} */ - schemaFormatters; - /** @type {TemplatesWorker} */ - templatesWorker; - /** @type {SchemaUtils} */ - schemaUtils; - /** @type {SchemaWalker} */ - schemaWalker; +export class SchemaParserFabric { + config: CodeGenConfig; + schemaComponentsMap: SchemaComponentsMap; + typeNameFormatter: TypeNameFormatter; + schemaFormatters: SchemaFormatters; + templatesWorker: TemplatesWorker; + schemaUtils: SchemaUtils; + schemaWalker: SchemaWalker; - constructor({ - config, - templatesWorker, - schemaComponentsMap, - typeNameFormatter, - schemaWalker, - }) { + constructor( + config: CodeGenConfig, + templatesWorker: TemplatesWorker, + schemaComponentsMap: SchemaComponentsMap, + typeNameFormatter: TypeNameFormatter, + schemaWalker: SchemaWalker, + ) { this.config = config; this.schemaComponentsMap = schemaComponentsMap; this.typeNameFormatter = typeNameFormatter; @@ -38,15 +42,6 @@ class SchemaParserFabric { return new SchemaParser(this, { schema, typeName, schemaPath }); }; - /** - * - * @param content schema content - * @param linkedSchema link content to attached schema - * @param linkedComponent link content and other schema props to attached component - * @param schemaPath - * @param otherSchemaProps - * @returns {{}} - */ createSchema = ({ content, linkedSchema = {}, @@ -54,6 +49,7 @@ class SchemaParserFabric { schemaPath, ...otherSchemaProps }) => { + // @ts-expect-error TS(2345) FIXME: Argument of type '{ schema: any; schemaPath: any; ... Remove this comment to see the full error message const parser = this.createSchemaParser({ schema: linkedComponent || linkedSchema, schemaPath, @@ -81,14 +77,13 @@ class SchemaParserFabric { return customComponent; }; - /** - * - * @param schema {any} - * @param typeName {null | string} - * @param [schemaPath] {string[]} - * @return {Record} - */ - parseSchema = (schema, typeName = null, schemaPath = []) => { + parseSchema = ( + schema: string, + typeName: string | null = null, + schemaPath: string[] = [], + ): ParsedSchema< + SchemaTypeObjectContent | SchemaTypeEnumContent | SchemaTypePrimitiveContent + > => { const schemaParser = this.createSchemaParser({ schema, typeName, @@ -97,29 +92,21 @@ class SchemaParserFabric { return schemaParser.parseSchema(); }; - /** - * - * @param schema {any} - * @param typeName {null | string} - * @param [schemaPath] {string[]} - * @return {Record} - */ - getInlineParseContent = (schema, typeName, schemaPath) => { + getInlineParseContent = ( + schema: string, + typeName: string | null, + schemaPath: string[], + ): Record => { const parser = this.createSchemaParser({ schema, typeName, schemaPath }); return parser.getInlineParseContent(); }; - /** - * - * @param schema {any} - * @param typeName {null | string} - * @param [schemaPath] {string[]} - * @return {Record} - */ - getParseContent = (schema, typeName, schemaPath) => { + getParseContent = ( + schema: string, + typeName: string | null, + schemaPath: string[], + ): Record => { const parser = this.createSchemaParser({ schema, typeName, schemaPath }); return parser.getParseContent(); }; } - -export { SchemaParserFabric }; diff --git a/src/schema-parser/schema-parser.js b/src/schema-parser/schema-parser.ts similarity index 89% rename from src/schema-parser/schema-parser.js rename to src/schema-parser/schema-parser.ts index d95a433b1..fc8e45878 100644 --- a/src/schema-parser/schema-parser.js +++ b/src/schema-parser/schema-parser.ts @@ -1,6 +1,11 @@ import { consola } from "consola"; import lodash from "lodash"; +import type { CodeGenConfig } from "../configuration.js"; import { SCHEMA_TYPES } from "../constants.js"; +import type { SchemaComponentsMap } from "../schema-components-map.js"; +import type { SchemaWalker } from "../schema-walker.js"; +import type { TemplatesWorker } from "../templates-worker.js"; +import type { TypeNameFormatter } from "../type-name-formatter.js"; import { sortByProperty } from "../util/sort-by-property.js"; import { ArraySchemaParser } from "./base-schema-parsers/array.js"; import { ComplexSchemaParser } from "./base-schema-parsers/complex.js"; @@ -12,31 +17,25 @@ import { AllOfSchemaParser } from "./complex-schema-parsers/all-of.js"; import { AnyOfSchemaParser } from "./complex-schema-parsers/any-of.js"; import { NotSchemaParser } from "./complex-schema-parsers/not.js"; import { OneOfSchemaParser } from "./complex-schema-parsers/one-of.js"; -import { SchemaFormatters } from "./schema-formatters.js"; -import { SchemaUtils } from "./schema-utils.js"; +import type { SchemaFormatters } from "./schema-formatters.js"; +import type { SchemaParserFabric } from "./schema-parser-fabric.js"; +import type { SchemaUtils } from "./schema-utils.js"; -class SchemaParser { - /** @type {SchemaParserFabric} */ - schemaParserFabric; - /** @type {CodeGenConfig} */ - config; - /** @type {SchemaComponentsMap} */ - schemaComponentsMap; - /** @type {TypeNameFormatter} */ - typeNameFormatter; - /** @type {SchemaFormatters} */ - schemaFormatters; - /** @type {SchemaUtils} */ - schemaUtils; - /** @type {TemplatesWorker} */ - templatesWorker; - /** @type {SchemaWalker} */ - schemaWalker; +export class SchemaParser { + schemaParserFabric: SchemaParserFabric; + config: CodeGenConfig; + schemaComponentsMap: SchemaComponentsMap; + typeNameFormatter: TypeNameFormatter; + schemaFormatters: SchemaFormatters; + schemaUtils: SchemaUtils; + templatesWorker: TemplatesWorker; + schemaWalker: SchemaWalker; typeName; schema; schemaPath = []; + // @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message constructor(schemaParserFabric, { typeName, schema, schemaPath } = {}) { this.schemaParserFabric = schemaParserFabric; this.config = schemaParserFabric.config; @@ -166,9 +165,6 @@ class SchemaParser { }, }; - /** - * @return {Record} - */ parseSchema = () => { if (!this.schema) return this._baseSchemaParsers[SCHEMA_TYPES.PRIMITIVE]( @@ -289,5 +285,3 @@ class SchemaParser { }; }; } - -export { SchemaParser }; diff --git a/src/schema-parser/schema-utils.js b/src/schema-parser/schema-utils.ts similarity index 94% rename from src/schema-parser/schema-utils.js rename to src/schema-parser/schema-utils.ts index 9d5f3ed7e..7c344687b 100644 --- a/src/schema-parser/schema-utils.js +++ b/src/schema-parser/schema-utils.ts @@ -1,17 +1,17 @@ import lodash from "lodash"; +import type { CodeGenConfig } from "../configuration.js"; import { SCHEMA_TYPES } from "../constants.js"; +import type { SchemaComponentsMap } from "../schema-components-map.js"; +import type { SchemaWalker } from "../schema-walker.js"; +import type { TypeNameFormatter } from "../type-name-formatter.js"; import { internalCase } from "../util/internal-case.js"; import { pascalCase } from "../util/pascal-case.js"; -class SchemaUtils { - /** @type {CodeGenConfig} */ - config; - /** @type {SchemaComponentsMap} */ - schemaComponentsMap; - /** @type {TypeNameFormatter} */ - typeNameFormatter; - /** @type {SchemaWalker} */ - schemaWalker; +export class SchemaUtils { + config: CodeGenConfig; + schemaComponentsMap: SchemaComponentsMap; + typeNameFormatter: TypeNameFormatter; + schemaWalker: SchemaWalker; constructor({ config, @@ -46,7 +46,6 @@ class SchemaUtils { getSchemaRefType = (schema) => { if (!this.isRefSchema(schema)) return null; - // const resolved = this.schemaWalker.findByRef(schema.$ref); return this.schemaComponentsMap.get(schema.$ref); }; @@ -187,7 +186,7 @@ class SchemaUtils { { suffixes, resolver, prefixes, shouldReserve = true }, ) => { if (resolver) { - return this.config.componentTypeNameResolver.resolve(null, (reserved) => { + return this.config.componentTypeNameResolver.resolve([], (reserved) => { return resolver(pascalCase(typeName), reserved); }); } @@ -328,5 +327,3 @@ class SchemaUtils { } }; } - -export { SchemaUtils }; diff --git a/src/schema-parser/util/enum-key-resolver.js b/src/schema-parser/util/enum-key-resolver.ts similarity index 70% rename from src/schema-parser/util/enum-key-resolver.js rename to src/schema-parser/util/enum-key-resolver.ts index a0e96d752..bc4035b2d 100644 --- a/src/schema-parser/util/enum-key-resolver.js +++ b/src/schema-parser/util/enum-key-resolver.ts @@ -1,13 +1,10 @@ import { consola } from "consola"; +import type { CodeGenConfig } from "../../configuration.js"; import { NameResolver } from "../../util/name-resolver.js"; -class EnumKeyResolver extends NameResolver { +export class EnumKeyResolver extends NameResolver { counter = 1; - /** - * @param {CodeGenConfig} config; - * @param {string[]} reservedNames - */ - constructor(config, reservedNames) { + constructor(config: CodeGenConfig, reservedNames: string[]) { super(config, reservedNames, (variants) => { const generatedVariant = (variants[0] && `${variants[0]}${this.counter++}`) || @@ -20,5 +17,3 @@ class EnumKeyResolver extends NameResolver { }); } } - -export { EnumKeyResolver }; diff --git a/src/schema-routes/schema-routes.js b/src/schema-routes/schema-routes.ts similarity index 93% rename from src/schema-routes/schema-routes.js rename to src/schema-routes/schema-routes.ts index 2d5bc1113..9ad602542 100644 --- a/src/schema-routes/schema-routes.js +++ b/src/schema-routes/schema-routes.ts @@ -1,5 +1,10 @@ import { consola } from "consola"; import lodash from "lodash"; +import type { + GenerateApiConfiguration, + ParsedRoute, +} from "../../types/index.js"; +import type { CodeGenConfig } from "../configuration.js"; import { DEFAULT_BODY_ARG_NAME, RESERVED_BODY_ARG_NAMES, @@ -7,6 +12,11 @@ import { RESERVED_PATH_ARG_NAMES, RESERVED_QUERY_ARG_NAMES, } from "../constants.js"; +import type { SchemaComponentsMap } from "../schema-components-map.js"; +import type { SchemaParserFabric } from "../schema-parser/schema-parser-fabric.js"; +import type { SchemaUtils } from "../schema-parser/schema-utils.js"; +import type { TemplatesWorker } from "../templates-worker.js"; +import type { TypeNameFormatter } from "../type-name-formatter.js"; import { generateId } from "../util/id.js"; import { SpecificArgNameResolver } from "./util/specific-arg-name-resolver.js"; @@ -19,46 +29,28 @@ const CONTENT_KIND = { TEXT: "TEXT", }; -class SchemaRoutes { - /** - * @type {CodeGenConfig} - */ - config; - /** - * @type {SchemaParserFabric} - */ - schemaParserFabric; - /** - * @type {SchemaUtils} - */ - schemaUtils; - /** - * @type {TypeNameFormatter} - */ - typeNameFormatter; - /** - * @type {SchemaComponentsMap} - */ - schemaComponentsMap; - /** - * @type {TemplatesWorker} - */ - templatesWorker; - - FORM_DATA_TYPES = []; - - routes = []; +export class SchemaRoutes { + config: CodeGenConfig; + schemaParserFabric: SchemaParserFabric; + schemaUtils: SchemaUtils; + typeNameFormatter: TypeNameFormatter; + schemaComponentsMap: SchemaComponentsMap; + templatesWorker: TemplatesWorker; + + FORM_DATA_TYPES: string[] = []; + + routes: ParsedRoute[] = []; hasSecurityRoutes = false; hasQueryRoutes = false; hasFormDataRoutes = false; - constructor({ - config, - schemaParserFabric, - schemaComponentsMap, - templatesWorker, - typeNameFormatter, - }) { + constructor( + config: CodeGenConfig, + schemaParserFabric: SchemaParserFabric, + schemaComponentsMap: SchemaComponentsMap, + templatesWorker: TemplatesWorker, + typeNameFormatter: TypeNameFormatter, + ) { this.config = config; this.schemaParserFabric = schemaParserFabric; this.schemaUtils = this.schemaParserFabric.schemaUtils; @@ -163,12 +155,14 @@ class SchemaRoutes { ); for (const paramName of paramNames) { + // @ts-expect-error TS(2339) FIXME: Property 'includes' does not exist on type 'unknow... Remove this comment to see the full error message if (paramName.includes("-")) { consola.warn("wrong query param name", paramName); } queryParams.push({ $match: paramName, + // @ts-expect-error TS(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message name: lodash.camelCase(paramName), required: true, type: "string", @@ -413,6 +407,7 @@ class SchemaRoutes { lodash.reduce( requestInfos, (acc, requestInfo, status) => { + // @ts-expect-error TS(2554) FIXME: Expected 2 arguments, but got 1. const contentTypes = this.getContentTypes([requestInfo]); return [ @@ -423,6 +418,7 @@ class SchemaRoutes { contentKind: this.getContentKind(contentTypes), type: this.schemaParserFabric.schemaUtils.safeAddNullToType( requestInfo, + // @ts-expect-error TS(2345) FIXME: Argument of type '{ requestInfo: any; parsedSchema... Remove this comment to see the full error message this.getTypeFromRequestInfo({ requestInfo, parsedSchemas, @@ -581,6 +577,7 @@ class SchemaRoutes { schema = this.getSchemaFromRequestType(requestBody); content = this.schemaParserFabric.schemaUtils.safeAddNullToType( requestBody, + // @ts-expect-error TS(2345) FIXME: Argument of type '{ requestInfo: any; parsedSchema... Remove this comment to see the full error message this.getTypeFromRequestInfo({ requestInfo: requestBody, parsedSchemas, @@ -857,7 +854,8 @@ class SchemaRoutes { const moduleName = moduleNameFirstTag && firstTag ? lodash.camelCase(firstTag) - : lodash.camelCase(lodash.compact(route.split("/"))[moduleNameIndex]); + : // @ts-expect-error TS(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message + lodash.camelCase(lodash.compact(route.split("/"))[moduleNameIndex]); let hasSecurity = !!globalSecurity?.length; if (security) { hasSecurity = security.length > 0; @@ -1114,9 +1112,7 @@ class SchemaRoutes { return modules; }, - { - $outOfModule: [], - }, + { $outOfModule: [] as ParsedRoute[] }, ); const routeGroups = lodash.reduce( @@ -1125,8 +1121,9 @@ class SchemaRoutes { if (moduleName === "$outOfModule") { acc.outOfModule = routesGroup; } else { - if (!acc.combined) acc.combined = []; - + if (!acc.combined) { + acc.combined = []; + } acc.combined.push({ moduleName, routes: routesGroup.map((route) => { @@ -1158,7 +1155,7 @@ class SchemaRoutes { } return acc; }, - {}, + {} as GenerateApiConfiguration["routes"], ); if (this.config.sortRoutes) { @@ -1175,7 +1172,7 @@ class SchemaRoutes { return routeGroups; }; - sortRoutes = (routes) => { + sortRoutes = (routes: ParsedRoute[]) => { return lodash .slice(routes) .sort((routeA, routeB) => @@ -1183,5 +1180,3 @@ class SchemaRoutes { ); }; } - -export { SchemaRoutes }; diff --git a/src/schema-routes/util/specific-arg-name-resolver.js b/src/schema-routes/util/specific-arg-name-resolver.ts similarity index 69% rename from src/schema-routes/util/specific-arg-name-resolver.js rename to src/schema-routes/util/specific-arg-name-resolver.ts index 928bcd377..8f984e444 100644 --- a/src/schema-routes/util/specific-arg-name-resolver.js +++ b/src/schema-routes/util/specific-arg-name-resolver.ts @@ -1,13 +1,10 @@ import { consola } from "consola"; +import type { CodeGenConfig } from "../../configuration.js"; import { NameResolver } from "../../util/name-resolver.js"; -class SpecificArgNameResolver extends NameResolver { +export class SpecificArgNameResolver extends NameResolver { counter = 1; - /** - * @param {CodeGenConfig} config; - * @param {string[]} reservedNames - */ - constructor(config, reservedNames) { + constructor(config: CodeGenConfig, reservedNames: string[]) { super(config, reservedNames, (variants) => { const generatedVariant = (variants[0] && `${variants[0]}${this.counter++}`) || @@ -20,5 +17,3 @@ class SpecificArgNameResolver extends NameResolver { }); } } - -export { SpecificArgNameResolver }; diff --git a/src/schema-walker.js b/src/schema-walker.js deleted file mode 100644 index 4ef92b5ca..000000000 --- a/src/schema-walker.js +++ /dev/null @@ -1,89 +0,0 @@ -import { consola } from "consola"; -import lodash from "lodash"; - -// TODO: WIP -// this class will be needed to walk by schema everywhere -class SchemaWalker { - /** @type {CodeGenConfig} */ - config; - /** @type {SwaggerSchemaResolver} */ - swaggerSchemaResolver; - /** @type {Map>} */ - schemas = new Map(); - /** @type {Map>} */ - caches = new Map(); - - constructor({ config }) { - this.config = config; - } - - /** - * @param name {string} - * @param schema {Record} - */ - addSchema = (name, schema) => { - this.schemas.set(name, structuredClone(schema)); - }; - - /** - * @param ref {string} - * @returns {any} - */ - findByRef = (ref) => { - consola.debug("try to resolve ref by path", ref); - - if (this.caches.has(ref)) { - return this.caches.get(ref); - } - - const schemas = Array.from(this.schemas.values()); - if (this._isLocalRef(ref)) { - for (const schema of schemas) { - const refData = this._getRefDataFromSchema(schema, ref); - if (refData) { - return refData; - } - } - } else if (this._isRemoteRef(ref)) { - consola.debug("remote refs not supported", ref); - return null; - } else { - const [address, path] = path.split("#"); - let swaggerSchemaObject; - - if (this.schemas.has(address)) { - swaggerSchemaObject = this.schemas.get(address); - } else { - const pathToSchema = path.resolve(process.cwd(), address); - const swaggerSchemaFile = - this.swaggerSchemaResolver.getSwaggerSchemaByPath(pathToSchema); - swaggerSchemaObject = - this.swaggerSchemaResolver.processSwaggerSchemaFile( - swaggerSchemaFile, - ); - this.schemas.set(address, swaggerSchemaObject); - } - - return this._getRefDataFromSchema(swaggerSchemaObject, path); - } - }; - - _isLocalRef = (ref) => { - return ref.startsWith("#"); - }; - - _isRemoteRef = (ref) => { - return ref.startsWith("http://") || ref.startsWith("https://"); - }; - - _getRefDataFromSchema = (schema, ref) => { - const path = ref.replace("#", "").split("/"); - const refData = lodash.get(schema, path); - if (refData) { - this.caches.set(ref, refData); - } - return refData; - }; -} - -export { SchemaWalker }; diff --git a/src/schema-walker.ts b/src/schema-walker.ts new file mode 100644 index 000000000..ee9740e7f --- /dev/null +++ b/src/schema-walker.ts @@ -0,0 +1,41 @@ +import lodash from "lodash"; +import type { CodeGenConfig } from "./configuration.js"; +import type { SwaggerSchemaResolver } from "./swagger-schema-resolver.js"; + +// TODO: WIP +// this class will be needed to walk by schema everywhere +export class SchemaWalker { + config: CodeGenConfig; + swaggerSchemaResolver: SwaggerSchemaResolver; + schemas = new Map>(); + caches = new Map>(); + + constructor( + config: CodeGenConfig, + swaggerSchemaResolver: SwaggerSchemaResolver, + ) { + this.config = config; + this.swaggerSchemaResolver = swaggerSchemaResolver; + } + + addSchema = (name: string, schema: Record) => { + this.schemas.set(name, structuredClone(schema)); + }; + + _isLocalRef = (ref: string) => { + return ref.startsWith("#"); + }; + + _isRemoteRef = (ref: string) => { + return ref.startsWith("http://") || ref.startsWith("https://"); + }; + + _getRefDataFromSchema = (schema: Record, ref: string) => { + const path = ref.replace("#", "").split("/"); + const refData = lodash.get(schema, path); + if (refData) { + this.caches.set(ref, refData); + } + return refData; + }; +} diff --git a/src/swagger-schema-resolver.js b/src/swagger-schema-resolver.ts similarity index 78% rename from src/swagger-schema-resolver.js rename to src/swagger-schema-resolver.ts index e52869d41..16e3526da 100644 --- a/src/swagger-schema-resolver.js +++ b/src/swagger-schema-resolver.ts @@ -2,42 +2,23 @@ import { consola } from "consola"; import * as yaml from "js-yaml"; import lodash from "lodash"; import * as swagger2openapi from "swagger2openapi"; +import type { CodeGenConfig } from "./configuration.js"; +import type { FileSystem } from "./util/file-system.js"; import { Request } from "./util/request.js"; -class SwaggerSchemaResolver { - /** - * @type {CodeGenConfig} - */ - config; - /** - * @type {FileSystem} - */ - fileSystem; - /** - * @type {Request} - */ - request; - - constructor({ config, fileSystem }) { +export class SwaggerSchemaResolver { + config: CodeGenConfig; + fileSystem: FileSystem; + request: Request; + + constructor(config: CodeGenConfig, fileSystem: FileSystem) { this.config = config; this.fileSystem = fileSystem; this.request = new Request(config); } - /** - * - * @returns {Promise<{usageSchema: Record, originalSchema: Record}>} - */ async create() { - const { - spec, - patch, - input, - url, - disableStrictSSL, - disableProxy, - authorizationToken, - } = this.config; + const { spec, patch, input, url, authorizationToken } = this.config; if (this.config.spec) { return await this.convertSwaggerObject(spec, { patch }); @@ -46,8 +27,6 @@ class SwaggerSchemaResolver { const swaggerSchemaFile = await this.fetchSwaggerSchemaFile( input, url, - disableStrictSSL, - disableProxy, authorizationToken, ); const swaggerSchemaObject = @@ -55,13 +34,13 @@ class SwaggerSchemaResolver { return await this.convertSwaggerObject(swaggerSchemaObject, { patch }); } - /** - * - * @param swaggerSchema {Record} - * @param converterOptions {{ patch?: boolean }} - * @returns {Promise<{ usageSchema: Record, originalSchema: Record}>} - */ - convertSwaggerObject(swaggerSchema, converterOptions) { + convertSwaggerObject( + swaggerSchema: Record, + converterOptions: { patch?: boolean }, + ): Promise<{ + usageSchema: Record; + originalSchema: Record; + }> { return new Promise((resolve) => { const result = structuredClone(swaggerSchema); result.info = lodash.merge( @@ -90,7 +69,7 @@ class SwaggerSchemaResolver { lodash.get(options, "openapi"), ); if (!parsedSwaggerSchema && err) { - throw new Error(err); + throw err; } this.config.update({ convertedFromSwagger2: true }); resolve({ @@ -108,17 +87,15 @@ class SwaggerSchemaResolver { }); } - getSwaggerSchemaByPath = (pathToSwagger) => { + getSwaggerSchemaByPath = (pathToSwagger: string) => { consola.info(`try to get swagger by path "${pathToSwagger}"`); return this.fileSystem.getFileContent(pathToSwagger); }; async fetchSwaggerSchemaFile( - pathToSwagger, - urlToSwagger, - disableStrictSSL, - disableProxy, - authToken, + pathToSwagger: string, + urlToSwagger: string, + authToken: string, ) { if (this.fileSystem.pathIsExist(pathToSwagger)) { return this.getSwaggerSchemaByPath(pathToSwagger); @@ -126,13 +103,11 @@ class SwaggerSchemaResolver { consola.info(`try to get swagger by URL "${urlToSwagger}"`); return await this.request.download({ url: urlToSwagger, - disableStrictSSL, authToken, - disableProxy, }); } - processSwaggerSchemaFile(file) { + processSwaggerSchemaFile(file: string) { if (typeof file !== "string") return file; try { @@ -189,5 +164,3 @@ class SwaggerSchemaResolver { }); } } - -export { SwaggerSchemaResolver }; diff --git a/src/templates-worker.js b/src/templates-worker.ts similarity index 78% rename from src/templates-worker.js rename to src/templates-worker.ts index 700c6230f..a547201da 100644 --- a/src/templates-worker.js +++ b/src/templates-worker.ts @@ -3,31 +3,28 @@ import * as url from "node:url"; import { consola } from "consola"; import * as Eta from "eta"; import lodash from "lodash"; - -class TemplatesWorker { - /** - * @type {CodeGenConfig} - */ - config; - /** - * @type {FileSystem} - */ - fileSystem; - - getRenderTemplateData; - - constructor({ config, fileSystem, getRenderTemplateData }) { +import type { CodeGenProcess } from "./code-gen-process.js"; +import type { CodeGenConfig } from "./configuration.js"; +import type { FileSystem } from "./util/file-system.js"; + +export class TemplatesWorker { + config: CodeGenConfig; + fileSystem: FileSystem; + getRenderTemplateData: CodeGenProcess["getRenderTemplateData"]; + + constructor( + config: CodeGenConfig, + fileSystem: FileSystem, + getRenderTemplateData: CodeGenProcess["getRenderTemplateData"], + ) { this.config = config; this.fileSystem = fileSystem; this.getRenderTemplateData = getRenderTemplateData; } - /** - * - * @param config {CodeGenConfig} - * @returns {CodeGenConfig.templatePaths} - */ - getTemplatePaths = (config) => { + getTemplatePaths = ( + config: CodeGenConfig, + ): CodeGenConfig["templatePaths"] => { const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); const baseTemplatesPath = path.resolve(__dirname, "../templates/base"); const defaultTemplatesPath = path.resolve( @@ -41,9 +38,7 @@ class TemplatesWorker { const originalTemplatesPath = config.modular ? modularTemplatesPath : defaultTemplatesPath; - const customTemplatesPath = - (config.templates && path.resolve(process.cwd(), config.templates)) || - null; + const customTemplatesPath = path.resolve(process.cwd(), config.templates); return { /** `templates/base` */ @@ -59,13 +54,13 @@ class TemplatesWorker { }; }; - cropExtension = (path) => + cropExtension = (path: string) => this.config.templateExtensions.reduce( (path, ext) => (path.endsWith(ext) ? path.replace(ext, "") : path), path, ); - getTemplateFullPath = (path_, fileName) => { + getTemplateFullPath = (path_: string, fileName: string) => { const raw = path.resolve(path_, "./", this.cropExtension(fileName)); const pathVariants = this.config.templateExtensions.map( (extension) => `${raw}${extension}`, @@ -76,7 +71,7 @@ class TemplatesWorker { ); }; - requireFnFromTemplate = async (packageOrPath) => { + requireFnFromTemplate = async (packageOrPath: string) => { const isPath = packageOrPath.startsWith("./") || packageOrPath.startsWith("../"); @@ -93,7 +88,7 @@ class TemplatesWorker { return await import(packageOrPath); }; - getTemplate = ({ fileName, name, path }) => { + getTemplate = (name: string, fileName: string, path?: string) => { const { templatePaths } = this.config; if (path) { @@ -146,7 +141,7 @@ class TemplatesWorker { return fileContent; }; - getTemplates = ({ templatePaths }) => { + getTemplates = ({ templatePaths }: CodeGenConfig) => { if (templatePaths.custom) { consola.info( `try to read templates from directory "${templatePaths.custom}"`, @@ -155,15 +150,15 @@ class TemplatesWorker { return lodash.reduce( this.config.templateInfos, - (acc, { fileName, name }) => ({ + (acc, { name, fileName }) => ({ ...acc, - [name]: this.getTemplate({ fileName, name }), + [name]: this.getTemplate(name, fileName), }), {}, ); }; - findTemplateWithExt = (path) => { + findTemplateWithExt = (path: string) => { const raw = this.cropExtension(path); const pathVariants = this.config.templateExtensions.map( (extension) => `${raw}${extension}`, @@ -171,7 +166,7 @@ class TemplatesWorker { return pathVariants.find((variant) => this.fileSystem.pathIsExist(variant)); }; - getTemplateContent = (path_) => { + getTemplateContent = (path_: string) => { const foundTemplatePathKey = lodash .keys(this.config.templatePaths) .find((key) => path_.startsWith(`@${key}`)); @@ -209,13 +204,11 @@ class TemplatesWorker { return ""; }; - /** - * @param template - * @param configuration - * @param options - * @returns {Promise} - */ - renderTemplate = (template, configuration, options) => { + renderTemplate = ( + template: string, + configuration: object, + options: object = {}, + ) => { if (!template) return ""; return Eta.render( @@ -226,8 +219,12 @@ class TemplatesWorker { }, { async: false, - ...(options || {}), - includeFile: (path, configuration, options) => { + ...options, + includeFile: ( + path: string, + configuration: object, + options: object = {}, + ) => { return this.renderTemplate( this.getTemplateContent(path), configuration, @@ -238,5 +235,3 @@ class TemplatesWorker { ); }; } - -export { TemplatesWorker }; diff --git a/src/translators/javascript.js b/src/translators/javascript.ts similarity index 89% rename from src/translators/javascript.js rename to src/translators/javascript.ts index b0692e0a6..e7e2920c9 100644 --- a/src/translators/javascript.js +++ b/src/translators/javascript.ts @@ -1,12 +1,8 @@ import * as typescript from "typescript"; -import { Translator } from "./translator.js"; +import { Translator, type TranslatorIO } from "./translator.js"; -class JavascriptTranslator extends Translator { - /** - * @param {TranslatorIO} input - * @returns {Record} - */ - compileTSCode = (input) => { +export class JavascriptTranslator extends Translator { + compileTSCode = (input: TranslatorIO): Record => { const fileNameFull = `${input.fileName}${input.fileExtension}`; const output = {}; const host = typescript.createCompilerHost( @@ -82,5 +78,3 @@ class JavascriptTranslator extends Translator { ]; }; } - -export { JavascriptTranslator }; diff --git a/src/translators/translator.js b/src/translators/translator.js deleted file mode 100644 index 43f6d3c23..000000000 --- a/src/translators/translator.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @typedef {{ fileName: string, fileExtension: string, fileContent: string }} TranslatorIO - */ - -class Translator { - /** @type {CodeGenConfig} */ - config; - /** @type {CodeFormatter} */ - codeFormatter; - - /** - * @param codeGenProcess - */ - constructor(codeGenProcess) { - this.config = codeGenProcess.config; - this.codeFormatter = codeGenProcess.codeFormatter; - } - - /** - * - * @param input {TranslatorIO} - * @return {Promise} - */ - translate(input) { - throw new Error("not implemented"); - } -} - -export { Translator }; diff --git a/src/translators/translator.ts b/src/translators/translator.ts new file mode 100644 index 000000000..cf869371e --- /dev/null +++ b/src/translators/translator.ts @@ -0,0 +1,22 @@ +import type { CodeFormatter } from "../code-formatter.js"; +import type { CodeGenConfig } from "../configuration.js"; + +export interface TranslatorIO { + fileName: string; + fileExtension: string; + fileContent: string; +} + +export class Translator { + config: CodeGenConfig; + codeFormatter: CodeFormatter; + + constructor(config: CodeGenConfig, codeFormatter: CodeFormatter) { + this.config = config; + this.codeFormatter = codeFormatter; + } + + translate(_input: TranslatorIO): Promise { + throw new Error("not implemented"); + } +} diff --git a/src/type-name-formatter.js b/src/type-name-formatter.ts similarity index 77% rename from src/type-name-formatter.js rename to src/type-name-formatter.ts index edcf23a91..8704c2dad 100644 --- a/src/type-name-formatter.js +++ b/src/type-name-formatter.ts @@ -1,26 +1,18 @@ import { consola } from "consola"; import lodash from "lodash"; +import type { CodeGenConfig } from "./configuration.js"; -/** - * @typedef {"enum-key" | "type-name"} FormattingSchemaType - */ +type FormattingSchemaType = "enum-key" | "type-name"; -class TypeNameFormatter { - /** @type {Map} */ - formattedModelNamesMap = new Map(); - /** @type {CodeGenConfig} */ - config; +export class TypeNameFormatter { + formattedModelNamesMap = new Map(); + config: CodeGenConfig; - constructor({ config }) { + constructor(config: CodeGenConfig) { this.config = config; } - /** - * @param name - * @param options {{ type?: FormattingSchemaType }} - * @return {string} - */ - format = (name, options = {}) => { + format = (name: string, options: { type?: FormattingSchemaType } = {}) => { const schemaType = options.type ?? "type-name"; const typePrefix = @@ -62,14 +54,12 @@ class TypeNameFormatter { return formattedResultName; }; - isValidName = (name) => /^([A-Za-z$_]{1,})$/g.test(name); + isValidName = (name: string) => /^([A-Za-z$_]{1,})$/g.test(name); - /** - * @param name - * @param options {{ type?: FormattingSchemaType }} - * @return {string} - */ - fixModelName = (name, options) => { + fixModelName = ( + name: string, + options: { type?: FormattingSchemaType }, + ): string => { const { type } = options || {}; if (!this.isValidName(name)) { @@ -96,5 +86,3 @@ class TypeNameFormatter { return name; }; } - -export { TypeNameFormatter }; diff --git a/src/util/file-system.js b/src/util/file-system.ts similarity index 83% rename from src/util/file-system.js rename to src/util/file-system.ts index 35b831bb7..20a78743e 100644 --- a/src/util/file-system.js +++ b/src/util/file-system.ts @@ -2,7 +2,6 @@ import * as fs from "node:fs"; import * as path from "node:path"; import * as url from "node:url"; import { consola } from "consola"; -import lodash from "lodash"; const FILE_PREFIX = `/* eslint-disable */ /* tslint:disable */ @@ -17,16 +16,16 @@ const FILE_PREFIX = `/* eslint-disable */ `; -class FileSystem { - getFileContent = (path) => { +export class FileSystem { + getFileContent = (path: string) => { return fs.readFileSync(path, { encoding: "utf8" }); }; - readDir = (path) => { + readDir = (path: string) => { return fs.readdirSync(path); }; - pathIsDir = (path) => { + pathIsDir = (path: string) => { if (!path) return false; try { @@ -37,7 +36,7 @@ class FileSystem { } }; - cropExtension = (fileName) => { + cropExtension = (fileName: string) => { const fileNameParts = fileName.split("."); if (fileNameParts.length > 1) { @@ -47,7 +46,7 @@ class FileSystem { return fileNameParts.join("."); }; - removeDir = (path) => { + removeDir = (path: string) => { try { if (typeof fs.rmSync === "function") { fs.rmSync(path, { recursive: true }); @@ -59,7 +58,7 @@ class FileSystem { } }; - createDir = (path) => { + createDir = (path: string) => { try { fs.mkdirSync(path, { recursive: true }); } catch (e) { @@ -67,12 +66,12 @@ class FileSystem { } }; - cleanDir = (path) => { + cleanDir = (path: string) => { this.removeDir(path); this.createDir(path); }; - pathIsExist = (path) => { + pathIsExist = (path: string) => { return !!path && fs.existsSync(path); }; @@ -81,8 +80,6 @@ class FileSystem { const absolutePath = path.resolve(__dirname, path_, `./${fileName}`); const fileContent = `${withPrefix ? FILE_PREFIX : ""}${content}`; - return fs.writeFileSync(absolutePath, fileContent, lodash.noop); + return fs.writeFileSync(absolutePath, fileContent); }; } - -export { FileSystem }; diff --git a/src/util/id.js b/src/util/id.ts similarity index 53% rename from src/util/id.js rename to src/util/id.ts index d5dcc7b0c..d63ee17f5 100644 --- a/src/util/id.js +++ b/src/util/id.ts @@ -2,6 +2,4 @@ import * as nanoid from "nanoid"; const ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789"; -const generateId = nanoid.customAlphabet(ALPHABET, 12); - -export { generateId }; +export const generateId = nanoid.customAlphabet(ALPHABET, 12); diff --git a/src/util/internal-case.js b/src/util/internal-case.ts similarity index 59% rename from src/util/internal-case.js rename to src/util/internal-case.ts index 8cfc0d9e0..bb9857096 100644 --- a/src/util/internal-case.js +++ b/src/util/internal-case.ts @@ -1,7 +1,5 @@ import lodash from "lodash"; -function internalCase(value) { +export function internalCase(value: string) { return lodash.camelCase(lodash.lowerCase(value)); } - -export { internalCase }; diff --git a/src/util/name-resolver.js b/src/util/name-resolver.ts similarity index 70% rename from src/util/name-resolver.js rename to src/util/name-resolver.ts index 49dcdf6fe..b6e1b2964 100644 --- a/src/util/name-resolver.js +++ b/src/util/name-resolver.ts @@ -1,27 +1,26 @@ import { consola } from "consola"; import lodash from "lodash"; +import type { CodeGenConfig } from "../configuration.js"; -class NameResolver { - reservedNames = []; - getFallbackName = null; +type Resolver = (reserved: string[], extras?: string[]) => string; - /** @type {CodeGenConfig} */ - config; +export class NameResolver { + reservedNames: string[] = []; + getFallbackName: Resolver; - /** - * @param {CodeGenConfig} config; - * @param {string[]} reservedNames - */ - constructor(config, reservedNames, getFallbackName) { + config: CodeGenConfig; + + constructor( + config: CodeGenConfig, + reservedNames: string[], + getFallbackName: Resolver, + ) { this.config = config; this.getFallbackName = getFallbackName; this.reserve(reservedNames); } - /** - * @param {string[]} names - */ - reserve(names) { + reserve(names: string[]) { const fixedNames = lodash.uniq(lodash.compact(names)); for (const name of fixedNames) { if (this.reservedNames.indexOf(name) === -1) { @@ -30,33 +29,31 @@ class NameResolver { } } - unreserve(names) { + unreserve(names: string[]) { this.reservedNames.filter( (reservedName) => !names.some((name) => name === reservedName), ); } - isReserved(name) { + isReserved(name: string) { return this.reservedNames.some((reservedName) => reservedName === name); } - /** - * - * @param {(string[])} variants - * @param {(reserved: string[]) => string)} [resolver] - * @param {any} [extras] - * @returns {string | null} - */ - resolve(variants, resolver, extras, shouldReserve = true) { + resolve( + variants: string[], + resolver?: Resolver, + extras?: string[], + shouldReserve = true, + ): string | null { if (typeof resolver === "function") { - let usageName = null; + let usageName: string | null = null; while (usageName === null) { const variant = resolver(variants, extras); if (variant === undefined) { consola.warn( "unable to resolve name. current reserved names: ", - this.reservedNames, + ...this.reservedNames, ); return null; } @@ -70,7 +67,7 @@ class NameResolver { } if (Array.isArray(variants)) { - let usageName = null; + let usageName: string | null = null; const uniqVariants = lodash.uniq(lodash.compact(variants)); for (const variant of uniqVariants) { @@ -86,17 +83,15 @@ class NameResolver { consola.debug( "trying to resolve name with using fallback name generator using variants", - variants, + ...variants, ); return this.resolve(variants, this.getFallbackName, extras); } consola.debug( "problem with reserving names. current reserved names: ", - this.reservedNames, + ...this.reservedNames, ); return null; } } - -export { NameResolver }; diff --git a/src/util/object-assign.js b/src/util/object-assign.js deleted file mode 100644 index cdeda1870..000000000 --- a/src/util/object-assign.js +++ /dev/null @@ -1,16 +0,0 @@ -import lodash from "lodash"; - -const objectAssign = (target, updaterFn) => { - if (!updaterFn) return; - const update = - typeof updaterFn === "function" ? updaterFn(target) : updaterFn; - const undefinedKeys = lodash - .map(update, (value, key) => value === undefined && key) - .filter(Boolean); - Object.assign(target, lodash.merge(target, update)); - for (const key of undefinedKeys) { - target[key] = undefined; - } -}; - -export { objectAssign }; diff --git a/src/util/object-assign.ts b/src/util/object-assign.ts new file mode 100644 index 000000000..320e9be26 --- /dev/null +++ b/src/util/object-assign.ts @@ -0,0 +1,15 @@ +import lodash from "lodash"; + +type Updater = (target: unknown) => unknown; + +export const objectAssign = (target: object, updater: Updater | unknown) => { + if (!updater) return; + const update = typeof updater === "function" ? updater(target) : updater; + const undefinedKeys = lodash + .map(update, (value, key) => value === undefined && key) + .filter((key) => typeof key === "string"); + Object.assign(target, lodash.merge(target, update)); + for (const key of undefinedKeys) { + target[key] = undefined; + } +}; diff --git a/src/util/pascal-case.js b/src/util/pascal-case.ts similarity index 61% rename from src/util/pascal-case.js rename to src/util/pascal-case.ts index a43176e8d..8e1b7fc10 100644 --- a/src/util/pascal-case.js +++ b/src/util/pascal-case.ts @@ -1,7 +1,5 @@ import lodash from "lodash"; -function pascalCase(value) { +export function pascalCase(value: string) { return lodash.upperFirst(lodash.camelCase(value)); } - -export { pascalCase }; diff --git a/src/util/random.js b/src/util/random.js deleted file mode 100644 index 31fef7483..000000000 --- a/src/util/random.js +++ /dev/null @@ -1,11 +0,0 @@ -const getRandomFloat = (min = 0, max = 1) => { - return Math.random() * (max - min) + min; -}; - -const getRandomInt = (min = 0, max = 1) => { - if (min === max) return min; - - return Math.round(getRandomFloat(min, max)); -}; - -export { getRandomInt, getRandomFloat }; diff --git a/src/util/random.ts b/src/util/random.ts new file mode 100644 index 000000000..9f536a838 --- /dev/null +++ b/src/util/random.ts @@ -0,0 +1,9 @@ +export const getRandomFloat = (min = 0, max = 1) => { + return Math.random() * (max - min) + min; +}; + +export const getRandomInt = (min = 0, max = 1) => { + if (min === max) return min; + + return Math.round(getRandomFloat(min, max)); +}; diff --git a/src/util/request.js b/src/util/request.js deleted file mode 100644 index 42abe891d..000000000 --- a/src/util/request.js +++ /dev/null @@ -1,59 +0,0 @@ -import { consola } from "consola"; -import lodash from "lodash"; - -class Request { - /** - * @type {CodeGenConfig} - */ - config; - - constructor(config) { - this.config = config; - } - - /** - * @param url {string} - * @param disableStrictSSL - * @param authToken - * @param options {Partial} - * @return {Promise} - */ - async download({ url, disableStrictSSL, authToken, ...options }) { - /** - * @type {Partial} - */ - const requestOptions = {}; - - if (disableStrictSSL && !url.startsWith("http://")) { - const undiciGlobalDispatcher = - global[Symbol.for("undici.globalDispatcher.1")]; - if (!undiciGlobalDispatcher) { - throw new Error("Could not find the global Undici dispatcher"); - } - const newDispatcher = new undiciGlobalDispatcher.constructor({ - connect: { - rejectUnauthorized: false, - }, - }); - global[unidiciGlobalDispatcherSymbol] = newDispatcher; - } - if (authToken) { - requestOptions.headers = { - Authorization: authToken, - }; - } - - lodash.merge(requestOptions, options, this.config.requestOptions); - - try { - const response = await fetch(url, requestOptions); - return await response.text(); - } catch (error) { - const message = `error while fetching data from URL "${url}"`; - consola.error(message, "response" in error ? error.response : error); - return message; - } - } -} - -export { Request }; diff --git a/src/util/request.ts b/src/util/request.ts new file mode 100644 index 000000000..7efcf1e0e --- /dev/null +++ b/src/util/request.ts @@ -0,0 +1,40 @@ +import { consola } from "consola"; +import lodash from "lodash"; +import type { CodeGenConfig } from "../configuration.js"; + +export class Request { + config: CodeGenConfig; + + constructor(config: CodeGenConfig) { + this.config = config; + } + + async download({ + url, + authToken, + ...options + }: { + url: string; + authToken?: string; + options?: Partial; + }) { + const requestOptions: Partial = {}; + + if (authToken) { + requestOptions.headers = { + Authorization: authToken, + }; + } + + lodash.merge(requestOptions, options, this.config.requestOptions); + + try { + const response = await fetch(url, requestOptions); + return await response.text(); + } catch (error) { + const message = `error while fetching data from URL "${url}"`; + consola.error(message, error); + return message; + } + } +} diff --git a/src/util/sort-by-property.js b/src/util/sort-by-property.js deleted file mode 100644 index 82dd85a54..000000000 --- a/src/util/sort-by-property.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @param propertyName {string} - * @returns {(o1: Record, o2: Record) => 1 | -1 | 0} - */ -const sortByProperty = (propertyName) => (o1, o2) => { - if (o1[propertyName] > o2[propertyName]) { - return 1; - } - if (o1[propertyName] < o2[propertyName]) { - return -1; - } - return 0; -}; - -export { sortByProperty }; diff --git a/src/util/sort-by-property.ts b/src/util/sort-by-property.ts new file mode 100644 index 000000000..eb69bf39b --- /dev/null +++ b/src/util/sort-by-property.ts @@ -0,0 +1,11 @@ +export const sortByProperty = + (propertyName: string) => + (o1: Record, o2: Record): 1 | -1 | 0 => { + if (o1[propertyName] > o2[propertyName]) { + return 1; + } + if (o1[propertyName] < o2[propertyName]) { + return -1; + } + return 0; + }; diff --git a/tests/spec/deprecated/basic.test.ts b/tests/spec/deprecated/basic.test.ts index 0109fc583..faa80f8e3 100644 --- a/tests/spec/deprecated/basic.test.ts +++ b/tests/spec/deprecated/basic.test.ts @@ -23,7 +23,6 @@ describe("basic", async () => { input: path.resolve(import.meta.dirname, "schema.json"), output: tmpdir, silent: true, - queryParamsWithBrackets: true, }); const content = await fs.readFile(path.join(tmpdir, "schema.ts"), { diff --git a/tests/utils.ts b/tests/utils.ts index 3178ec1a3..3211b6c48 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -1,8 +1,13 @@ import * as fs from "node:fs/promises"; import * as path from "node:path"; +interface Schema { + name: string; + filePath: string; +} + export async function collectAllSchemas() { - const schemas = []; + const schemas: Schema[] = []; const schemaPath = path.join(import.meta.dirname, "fixtures", "schemas"); const schemaFiles = await fs.readdir(schemaPath, { recursive: true }); for (const schemaFile of schemaFiles) { diff --git a/tsconfig.json b/tsconfig.json index 61fe4989c..250ec986a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,10 +4,11 @@ "@tsconfig/node18/tsconfig.json" ], "compilerOptions": { - "checkJs": false, + "exactOptionalPropertyTypes": false, "module": "NodeNext", "moduleResolution": "NodeNext", "noEmit": true, + "noPropertyAccessFromIndexSignature": false, "resolveJsonModule": true }, "exclude": ["dist"] diff --git a/tsup.config.ts b/tsup.config.ts index ce22a735b..d93df8fb1 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -2,15 +2,10 @@ import { defineConfig } from "tsup"; export default defineConfig({ entry: { - lib: "src/index.js", + lib: "src/index.ts", cli: "index.ts", }, clean: true, - dts: { - entry: { - types: "types/index.d.ts", - }, - }, format: ["esm", "cjs"], minify: true, sourcemap: true, diff --git a/types/index.d.ts b/types/index.ts similarity index 97% rename from types/index.d.ts rename to types/index.ts index 587b3a003..c36f5e3ea 100644 --- a/types/index.d.ts +++ b/types/index.ts @@ -84,14 +84,6 @@ interface GenerateApiParamsBase { * users operation's first tag for route separation */ moduleNameFirstTag?: boolean; - /** - * disabled SSL check - */ - disableStrictSSL?: boolean; - /** - * disabled Proxy - */ - disableProxy?: boolean; /** * generate separated files for http client, data contracts, and routes (default: false) */ @@ -178,14 +170,20 @@ interface GenerateApiParamsBase { typeSuffix?: string; /** extra configuration for extracting type names operations */ - extractingOptions?: Partial; + extractingOptions?: ExtractingOptions; /** configuration for fetching swagger schema requests */ - requestOptions?: null | Partial; + requestOptions?: Partial; /** ts compiler configuration object (for --to-js option) */ compilerTsConfig?: Record; + /** extract all enums from inline interface\\type content to typescript enum construction */ + extractResponses?: boolean; + + /** generate array types as Array (by default Type[]) */ + anotherArrayType?: boolean; + /** * custom ts->* translator * do not use constructor args, it can break functionality of this property, just send class reference @@ -550,7 +548,7 @@ type MAIN_SCHEMA_TYPES = | SCHEMA_TYPES.OBJECT | SCHEMA_TYPES.ENUM; -type ExtractingOptions = { +export type ExtractingOptions = { requestBodySuffix: string[]; responseBodySuffix: string[]; responseErrorSuffix: string[]; @@ -595,7 +593,7 @@ export interface GenerateApiConfiguration { }; config: { input: string; - output: string; + output: string | false; url: string; spec: unknown; fileName: string; @@ -624,8 +622,6 @@ export interface GenerateApiConfiguration { moduleNameIndex: number; moduleNameFirstTag: boolean; extraTemplates: { name: string; path: string }[]; - disableStrictSSL: boolean; - disableProxy: boolean; extractRequestParams: boolean; unwrapResponseData: boolean; sortTypes: boolean; @@ -645,13 +641,14 @@ export interface GenerateApiConfiguration { extractResponseBody: boolean; extractResponseError: boolean; extractEnums: boolean; + extractResponses: boolean; fixInvalidTypeNamePrefix: string; fixInvalidEnumKeyPrefix: string; defaultResponseType: string; toJS: boolean; disableThrowOnError: boolean; silent: boolean; - hooks: Hooks; + hooks: Partial; enumNamesAsValues: boolean; version: string; compilerTsConfig: Record; @@ -701,7 +698,7 @@ export interface GenerateApiConfiguration { routes: ParsedRoute[]; }[]; }; - requestOptions?: null | Partial; + requestOptions?: Partial; utils: { formatDescription: (description: string, inline?: boolean) => string; internalCase: (value: string) => string;