diff --git a/README.md b/README.md index 984a53bc..ba5dad7f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +### This is a fork of the original project [openapi-codegen](https://github.com/fabien0102/openapi-codegen) by Fabien BERNARD. +


@@ -33,7 +35,7 @@ 1. **Initialize the generator** ```bash - npx @openapi-codegen/cli init + npx @sschw/openapi-codegen-cli init ``` @@ -167,11 +169,11 @@ Everything is typed and self-documented, but just in case, you can find here exa ```ts // openapi-codegen.config.ts -import { defineConfig } from "@openapi-codegen/cli"; +import { defineConfig } from "@sschw/openapi-codegen-cli"; import { generateSchemaTypes, generateReactQueryComponents, -} from "@openapi-codegen/typescript"; +} from "@sschw/openapi-codegen-typescript"; export default defineConfig({ example: { @@ -207,7 +209,7 @@ export default defineConfig({ ### Plugins -the `@openapi-codegen/cli` supports these generator plugins: +the `@sschw/openapi-codegen-cli` supports these generator plugins: #### **generateSchemaTypes** (frontend/backend) diff --git a/cli/README.md b/cli/README.md index 0ace8a70..59edf609 100644 --- a/cli/README.md +++ b/cli/README.md @@ -1,3 +1,5 @@ +### This is a fork of the original project [openapi-codegen](https://github.com/fabien0102/openapi-codegen) by Fabien BERNARD. + # OpenAPI Codegen ## Getting started @@ -6,11 +8,11 @@ ```ts // openapi-codegen.config.ts -import { defineConfig } from "@openapi-codegen/cli"; +import { defineConfig } from "@sschw/openapi-codegen-cli"; import { generateSchemaTypes, generateReactQueryComponents, -} from "@openapi-codegen/typescript"; +} from "@sschw/openapi-codegen-typescript"; export default defineConfig({ example: { diff --git a/cli/package.json b/cli/package.json index 1a3b2328..4a46ba81 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,5 +1,5 @@ { - "name": "@openapi-codegen/cli", + "name": "@sschw/openapi-codegen-cli", "version": "3.0.1", "description": "OpenAPI Codegen cli", "main": "lib/index.js", @@ -9,7 +9,8 @@ "openapi-codegen": "lib/cli.js" }, "repository": { - "url": "https://github.com/fabien0102/openapi-codegen", + "type": "git", + "url": "git+https://github.com/sschw/openapi-codegen.git", "directory": "cli" }, "publishConfig": { diff --git a/cli/src/commands/InitCommand.ts b/cli/src/commands/InitCommand.ts index ed5b64cb..60fb5197 100644 --- a/cli/src/commands/InitCommand.ts +++ b/cli/src/commands/InitCommand.ts @@ -94,7 +94,7 @@ export class InitCommand extends Command { return { isExistingConfig: false, sourceFile, - importModules: ["@openapi-codegen/cli"], + importModules: ["@sschw/openapi-codegen-cli"], }; } @@ -236,22 +236,22 @@ export class InitCommand extends Command { path.join(process.cwd(), "package.json") ); const hasCli = this.hasDependencyInstalled( - "@openapi-codegen/cli", + "@sschw/openapi-codegen-cli", packageJson ); const hasTsPlugin = this.hasDependencyInstalled( - "@openapi-codegen/typescript", + "@sschw/openapi-codegen-typescript", packageJson ); if (!hasCli && !hasTsPlugin) { - nextSteps.push("npm install -D @openapi-codegen/{cli,typescript}"); + nextSteps.push("npm install -D @sschw/openapi-codegen-{cli,typescript}"); } else if (!hasCli) { - nextSteps.push("npm install -D @openapi-codegen/cli"); + nextSteps.push("npm install -D @sschw/openapi-codegen-cli"); } else if (!hasTsPlugin) { - nextSteps.push("npm install -D @openapi-codegen/typescript"); + nextSteps.push("npm install -D @sschw/openapi-codegen-typescript"); } } catch { - nextSteps.push("npm install -D @openapi-codegen/{cli,typescript}"); + nextSteps.push("npm install -D @sschw/openapi-codegen-{cli,typescript}"); } nextSteps.push(`npx openapi-codegen gen ${namespace}`); diff --git a/cli/src/core/generateConfigProperty.ts b/cli/src/core/generateConfigProperty.ts index e3db7e29..78a72d06 100644 --- a/cli/src/core/generateConfigProperty.ts +++ b/cli/src/core/generateConfigProperty.ts @@ -295,21 +295,21 @@ export function getImports(plugin: Plugin): Import[] { case "typescript/fetch": return [ { - module: "@openapi-codegen/typescript", + module: "@sschw/openapi-codegen-typescript", namedImports: ["generateSchemaTypes", "generateFetchers"], }, ]; case "typescript/types-only": return [ { - module: "@openapi-codegen/typescript", + module: "@sschw/openapi-codegen-typescript", namedImports: ["generateSchemaTypes"], }, ]; case "typescript/react-query": return [ { - module: "@openapi-codegen/typescript", + module: "@sschw/openapi-codegen-typescript", namedImports: ["generateSchemaTypes", "generateReactQueryComponents"], }, ]; diff --git a/cli/src/core/updateConfig.test.ts b/cli/src/core/updateConfig.test.ts index f1988cbc..b2f33a9f 100644 --- a/cli/src/core/updateConfig.test.ts +++ b/cli/src/core/updateConfig.test.ts @@ -8,7 +8,7 @@ describe("updateConfig", () => { ); it("should add import statement if not already existing", () => { - const sourceText = `import { defineConfig } from "@openapi-codegen/cli"; + const sourceText = `import { defineConfig } from "@sschw/openapi-codegen-cli"; // This comment should stay export default defineConfig({})`; @@ -20,19 +20,19 @@ describe("updateConfig", () => { const transformedSourceFile = updateConfig({ sourceFile, - existingImports: ["@openapi-codegen/cli"], + existingImports: ["@sschw/openapi-codegen-cli"], importsToInsert: [ { namedImports: ["generateReactQueryComponents", "generateSchemaTypes"], - module: "@openapi-codegen/typescript", + module: "@sschw/openapi-codegen-typescript", }, ], configProperty, }); expect(printer.printFile(transformedSourceFile)).toMatchInlineSnapshot(` - "import { generateReactQueryComponents, generateSchemaTypes } from "@openapi-codegen/typescript"; - import { defineConfig } from "@openapi-codegen/cli"; + "import { generateReactQueryComponents, generateSchemaTypes } from "@sschw/openapi-codegen-typescript"; + import { defineConfig } from "@sschw/openapi-codegen-cli"; // This comment should stay export default defineConfig({ test: {} @@ -42,8 +42,8 @@ describe("updateConfig", () => { }); it("should update import statement if already existing", () => { - const sourceText = `import { defineConfig } from "@openapi-codegen/cli"; - import { renameComponent } from "@openapi-codegen/typescript"; + const sourceText = `import { defineConfig } from "@sschw/openapi-codegen-cli"; + import { renameComponent } from "@sschw/openapi-codegen-typescript"; export default defineConfig({ plop: {} @@ -56,19 +56,22 @@ describe("updateConfig", () => { const transformedSourceFile = updateConfig({ sourceFile, - existingImports: ["@openapi-codegen/cli", "@openapi-codegen/typescript"], + existingImports: [ + "@sschw/openapi-codegen-cli", + "@sschw/openapi-codegen-typescript", + ], importsToInsert: [ { namedImports: ["generateReactQueryComponents", "generateSchemaTypes"], - module: "@openapi-codegen/typescript", + module: "@sschw/openapi-codegen-typescript", }, ], configProperty, }); expect(printer.printFile(transformedSourceFile)).toMatchInlineSnapshot(` - "import { defineConfig } from "@openapi-codegen/cli"; - import { renameComponent, generateReactQueryComponents, generateSchemaTypes } from "@openapi-codegen/typescript"; + "import { defineConfig } from "@sschw/openapi-codegen-cli"; + import { renameComponent, generateReactQueryComponents, generateSchemaTypes } from "@sschw/openapi-codegen-typescript"; export default defineConfig({ plop: {}, test: {} @@ -78,8 +81,8 @@ describe("updateConfig", () => { }); it("should not create duplicates imports", () => { - const sourceText = `import { defineConfig } from "@openapi-codegen/cli"; - import { renameComponent, generateReactQueryComponents } from "@openapi-codegen/typescript"; + const sourceText = `import { defineConfig } from "@sschw/openapi-codegen-cli"; + import { renameComponent, generateReactQueryComponents } from "@sschw/openapi-codegen-typescript"; export default defineConfig({})`; const sourceFile = ts.createSourceFile( @@ -90,19 +93,22 @@ describe("updateConfig", () => { const transformedSourceFile = updateConfig({ sourceFile, - existingImports: ["@openapi-codegen/cli", "@openapi-codegen/typescript"], + existingImports: [ + "@sschw/openapi-codegen-cli", + "@sschw/openapi-codegen-typescript", + ], importsToInsert: [ { namedImports: ["generateReactQueryComponents", "generateSchemaTypes"], - module: "@openapi-codegen/typescript", + module: "@sschw/openapi-codegen-typescript", }, ], configProperty, }); expect(printer.printFile(transformedSourceFile)).toMatchInlineSnapshot(` - "import { defineConfig } from "@openapi-codegen/cli"; - import { renameComponent, generateReactQueryComponents, generateSchemaTypes } from "@openapi-codegen/typescript"; + "import { defineConfig } from "@sschw/openapi-codegen-cli"; + import { renameComponent, generateReactQueryComponents, generateSchemaTypes } from "@sschw/openapi-codegen-typescript"; export default defineConfig({ test: {} }); diff --git a/cli/src/templates/emptyConfig.ts b/cli/src/templates/emptyConfig.ts index 12ff6658..d0f09697 100644 --- a/cli/src/templates/emptyConfig.ts +++ b/cli/src/templates/emptyConfig.ts @@ -1,3 +1,3 @@ -export default `import { defineConfig } from "@openapi-codegen/cli"; +export default `import { defineConfig } from "@sschw/openapi-codegen-cli"; export default defineConfig({});`; diff --git a/examples/frontend/openapi-codegen.config.ts b/examples/frontend/openapi-codegen.config.ts index 71e59805..3aef17f6 100644 --- a/examples/frontend/openapi-codegen.config.ts +++ b/examples/frontend/openapi-codegen.config.ts @@ -1,8 +1,8 @@ import { generateSchemaTypes, generateReactQueryComponents, -} from "@openapi-codegen/typescript"; -import { defineConfig } from "@openapi-codegen/cli"; +} from "@sschw/openapi-codegen-typescript"; +import { defineConfig } from "@sschw/openapi-codegen-cli"; export default defineConfig({ github: { diff --git a/examples/frontend/package-lock.json b/examples/frontend/package-lock.json index 3bb16810..11347f3f 100644 --- a/examples/frontend/package-lock.json +++ b/examples/frontend/package-lock.json @@ -13,8 +13,8 @@ "react-dom": "^18.0.0" }, "devDependencies": { - "@openapi-codegen/cli": "^1.5.2", - "@openapi-codegen/typescript": "^5.1.0", + "@sschw/openapi-codegen-cli": "^1.5.2", + "@sschw/openapi-codegen-typescript": "^5.1.0", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@vitejs/plugin-react": "^1.3.0", @@ -602,9 +602,9 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@openapi-codegen/cli": { + "node_modules/@sschw/openapi-codegen-cli": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@openapi-codegen/cli/-/cli-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/@sschw/openapi-codegen-cli/-/cli-1.5.2.tgz", "integrity": "sha512-Zi/IWq2th/yODf2PNlaj5xOdMvF9GK4PlGk2Zyv9EAS7zd0IiAr2ulGEBLtNjPOek8tgdpUdWMzLqVOi/gGU0w==", "dev": true, "dependencies": { @@ -633,9 +633,9 @@ "openapi-codegen": "lib/cli.js" } }, - "node_modules/@openapi-codegen/typescript": { + "node_modules/@sschw/openapi-codegen-typescript": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@openapi-codegen/typescript/-/typescript-5.1.0.tgz", + "resolved": "https://registry.npmjs.org/@sschw/openapi-codegen-typescript/-/typescript-5.1.0.tgz", "integrity": "sha512-WBqUL29004yTlq9EKZUJKrxQEzxGjIjrYYKvJ4x1+mo5sYrhNkrXAmOnOIEEtsv6dl9+X+L/T9j3i7oJAzoz+g==", "dev": true, "dependencies": { @@ -4057,9 +4057,9 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "@openapi-codegen/cli": { + "@sschw/openapi-codegen-cli": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@openapi-codegen/cli/-/cli-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/@sschw/openapi-codegen-cli/-/cli-1.5.2.tgz", "integrity": "sha512-Zi/IWq2th/yODf2PNlaj5xOdMvF9GK4PlGk2Zyv9EAS7zd0IiAr2ulGEBLtNjPOek8tgdpUdWMzLqVOi/gGU0w==", "dev": true, "requires": { @@ -4085,9 +4085,9 @@ "typescript": "^4.6.2" } }, - "@openapi-codegen/typescript": { + "@sschw/openapi-codegen-typescript": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@openapi-codegen/typescript/-/typescript-5.1.0.tgz", + "resolved": "https://registry.npmjs.org/@sschw/openapi-codegen-typescript/-/typescript-5.1.0.tgz", "integrity": "sha512-WBqUL29004yTlq9EKZUJKrxQEzxGjIjrYYKvJ4x1+mo5sYrhNkrXAmOnOIEEtsv6dl9+X+L/T9j3i7oJAzoz+g==", "dev": true, "requires": { diff --git a/examples/frontend/package.json b/examples/frontend/package.json index 0306a284..ecd66b90 100644 --- a/examples/frontend/package.json +++ b/examples/frontend/package.json @@ -14,8 +14,8 @@ "react-dom": "^18.0.0" }, "devDependencies": { - "@openapi-codegen/cli": "^1.5.2", - "@openapi-codegen/typescript": "^5.1.0", + "@sschw/openapi-codegen-cli": "^1.5.2", + "@sschw/openapi-codegen-typescript": "^5.1.0", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@vitejs/plugin-react": "^1.3.0", diff --git a/examples/frontend/src/github/githubComponents.ts b/examples/frontend/src/github/githubComponents.ts index d79080c3..454bd3c6 100644 --- a/examples/frontend/src/github/githubComponents.ts +++ b/examples/frontend/src/github/githubComponents.ts @@ -1,5 +1,5 @@ /** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.1.4 */ diff --git a/examples/frontend/src/github/githubParameters.ts b/examples/frontend/src/github/githubParameters.ts index a0742097..0543f12f 100644 --- a/examples/frontend/src/github/githubParameters.ts +++ b/examples/frontend/src/github/githubParameters.ts @@ -1,5 +1,5 @@ /** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.1.4 */ diff --git a/examples/frontend/src/github/githubResponses.ts b/examples/frontend/src/github/githubResponses.ts index b8ec0198..03d8dfcc 100644 --- a/examples/frontend/src/github/githubResponses.ts +++ b/examples/frontend/src/github/githubResponses.ts @@ -1,5 +1,5 @@ /** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.1.4 */ diff --git a/examples/frontend/src/github/githubSchemas.ts b/examples/frontend/src/github/githubSchemas.ts index dde6c518..00b2a32b 100644 --- a/examples/frontend/src/github/githubSchemas.ts +++ b/examples/frontend/src/github/githubSchemas.ts @@ -1,5 +1,5 @@ /** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.1.4 */ diff --git a/package-lock.json b/package-lock.json index 3dfe4bdc..9b9b2697 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "openapi-codegen", + "name": "@sschw/openapi-codegen", "version": "0.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "openapi-codegen", + "name": "@sschw/openapi-codegen", "version": "0.0.1", "license": "MIT", "workspaces": [ @@ -33,8 +33,8 @@ } }, "cli": { - "name": "@openapi-codegen/cli", - "version": "2.0.4", + "name": "@sschw/openapi-codegen-cli", + "version": "3.0.1", "license": "MIT", "dependencies": { "@clack/prompts": "^0.9.1", @@ -4133,14 +4133,6 @@ "@octokit/openapi-types": "^18.0.0" } }, - "node_modules/@openapi-codegen/cli": { - "resolved": "cli", - "link": true - }, - "node_modules/@openapi-codegen/typescript": { - "resolved": "plugins/typescript", - "link": true - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -4519,6 +4511,14 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@sschw/openapi-codegen-cli": { + "resolved": "cli", + "link": true + }, + "node_modules/@sschw/openapi-codegen-typescript": { + "resolved": "plugins/typescript", + "link": true + }, "node_modules/@swc-node/core": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.0.tgz", @@ -16076,8 +16076,8 @@ } }, "plugins/typescript": { - "name": "@openapi-codegen/typescript", - "version": "8.1.1", + "name": "@sschw/openapi-codegen-typescript", + "version": "8.1.4", "license": "MIT", "dependencies": { "case": "^1.6.3", @@ -18961,150 +18961,6 @@ "@octokit/openapi-types": "^18.0.0" } }, - "@openapi-codegen/cli": { - "version": "file:cli", - "requires": { - "@clack/prompts": "^0.9.1", - "@octokit/request": "^9.2.0", - "@swc-node/register": "^1.4.0", - "@swc/core": "^1.2.118", - "@types/fs-extra": "^9.0.13", - "@types/js-yaml": "^4.0.3", - "@types/nock": "^11.1.0", - "@types/prettier": "^3.0.0", - "@types/slash": "^3.0.0", - "case": "^1.6.3", - "cli-highlight": "^2.1.11", - "clipanion": "^4.0.0-rc.4", - "fs-extra": "^10.0.0", - "got": "^12.0.0", - "got-fetch": "^5.1.1", - "js-yaml": "^4.1.0", - "nock": "^13.2.1", - "openapi3-ts": "^2.0.1", - "prettier": "^3.2.5", - "react": "^18.3.1", - "slash": "^4.0.0", - "swagger2openapi": "^7.0.8", - "tslib": "^2.3.1", - "tsup": "^8.3.5", - "typanion": "^3.14.0", - "typescript": "4.8.2" - }, - "dependencies": { - "@octokit/endpoint": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.2.tgz", - "integrity": "sha512-XybpFv9Ms4hX5OCHMZqyODYqGTZ3H6K6Vva+M9LR7ib/xr1y1ZnlChYv9H680y77Vd/i/k+thXApeRASBQkzhA==", - "requires": { - "@octokit/types": "^13.6.2", - "universal-user-agent": "^7.0.2" - } - }, - "@octokit/openapi-types": { - "version": "23.0.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", - "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==" - }, - "@octokit/request": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.0.tgz", - "integrity": "sha512-kXLfcxhC4ozCnAXy2ff+cSxpcF0A1UqxjvYMqNuPIeOAzJbVWQ+dy5G2fTylofB/gTbObT8O6JORab+5XtA1Kw==", - "requires": { - "@octokit/endpoint": "^10.0.0", - "@octokit/request-error": "^6.0.1", - "@octokit/types": "^13.6.2", - "fast-content-type-parse": "^2.0.0", - "universal-user-agent": "^7.0.2" - } - }, - "@octokit/request-error": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.6.tgz", - "integrity": "sha512-pqnVKYo/at0NuOjinrgcQYpEbv4snvP3bKMRqHaD9kIsk9u1LCpb2smHZi8/qJfgeNqLo5hNW4Z7FezNdEo0xg==", - "requires": { - "@octokit/types": "^13.6.2" - } - }, - "@octokit/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.7.0.tgz", - "integrity": "sha512-BXfRP+3P3IN6fd4uF3SniaHKOO4UXWBfkdR3vA8mIvaoO/wLjGN5qivUtW0QRitBHHMcfC41SLhNVYIZZE+wkA==", - "requires": { - "@octokit/openapi-types": "^23.0.1" - } - }, - "@types/prettier": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-3.0.0.tgz", - "integrity": "sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==", - "dev": true, - "requires": { - "prettier": "*" - } - }, - "form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==" - }, - "got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "requires": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - } - }, - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" - }, - "typescript": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", - "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" - }, - "universal-user-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", - "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==" - } - } - }, - "@openapi-codegen/typescript": { - "version": "file:plugins/typescript", - "requires": { - "@types/lodash": "^4.14.175", - "@types/pluralize": "^0.0.29", - "@types/qs": "^6.9.7", - "case": "^1.6.3", - "lodash": "^4.17.21", - "openapi3-ts": "^2.0.1", - "pluralize": "^8.0.0", - "tslib": "^2.3.1", - "tsutils": "^3.21.0", - "typescript": "4.8.2" - }, - "dependencies": { - "typescript": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", - "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" - } - } - }, "@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -19336,6 +19192,150 @@ "@sinonjs/commons": "^3.0.0" } }, + "@sschw/openapi-codegen-cli": { + "version": "file:cli", + "requires": { + "@clack/prompts": "^0.9.1", + "@octokit/request": "^9.2.0", + "@swc-node/register": "^1.4.0", + "@swc/core": "^1.2.118", + "@types/fs-extra": "^9.0.13", + "@types/js-yaml": "^4.0.3", + "@types/nock": "^11.1.0", + "@types/prettier": "^3.0.0", + "@types/slash": "^3.0.0", + "case": "^1.6.3", + "cli-highlight": "^2.1.11", + "clipanion": "^4.0.0-rc.4", + "fs-extra": "^10.0.0", + "got": "^12.0.0", + "got-fetch": "^5.1.1", + "js-yaml": "^4.1.0", + "nock": "^13.2.1", + "openapi3-ts": "^2.0.1", + "prettier": "^3.2.5", + "react": "^18.3.1", + "slash": "^4.0.0", + "swagger2openapi": "^7.0.8", + "tslib": "^2.3.1", + "tsup": "^8.3.5", + "typanion": "^3.14.0", + "typescript": "4.8.2" + }, + "dependencies": { + "@octokit/endpoint": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.2.tgz", + "integrity": "sha512-XybpFv9Ms4hX5OCHMZqyODYqGTZ3H6K6Vva+M9LR7ib/xr1y1ZnlChYv9H680y77Vd/i/k+thXApeRASBQkzhA==", + "requires": { + "@octokit/types": "^13.6.2", + "universal-user-agent": "^7.0.2" + } + }, + "@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==" + }, + "@octokit/request": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.0.tgz", + "integrity": "sha512-kXLfcxhC4ozCnAXy2ff+cSxpcF0A1UqxjvYMqNuPIeOAzJbVWQ+dy5G2fTylofB/gTbObT8O6JORab+5XtA1Kw==", + "requires": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.6.2", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" + } + }, + "@octokit/request-error": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.6.tgz", + "integrity": "sha512-pqnVKYo/at0NuOjinrgcQYpEbv4snvP3bKMRqHaD9kIsk9u1LCpb2smHZi8/qJfgeNqLo5hNW4Z7FezNdEo0xg==", + "requires": { + "@octokit/types": "^13.6.2" + } + }, + "@octokit/types": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.7.0.tgz", + "integrity": "sha512-BXfRP+3P3IN6fd4uF3SniaHKOO4UXWBfkdR3vA8mIvaoO/wLjGN5qivUtW0QRitBHHMcfC41SLhNVYIZZE+wkA==", + "requires": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "@types/prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==", + "dev": true, + "requires": { + "prettier": "*" + } + }, + "form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==" + }, + "got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "requires": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + }, + "typescript": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" + }, + "universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==" + } + } + }, + "@sschw/openapi-codegen-typescript": { + "version": "file:plugins/typescript", + "requires": { + "@types/lodash": "^4.14.175", + "@types/pluralize": "^0.0.29", + "@types/qs": "^6.9.7", + "case": "^1.6.3", + "lodash": "^4.17.21", + "openapi3-ts": "^2.0.1", + "pluralize": "^8.0.0", + "tslib": "^2.3.1", + "tsutils": "^3.21.0", + "typescript": "4.8.2" + }, + "dependencies": { + "typescript": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" + } + } + }, "@swc-node/core": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.0.tgz", diff --git a/package.json b/package.json index 9bf81b67..8de4fb82 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,11 @@ { - "name": "openapi-codegen", + "name": "@sschw/openapi-codegen", "version": "0.0.1", "description": "OpenAPI code generator framework", - "repository": "https://github.com/fabien0102/openapi-codegen", + "repository": { + "type": "git", + "url": "git+https://github.com/sschw/openapi-codegen.git" + }, "author": "Fabien Bernard", "license": "MIT", "private": true, diff --git a/plugins/typescript/README.md b/plugins/typescript/README.md index 6dd07507..e62ec2e6 100644 --- a/plugins/typescript/README.md +++ b/plugins/typescript/README.md @@ -1,3 +1,5 @@ +### This is a fork of the original project [openapi-codegen](https://github.com/fabien0102/openapi-codegen) by Fabien BERNARD. + # OpenAPI Codegen typescript Collection of typescript generators & utils @@ -25,11 +27,11 @@ Example: ```ts // openapi-codegen.config.ts -import { defineConfig } from "@openapi-codegen/cli"; +import { defineConfig } from "@sschw/openapi-codegen-cli"; import { generateReactQueryComponents, generateSchemaTypes, -} from "@openapi-codegen/typescript"; +} from "@sschw/openapi-codegen-typescript"; export default defineConfig({ petstore: { @@ -178,12 +180,12 @@ Example: ```ts // openapi-codegen.config.ts -import { defineConfig } from "@openapi-codegen/cli"; +import { defineConfig } from "@sschw/openapi-codegen-cli"; import { generateReactQueryComponents, generateSchemaTypes, renameComponent, -} from "@openapi-codegen/typescript"; +} from "@sschw/openapi-codegen-typescript"; export default defineConfig({ myAPI: { @@ -221,12 +223,12 @@ Example: ```ts // openapi-codegen.config.ts -import { defineConfig } from "@openapi-codegen/cli"; +import { defineConfig } from "@sschw/openapi-codegen-cli"; import { generateReactQueryComponents, generateSchemaTypes, renameComponent, -} from "@openapi-codegen/typescript"; +} from "@sschw/openapi-codegen-typescript"; export default defineConfig({ myAPI: { diff --git a/plugins/typescript/package.json b/plugins/typescript/package.json index c2f72bf9..273cbd42 100644 --- a/plugins/typescript/package.json +++ b/plugins/typescript/package.json @@ -1,11 +1,12 @@ { - "name": "@openapi-codegen/typescript", - "version": "8.1.1", + "name": "@sschw/openapi-codegen-typescript", + "version": "8.1.4", "description": "OpenAPI Codegen typescript generators", "main": "lib/index.js", "types": "lib/index.d.ts", "repository": { - "url": "https://github.com/fabien0102/openapi-codegen", + "type": "git", + "url": "git+https://github.com/sschw/openapi-codegen.git", "directory": "plugins/typescript" }, "publishConfig": { diff --git a/plugins/typescript/src/core/createWatermark.ts b/plugins/typescript/src/core/createWatermark.ts index 8b53b9b5..326e3995 100644 --- a/plugins/typescript/src/core/createWatermark.ts +++ b/plugins/typescript/src/core/createWatermark.ts @@ -8,7 +8,7 @@ import { factory as f } from "typescript"; * @returns ts.node with the watermark */ export const createWatermark = (info: InfoObject) => - f.createJSDocComment("Generated by @openapi-codegen\n", [ + f.createJSDocComment("Generated by @sschw/openapi-codegen\n", [ f.createJSDocPropertyTag( f.createIdentifier("version"), f.createIdentifier(info.version), diff --git a/plugins/typescript/src/core/schemaToEnumDeclaration.ts b/plugins/typescript/src/core/schemaToEnumDeclaration.ts index f765324e..f9173cbc 100644 --- a/plugins/typescript/src/core/schemaToEnumDeclaration.ts +++ b/plugins/typescript/src/core/schemaToEnumDeclaration.ts @@ -42,7 +42,8 @@ function getEnumMembers( let enumValueNode: ts.Expression | undefined = undefined; if (typeof enumValue === "string") { - enumName = enumValue; + // Enum name must be wrapped in quotes if it starts with a number or contains special characters (except _ and $) + enumName = /^[A-Za-z_$][A-Za-z0-9_$]+$/.test(enumValue) ? enumValue : `"${enumValue}"`; enumValueNode = f.createStringLiteral(enumValue); } else if (typeof enumValue === "number") { enumName = convertNumberToWord(enumValue) diff --git a/plugins/typescript/src/core/schemaToTypeAliasDeclaration.ts b/plugins/typescript/src/core/schemaToTypeAliasDeclaration.ts index f92ffa54..1cf52db2 100644 --- a/plugins/typescript/src/core/schemaToTypeAliasDeclaration.ts +++ b/plugins/typescript/src/core/schemaToTypeAliasDeclaration.ts @@ -1,5 +1,5 @@ import { pascal } from "case"; -import { findKey, get, intersection, merge, omit } from "lodash"; +import { keys, pickBy, get, intersection, merge, omit } from "lodash"; import { ComponentsObject, DiscriminatorObject, @@ -315,17 +315,20 @@ const withDiscriminator = ( return node; } - const discriminatedValue = findKey( + const discriminatedValues = keys(pickBy( discriminator.mapping, (i) => i === schema.$ref - ); - if (discriminatedValue) { + )); + + if (discriminatedValues.length > 0) { + const discriminatedValuesType = f.createUnionTypeNode(discriminatedValues.map(val => f.createLiteralTypeNode(f.createStringLiteral(val)))); + const propertyNameAsLiteral = f.createTypeLiteralNode([ f.createPropertySignature( undefined, f.createIdentifier(discriminator.propertyName), undefined, - f.createLiteralTypeNode(f.createStringLiteral(discriminatedValue)) + discriminatedValuesType ), ]); @@ -339,7 +342,7 @@ const withDiscriminator = ( property && isSchemaObject(property) && property.enum?.length === 1 && - property.enum[0] === discriminatedValue && + discriminatedValues.includes(property.enum[0]) && spec.required?.includes(discriminator.propertyName) ) { return node; diff --git a/plugins/typescript/src/fixtures/petstore.ts b/plugins/typescript/src/fixtures/petstore.ts index 6e5e669b..c397079b 100644 --- a/plugins/typescript/src/fixtures/petstore.ts +++ b/plugins/typescript/src/fixtures/petstore.ts @@ -243,6 +243,16 @@ export const petstore: OpenAPIObject = { type: "string", }, }, + petFilterParam: { + name: "petFilter", + in: "query", + required: false, + schema: { + description: "Filter by type", + type: "string", + enum: ["cat", "dog"], + }, + }, }, requestBodies: { updatePetRequest: { @@ -255,6 +265,17 @@ export const petstore: OpenAPIObject = { }, required: true, }, + searchPetRequest: { + content: { + "application/json": { + schema: { + type: "string", + enum: ["cat", "dog"], + }, + }, + }, + required: true, + }, }, responses: { NotModified: { @@ -270,6 +291,17 @@ export const petstore: OpenAPIObject = { }, }, }, + PetTypeResponse: { + description: "Type of pet", + content: { + "application/json": { + schema: { + type: "string", + enum: ["cat", "dog"], + }, + }, + }, + }, }, schemas: { Pet: { diff --git a/plugins/typescript/src/generators/generateFetchers.test.ts b/plugins/typescript/src/generators/generateFetchers.test.ts index df7ee263..f10e7e64 100644 --- a/plugins/typescript/src/generators/generateFetchers.test.ts +++ b/plugins/typescript/src/generators/generateFetchers.test.ts @@ -73,7 +73,7 @@ describe("generateFetchers", () => { expect(writeFile.mock.calls[1][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -117,7 +117,7 @@ describe("generateFetchers", () => { expect(writeFile.mock.calls[1][0]).toBe("components.ts"); expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -168,7 +168,7 @@ describe("generateFetchers", () => { expect(writeFile.mock.calls[1][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -220,7 +220,7 @@ describe("generateFetchers", () => { expect(writeFile.mock.calls[1][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ diff --git a/plugins/typescript/src/generators/generateReactQueryComponents.test.ts b/plugins/typescript/src/generators/generateReactQueryComponents.test.ts index 7687f082..56eb4731 100644 --- a/plugins/typescript/src/generators/generateReactQueryComponents.test.ts +++ b/plugins/typescript/src/generators/generateReactQueryComponents.test.ts @@ -85,7 +85,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -170,7 +170,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -290,7 +290,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -413,7 +413,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -532,7 +532,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -638,7 +638,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -768,7 +768,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -884,7 +884,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1010,7 +1010,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1144,7 +1144,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1284,7 +1284,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1397,7 +1397,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1509,7 +1509,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1621,7 +1621,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreComponents.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1733,7 +1733,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("components.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1829,7 +1829,7 @@ describe("generateReactQueryComponents", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreUtils.ts"); expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ diff --git a/plugins/typescript/src/generators/generateReactQueryFunctions.test.ts b/plugins/typescript/src/generators/generateReactQueryFunctions.test.ts index ac89ba0a..65eadc1b 100644 --- a/plugins/typescript/src/generators/generateReactQueryFunctions.test.ts +++ b/plugins/typescript/src/generators/generateReactQueryFunctions.test.ts @@ -85,7 +85,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -205,7 +205,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -324,7 +324,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -453,7 +453,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -578,7 +578,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -713,7 +713,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -818,7 +818,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -929,7 +929,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1019,7 +1019,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1109,7 +1109,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("functions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1183,7 +1183,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreUtils.ts"); expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -1282,7 +1282,7 @@ describe("generateReactQueryFunctions", () => { expect(writeFile.mock.calls[0][0]).toBe("petstoreFunctions.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ diff --git a/plugins/typescript/src/generators/generateSchemaTypes.test.ts b/plugins/typescript/src/generators/generateSchemaTypes.test.ts index 64232dcb..b27d8b07 100644 --- a/plugins/typescript/src/generators/generateSchemaTypes.test.ts +++ b/plugins/typescript/src/generators/generateSchemaTypes.test.ts @@ -134,7 +134,7 @@ describe("generateSchemaTypes", () => { expect(writeFile.mock.calls[0][0]).toBe("swaggerPetstoreSchemas.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -220,7 +220,7 @@ describe("generateSchemaTypes", () => { expect(writeFile.mock.calls[0][0]).toBe("swaggerPetstoreSchemas.ts"); expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -233,7 +233,7 @@ describe("generateSchemaTypes", () => { export enum DogBreed { saimois = "saimois", bengal = "bengal", - british shorthair = "british shorthair" + "british shorthair" = "british shorthair" } /** @@ -317,7 +317,7 @@ describe("generateSchemaTypes", () => { expect(writeFile.mock.calls[1][0]).toBe("swaggerPetstoreResponses.ts"); expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ @@ -326,6 +326,8 @@ describe("generateSchemaTypes", () => { export type NotModified = void; export type PetResponse = Schemas.Pet; + + export type PetTypeResponse = "cat" | "dog"; " `); }); @@ -349,13 +351,15 @@ describe("generateSchemaTypes", () => { ); expect(writeFile.mock.calls[2][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ import type * as Schemas from "./swaggerPetstoreSchemas"; export type UpdatePetRequest = Schemas.NewPet; + + export type SearchPetRequest = "cat" | "dog"; " `); }); @@ -378,10 +382,126 @@ describe("generateSchemaTypes", () => { expect(writeFile.mock.calls[3][0]).toBe("swaggerPetstoreParameters.ts"); expect(writeFile.mock.calls[3][1]).toMatchInlineSnapshot(` "/** - * Generated by @openapi-codegen + * Generated by @sschw/openapi-codegen + * + * @version 1.0.0 + */ + /** + * Unique identifier + */ + export type IdParam = string; + + /** + * Filter by type + */ + export type PetFilterParam = "cat" | "dog"; + " + `); + }); + + it("should generate the responses file with enums instead of string unions", async () => { + const writeFile = jest.fn(); + const readFile = jest.fn(() => Promise.resolve("")); + await generateSchemaTypes( + { + openAPIDocument: petstore, + writeFile, + readFile, + existsFile: () => true, + }, + { + filenameCase: "camel", + useEnums: true, + }, + ); + expect(writeFile.mock.calls[1][0]).toBe("swaggerPetstoreResponses.ts"); + expect(writeFile.mock.calls[1][1]).toMatchInlineSnapshot(` + "/** + * Generated by @sschw/openapi-codegen + * + * @version 1.0.0 + */ + import type * as Schemas from "./swaggerPetstoreSchemas"; + + export enum PetTypeResponse { + cat = "cat", + dog = "dog" + } + + export type NotModified = void; + + export type PetResponse = Schemas.Pet; + " + `); + }); + + it("should generate the request bodies file with enums instead of string unions", async () => { + const writeFile = jest.fn(); + const readFile = jest.fn(() => Promise.resolve("")); + await generateSchemaTypes( + { + openAPIDocument: petstore, + writeFile, + readFile, + existsFile: () => true, + }, + { + filenameCase: "camel", + useEnums: true, + }, + ); + expect(writeFile.mock.calls[2][0]).toBe( + "swaggerPetstoreRequestBodies.ts", + ); + expect(writeFile.mock.calls[2][1]).toMatchInlineSnapshot(` + "/** + * Generated by @sschw/openapi-codegen + * + * @version 1.0.0 + */ + import type * as Schemas from "./swaggerPetstoreSchemas"; + + export enum SearchPetRequest { + cat = "cat", + dog = "dog" + } + + export type UpdatePetRequest = Schemas.NewPet; + " + `); + }); + + it("should generate the parameters file with enums instead of string unions", async () => { + const writeFile = jest.fn(); + const readFile = jest.fn(() => Promise.resolve("")); + + await generateSchemaTypes( + { + openAPIDocument: petstore, + writeFile, + readFile, + existsFile: () => true, + }, + { + filenameCase: "camel", + useEnums: true, + }, + ); + expect(writeFile.mock.calls[3][0]).toBe("swaggerPetstoreParameters.ts"); + expect(writeFile.mock.calls[3][1]).toMatchInlineSnapshot(` + "/** + * Generated by @sschw/openapi-codegen * * @version 1.0.0 */ + /** + * Filter by type + */ + export enum PetFilterParam { + cat = "cat", + dog = "dog" + } + /** * Unique identifier */ diff --git a/plugins/typescript/src/generators/generateSchemaTypes.ts b/plugins/typescript/src/generators/generateSchemaTypes.ts index 14a32de9..793b64bb 100644 --- a/plugins/typescript/src/generators/generateSchemaTypes.ts +++ b/plugins/typescript/src/generators/generateSchemaTypes.ts @@ -4,7 +4,10 @@ import ts from "typescript"; import { ReferenceObject, SchemaObject } from "openapi3-ts"; import { createWatermark } from "../core/createWatermark"; import { getUsedImports } from "../core/getUsedImports"; -import { schemaToTypeAliasDeclaration } from "../core/schemaToTypeAliasDeclaration"; +import { + OpenAPIComponentType, + schemaToTypeAliasDeclaration, +} from "../core/schemaToTypeAliasDeclaration"; import { getEnumProperties } from "../utils/getEnumProperties"; import { ConfigBase, Context } from "./types"; @@ -51,7 +54,8 @@ export const generateSchemaTypes = async ( .join("\n"); const handleTypeAlias = ( - componentSchema: [string, SchemaObject | ReferenceObject][] + componentSchema: [string, SchemaObject | ReferenceObject][], + currentComponent: OpenAPIComponentType ) => componentSchema.reduce( (mem, [name, schema]) => [ @@ -61,7 +65,7 @@ export const generateSchemaTypes = async ( schema, { openAPIDocument: context.openAPIDocument, - currentComponent: "schemas", + currentComponent: currentComponent, }, config.useEnums ), @@ -69,23 +73,10 @@ export const generateSchemaTypes = async ( [] ); - const filenamePrefix = - c.snake(config.filenamePrefix ?? context.openAPIDocument.info.title) + "-"; - - const formatFilename = config.filenameCase ? c[config.filenameCase] : c.camel; - const files = { - requestBodies: formatFilename(filenamePrefix + "-request-bodies"), - schemas: formatFilename(filenamePrefix + "-schemas"), - parameters: formatFilename(filenamePrefix + "-parameters"), - responses: formatFilename(filenamePrefix + "-responses"), - utils: formatFilename(filenamePrefix + "-utils"), - }; - - // Generate `components/schemas` types - if (components.schemas) { - const schemas: ts.Node[] = []; - const componentSchemaEntries = Object.entries(components.schemas); - + const generateTypeAliasDeclarations = ( + componentSchemaEntries: [string, SchemaObject | ReferenceObject][], + currentComponent: OpenAPIComponentType + ) => { if (config.useEnums) { const enumSchemaEntries = getEnumProperties(componentSchemaEntries); const enumSchemas = enumSchemaEntries.reduce( @@ -93,7 +84,7 @@ export const generateSchemaTypes = async ( ...mem, ...schemaToEnumDeclaration(name, schema, { openAPIDocument: context.openAPIDocument, - currentComponent: "schemas", + currentComponent, }), ], [] @@ -102,14 +93,35 @@ export const generateSchemaTypes = async ( const componentsSchemas = handleTypeAlias( componentSchemaEntries.filter( ([name]) => !enumSchemaEntries.some(([enumName]) => name === enumName) - ) + ), + currentComponent ); - schemas.push(...enumSchemas, ...componentsSchemas); + return [...enumSchemas, ...componentsSchemas]; } else { - const componentsSchemas = handleTypeAlias(componentSchemaEntries); - schemas.push(...componentsSchemas); + return handleTypeAlias(componentSchemaEntries, currentComponent); } + }; + + const filenamePrefix = + c.snake(config.filenamePrefix ?? context.openAPIDocument.info.title) + "-"; + + const formatFilename = config.filenameCase ? c[config.filenameCase] : c.camel; + const files = { + requestBodies: formatFilename(filenamePrefix + "-request-bodies"), + schemas: formatFilename(filenamePrefix + "-schemas"), + parameters: formatFilename(filenamePrefix + "-parameters"), + responses: formatFilename(filenamePrefix + "-responses"), + utils: formatFilename(filenamePrefix + "-utils"), + }; + + // Generate `components/schemas` types + if (components.schemas) { + const componentSchemaEntries = Object.entries(components.schemas); + const schemas = generateTypeAliasDeclarations( + componentSchemaEntries, + "schemas" + ); await context.writeFile( files.schemas + ".ts", @@ -123,28 +135,29 @@ export const generateSchemaTypes = async ( // Generate `components/responses` types if (components.responses) { - const componentsResponses = Object.entries(components.responses).reduce< - ts.Node[] - >((mem, [name, responseObject]) => { + // Convert responses to schemas + const componentsResponsesEntries = Object.entries( + components.responses + ).reduce<[string, SchemaObject][]>((mem, [name, responseObject]) => { if (isReferenceObject(responseObject)) return mem; const mediaType = findCompatibleMediaType(responseObject); - return [ - ...mem, - ...schemaToTypeAliasDeclaration(name, mediaType?.schema || {}, { - openAPIDocument: context.openAPIDocument, - currentComponent: "responses", - }), - ]; + mem.push([name, mediaType?.schema || {}]); + return mem; }, []); - if (componentsResponses.length) { + const schemas = generateTypeAliasDeclarations( + componentsResponsesEntries, + "responses" + ); + + if (schemas.length) { await context.writeFile( files.responses + ".ts", printNodes([ createWatermark(context.openAPIDocument.info), - ...getUsedImports(componentsResponses, files).nodes, - ...componentsResponses, + ...getUsedImports(schemas, files).nodes, + ...schemas, ]) ); } @@ -152,29 +165,30 @@ export const generateSchemaTypes = async ( // Generate `components/requestBodies` types if (components.requestBodies) { - const componentsRequestBodies = Object.entries( + // Convert requestBodies to schemas + const componentsRequestBodiesEntries = Object.entries( components.requestBodies - ).reduce((mem, [name, requestBodyObject]) => { + ).reduce<[string, SchemaObject][]>((mem, [name, requestBodyObject]) => { if (isReferenceObject(requestBodyObject)) return mem; const mediaType = findCompatibleMediaType(requestBodyObject); if (!mediaType || !mediaType.schema) return mem; - return [ - ...mem, - ...schemaToTypeAliasDeclaration(name, mediaType.schema, { - openAPIDocument: context.openAPIDocument, - currentComponent: "requestBodies", - }), - ]; + mem.push([name, mediaType.schema]); + return mem; }, []); - if (componentsRequestBodies.length) { + const schemas = generateTypeAliasDeclarations( + componentsRequestBodiesEntries, + "requestBodies" + ); + + if (schemas.length) { await context.writeFile( files.requestBodies + ".ts", printNodes([ createWatermark(context.openAPIDocument.info), - ...getUsedImports(componentsRequestBodies, files).nodes, - ...componentsRequestBodies, + ...getUsedImports(schemas, files).nodes, + ...schemas, ]) ); } @@ -182,27 +196,27 @@ export const generateSchemaTypes = async ( // Generate `components/parameters` types if (components.parameters) { - const componentsParameters = Object.entries(components.parameters).reduce< - ts.Node[] - >((mem, [name, parameterObject]) => { - if (isReferenceObject(parameterObject) || !parameterObject.schema) { + // Convert parameters to schemas + const componentsParametersEntries = Object.entries( + components.parameters + ).reduce<[string, SchemaObject][]>((mem, [name, parameterObject]) => { + if (isReferenceObject(parameterObject) || !parameterObject.schema) return mem; - } - return [ - ...mem, - ...schemaToTypeAliasDeclaration(name, parameterObject.schema, { - openAPIDocument: context.openAPIDocument, - currentComponent: "parameters", - }), - ]; + mem.push([name, parameterObject.schema as SchemaObject]); + return mem; }, []); + const schemas = generateTypeAliasDeclarations( + componentsParametersEntries, + "parameters" + ); + await context.writeFile( files.parameters + ".ts", printNodes([ createWatermark(context.openAPIDocument.info), - ...getUsedImports(componentsParameters, files).nodes, - ...componentsParameters, + ...getUsedImports(schemas, files).nodes, + ...schemas, ]) ); } diff --git a/plugins/typescript/src/generators/types.ts b/plugins/typescript/src/generators/types.ts index 18708fca..fe744508 100644 --- a/plugins/typescript/src/generators/types.ts +++ b/plugins/typescript/src/generators/types.ts @@ -2,7 +2,7 @@ import { OpenAPIObject } from "openapi3-ts"; import * as c from "case"; /** - * Generator context (provided by `@openapi-codegen/cli`) + * Generator context (provided by `@sschw/openapi-codegen-cli`) */ export type Context = { openAPIDocument: OpenAPIObject;