Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(client): generate schemas and models in one file each #168

Merged
merged 1 commit into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .changeset/rude-seas-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hey-api/openapi-ts": minor
---

generate all models in single `models.ts` file
5 changes: 5 additions & 0 deletions .changeset/yellow-years-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hey-api/openapi-ts": minor
---

generate all schemas in single `schemas.ts` file
2 changes: 0 additions & 2 deletions src/templates/exportModel.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
{{{modelImports this './'}}}

{{#equals export 'interface'}}
{{>exportInterface}}
{{else equals export 'one-of'}}
Expand Down
2 changes: 1 addition & 1 deletion src/templates/exportService.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { HttpClient } from '@angular/common/http';
import type { Observable } from 'rxjs';
{{/if}}
{{/equals}}
{{{modelImports this '../models/'}}}
{{{modelImports this '../models'}}}
{{#equals @root.$config.serviceResponse 'response'}}
import type { ApiResult } from '../core/ApiResult';
{{/equals}}
Expand Down
4 changes: 2 additions & 2 deletions src/utils/handlebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@
.replace(/\/\*/g, '*')
.replace(/\r?\n(.*)/g, (_, w) => `${EOL} * ${w.trim()}`);

const modelImports = (model: Model | Service, path: string) => {
const output = model.imports.map(item => `import type { ${item} } from '${path + item}';`);
const modelImports = (model: Service, path: string) => {
const output = model.imports.map(item => `import type { ${item} } from '${path}';`);

Check warning on line 104 in src/utils/handlebars.ts

View check run for this annotation

Codecov / codecov/patch

src/utils/handlebars.ts#L104

Added line #L104 was not covered by tests
return output.join('\n');
};

Expand Down
2 changes: 1 addition & 1 deletion src/utils/write/__tests__/models.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ describe('writeClientModels', () => {
write: true,
});

expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/', '/User.ts'), 'model');
expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/', '/models.ts'), 'model');
});
});
2 changes: 1 addition & 1 deletion src/utils/write/__tests__/schemas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ describe('writeClientSchemas', () => {
write: true,
});

expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/', '/$User.ts'), 'schema');
expect(writeFileSync).toHaveBeenCalledWith(path.resolve('/', '/schemas.ts'), 'schema');
});
});
4 changes: 2 additions & 2 deletions src/utils/write/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ export const writeClient = async (client: Client, templates: Templates, config:
fn: writeClientCore,
},
{
dir: 'schemas',
dir: '',
enabled: config.exportSchemas,
fn: writeClientSchemas,
},
{
dir: 'models',
dir: '',
enabled: config.exportModels,
fn: writeClientModels,
},
Expand Down
37 changes: 6 additions & 31 deletions src/utils/write/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import path from 'node:path';

import type { Client } from '../../types/client';
import type { Config } from '../../types/config';
import { enumName } from '../enum';
import type { Templates } from '../handlebars';

/**
Expand All @@ -19,39 +18,15 @@ export const writeClientModels = async (
outputPath: string,
config: Config
): Promise<void> => {
// Generate a file for each model.
// Generate a file with all models
const results: string[] = [];
for (const model of client.models) {
const file = path.resolve(outputPath, `${model.name}.ts`);
const templateResult = templates.exports.model({
const result = templates.exports.model({
$config: config,
...model,
});
await writeFileSync(file, templateResult);
results.push(result);
}
// Generate an index.ts file exporting all models from each file generated above.
const file = path.resolve(outputPath, 'index.ts');
const content = exportsModels(config, client);
await writeFileSync(file, content);
};

const exportsModels = (config: Config, client: Client) => {
const path = './';
const output = client.models.map(model => {
const importedModel = config.postfixModels
? `${model.name} as ${model.name + config.postfixModels}`
: model.name;
let result = [`export type { ${importedModel} } from '${path + model.name}';`];
if (config.enums && (model.enum.length || model.enums.length)) {
const names = model.enums.map(enumerator => enumerator.name).filter(Boolean);
const enumExports = names.length ? names : [model.name];
const enumExportsString = enumExports.map(name => enumName(name)).join(', ');
result = [...result, `export { ${enumExportsString} } from '${path + model.name}';`];
}
if (config.useLegacyEnums && model.enum.length) {
result = [`export { ${importedModel} } from '${path + model.name}';`];
}

return result.join('\n');
});
return output.join('\n');
const file = path.resolve(outputPath, 'models.ts');
writeFileSync(file, results.join('\n\n'));
};
15 changes: 6 additions & 9 deletions src/utils/write/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import path from 'node:path';
import type { Client } from '../../types/client';
import type { Config } from '../../types/config';
import type { Templates } from '../handlebars';
import { sortByName } from '../sort';

/**
* Generate Schemas using the Handlebar template and write to disk.
Expand All @@ -19,17 +18,15 @@ export const writeClientSchemas = async (
outputPath: string,
config: Config
): Promise<void> => {
// Generate file for each models schema.
// Generate file with all schemas
const results: string[] = [];
for (const model of client.models) {
const file = path.resolve(outputPath, `$${model.name}.ts`);
const templateResult = templates.exports.schema({
const result = templates.exports.schema({
$config: config,
...model,
});
await writeFileSync(file, templateResult);
results.push(result);
}
// Generate index file exporting all generated schema files.
const file = path.resolve(outputPath, 'index.ts');
const content = sortByName(client.models).map(model => `export { $${model.name} } from './$${model.name}';`);
await writeFileSync(file, content.join('\n'));
const file = path.resolve(outputPath, 'schemas.ts');
await writeFileSync(file, results.join('\n\n'));
};
Loading