fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #399 from hey-api/fix/0-39-1

fix: export enums from index.ts

authored by

Lubos and committed by
GitHub
dad799de d0cc1a31

+285 -190
+5
.changeset/polite-rice-leave.md
··· 1 + --- 2 + "@hey-api/openapi-ts": patch 3 + --- 4 + 5 + fix: rename models.gen.ts to types.gen.ts
+5
.changeset/spicy-numbers-smell.md
··· 1 + --- 2 + "@hey-api/openapi-ts": patch 3 + --- 4 + 5 + fix: export enums from index.ts
+23 -6
docs/openapi-ts/migrating.md
··· 19 19 export { ApiError } from './core/ApiError'; 20 20 export { CancelablePromise, CancelError } from './core/CancelablePromise'; 21 21 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 22 - export * from './models'; // [!code --] 23 - export * from './schemas'; // [!code --] 24 - export * from './services'; // [!code --] 22 + export * from './enums.gen'; // [!code --] 23 + export * from './schemas.gen'; // [!code --] 24 + export * from './services.gen'; // [!code --] 25 + export * from './types.gen'; // [!code --] 25 26 ``` 26 27 27 28 Any non-core related imports should be imported as 28 29 29 30 ```js 30 - import type { Model } from 'client/models'; 31 - import { $Schema } from 'client/schemas'; 32 - import { DefaultService } from 'client/services'; 31 + import { Enum } from 'client/enums.gen' 32 + import { $Schema } from 'client/schemas.gen'; 33 + import { DefaultService } from 'client/services.gen'; 34 + import type { Model } from 'client/types.gen'; 33 35 ``` 34 36 35 37 You don't have to update imports from `core` directory. These will be addressed in later releases. ··· 49 51 ### Deprecated `name` 50 52 51 53 This config option is deprecated and will be removed. 54 + 55 + ## v0.40.0 56 + 57 + ### Exported `enums.gen.ts` file 58 + 59 + Enums are now re-exported from the main `index.ts` file. This enables a cleaner migration to v0.39.0. 60 + 61 + ### Renamed `models.gen.ts` file 62 + 63 + `models.gen.ts` is now called `types.gen.ts`. If you use imports from `models.gen.ts`, you should be able to easily find and replace all instances. 64 + 65 + ```js 66 + import type { Model } from 'client/models.gen' // [!code --] 67 + import type { Model } from 'client/types.gen' // [!code ++] 68 + ``` 52 69 53 70 ## v0.39.0 54 71
+36 -18
packages/openapi-ts/src/compiler/index.ts
··· 14 14 export type { Comments } from './utils'; 15 15 export type { ClassElement, Node, TypeNode } from 'typescript'; 16 16 17 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 18 - export const generatedFileName = (fileName: string, insertGen = true) => { 17 + const splitNameAndExtension = (fileName: string) => { 19 18 const match = fileName.match(/\.[0-9a-z]+$/i); 20 19 const extension = match ? match[0].slice(1) : ''; 21 - const filePath = fileName.slice(0, fileName.length - (extension ? extension.length + 1 : 0)); 22 - return [filePath, insertGen && 'gen', extension].filter(Boolean).join('.'); 23 - }; 24 - 25 - export const filePath = (folderPath: string, fileName: string, insertGen = true) => { 26 - const name = generatedFileName(fileName, insertGen); 27 - return path.resolve(folderPath, name); 20 + const name = fileName.slice(0, fileName.length - (extension ? extension.length + 1 : 0)); 21 + return { extension, name }; 28 22 }; 29 23 30 24 export class TypeScriptFile { 31 25 private _headers: Array<string> = []; 32 26 private _imports: Array<ts.Node> = []; 33 27 private _items: Array<ts.Node | string> = []; 28 + private _name: string; 34 29 private _path: PathLike; 35 30 36 - public constructor({ path, header = true }: { path: PathLike; header?: boolean }) { 37 - this._path = path; 31 + public constructor({ dir, name, header = true }: { dir: string; name: string; header?: boolean }) { 32 + this._name = this._setName(name); 33 + this._path = path.resolve(dir, this.getName()); 34 + 38 35 if (header) { 39 36 const text = 'This file is auto-generated by @hey-api/openapi-ts'; 40 37 const comment = addLeadingComment(undefined, [text], true, false); ··· 46 43 this._items = [...this._items, ...nodes]; 47 44 } 48 45 49 - public addNamedImport(...params: Parameters<typeof module.createNamedImportDeclarations>): void { 46 + public addNamedImport(...params: Parameters<typeof compiler.import.named>): void { 50 47 this._imports = [...this._imports, compiler.import.named(...params)]; 51 48 } 52 49 50 + public getName(withExtension = true) { 51 + if (withExtension) { 52 + return this._name; 53 + } 54 + 55 + const { name } = splitNameAndExtension(this._name); 56 + return name; 57 + } 58 + 59 + public isEmpty() { 60 + return !this._items.length; 61 + } 62 + 63 + public remove(options?: Parameters<typeof rmSync>[1]) { 64 + rmSync(this._path, options); 65 + } 66 + 67 + private _setName(fileName: string) { 68 + if (fileName.includes('index')) { 69 + return fileName; 70 + } 71 + 72 + const { extension, name } = splitNameAndExtension(fileName); 73 + return [name, 'gen', extension].filter(Boolean).join('.'); 74 + } 75 + 53 76 public toString(seperator: string = '\n') { 54 77 let output: string[] = []; 55 78 if (this._headers.length) { ··· 63 86 } 64 87 65 88 public write(seperator = '\n') { 66 - // TODO: throw if path is not set. do not throw if items are empty 67 - if (!this._items.length || !this._path) { 89 + if (this.isEmpty()) { 68 90 this.remove({ force: true }); 69 91 return; 70 92 } 71 93 writeFileSync(this._path, this.toString(seperator)); 72 - } 73 - 74 - public remove(options?: Parameters<typeof rmSync>[1]) { 75 - rmSync(this._path, options); 76 94 } 77 95 } 78 96
+27 -9
packages/openapi-ts/src/utils/write/__tests__/index.spec.ts
··· 3 3 4 4 import { describe, expect, it, vi } from 'vitest'; 5 5 6 + import { TypeScriptFile } from '../../../compiler'; 6 7 import { setConfig } from '../../config'; 7 - import { writeClientIndex } from '../index'; 8 + import { processIndex } from '../index'; 8 9 9 10 vi.mock('node:fs'); 10 11 11 - describe('writeClientIndex', () => { 12 + describe('processIndex', () => { 12 13 it('writes to filesystem', async () => { 13 14 setConfig({ 14 15 client: 'fetch', ··· 30 31 useOptions: true, 31 32 }); 32 33 33 - const client: Parameters<typeof writeClientIndex>[0] = { 34 - enumNames: [], 35 - models: [], 36 - server: 'http://localhost:8080', 37 - services: [], 38 - version: '1.0', 34 + const files: Parameters<typeof processIndex>[0]['files'] = { 35 + enums: new TypeScriptFile({ 36 + dir: '/', 37 + name: 'enums.ts', 38 + }), 39 + index: new TypeScriptFile({ 40 + dir: '/', 41 + name: 'index.ts', 42 + }), 43 + schemas: new TypeScriptFile({ 44 + dir: '/', 45 + name: 'schemas.ts', 46 + }), 47 + services: new TypeScriptFile({ 48 + dir: '/', 49 + name: 'services.ts', 50 + }), 51 + types: new TypeScriptFile({ 52 + dir: '/', 53 + name: 'models.ts', 54 + }), 39 55 }; 40 56 41 - await writeClientIndex(client, '/'); 57 + await processIndex({ files }); 58 + 59 + files.index.write(); 42 60 43 61 expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/', '/index.ts'), expect.anything()); 44 62 });
+22 -6
packages/openapi-ts/src/utils/write/__tests__/models.spec.ts
··· 3 3 4 4 import { describe, expect, it, vi } from 'vitest'; 5 5 6 + import { TypeScriptFile } from '../../../compiler'; 6 7 import { setConfig } from '../../config'; 7 - import { writeTypesAndEnums } from '../models'; 8 - import { openApi } from './models'; 8 + import { processTypesAndEnums } from '../models'; 9 9 10 10 vi.mock('node:fs'); 11 11 12 - describe('writeTypesAndEnums', () => { 12 + describe('processTypesAndEnums', () => { 13 13 it('writes to filesystem', async () => { 14 14 setConfig({ 15 15 client: 'fetch', ··· 32 32 useOptions: true, 33 33 }); 34 34 35 - const client: Parameters<typeof writeTypesAndEnums>[2] = { 35 + const client: Parameters<typeof processTypesAndEnums>[0]['client'] = { 36 36 enumNames: [], 37 37 models: [ 38 38 { ··· 59 59 version: 'v1', 60 60 }; 61 61 62 - await writeTypesAndEnums(openApi, '/', client); 62 + const fileEnums = new TypeScriptFile({ 63 + dir: '/', 64 + name: 'enums.ts', 65 + }); 66 + const fileModels = new TypeScriptFile({ 67 + dir: '/', 68 + name: 'models.ts', 69 + }); 63 70 64 - expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/', '/models.gen.ts'), expect.anything()); 71 + await processTypesAndEnums({ 72 + client, 73 + fileEnums, 74 + fileModels, 75 + }); 76 + 77 + fileEnums.write(); 78 + fileModels.write(); 79 + 80 + expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/models.gen.ts'), expect.anything()); 65 81 }); 66 82 });
+12 -4
packages/openapi-ts/src/utils/write/__tests__/schemas.spec.ts
··· 3 3 4 4 import { describe, expect, it, vi } from 'vitest'; 5 5 6 + import { TypeScriptFile } from '../../../compiler'; 6 7 import { setConfig } from '../../config'; 7 - import { writeSchemas } from '../schemas'; 8 + import { processSchemas } from '../schemas'; 8 9 import { openApi } from './models'; 9 10 10 11 vi.mock('node:fs'); 11 12 12 - describe('writeSchemas', () => { 13 + describe('processSchemas', () => { 13 14 it('writes to filesystem', async () => { 14 15 setConfig({ 15 16 client: 'fetch', ··· 42 43 }; 43 44 } 44 45 45 - await writeSchemas(openApi, '/'); 46 + const file = new TypeScriptFile({ 47 + dir: '/', 48 + name: 'schemas.ts', 49 + }); 50 + 51 + await processSchemas({ file, openApi }); 52 + 53 + file.write(); 46 54 47 - expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/', '/schemas.gen.ts'), expect.anything()); 55 + expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/schemas.gen.ts'), expect.anything()); 48 56 }); 49 57 });
+17 -6
packages/openapi-ts/src/utils/write/__tests__/services.spec.ts
··· 1 1 import { writeFileSync } from 'node:fs'; 2 + import path from 'node:path'; 2 3 3 4 import { describe, expect, it, vi } from 'vitest'; 4 5 6 + import { TypeScriptFile } from '../../../compiler'; 5 7 import { setConfig } from '../../config'; 6 - import { writeServices } from '../services'; 7 - import { openApi } from './models'; 8 + import { processServices } from '../services'; 8 9 9 10 vi.mock('node:fs'); 10 11 11 - describe('writeServices', () => { 12 + describe('processServices', () => { 12 13 it('writes to filesystem', async () => { 13 14 setConfig({ 14 15 client: 'fetch', ··· 30 31 useOptions: false, 31 32 }); 32 33 33 - const client: Parameters<typeof writeServices>[2] = { 34 + const client: Parameters<typeof processServices>[0]['client'] = { 34 35 enumNames: [], 35 36 models: [], 36 37 server: 'http://localhost:8080', ··· 45 46 version: 'v1', 46 47 }; 47 48 48 - await writeServices(openApi, '/', client); 49 + const file = new TypeScriptFile({ 50 + dir: '/', 51 + name: 'services.ts', 52 + }); 53 + const files = { 54 + services: file, 55 + }; 56 + 57 + await processServices({ client, files }); 58 + 59 + file.write(); 49 60 50 - expect(writeFileSync).toHaveBeenCalled(); 61 + expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/services.gen.ts'), expect.anything()); 51 62 }); 52 63 });
+53 -33
packages/openapi-ts/src/utils/write/client.ts
··· 1 1 import { existsSync, mkdirSync } from 'node:fs'; 2 2 import path from 'node:path'; 3 3 4 + import { TypeScriptFile } from '../../compiler'; 4 5 import type { OpenApi } from '../../openApi'; 5 6 import type { Client } from '../../types/client'; 6 7 import { getConfig } from '../config'; 7 8 import type { Templates } from '../handlebars'; 8 9 import { writeClientClass } from './class'; 9 10 import { writeCore } from './core'; 10 - import { writeClientIndex } from './index'; 11 - import { writeTypesAndEnums } from './models'; 12 - import { writeSchemas } from './schemas'; 13 - import { writeServices } from './services'; 11 + import { processIndex } from './index'; 12 + import { processTypesAndEnums } from './models'; 13 + import { processSchemas } from './schemas'; 14 + import { processServices } from './services'; 14 15 15 16 /** 16 17 * Write our OpenAPI client, using the given templates at the given output ··· 31 32 client.models = client.models.filter(model => regexp.test(model.name)); 32 33 } 33 34 34 - if (!existsSync(path.resolve(config.output))) { 35 - mkdirSync(path.resolve(config.output), { recursive: true }); 35 + const outputPath = path.resolve(config.output); 36 + 37 + if (!existsSync(outputPath)) { 38 + mkdirSync(outputPath, { recursive: true }); 36 39 } 37 40 38 - const sections = [ 39 - { 40 - dir: 'core', 41 - fn: writeCore, 42 - }, 43 - { 44 - dir: '', 45 - fn: writeSchemas, 46 - }, 47 - { 48 - dir: '', 49 - fn: writeTypesAndEnums, 50 - }, 51 - { 52 - dir: '', 53 - fn: writeServices, 54 - }, 55 - { 56 - dir: '', 57 - fn: writeClientClass, 58 - }, 59 - ] as const; 60 - 61 - for (const section of sections) { 62 - const sectionPath = path.resolve(config.output, section.dir); 63 - await section.fn(openApi, sectionPath, client, templates); 41 + const files: Record<string, TypeScriptFile> = { 42 + index: new TypeScriptFile({ 43 + dir: config.output, 44 + name: 'index.ts', 45 + }), 46 + }; 47 + if (config.enums) { 48 + files.enums = new TypeScriptFile({ 49 + dir: config.output, 50 + name: 'enums.ts', 51 + }); 52 + } 53 + if (config.schemas) { 54 + files.schemas = new TypeScriptFile({ 55 + dir: config.output, 56 + name: 'schemas.ts', 57 + }); 58 + } 59 + if (config.exportServices) { 60 + files.services = new TypeScriptFile({ 61 + dir: config.output, 62 + name: 'services.ts', 63 + }); 64 + } 65 + if (config.exportModels) { 66 + files.types = new TypeScriptFile({ 67 + dir: config.output, 68 + name: 'types.ts', 69 + }); 64 70 } 65 71 66 - await writeClientIndex(client, config.output); 72 + await processSchemas({ file: files.schemas, openApi }); 73 + await processTypesAndEnums({ client, fileEnums: files.enums, fileModels: files.types }); 74 + await processServices({ client, files }); 75 + 76 + // deprecated files 77 + await writeClientClass(openApi, outputPath, client, templates); 78 + await writeCore(openApi, path.resolve(config.output, 'core'), client, templates); 79 + 80 + await processIndex({ files }); 81 + 82 + files.enums?.write('\n\n'); 83 + files.schemas?.write('\n\n'); 84 + files.services?.write('\n\n'); 85 + files.types?.write('\n\n'); 86 + files.index.write(); 67 87 };
+18 -29
packages/openapi-ts/src/utils/write/index.ts
··· 1 - import { compiler, filePath, generatedFileName, TypeScriptFile } from '../../compiler'; 2 - import type { Client } from '../../types/client'; 1 + import { compiler, TypeScriptFile } from '../../compiler'; 3 2 import { getConfig } from '../config'; 4 3 5 - /** 6 - * Generate the OpenAPI client index file and write it to disk. 7 - * The index file just contains all the exports you need to use the client as a standalone. 8 - * @param client Client containing models, schemas, and services 9 - * @param outputPath Directory to write the generated files to 10 - */ 11 - export const writeClientIndex = async (client: Client, outputPath: string): Promise<void> => { 4 + export const processIndex = async ({ files }: { files: Record<string, TypeScriptFile> }): Promise<void> => { 12 5 const config = getConfig(); 13 6 14 - const fileIndex = new TypeScriptFile({ path: filePath(outputPath, 'index.ts', false) }); 15 - 16 7 if (config.name) { 17 - fileIndex.add(compiler.export.named([config.name], `./${config.name}`)); 8 + files.index.add(compiler.export.named([config.name], `./${config.name}`)); 18 9 } 19 10 20 11 if (config.exportCore) { 21 - fileIndex.add(compiler.export.named('ApiError', './core/ApiError')); 12 + files.index.add(compiler.export.named('ApiError', './core/ApiError')); 22 13 if (config.serviceResponse === 'response') { 23 - fileIndex.add(compiler.export.named({ isTypeOnly: true, name: 'ApiResult' }, './core/ApiResult')); 14 + files.index.add(compiler.export.named({ isTypeOnly: true, name: 'ApiResult' }, './core/ApiResult')); 24 15 } 25 16 if (config.name) { 26 - fileIndex.add(compiler.export.named('BaseHttpRequest', './core/BaseHttpRequest')); 17 + files.index.add(compiler.export.named('BaseHttpRequest', './core/BaseHttpRequest')); 27 18 } 28 19 if (config.client !== 'angular') { 29 - fileIndex.add(compiler.export.named(['CancelablePromise', 'CancelError'], './core/CancelablePromise')); 20 + files.index.add(compiler.export.named(['CancelablePromise', 'CancelError'], './core/CancelablePromise')); 30 21 } 31 - fileIndex.add( 22 + files.index.add( 32 23 compiler.export.named(['OpenAPI', { isTypeOnly: true, name: 'OpenAPIConfig' }], './core/OpenAPI') 33 24 ); 34 25 } 35 26 36 - if (client.models.length) { 37 - if (config.exportModels) { 38 - fileIndex.add(compiler.export.all(generatedFileName('./models'))); 39 - } 40 - if (config.schemas) { 41 - fileIndex.add(compiler.export.all(generatedFileName('./schemas'))); 42 - } 27 + if (files.enums && !files.enums.isEmpty()) { 28 + files.index.add(compiler.export.all(`./${files.enums.getName(false)}`)); 29 + } 30 + if (files.schemas && !files.schemas.isEmpty()) { 31 + files.index.add(compiler.export.all(`./${files.schemas.getName(false)}`)); 32 + } 33 + if (files.services && !files.services.isEmpty()) { 34 + files.index.add(compiler.export.all(`./${files.services.getName(false)}`)); 43 35 } 44 - 45 - if (client.services.length && config.exportServices) { 46 - fileIndex.add(compiler.export.all(generatedFileName('./services'))); 36 + if (files.types && !files.types.isEmpty()) { 37 + files.index.add(compiler.export.all(`./${files.types.getName(false)}`)); 47 38 } 48 - 49 - fileIndex.write(); 50 39 };
+14 -22
packages/openapi-ts/src/utils/write/models.ts
··· 1 - import { type Comments, compiler, filePath, type Node, TypeScriptFile } from '../../compiler'; 1 + import { type Comments, compiler, type Node, TypeScriptFile } from '../../compiler'; 2 2 import { addLeadingComment } from '../../compiler/utils'; 3 - import type { Model, OpenApi, OperationParameter, Service } from '../../openApi'; 3 + import type { Model, OperationParameter, Service } from '../../openApi'; 4 4 import { ensureValidTypeScriptJavaScriptIdentifier } from '../../openApi/common/parser/sanitize'; 5 5 import type { Client } from '../../types/client'; 6 6 import { getConfig } from '../config'; ··· 214 214 onNode(node); 215 215 }; 216 216 217 - /** 218 - * Generate Models using the Handlebar template and write to disk. 219 - * @param openApi {@link OpenApi} Dereferenced OpenAPI specification 220 - * @param outputPath Directory to write the generated files to 221 - * @param client Client containing models, schemas, and services 222 - */ 223 - export const writeTypesAndEnums = async (openApi: OpenApi, outputPath: string, client: Client): Promise<void> => { 224 - const config = getConfig(); 225 - 226 - const fileEnums = new TypeScriptFile({ path: filePath(outputPath, 'enums.ts') }); 227 - const fileModels = new TypeScriptFile({ path: filePath(outputPath, 'models.ts') }); 228 - 217 + export const processTypesAndEnums = async ({ 218 + client, 219 + fileEnums, 220 + fileModels, 221 + }: { 222 + client: Client; 223 + fileEnums?: TypeScriptFile; 224 + fileModels?: TypeScriptFile; 225 + }): Promise<void> => { 229 226 for (const model of client.models) { 230 227 processModel(client, model, (node, type) => { 231 228 if (type === 'enum') { 232 - fileEnums.add(node); 229 + fileEnums?.add(node); 233 230 } else { 234 - fileModels.add(node); 231 + fileModels?.add(node); 235 232 } 236 233 }); 237 234 } 238 235 239 236 if (client.services.length) { 240 237 processServiceTypes(client.services, node => { 241 - fileModels.add(node); 238 + fileModels?.add(node); 242 239 }); 243 - } 244 - 245 - if (config.exportModels) { 246 - fileEnums.write('\n\n'); 247 - fileModels.write('\n\n'); 248 240 } 249 241 };
+6 -16
packages/openapi-ts/src/utils/write/schemas.ts
··· 1 - import { compiler, filePath, TypeScriptFile } from '../../compiler'; 1 + import { compiler, TypeScriptFile } from '../../compiler'; 2 2 import type { OpenApi } from '../../openApi'; 3 3 import { ensureValidTypeScriptJavaScriptIdentifier } from '../../openApi/common/parser/sanitize'; 4 - import { getConfig } from '../config'; 5 4 6 - /** 7 - * Generate Schemas using the Handlebar template and write to disk. 8 - * @param openApi {@link OpenApi} Dereferenced OpenAPI specification 9 - * @param outputPath Directory to write the generated files to 10 - */ 11 - export const writeSchemas = async (openApi: OpenApi, outputPath: string): Promise<void> => { 12 - const config = getConfig(); 13 - 14 - const fileSchemas = new TypeScriptFile({ path: filePath(outputPath, 'schemas.ts') }); 5 + export const processSchemas = async ({ file, openApi }: { file?: TypeScriptFile; openApi: OpenApi }): Promise<void> => { 6 + if (!file) { 7 + return; 8 + } 15 9 16 10 const addSchema = (name: string, obj: any) => { 17 11 const validName = `$${ensureValidTypeScriptJavaScriptIdentifier(name)}`; 18 12 const expression = compiler.types.object({ obj }); 19 13 const statement = compiler.export.asConst(validName, expression); 20 - fileSchemas.add(statement); 14 + file.add(statement); 21 15 }; 22 16 23 17 // OpenAPI 2.0 ··· 46 40 } 47 41 } 48 42 } 49 - } 50 - 51 - if (config.schemas) { 52 - fileSchemas.write('\n\n'); 53 43 } 54 44 };
+27 -25
packages/openapi-ts/src/utils/write/services.ts
··· 1 - import { ClassElement, compiler, filePath, FunctionParameter, generatedFileName, TypeScriptFile } from '../../compiler'; 2 - import type { OpenApi, Operation, OperationParameter, Service } from '../../openApi'; 1 + import { ClassElement, compiler, FunctionParameter, TypeScriptFile } from '../../compiler'; 2 + import type { Operation, OperationParameter, Service } from '../../openApi'; 3 3 import type { Client } from '../../types/client'; 4 4 import { getConfig } from '../config'; 5 5 import { escapeComment, escapeDescription, escapeName } from '../escape'; ··· 209 209 }); 210 210 }; 211 211 212 - /** 213 - * Generate Services using the Handlebar template and write to disk. 214 - * @param openApi {@link OpenApi} Dereferenced OpenAPI specification 215 - * @param outputPath Directory to write the generated files to 216 - * @param client Client containing models, schemas, and services 217 - */ 218 - export const writeServices = async (openApi: OpenApi, outputPath: string, client: Client): Promise<void> => { 219 - const config = getConfig(); 212 + export const processServices = async ({ 213 + client, 214 + files, 215 + }: { 216 + client: Client; 217 + files: Record<string, TypeScriptFile>; 218 + }): Promise<void> => { 219 + const file = files.services; 220 220 221 - const fileServices = new TypeScriptFile({ path: filePath(outputPath, 'services.ts') }); 221 + if (!file) { 222 + return; 223 + } 224 + 225 + const config = getConfig(); 222 226 223 227 let imports: string[] = []; 224 228 225 229 for (const service of client.services) { 226 - fileServices.add(processService(service)); 230 + file.add(processService(service)); 227 231 const exported = serviceExportedNamespace(); 228 232 imports = [...imports, exported]; 229 233 } 230 234 231 235 // Import required packages and core files. 232 236 if (config.client === 'angular') { 233 - fileServices.addNamedImport('Injectable', '@angular/core'); 237 + file.addNamedImport('Injectable', '@angular/core'); 234 238 if (config.name === undefined) { 235 - fileServices.addNamedImport('HttpClient', '@angular/common/http'); 239 + file.addNamedImport('HttpClient', '@angular/common/http'); 236 240 } 237 - fileServices.addNamedImport({ isTypeOnly: true, name: 'Observable' }, 'rxjs'); 241 + file.addNamedImport({ isTypeOnly: true, name: 'Observable' }, 'rxjs'); 238 242 } else { 239 - fileServices.addNamedImport({ isTypeOnly: true, name: 'CancelablePromise' }, './core/CancelablePromise'); 243 + file.addNamedImport({ isTypeOnly: true, name: 'CancelablePromise' }, './core/CancelablePromise'); 240 244 } 241 245 if (config.serviceResponse === 'response') { 242 - fileServices.addNamedImport({ isTypeOnly: true, name: 'ApiResult' }, './core/ApiResult'); 246 + file.addNamedImport({ isTypeOnly: true, name: 'ApiResult' }, './core/ApiResult'); 243 247 } 244 248 if (config.name) { 245 - fileServices.addNamedImport( 249 + file.addNamedImport( 246 250 { isTypeOnly: config.client !== 'angular', name: 'BaseHttpRequest' }, 247 251 './core/BaseHttpRequest' 248 252 ); 249 253 } else { 250 - fileServices.addNamedImport('OpenAPI', './core/OpenAPI'); 251 - fileServices.addNamedImport({ alias: '__request', name: 'request' }, './core/request'); 254 + file.addNamedImport('OpenAPI', './core/OpenAPI'); 255 + file.addNamedImport({ alias: '__request', name: 'request' }, './core/request'); 252 256 } 253 257 254 258 // Import all models required by the services. 255 - const models = imports.filter(unique).map(imp => ({ isTypeOnly: true, name: imp })); 256 - fileServices.addNamedImport(models, generatedFileName('./models')); 257 - 258 - if (config.exportServices) { 259 - fileServices.write('\n\n'); 259 + if (files.types && !files.types.isEmpty()) { 260 + const models = imports.filter(unique).map(name => ({ isTypeOnly: true, name })); 261 + file.addNamedImport(models, `./${files.types.getName(false)}`); 260 262 } 261 263 };
+2 -1
packages/openapi-ts/test/__snapshots__/test/generated/v2/index.ts.snap
··· 3 3 export { ApiError } from './core/ApiError'; 4 4 export { CancelablePromise, CancelError } from './core/CancelablePromise'; 5 5 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 6 - export * from './models.gen'; 6 + export * from './enums.gen'; 7 7 export * from './schemas.gen'; 8 8 export * from './services.gen'; 9 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v2/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v2/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v2/services.gen.ts.snap
··· 3 3 import type { CancelablePromise } from './core/CancelablePromise'; 4 4 import { OpenAPI } from './core/OpenAPI'; 5 5 import { request as __request } from './core/request'; 6 - import type { $OpenApiTs } from './models.gen'; 6 + import type { $OpenApiTs } from './types.gen'; 7 7 8 8 export class DefaultService { 9 9 /**
+2 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3/index.ts.snap
··· 3 3 export { ApiError } from './core/ApiError'; 4 4 export { CancelablePromise, CancelError } from './core/CancelablePromise'; 5 5 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 6 - export * from './models.gen'; 6 + export * from './enums.gen'; 7 7 export * from './schemas.gen'; 8 8 export * from './services.gen'; 9 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3/services.gen.ts.snap
··· 3 3 import type { CancelablePromise } from './core/CancelablePromise'; 4 4 import { OpenAPI } from './core/OpenAPI'; 5 5 import { request as __request } from './core/request'; 6 - import type { $OpenApiTs } from './models.gen'; 6 + import type { $OpenApiTs } from './types.gen'; 7 7 8 8 export class DefaultService { 9 9 /**
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/index.ts.snap
··· 2 2 3 3 export { ApiError } from './core/ApiError'; 4 4 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 5 - export * from './models.gen'; 6 5 export * from './schemas.gen'; 7 6 export * from './services.gen'; 7 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/services.gen.ts.snap
··· 5 5 import type { Observable } from 'rxjs'; 6 6 import { OpenAPI } from './core/OpenAPI'; 7 7 import { request as __request } from './core/request'; 8 - import type { $OpenApiTs } from './models.gen'; 8 + import type { $OpenApiTs } from './types.gen'; 9 9 10 10 @Injectable({ 11 11 providedIn: 'root',
+2 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_client/index.ts.snap
··· 5 5 export { BaseHttpRequest } from './core/BaseHttpRequest'; 6 6 export { CancelablePromise, CancelError } from './core/CancelablePromise'; 7 7 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 8 - export * from './models.gen'; 8 + export * from './enums.gen'; 9 9 export * from './services.gen'; 10 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3_client/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3_client/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_client/services.gen.ts.snap
··· 2 2 3 3 import type { CancelablePromise } from './core/CancelablePromise'; 4 4 import type { BaseHttpRequest } from './core/BaseHttpRequest'; 5 - import type { $OpenApiTs } from './models.gen'; 5 + import type { $OpenApiTs } from './types.gen'; 6 6 7 7 export class DefaultService { 8 8 constructor(public readonly httpRequest: BaseHttpRequest) {}
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_date/index.ts.snap
··· 1 1 // This file is auto-generated by @hey-api/openapi-ts 2 2 3 - export * from './models.gen'; 4 3 export * from './schemas.gen'; 4 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3_date/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3_date/types.gen.ts.snap
+2 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/index.ts.snap
··· 3 3 export { ApiError } from './core/ApiError'; 4 4 export { CancelablePromise, CancelError } from './core/CancelablePromise'; 5 5 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 6 - export * from './models.gen'; 6 + export * from './enums.gen'; 7 7 export * from './schemas.gen'; 8 8 export * from './services.gen'; 9 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/services.gen.ts.snap
··· 3 3 import type { CancelablePromise } from './core/CancelablePromise'; 4 4 import { OpenAPI } from './core/OpenAPI'; 5 5 import { request as __request } from './core/request'; 6 - import type { $OpenApiTs } from './models.gen'; 6 + import type { $OpenApiTs } from './types.gen'; 7 7 8 8 export class DefaultService { 9 9 /**
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_legacy_positional_args/index.ts.snap
··· 3 3 export { ApiError } from './core/ApiError'; 4 4 export { CancelablePromise, CancelError } from './core/CancelablePromise'; 5 5 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 6 - export * from './models.gen'; 7 6 export * from './services.gen'; 7 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3_legacy_positional_args/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3_legacy_positional_args/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_legacy_positional_args/services.gen.ts.snap
··· 3 3 import type { CancelablePromise } from './core/CancelablePromise'; 4 4 import { OpenAPI } from './core/OpenAPI'; 5 5 import { request as __request } from './core/request'; 6 - import type { $OpenApiTs } from './models.gen'; 6 + import type { $OpenApiTs } from './types.gen'; 7 7 8 8 export class DefaultsService { 9 9 /**
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_models/index.ts.snap
··· 1 1 // This file is auto-generated by @hey-api/openapi-ts 2 2 3 - export * from './models.gen'; 3 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3_models/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3_models/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_options/index.ts.snap
··· 3 3 export { ApiError } from './core/ApiError'; 4 4 export { CancelablePromise, CancelError } from './core/CancelablePromise'; 5 5 export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI'; 6 - export * from './models.gen'; 7 6 export * from './services.gen'; 7 + export * from './types.gen';
packages/openapi-ts/test/__snapshots__/test/generated/v3_options/models.gen.ts.snap packages/openapi-ts/test/__snapshots__/test/generated/v3_options/types.gen.ts.snap
+1 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3_options/services.gen.ts.snap
··· 3 3 import type { CancelablePromise } from './core/CancelablePromise'; 4 4 import { OpenAPI } from './core/OpenAPI'; 5 5 import { request as __request } from './core/request'; 6 - import type { $OpenApiTs } from './models.gen'; 6 + import type { $OpenApiTs } from './types.gen'; 7 7 8 8 export class DefaultsService { 9 9 /**