Skip to content

Commit 54b3152

Browse files
committed
implement M5 - operation response factory
1 parent 3d1d001 commit 54b3152

12 files changed

Lines changed: 654 additions & 4 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// This file is auto-generated by @hey-api/openapi-ts
2+
3+
import { faker, type Faker } from '@faker-js/faker';
4+
5+
export type Options = {
6+
faker?: Faker;
7+
/**
8+
* Whether to include optional properties.
9+
* Provide a number between 0 and 1 to randomly include based on that probability.
10+
* @default true
11+
*/
12+
includeOptional?: boolean | number;
13+
/**
14+
* Whether to use schema default values instead of generating fake data.
15+
* Provide a number between 0 and 1 to randomly use defaults based on that probability.
16+
* @default false
17+
*/
18+
useDefault?: boolean | number;
19+
};
20+
21+
const resolveCondition = (condition: boolean | number, faker: Faker): boolean => condition === true || typeof condition === 'number' && faker.datatype.boolean({ probability: condition });
22+
23+
const ensureFaker = (options?: Options): Faker => options?.faker ?? faker;
24+
25+
export const fakePet = (options?: Options) => ({
26+
id: ensureFaker(options).string.uuid(),
27+
name: ensureFaker(options).string.sample(),
28+
...!resolveCondition(options?.includeOptional ?? true, ensureFaker(options)) ? {} : { age: ensureFaker(options).number.int({ min: 1, max: 120 }) }
29+
});
30+
31+
export const fakeError = (options?: Options) => ({
32+
code: ensureFaker(options).number.int(),
33+
message: ensureFaker(options).string.sample()
34+
});
35+
36+
export const fakeListPetsResponse = (options?: Options) => ensureFaker(options).helpers.multiple(() => fakePet(options));
37+
38+
export const fakeCreatePetResponse = (options?: Options) => fakePet(options);
39+
40+
export const fakeDeletePetResponse404 = (options?: Options) => fakeError(options);
41+
42+
export const fakeGetPetResponse200 = (options?: Options) => fakePet(options);
43+
44+
export const fakeGetPetResponse404 = (options?: Options) => fakeError(options);
45+
46+
export const fakeCreateJobResponse2Xx = (options?: Options) => fakePet(options);
47+
48+
export const fakeCreateJobResponse4Xx = (options?: Options) => fakeError(options);
49+
50+
export const fakeHealthCheckResponse = (options?: Options) => ensureFaker(options).string.sample();
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// This file is auto-generated by @hey-api/openapi-ts
2+
3+
import { faker, type Faker } from '@faker-js/faker';
4+
5+
import type { CreateJobErrors, CreateJobResponses, CreatePetResponse, DeletePetErrors, Error, GetPetErrors, GetPetResponses, HealthCheckResponse, ListPetsResponse, Pet } from '../types.gen';
6+
7+
export type Options = {
8+
faker?: Faker;
9+
/**
10+
* Whether to include optional properties.
11+
* Provide a number between 0 and 1 to randomly include based on that probability.
12+
* @default true
13+
*/
14+
includeOptional?: boolean | number;
15+
/**
16+
* Whether to use schema default values instead of generating fake data.
17+
* Provide a number between 0 and 1 to randomly use defaults based on that probability.
18+
* @default false
19+
*/
20+
useDefault?: boolean | number;
21+
};
22+
23+
const resolveCondition = (condition: boolean | number, faker: Faker): boolean => condition === true || typeof condition === 'number' && faker.datatype.boolean({ probability: condition });
24+
25+
const ensureFaker = (options?: Options): Faker => options?.faker ?? faker;
26+
27+
export const fakePet = (options?: Options): Pet => ({
28+
id: ensureFaker(options).string.uuid(),
29+
name: ensureFaker(options).string.sample(),
30+
...!resolveCondition(options?.includeOptional ?? true, ensureFaker(options)) ? {} : { age: ensureFaker(options).number.int({ min: 1, max: 120 }) }
31+
});
32+
33+
export const fakeError = (options?: Options): Error => ({
34+
code: ensureFaker(options).number.int(),
35+
message: ensureFaker(options).string.sample()
36+
});
37+
38+
export const fakeListPetsResponse = (options?: Options): ListPetsResponse => ensureFaker(options).helpers.multiple(() => fakePet(options));
39+
40+
export const fakeCreatePetResponse = (options?: Options): CreatePetResponse => fakePet(options);
41+
42+
export const fakeDeletePetResponse404 = (options?: Options): DeletePetErrors[404] => fakeError(options);
43+
44+
export const fakeGetPetResponse200 = (options?: Options): GetPetResponses[200] => fakePet(options);
45+
46+
export const fakeGetPetResponse404 = (options?: Options): GetPetErrors[404] => fakeError(options);
47+
48+
export const fakeCreateJobResponse2Xx = (options?: Options): CreateJobResponses['2XX'] => fakePet(options);
49+
50+
export const fakeCreateJobResponse4Xx = (options?: Options): CreateJobErrors['4XX'] => fakeError(options);
51+
52+
export const fakeHealthCheckResponse = (options?: Options): HealthCheckResponse => ensureFaker(options).string.sample();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// This file is auto-generated by @hey-api/openapi-ts
2+
3+
export type { ClientOptions, CreateJobData, CreateJobError, CreateJobErrors, CreateJobResponse, CreateJobResponses, CreatePetData, CreatePetResponse, CreatePetResponses, DeletePetData, DeletePetError, DeletePetErrors, DeletePetResponse, DeletePetResponses, Error, GetPetData, GetPetError, GetPetErrors, GetPetResponse, GetPetResponses, HealthCheckData, HealthCheckResponse, HealthCheckResponses, ListPetsData, ListPetsResponse, ListPetsResponses, Pet } from './types.gen';
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// This file is auto-generated by @hey-api/openapi-ts
2+
3+
export type ClientOptions = {
4+
baseUrl: `${string}://${string}` | (string & {});
5+
};
6+
7+
export type Pet = {
8+
id: string;
9+
name: string;
10+
age?: number;
11+
};
12+
13+
export type Error = {
14+
code: number;
15+
message: string;
16+
};
17+
18+
export type ListPetsData = {
19+
body?: never;
20+
path?: never;
21+
query?: never;
22+
url: '/pets';
23+
};
24+
25+
export type ListPetsResponses = {
26+
/**
27+
* A list of pets
28+
*/
29+
200: Array<Pet>;
30+
};
31+
32+
export type ListPetsResponse = ListPetsResponses[keyof ListPetsResponses];
33+
34+
export type CreatePetData = {
35+
body?: never;
36+
path?: never;
37+
query?: never;
38+
url: '/pets';
39+
};
40+
41+
export type CreatePetResponses = {
42+
/**
43+
* Pet created
44+
*/
45+
201: Pet;
46+
/**
47+
* No content
48+
*/
49+
204: void;
50+
};
51+
52+
export type CreatePetResponse = CreatePetResponses[keyof CreatePetResponses];
53+
54+
export type DeletePetData = {
55+
body?: never;
56+
path: {
57+
id: string;
58+
};
59+
query?: never;
60+
url: '/pets/{id}';
61+
};
62+
63+
export type DeletePetErrors = {
64+
/**
65+
* Not found
66+
*/
67+
404: Error;
68+
};
69+
70+
export type DeletePetError = DeletePetErrors[keyof DeletePetErrors];
71+
72+
export type DeletePetResponses = {
73+
/**
74+
* Deleted
75+
*/
76+
204: void;
77+
};
78+
79+
export type DeletePetResponse = DeletePetResponses[keyof DeletePetResponses];
80+
81+
export type GetPetData = {
82+
body?: never;
83+
path: {
84+
id: string;
85+
};
86+
query?: never;
87+
url: '/pets/{id}';
88+
};
89+
90+
export type GetPetErrors = {
91+
/**
92+
* Not found
93+
*/
94+
404: Error;
95+
};
96+
97+
export type GetPetError = GetPetErrors[keyof GetPetErrors];
98+
99+
export type GetPetResponses = {
100+
/**
101+
* A pet
102+
*/
103+
200: Pet;
104+
};
105+
106+
export type GetPetResponse = GetPetResponses[keyof GetPetResponses];
107+
108+
export type CreateJobData = {
109+
body?: never;
110+
path?: never;
111+
query?: never;
112+
url: '/jobs';
113+
};
114+
115+
export type CreateJobErrors = {
116+
/**
117+
* Client error
118+
*/
119+
'4XX': Error;
120+
};
121+
122+
export type CreateJobError = CreateJobErrors[keyof CreateJobErrors];
123+
124+
export type CreateJobResponses = {
125+
/**
126+
* Job accepted
127+
*/
128+
'2XX': Pet;
129+
};
130+
131+
export type CreateJobResponse = CreateJobResponses[keyof CreateJobResponses];
132+
133+
export type HealthCheckData = {
134+
body?: never;
135+
path?: never;
136+
query?: never;
137+
url: '/health';
138+
};
139+
140+
export type HealthCheckResponses = {
141+
/**
142+
* OK
143+
*/
144+
200: string;
145+
};
146+
147+
export type HealthCheckResponse = HealthCheckResponses[keyof HealthCheckResponses];

packages/openapi-ts-tests/faker/v1/test/3.1.x.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ describe(`OpenAPI ${version}`, () => {
6464
description:
6565
'infers faker helpers from property names with ancestor context and constraint merging',
6666
},
67+
{
68+
config: createConfig({
69+
input: 'faker-m5.yaml',
70+
output: 'faker-m5',
71+
plugins: ['@hey-api/typescript', '@faker-js/faker'],
72+
}),
73+
description: 'generates per-operation response factories with return type annotations',
74+
},
75+
{
76+
config: createConfig({
77+
input: 'faker-m5.yaml',
78+
output: 'faker-m5-untyped',
79+
}),
80+
description: 'generates per-operation response factories without return type annotations',
81+
},
6782
];
6883

6984
it.each(scenarios)('$description', async ({ config }) => {

packages/openapi-ts/src/plugins/@faker-js/faker/config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ export const defaultConfig: FakerJsFakerPlugin['Config'] = {
2222
mappers,
2323
value: plugin.config.definitions,
2424
});
25+
26+
plugin.config.responses = context.valueToObject({
27+
defaultValue: {
28+
case: plugin.config.case ?? 'camelCase',
29+
enabled: true,
30+
name: 'fake{{name}}Response',
31+
},
32+
mappers,
33+
value: plugin.config.responses,
34+
});
2535
},
2636
tags: ['mocker'],
2737
};

packages/openapi-ts/src/plugins/@faker-js/faker/shared/export.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@ export function exportAst({
3434
}),
3535
);
3636

37-
// Look up the TypeScript type for this schema (e.g. Foo, Bar)
37+
// Look up the TypeScript type for this schema (e.g. Foo, Bar, or PostFooResponse)
3838
const typeSymbol = plugin.querySymbol({
3939
category: 'type',
40-
resource: 'definition',
40+
resource: meta.resource,
4141
resourceId: meta.resourceId,
4242
tool: 'typescript',
43+
...(meta.role ? { role: meta.role } : undefined),
4344
});
4445

4546
// Build arrow function, only adding options param when the expression uses faker

0 commit comments

Comments
 (0)