Skip to content

Commit

Permalink
feat: change schemas name pattern, add schemas.name option
Browse files Browse the repository at this point in the history
  • Loading branch information
mrlubos committed Sep 4, 2024
1 parent 820d0de commit c6b044d
Show file tree
Hide file tree
Showing 11 changed files with 2,419 additions and 308 deletions.
6 changes: 6 additions & 0 deletions .changeset/violet-snakes-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@hey-api/openapi-ts': minor
'@hey-api/docs': minor
---

feat: change schemas name pattern, add schemas.name option
14 changes: 14 additions & 0 deletions docs/openapi-ts/migrating.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ This config option is deprecated and will be removed.

## v0.53.0

### Changed schemas name pattern

Previously, generated schemas would have their definition names prefixed with `$`. This was problematic when using them with Svelte due to reserved keyword conflicts. The new naming pattern for schemas suffixes their definition names with `Schema`. You can continue using the previous pattern by setting the `schemas.name` configuration option.

```js
export default {
input: 'path/to/openapi.json',
output: 'src/client',
schemas: {
name: (name) => `$${name}`, // [!code ++]
},
};
```

### Renamed legacy clients

Legacy clients were renamed to signal they are deprecated more clearly. To continue using legacy clients, you will need to update your configuration and prefix them with `legacy/`.
Expand Down
56 changes: 56 additions & 0 deletions packages/openapi-ts/src/generate/__tests__/schemas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'node:path';

import { describe, expect, it, vi } from 'vitest';

import type { OpenApiSchema } from '../../openApi/v3/interfaces/OpenApiSchema';
import type { Files } from '../../types/utils';
import { setConfig } from '../../utils/config';
import { generateSchemas } from '../schemas';
Expand Down Expand Up @@ -58,4 +59,59 @@ describe('generateSchemas', () => {
expect.anything(),
);
});

it('uses custom schema name', async () => {
const nameFn = vi.fn().mockReturnValue('customName');

setConfig({
client: {
name: 'legacy/fetch',
},
configFile: '',
debug: false,
dryRun: false,
experimental_parser: false,
exportCore: true,
input: '',
name: 'AppClient',
output: {
path: '',
},
plugins: [],
schemas: {
export: true,
name: nameFn,
},
services: {},
types: {
enums: 'javascript',
},
useOptions: true,
});

const schema: OpenApiSchema = {
type: 'object',
};

if ('openapi' in openApi) {
openApi.components = {
schemas: {
foo: schema,
},
};
}

const files: Files = {};

await generateSchemas({ files, openApi });

files.schemas.write();

expect(writeFileSync).toHaveBeenCalledWith(
expect.stringContaining(path.resolve('schemas.gen.ts')),
expect.anything(),
);

expect(nameFn).toHaveBeenCalledWith('foo', schema);
});
});
25 changes: 22 additions & 3 deletions packages/openapi-ts/src/generate/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { compiler, TypeScriptFile } from '../compiler';
import type { OpenApi } from '../openApi';
import { ensureValidTypeScriptJavaScriptIdentifier } from '../openApi/common/parser/sanitize';
import type { OpenApiSchema as OpenApiV2Schema } from '../openApi/v2/interfaces/OpenApiSchema';
import type { OpenApiSchema as OpenApiV3Schema } from '../openApi/v3/interfaces/OpenApiSchema';
import type { Files } from '../types/utils';
import { getConfig } from '../utils/config';

Expand Down Expand Up @@ -52,6 +54,21 @@ const ensureValidSchemaOutput = (
return result;
};

const toSchemaName = (
name: string,
schema: OpenApiV2Schema | OpenApiV3Schema,
): string => {
const config = getConfig();

const validName = ensureValidTypeScriptJavaScriptIdentifier(name);

if (config.schemas.name) {
return config.schemas.name(validName, schema);
}

return `${validName}Schema`;
};

export const generateSchemas = async ({
files,
openApi,
Expand All @@ -70,15 +87,17 @@ export const generateSchemas = async ({
name: 'schemas.ts',
});

const addSchema = (name: string, schema: object) => {
const validName = `$${ensureValidTypeScriptJavaScriptIdentifier(name)}`;
const addSchema = (
name: string,
schema: OpenApiV2Schema | OpenApiV3Schema,
) => {
const obj = ensureValidSchemaOutput(schema);
const expression = compiler.objectExpression({ obj });
const statement = compiler.constVariable({
assertion: 'const',
exportConst: true,
expression,
name: validName,
name: toSchemaName(name, schema),
});
files.schemas.add(statement);
};
Expand Down
13 changes: 12 additions & 1 deletion packages/openapi-ts/src/types/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Operation } from '../openApi';
import type { OpenApiSchema as OpenApiV2Schema } from '../openApi/v2/interfaces/OpenApiSchema';
import type { OpenApiSchema as OpenApiV3Schema } from '../openApi/v3/interfaces/OpenApiSchema';
import type { Plugins } from '../plugins/';
import type { ExtractArrayOfObjects } from './utils';

Expand Down Expand Up @@ -115,6 +117,15 @@ export interface ClientConfig {
* @default true
*/
export?: boolean;
/**
* Customise the schema name. By default, `{{name}}Schema` is used. `name` is a
* valid JavaScript/TypeScript identifier, e.g. if your schema name is
* "Foo-Bar", `name` value would be "FooBar".
*/
name?: (
name: string,
schema: OpenApiV2Schema | OpenApiV3Schema,
) => string;
/**
* Choose schema type to generate. Select 'form' if you don't want
* descriptions to reduce bundle size and you plan to use schemas
Expand Down Expand Up @@ -162,7 +173,7 @@ export interface ClientConfig {
*/
include?: string;
/**
* Customise the method name of methods within the service. By default, {@link Operation.name} is used.
* Customise the name of methods within the service. By default, {@link Operation.name} is used.
*/
methodNameBuilder?: (operation: Operation) => string;
/**
Expand Down
Loading

0 comments on commit c6b044d

Please sign in to comment.