Skip to content

Commit 8431fbc

Browse files
feature(scalars): support distinction between input and output generator configs (#182)
This addresses #139.
1 parent fe0be92 commit 8431fbc

File tree

9 files changed

+638
-178
lines changed

9 files changed

+638
-178
lines changed

.github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Get yarn cache directory path
2020
id: yarn-cache-dir-path
2121
run: echo "::set-output name=dir::$(yarn cache dir)"
22-
- uses: actions/cache@v2
22+
- uses: actions/cache@v4
2323
with:
2424
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
2525
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}

.github/workflows/deploy.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Get yarn cache directory path
2626
id: yarn-cache-dir-path
2727
run: echo "::set-output name=dir::$(yarn cache dir)"
28-
- uses: actions/cache@v2
28+
- uses: actions/cache@v4
2929
with:
3030
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
3131
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}

.github/workflows/lint.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Get yarn cache directory path
2020
id: yarn-cache-dir-path
2121
run: echo "::set-output name=dir::$(yarn cache dir)"
22-
- uses: actions/cache@v2
22+
- uses: actions/cache@v4
2323
with:
2424
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
2525
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Get yarn cache directory path
2020
id: yarn-cache-dir-path
2121
run: echo "::set-output name=dir::$(yarn cache dir)"
22-
- uses: actions/cache@v2
22+
- uses: actions/cache@v4
2323
with:
2424
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
2525
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}

README.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ keep all GraphQL names as-is. Available case functions in `change-case-all` are
8686
`localeLowerCase`, `lowerCaseFirst`, `spongeCase`, `titleCase`, `upperCase`, `localeUpperCase` and `upperCaseFirst`
8787
[See more](https://github.com/btxtiger/change-case-all)
8888

89-
### scalars (`{ [Scalar: string]: GeneratorOptions }`, defaultValue: `undefined`)
89+
### scalars (`{ [Scalar: string]: GeneratorOptions | InputOutputGeneratorOptions }`, defaultValue: `undefined`)
9090

9191
Allows you to define mappings for your custom scalars. Allows you to map any GraphQL Scalar to a
9292
[casual](https://github.com/boo1ean/casual#embedded-generators) embedded generator (string or
@@ -371,6 +371,24 @@ fieldName: # gets translated to casual.integer.toFixed(3)
371371
arguments: 3
372372
```
373373

374+
### `InputOutputGeneratorOptions` type
375+
376+
This type is used in the `scalars` option. It allows you to specify different `GeneratorOptions` for `input` and `output` types for
377+
your scalars, in the same way the [typescript-operations](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-operations#scalars) plugin does.
378+
379+
So, using the first example of the previous section, you can specify a `string` for your input and a `Date` for your `output`:
380+
381+
```yaml
382+
plugins:
383+
- typescript-mock-data:
384+
scalars:
385+
Date:
386+
input: date.weekday # Date fields in input objects will be mocked as strings
387+
output:
388+
generator: date.past # Date fields in other GraphQL types will be mocked as JS Dates
389+
arguments: 10
390+
```
391+
374392
## Examples of usage
375393

376394
**codegen.yml**

src/index.ts

+55-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type NamingConvention = 'change-case-all#pascalCase' | 'keep' | string;
1212
type Options<T = TypeNode> = {
1313
typeName: string;
1414
fieldName: string;
15+
generatorMode: 'input' | 'output';
1516
types: TypeItem[];
1617
typeNamesConvention: NamingConvention;
1718
enumValuesConvention: NamingConvention;
@@ -90,14 +91,26 @@ const hashedString = (value: string) => {
9091
return hash;
9192
};
9293

93-
const getGeneratorDefinition = (value: GeneratorDefinition | GeneratorName): GeneratorDefinition => {
94-
if (typeof value === 'string') {
94+
const getGeneratorDefinition = (
95+
opts: GeneratorOptions | InputOutputGeneratorOptions,
96+
generatorMode: Options['generatorMode'],
97+
): GeneratorDefinition => {
98+
if (isAnInputOutputGeneratorOptions(opts)) {
99+
return buildGeneratorDefinition(opts[generatorMode]);
100+
}
101+
102+
return buildGeneratorDefinition(opts);
103+
};
104+
105+
const buildGeneratorDefinition = (opts: GeneratorOptions) => {
106+
if (typeof opts === 'string') {
95107
return {
96-
generator: value,
108+
generator: opts,
97109
arguments: [],
98110
};
99111
}
100-
return value;
112+
113+
return opts;
101114
};
102115

103116
const getCasualCustomValue = (
@@ -246,12 +259,18 @@ const handleValueGeneration = (
246259
if (opts.fieldGeneration) {
247260
// Check for a specific generation for the type & field
248261
if (opts.typeName in opts.fieldGeneration && opts.fieldName in opts.fieldGeneration[opts.typeName]) {
249-
const generatorDefinition = getGeneratorDefinition(opts.fieldGeneration[opts.typeName][opts.fieldName]);
262+
const generatorDefinition = getGeneratorDefinition(
263+
opts.fieldGeneration[opts.typeName][opts.fieldName],
264+
opts.generatorMode,
265+
);
250266
return getCustomValue(generatorDefinition, opts);
251267
}
252268
// Check for a general field generation definition
253269
if ('_all' in opts.fieldGeneration && opts.fieldName in opts.fieldGeneration['_all']) {
254-
const generatorDefinition = getGeneratorDefinition(opts.fieldGeneration['_all'][opts.fieldName]);
270+
const generatorDefinition = getGeneratorDefinition(
271+
opts.fieldGeneration['_all'][opts.fieldName],
272+
opts.generatorMode,
273+
);
255274
return getCustomValue(generatorDefinition, opts);
256275
}
257276
}
@@ -290,25 +309,36 @@ const getNamedType = (opts: Options<NamedTypeNode | ObjectTypeDefinitionNode>):
290309
if (!opts.dynamicValues) mockValueGenerator.seed(hashedString(opts.typeName + opts.fieldName));
291310
const name = opts.currentType.name.value;
292311
const casedName = createNameConverter(opts.typeNamesConvention, opts.transformUnderscore)(name);
312+
293313
switch (name) {
294314
case 'String': {
295-
const customScalar = opts.customScalars ? getGeneratorDefinition(opts.customScalars['String']) : null;
315+
const customScalar = opts.customScalars
316+
? getGeneratorDefinition(opts.customScalars['String'], opts.generatorMode)
317+
: null;
296318
return handleValueGeneration(opts, customScalar, mockValueGenerator.word);
297319
}
298320
case 'Float': {
299-
const customScalar = opts.customScalars ? getGeneratorDefinition(opts.customScalars['Float']) : null;
321+
const customScalar = opts.customScalars
322+
? getGeneratorDefinition(opts.customScalars['Float'], opts.generatorMode)
323+
: null;
300324
return handleValueGeneration(opts, customScalar, mockValueGenerator.float);
301325
}
302326
case 'ID': {
303-
const customScalar = opts.customScalars ? getGeneratorDefinition(opts.customScalars['ID']) : null;
327+
const customScalar = opts.customScalars
328+
? getGeneratorDefinition(opts.customScalars['ID'], opts.generatorMode)
329+
: null;
304330
return handleValueGeneration(opts, customScalar, mockValueGenerator.uuid);
305331
}
306332
case 'Boolean': {
307-
const customScalar = opts.customScalars ? getGeneratorDefinition(opts.customScalars['Boolean']) : null;
333+
const customScalar = opts.customScalars
334+
? getGeneratorDefinition(opts.customScalars['Boolean'], opts.generatorMode)
335+
: null;
308336
return handleValueGeneration(opts, customScalar, mockValueGenerator.boolean);
309337
}
310338
case 'Int': {
311-
const customScalar = opts.customScalars ? getGeneratorDefinition(opts.customScalars['Int']) : null;
339+
const customScalar = opts.customScalars
340+
? getGeneratorDefinition(opts.customScalars['Int'], opts.generatorMode)
341+
: null;
312342
return handleValueGeneration(opts, customScalar, mockValueGenerator.integer);
313343
}
314344
default: {
@@ -345,7 +375,7 @@ const getNamedType = (opts: Options<NamedTypeNode | ObjectTypeDefinitionNode>):
345375
});
346376
case 'scalar': {
347377
const customScalar = opts.customScalars
348-
? getGeneratorDefinition(opts.customScalars[foundType.name])
378+
? getGeneratorDefinition(opts.customScalars[foundType.name], opts.generatorMode)
349379
: null;
350380

351381
// it's a scalar, let's use a string as a value if there is no custom
@@ -559,9 +589,18 @@ type GeneratorDefinition = {
559589
};
560590
};
561591
type GeneratorOptions = GeneratorName | GeneratorDefinition;
592+
type InputOutputGeneratorOptions = {
593+
input: GeneratorOptions;
594+
output: GeneratorOptions;
595+
};
596+
597+
const isAnInputOutputGeneratorOptions = (
598+
opts: GeneratorOptions | InputOutputGeneratorOptions,
599+
): opts is InputOutputGeneratorOptions =>
600+
opts !== undefined && typeof opts !== 'string' && 'input' in opts && 'output' in opts;
562601

563602
type ScalarMap = {
564-
[name: string]: GeneratorOptions;
603+
[name: string]: GeneratorOptions | InputOutputGeneratorOptions;
565604
};
566605

567606
type TypeFieldMap = {
@@ -728,6 +767,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
728767
const value = generateMockValue({
729768
typeName,
730769
fieldName,
770+
generatorMode: 'output',
731771
currentType: node.type,
732772
...sharedGenerateMockOpts,
733773
});
@@ -753,6 +793,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
753793
typeName: fieldName,
754794
fieldName: field.name.value,
755795
currentType: field.type,
796+
generatorMode: 'input',
756797
...sharedGenerateMockOpts,
757798
});
758799

@@ -764,6 +805,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
764805
typeName: fieldName,
765806
fieldName: field.name.value,
766807
currentType: field.type,
808+
generatorMode: 'input',
767809
...sharedGenerateMockOpts,
768810
});
769811

0 commit comments

Comments
 (0)