diff --git a/README.md b/README.md index 20c2d3bff..f079a3ca0 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - [Installation](#installation) - [Configuration](#configuration) - [Formatting](#formatting) + - [Linting](#linting) - [Enums](#enums) - [Config API](#config-api) - [Contributing](#contributing) @@ -97,19 +98,35 @@ export default defineConfig({ ### Formatting -By default, `openapi-ts` will automatically format your client according to your project configuration. To disable automatic formatting, set `autoformat` to false +By default, `openapi-ts` will automatically format your client according to your project configuration. To disable automatic formatting, set `format` to false ```ts import { defineConfig } from '@nicolas-chaulet/openapi-typescript-codegen'; export default defineConfig({ - autoformat: false, + format: false, input: 'path/to/openapi.json', output: 'src/client', }) ``` -You can also prevent your client from being processed by formatters and linters by adding your output path to the tool's ignore file (e.g. `.eslintignore`, `.prettierignore`). +You can also prevent your client from being processed by formatters by adding your output path to the tool's ignore file (e.g. `.prettierignore`). + +### Linting + +For performance reasons, `openapi-ts` does not automatically lint your client. To enable this feature, set `lint` to true + +```ts +import { defineConfig } from '@nicolas-chaulet/openapi-typescript-codegen'; + +export default defineConfig({ + input: 'path/to/openapi.json', + lint: true, + output: 'src/client', +}) +``` + +You can also prevent your client from being processed by linters by adding your output path to the tool's ignore file (e.g. `.eslintignore`). ### Enums @@ -148,13 +165,16 @@ $ openapi-ts --help -c, --client HTTP client to generate [fetch, xhr, node, axios, angular] (default: "fetch") --name Custom client class name --useOptions Use options instead of arguments (default: false) - --no-autoformat Disable processing generated files with formatter --base Manually set base in OpenAPI config instead of inferring from server value --enums Generate JavaScript objects from enum definitions (default: false) --exportCore Write core files to disk (default: true) --exportServices Write services to disk [true, false, regexp] (default: true) --exportModels Write models to disk [true, false, regexp] (default: true) --exportSchemas Write schemas to disk (default: false) + --format Process output folder with formatter? + --no-format Disable processing output folder with formatter + --lint Process output folder with linter? + --no-lint Disable processing output folder with linter --no-operationId Use path URL to generate operation ID --postfixServices Service name postfix (default: "Service") --postfixModels Model name postfix diff --git a/bin/index.js b/bin/index.js index 6c114f213..ef50fb372 100755 --- a/bin/index.js +++ b/bin/index.js @@ -17,14 +17,16 @@ const params = program .option('-c, --client ', 'HTTP client to generate [angular, axios, fetch, node, xhr]') .option('--name ', 'Custom client class name') .option('--useOptions [value]', 'Use options instead of arguments') - .option('--autoformat', 'Process generated files with formatter?') - .option('--no-autoformat', 'Disable processing generated files with formatter') .option('--base [value]', 'Manually set base in OpenAPI config instead of inferring from server value') .option('--enums', 'Generate JavaScript objects from enum definitions') .option('--exportCore ', 'Write core files to disk') .option('--exportServices ', 'Write services to disk') .option('--exportModels ', 'Write models to disk') .option('--exportSchemas ', 'Write schemas to disk') + .option('--format', 'Process output folder with formatter?') + .option('--no-format', 'Disable processing output folder with formatter') + .option('--lint', 'Process output folder with linter?') + .option('--no-lint', 'Disable processing output folder with linter') .option('--operationId', 'Use operationd ID?') .option('--no-operationId', 'Use path URL to generate operation ID') .option('--postfixServices ', 'Service name postfix') @@ -39,7 +41,7 @@ const params = program async function start() { try { - const { createClient } = await import(new URL('../dist/index.js', import.meta.url)); + const { createClient } = await import(new URL('../dist/node/index.js', import.meta.url)); await createClient(params); process.exit(0); } catch (error) { diff --git a/package-lock.json b/package-lock.json index 279084384..9904c8bbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@nicolas-chaulet/openapi-typescript-codegen", - "version": "0.27.33", + "version": "0.27.34", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@nicolas-chaulet/openapi-typescript-codegen", - "version": "0.27.33", + "version": "0.27.34", "license": "MIT", "dependencies": { "@apidevtools/json-schema-ref-parser": "11.5.4", diff --git a/package.json b/package.json index 333ff8491..2a929048b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nicolas-chaulet/openapi-typescript-codegen", - "version": "0.27.33", + "version": "0.27.34", "type": "module", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", @@ -32,7 +32,7 @@ "email": "info@madebyferdi.com" } ], - "main": "./dist/index.js", + "main": "./dist/node/index.js", "types": "./dist/node/index.d.ts", "bin": { "openapi-ts": "bin/index.js" diff --git a/rollup.config.ts b/rollup.config.ts index b69220863..7a46c5e70 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -19,9 +19,9 @@ const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url)). function createConfig(isProduction: boolean) { return defineConfig({ external: [...Object.keys(pkg.dependencies)], - input: path.resolve(__dirname, 'src/index.ts'), + input: path.resolve(__dirname, 'src/node/index.ts'), output: { - file: path.resolve(__dirname, 'dist/index.js'), + file: path.resolve(__dirname, 'dist/node/index.js'), format: 'esm', }, plugins: [ diff --git a/src/index.spec.ts b/src/index.spec.ts index 38f9a42ec..e3d84aa45 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -44,14 +44,15 @@ describe('parseOpenApiSpecification', () => { }); const options: Parameters[1] = { - autoformat: true, client: 'fetch', enums: true, exportCore: true, exportModels: true, exportSchemas: true, exportServices: true, + format: true, input: '', + lint: false, operationId: true, output: '', postfixModels: '', diff --git a/src/index.ts b/src/index.ts index 6877a2406..d7a2d4089 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,29 +19,29 @@ type Dependencies = Record; // add support for `openapi-ts.config.ts` const configFiles = ['openapi-ts.config.js']; -export const parseOpenApiSpecification = (openApi: Awaited>, options: Config) => { - if ('swagger' in openApi) { - return parseV2(openApi, options); - } +export const parseOpenApiSpecification = (openApi: Awaited>, config: Config) => { if ('openapi' in openApi) { - return parseV3(openApi, options); + return parseV3(openApi, config); + } + if ('swagger' in openApi) { + return parseV2(openApi, config); } throw new Error(`Unsupported Open API specification: ${JSON.stringify(openApi, null, 2)}`); }; -const formatClient = (options: Config, dependencies: Dependencies) => { - if (!options.autoformat) { - return; - } - - if (dependencies.prettier) { - console.log('✨ Running Prettier'); - sync('prettier', ['--ignore-unknown', options.output, '--write', '--ignore-path', './.prettierignore']); +const processOutput = (config: Config, dependencies: Dependencies) => { + if (config.format) { + if (dependencies.prettier) { + console.log('✨ Running Prettier'); + sync('prettier', ['--ignore-unknown', config.output, '--write', '--ignore-path', './.prettierignore']); + } } - if (dependencies.eslint) { - console.log('✨ Running Eslint'); - sync('eslint', [options.output, '--fix', '--quiet', '--ignore-path', './.eslintignore']); + if (config.lint) { + if (dependencies.eslint) { + console.log('✨ Running ESLint'); + sync('eslint', [config.output, '--fix', '--quiet', '--ignore-path', './.eslintignore']); + } } }; @@ -89,14 +89,15 @@ const getConfig = async (userConfig: UserConfig, dependencies: Dependencies) => } const { - autoformat = true, base, enums = false, exportCore = true, exportModels = true, exportSchemas = false, exportServices = true, + format = true, input, + lint = false, name, operationId = true, output, @@ -112,7 +113,6 @@ const getConfig = async (userConfig: UserConfig, dependencies: Dependencies) => const client = userConfig.client || inferClient(dependencies); const config: Config = { - autoformat, base, client, enums, @@ -120,7 +120,9 @@ const getConfig = async (userConfig: UserConfig, dependencies: Dependencies) => exportModels, exportSchemas, exportServices, + format, input, + lint, name, operationId, output, @@ -174,7 +176,7 @@ export async function createClient(userConfig: UserConfig): Promise { if (config.write) { logClientMessage(config.client); await writeClient(client, templates, config); - formatClient(config, dependencies); + processOutput(config, dependencies); } console.log('✨ Done! Your client is located in:', config.output); diff --git a/src/openApi/v2/parser/getServices.spec.ts b/src/openApi/v2/parser/getServices.spec.ts index 0bb4ed0b4..0fbc2faba 100644 --- a/src/openApi/v2/parser/getServices.spec.ts +++ b/src/openApi/v2/parser/getServices.spec.ts @@ -5,14 +5,15 @@ import { getServices } from './getServices'; describe('getServices', () => { it('should create a unnamed service if tags are empty', () => { const options: Parameters[1] = { - autoformat: false, client: 'fetch', enums: false, exportCore: true, exportModels: true, exportSchemas: true, exportServices: true, + format: false, input: '', + lint: false, operationId: false, output: '', postfixModels: '', diff --git a/src/openApi/v3/parser/__tests__/getServices.spec.ts b/src/openApi/v3/parser/__tests__/getServices.spec.ts index 5f6eaa8b0..32d02dd7f 100644 --- a/src/openApi/v3/parser/__tests__/getServices.spec.ts +++ b/src/openApi/v3/parser/__tests__/getServices.spec.ts @@ -5,14 +5,15 @@ import { getServices } from '../getServices'; describe('getServices', () => { it('should create a unnamed service if tags are empty', () => { const options: Parameters[1] = { - autoformat: false, client: 'fetch', enums: false, exportCore: true, exportModels: true, exportSchemas: true, exportServices: true, + format: false, input: '', + lint: false, operationId: true, output: '', postfixModels: '', diff --git a/src/types/config.ts b/src/types/config.ts index 7f781478a..1d4350ca1 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,9 +1,4 @@ export interface UserConfig { - /** - * Process generated files with autoformatter - * @default true - */ - autoformat?: boolean; /** * Manually set base in OpenAPI config instead of inferring from server value */ @@ -38,10 +33,20 @@ export interface UserConfig { * @default true */ exportServices?: boolean | string; + /** + * Process output folder with formatter? + * @default true + */ + format?: boolean; /** * The relative location of the OpenAPI spec */ input: string | Record; + /** + * Process output folder with linter? + * @default false + */ + lint?: boolean; /** * Custom client class name */ diff --git a/src/utils/__tests__/handlebars.spec.ts b/src/utils/__tests__/handlebars.spec.ts index bf2995889..d935781db 100644 --- a/src/utils/__tests__/handlebars.spec.ts +++ b/src/utils/__tests__/handlebars.spec.ts @@ -7,14 +7,15 @@ describe('registerHandlebarHelpers', () => { it('should register the helpers', () => { registerHandlebarHelpers( { - autoformat: true, client: 'fetch', enums: true, exportCore: true, exportModels: true, exportSchemas: true, exportServices: true, + format: true, input: '', + lint: false, operationId: true, output: '', postfixModels: '', @@ -59,14 +60,15 @@ describe('registerHandlebarTemplates', () => { it('should return correct templates', () => { const templates = registerHandlebarTemplates( { - autoformat: true, client: 'fetch', enums: true, exportCore: true, exportModels: true, exportSchemas: true, exportServices: true, + format: true, input: '', + lint: false, operationId: true, output: '', postfixModels: '', diff --git a/src/utils/write/__tests__/client.spec.ts b/src/utils/write/__tests__/client.spec.ts index 810c42dba..96b2dd99e 100644 --- a/src/utils/write/__tests__/client.spec.ts +++ b/src/utils/write/__tests__/client.spec.ts @@ -37,14 +37,15 @@ describe('writeClient', () => { }; await writeClient(client, templates, { - autoformat: true, client: 'fetch', enums: true, exportCore: true, exportModels: true, exportSchemas: true, exportServices: true, + format: true, input: '', + lint: false, operationId: true, output: './dist', postfixModels: 'AppClient', diff --git a/src/utils/write/__tests__/services.spec.ts b/src/utils/write/__tests__/services.spec.ts index 83792edbb..c921291b9 100644 --- a/src/utils/write/__tests__/services.spec.ts +++ b/src/utils/write/__tests__/services.spec.ts @@ -45,14 +45,15 @@ describe('writeClientServices', () => { }; await writeClientServices(client, templates, '/', { - autoformat: false, client: 'fetch', enums: false, exportCore: true, exportModels: true, exportSchemas: true, exportServices: true, + format: false, input: '', + lint: false, operationId: true, output: '', postfixModels: '', diff --git a/test/bin.spec.ts b/test/bin.spec.ts index 3249ed63d..2ad4d3872 100755 --- a/test/bin.spec.ts +++ b/test/bin.spec.ts @@ -135,7 +135,7 @@ describe('bin', () => { expect(result.stderr.toString()).toBe(''); }); - it('autoformats output with Prettier', async () => { + it('formats output with Prettier', async () => { const result = sync('node', [ './bin/index.js', '--input', @@ -147,15 +147,16 @@ describe('bin', () => { expect(result.stderr.toString()).toBe(''); }); - it('auto fixes output with Eslint', async () => { + it('lints output with ESLint', async () => { const result = sync('node', [ './bin/index.js', '--input', './test/spec/v3.json', '--output', './test/generated/bin', + '--lint', ]); - expect(result.stdout.toString()).toContain('Eslint'); + expect(result.stdout.toString()).toContain('ESLint'); expect(result.stderr.toString()).toBe(''); });