Skip to content

Commit 6dadd18

Browse files
authored
feat: use faker as generator (#169)
`casual` is quite old and not maintained compared to `faker` ## Changes - Update faker version to latest (v8) - Update deprecated faker generators to new ones (`number.int`, `number.float` ...) - Set `faker` as default `generatorLibrary` - Fix handling of `locale` as faker doesn't allow `setLocale` anymore BREAKING CHANGES: update faker to v8 and update default `generatorLibrary` to `faker` instead of `casual`
1 parent 6589706 commit 6dadd18

File tree

21 files changed

+914
-839
lines changed

21 files changed

+914
-839
lines changed

README.md

+55-54
Original file line numberDiff line numberDiff line change
@@ -207,60 +207,16 @@ In the above example all resolvers with the name `email` will use the `internet.
207207

208208
For detailed configuration options, see [GeneratorOptions](#generatoroptions-type) documentation.
209209

210-
### generateLibrary (`'casual' | 'faker'`, defaultValue: `'casual'`)
210+
### generateLibrary (`'casual' | 'faker'`, defaultValue: `'faker'`)
211211

212-
Select a library to generate mock values. The default is [casual](https://github.com/boo1ean/casual), Other options include [faker](https://github.com/faker-js/faker).
213-
casual dependents on Node API and cannot be executed in a browser. faker is useful when you want to use a mock function with the dynamicValues option enabled in the browser.
212+
Select a library to generate mock values. The default is [faker](https://github.com/faker-js/faker), Other options include [casual](https://github.com/boo1ean/casual)
213+
casual is not maintained and will be remove in future major versions.
214+
faker is useful when you want to use a mock function with the dynamicValues option enabled in the browser.
214215

215216
### `GeneratorOptions` type
216217

217218
This type is used in `scalars` and `fieldGeneration` options.
218219

219-
Examples using **casual**
220-
221-
**Shorthand if you don't have arguments**
222-
223-
```yaml
224-
fieldName: date # gets translated to casual.date()
225-
```
226-
227-
**With arguments**
228-
229-
```yaml
230-
fieldName: # gets translated to casual.date('YYYY-MM-DD')
231-
generator: date
232-
arguments: 'YYYY-MM-DD'
233-
```
234-
235-
**With multiple arguments**
236-
237-
```yaml
238-
fieldName: # gets translated to casual.integer(-100, 100)
239-
generator: integer
240-
arguments:
241-
- -100
242-
- 100
243-
```
244-
245-
**With extra function call**
246-
247-
```yaml
248-
fieldName: # gets translated to casual.integer.toFixed()
249-
generator: integer
250-
extra:
251-
function: toFixed
252-
```
253-
254-
**With extra function call arguments**
255-
256-
```yaml
257-
fieldName: # gets translated to casual.integer.toFixed(3)
258-
generator: integer
259-
extra:
260-
function: toFixed
261-
arguments: 3
262-
```
263-
264220
Examples using **faker**
265221

266222
**With arguments**
@@ -299,17 +255,17 @@ plugins:
299255
**With extra function call**
300256

301257
```yaml
302-
fieldName: # gets translated to casual.date().toLocaleDateString()
303-
generator: date
258+
fieldName: # gets translated to faker.date.past().toLocaleDateString()
259+
generator: date.past
304260
extra:
305261
function: toLocaleDateString
306262
```
307263

308264
**With extra function call arguments**
309265

310266
```yaml
311-
fieldName: # gets translated to casual.date().toLocaleDateString('en_GB)
312-
generator: date
267+
fieldName: # gets translated to faker.date.past().toLocaleDateString('en_GB)
268+
generator: date.past
313269
extra:
314270
function: toLocaleDateString
315271
arguments: 'en_GB'
@@ -322,6 +278,51 @@ fieldName: # gets translated to casual.date().toLocaleDateString('en_GB)
322278
fieldName: arrayBufferGenerator()
323279
```
324280

281+
Examples using **casual** (deprecated)
282+
283+
**Shorthand if you don't have arguments**
284+
285+
```yaml
286+
fieldName: date # gets translated to casual.date()
287+
```
288+
289+
**With arguments**
290+
291+
```yaml
292+
fieldName: # gets translated to casual.date('YYYY-MM-DD')
293+
generator: date
294+
arguments: 'YYYY-MM-DD'
295+
```
296+
297+
**With multiple arguments**
298+
299+
```yaml
300+
fieldName: # gets translated to casual.integer(-100, 100)
301+
generator: integer
302+
arguments:
303+
- -100
304+
- 100
305+
```
306+
307+
**With extra function call**
308+
309+
```yaml
310+
fieldName: # gets translated to casual.integer.toFixed()
311+
generator: integer
312+
extra:
313+
function: toFixed
314+
```
315+
316+
**With extra function call arguments**
317+
318+
```yaml
319+
fieldName: # gets translated to casual.integer.toFixed(3)
320+
generator: integer
321+
extra:
322+
function: toFixed
323+
arguments: 3
324+
```
325+
325326
## Examples of usage
326327

327328
**codegen.yml**
@@ -340,7 +341,7 @@ generates:
340341
enumValues: upper-case#upperCase
341342
typeNames: keep
342343
scalars:
343-
AWSTimestamp: unix_time # gets translated to casual.unix_time
344+
AWSTimestamp: number.int # gets translated to faker.number.int()
344345
```
345346

346347
### With `eslint-disable` rule
@@ -363,7 +364,7 @@ generates:
363364
enumValues: upper-case#upperCase
364365
typeNames: keep
365366
scalars:
366-
AWSTimestamp: unix_time # gets translated to casual.unix_time
367+
AWSTimestamp: number.int # gets translated to faker.number.int()
367368
```
368369

369370
## Example of generated code

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"fakes"
2323
],
2424
"dependencies": {
25-
"@faker-js/faker": "^7.5.0",
25+
"@faker-js/faker": "^8.4.1",
2626
"@graphql-codegen/plugin-helpers": "^5.0.4",
2727
"casual": "^1.6.2",
2828
"change-case-all": "^1.0.15",

src/index.ts

+14-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
NamedTypeNode,
88
ObjectTypeDefinitionNode,
99
} from 'graphql';
10-
import { faker } from '@faker-js/faker';
10+
import * as allFakerLocales from '@faker-js/faker';
1111
import casual from 'casual';
1212
import { oldVisit, PluginFunction, resolveExternalModuleAndFn } from '@graphql-codegen/plugin-helpers';
1313
import { sentenceCase } from 'sentence-case';
@@ -32,6 +32,7 @@ type Options<T = TypeNode> = {
3232
listElementCount: number;
3333
dynamicValues: boolean;
3434
generateLibrary: 'casual' | 'faker';
35+
generatorLocale: string;
3536
fieldGeneration?: TypeFieldMap;
3637
enumsAsTypes?: boolean;
3738
useTypeImports?: boolean;
@@ -146,8 +147,8 @@ const getCasualCustomValue = (
146147
return value;
147148
};
148149

149-
const getFakerGenerators = (generatorName: GeneratorName) => {
150-
let embeddedGenerator: unknown = faker;
150+
const getFakerGenerators = (generatorName: GeneratorName, locale: string) => {
151+
let embeddedGenerator: unknown = allFakerLocales[`faker${locale.toUpperCase()}`];
151152
let dynamicGenerator = 'faker';
152153

153154
if (typeof generatorName === 'string') {
@@ -173,7 +174,10 @@ const getFakerCustomValue = (
173174
opts: Options<NamedTypeNode | ObjectTypeDefinitionNode>,
174175
) => {
175176
// If there is a mapping to a `faker` type, then use it
176-
const { embeddedGenerator, dynamicGenerator } = getFakerGenerators(generatorDefinition.generator);
177+
const { embeddedGenerator, dynamicGenerator } = getFakerGenerators(
178+
generatorDefinition.generator,
179+
opts.generatorLocale,
180+
);
177181
if (!embeddedGenerator && generatorDefinition.generator) {
178182
return generatorDefinition.generator;
179183
}
@@ -278,6 +282,7 @@ const getNamedType = (opts: Options<NamedTypeNode | ObjectTypeDefinitionNode>):
278282
const mockValueGenerator = setupMockValueGenerator({
279283
generateLibrary: opts.generateLibrary,
280284
dynamicValues: opts.dynamicValues,
285+
generatorLocale: opts.generatorLocale,
281286
});
282287
if (!opts.dynamicValues) mockValueGenerator.seed(hashedString(opts.typeName + opts.fieldName));
283288
const name = opts.currentType.name.value;
@@ -603,15 +608,12 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
603608
const transformUnderscore = config.transformUnderscore ?? true;
604609
const listElementCount = Math.max(0, config.listElementCount ?? 1);
605610
const dynamicValues = !!config.dynamicValues;
606-
const generateLibrary = config.generateLibrary || 'casual';
611+
const generateLibrary = config.generateLibrary || 'faker';
607612
const enumsAsTypes = config.enumsAsTypes ?? false;
608613
const useTypeImports = config.useTypeImports ?? false;
609614
const useImplementingTypes = config.useImplementingTypes ?? false;
610615
const defaultNullableToNull = config.defaultNullableToNull ?? false;
611-
612-
if (generateLibrary === 'faker' && config.locale) {
613-
faker.setLocale(config.locale);
614-
}
616+
const generatorLocale = config.locale || 'en';
615617

616618
// List of types that are enums
617619
const types: TypeItem[] = [];
@@ -684,6 +686,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
684686
listElementCount,
685687
dynamicValues,
686688
generateLibrary,
689+
generatorLocale,
687690
fieldGeneration: config.fieldGeneration,
688691
enumsAsTypes,
689692
useTypeImports,
@@ -721,6 +724,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
721724
listElementCount,
722725
dynamicValues,
723726
generateLibrary,
727+
generatorLocale,
724728
fieldGeneration: config.fieldGeneration,
725729
enumsAsTypes,
726730
useTypeImports,
@@ -817,7 +821,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
817821
.filter((mockFn: () => string) => !!mockFn)
818822
.map((mockFn: () => string) => mockFn())
819823
.join('\n');
820-
const functionTokens = setupFunctionTokens(generateLibrary);
824+
const functionTokens = setupFunctionTokens(generateLibrary, generatorLocale);
821825

822826
let mockFile = '';
823827
if (dynamicValues) mockFile += `${functionTokens.import}\n`;

src/mockValueGenerator.ts

+32-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { faker } from '@faker-js/faker';
1+
import { Faker } from '@faker-js/faker';
2+
import * as allFakerLocales from '@faker-js/faker';
23
import casual from 'casual';
34

45
interface MockValueGenerator {
@@ -14,12 +15,14 @@ interface MockValueGenerator {
1415

1516
type MockValueGeneratorOptions = {
1617
dynamicValues: boolean;
18+
generatorLocale: string;
1719
};
1820

1921
type FunctionTokens = Record<'import' | 'seed' | 'seedFunction', string>;
2022

2123
type SetupMockValueGeneratorOptions = {
2224
generateLibrary: 'casual' | 'faker';
25+
generatorLocale: string;
2326
dynamicValues: boolean;
2427
};
2528

@@ -53,52 +56,61 @@ const casualFunctionTokens: FunctionTokens = {
5356

5457
class FakerMockValueGenerator implements MockValueGenerator {
5558
dynamicValues: boolean;
59+
private fakerInstance: Faker;
5660

5761
constructor(opts: MockValueGeneratorOptions) {
5862
this.dynamicValues = opts.dynamicValues;
63+
const fakerImport = `faker${opts.generatorLocale.toUpperCase()}`;
64+
if (!(fakerImport in allFakerLocales)) {
65+
throw new Error(`Cannot find faker version for locale ${opts.generatorLocale.toUpperCase()}`);
66+
}
67+
this.fakerInstance = allFakerLocales[`faker${opts.generatorLocale.toUpperCase()}`];
5968
}
6069

61-
word = () => (this.dynamicValues ? `faker.lorem.word()` : `'${faker.lorem.word()}'`);
62-
uuid = () => (this.dynamicValues ? `faker.datatype.uuid()` : `'${faker.datatype.uuid()}'`);
63-
boolean = () => (this.dynamicValues ? `faker.datatype.boolean()` : faker.datatype.boolean());
70+
word = () => (this.dynamicValues ? `faker.lorem.word()` : `'${this.fakerInstance.lorem.word()}'`);
71+
uuid = () => (this.dynamicValues ? `faker.string.uuid()` : `'${this.fakerInstance.string.uuid()}'`);
72+
boolean = () => (this.dynamicValues ? `faker.datatype.boolean()` : this.fakerInstance.datatype.boolean());
6473
integer = () =>
6574
this.dynamicValues
66-
? `faker.datatype.number({ min: 0, max: 9999 })`
67-
: faker.datatype.number({ min: 0, max: 9999 });
75+
? `faker.number.int({ min: 0, max: 9999 })`
76+
: this.fakerInstance.number.int({ min: 0, max: 9999 });
6877
float = () =>
6978
this.dynamicValues
70-
? `faker.datatype.float({ min: 0, max: 10, precision: 0.1 })`
71-
: faker.datatype.float({ min: 0, max: 10, precision: 0.1 });
79+
? `faker.number.float({ min: 0, max: 10, fractionDigits: 1 })`
80+
: this.fakerInstance.number.float({ min: 0, max: 10, fractionDigits: 1 });
7281
date = () =>
7382
this.dynamicValues
74-
? `faker.date.past(1, new Date(2022, 0)).toISOString()`
75-
: `'${faker.date.past(1, new Date(2022, 0)).toISOString()}'`;
76-
seed = (seed: number) => faker.seed(seed);
83+
? `faker.date.past({ years: 1, refDate: new Date(2022, 0) }).toISOString()`
84+
: `'${this.fakerInstance.date.past({ years: 1, refDate: new Date(2022, 0) }).toISOString()}'`;
85+
seed = (seed: number) => this.fakerInstance.seed(seed);
7786
}
7887

79-
const fakerFunctionTokens: FunctionTokens = {
80-
import: `import { faker } from '@faker-js/faker';`,
81-
seed: 'faker.seed(0);',
82-
seedFunction: 'export const seedMocks = (seed: number) => faker.seed(seed);',
83-
};
88+
function getFakerFunctionTokens(locale = 'en'): FunctionTokens {
89+
return {
90+
import: `import { faker${locale.toUpperCase()} as faker } from '@faker-js/faker';`,
91+
seed: 'faker.seed(0);',
92+
seedFunction: 'export const seedMocks = (seed: number) => faker.seed(seed);',
93+
};
94+
}
8495

8596
export const setupMockValueGenerator = ({
8697
generateLibrary,
8798
dynamicValues,
99+
generatorLocale,
88100
}: SetupMockValueGeneratorOptions): MockValueGenerator => {
89101
switch (generateLibrary) {
90102
case 'casual':
91-
return new CasualMockValueGenerator({ dynamicValues });
103+
return new CasualMockValueGenerator({ dynamicValues, generatorLocale });
92104
case 'faker':
93-
return new FakerMockValueGenerator({ dynamicValues });
105+
return new FakerMockValueGenerator({ dynamicValues, generatorLocale });
94106
}
95107
};
96108

97-
export const setupFunctionTokens = (generateLibrary: 'casual' | 'faker'): FunctionTokens => {
109+
export const setupFunctionTokens = (generateLibrary: 'casual' | 'faker', locale?: string): FunctionTokens => {
98110
switch (generateLibrary) {
99111
case 'casual':
100112
return casualFunctionTokens;
101113
case 'faker':
102-
return fakerFunctionTokens;
114+
return getFakerFunctionTokens(locale);
103115
}
104116
};

0 commit comments

Comments
 (0)