diff --git a/README.md b/README.md index 214e2b7..03b513e 100644 --- a/README.md +++ b/README.md @@ -428,6 +428,35 @@ const config: CodegenConfig = { module.exports = config; ``` +### `nonOptionalDefaultFields` + +type: `boolean`, default: `false` + +Make it mandatory to pass all fields to `defaultFields`. This is useful to force the `defaultFields` to be updated when new fields are added to the schema. + +```ts +import { CodegenConfig } from '@graphql-codegen/cli'; +const config: CodegenConfig = { + schema: './schema.graphql', + generates: { + '__generated__/types.ts': { + plugins: ['typescript'], + config: { + // ... + }, + }, + './__generated__/fabbrica.ts': { + plugins: ['@mizdra/graphql-fabbrica'], + config: { + // ... + nonOptionalDefaultFields: true, + }, + }, + }, +}; +module.exports = config; +``` + ### `namingConvention` type: `NamingConvention`, default: `change-case-all#pascalCase` diff --git a/e2e/1-basic-schema.graphql b/e2e/1-basic-schema.graphql index 190bbf4..9df7809 100644 --- a/e2e/1-basic-schema.graphql +++ b/e2e/1-basic-schema.graphql @@ -87,8 +87,8 @@ type NamingConventionTest_SubType { field: String! } -# NonOptionalFields -type NonOptionalFields_OptionalFieldsType { +# NonOptionalDefaultFields +type NonOptionalDefaultFields_OptionalDefaultFieldsType { field1: String! field2: String! } diff --git a/e2e/4-non-optional-fields-schema.graphql b/e2e/4-non-optional-fields-schema.graphql index 0225643..da58345 100644 --- a/e2e/4-non-optional-fields-schema.graphql +++ b/e2e/4-non-optional-fields-schema.graphql @@ -1,4 +1,4 @@ -type NonOptionalFields_NonOptionalFieldsType { +type NonOptionalDefaultFields_NonOptionalDefaultFieldsType { field1: String! field2: String! } diff --git a/e2e/codegen.ts b/e2e/codegen.ts index 8004e20..63a75d5 100644 --- a/e2e/codegen.ts +++ b/e2e/codegen.ts @@ -81,7 +81,7 @@ const config: CodegenConfig = { plugins: ['@mizdra/graphql-fabbrica'], config: { ...defaultFabbricaPluginConfig, - nonOptionalFields: true, + nonOptionalDefaultFields: true, }, }, }, diff --git a/e2e/index.e2e.ts b/e2e/index.e2e.ts index eb70b75..bfdb2ad 100644 --- a/e2e/index.e2e.ts +++ b/e2e/index.e2e.ts @@ -21,12 +21,12 @@ import { defineNamingConventionTest_RenamedTypeFactory, defineNullableTest_TypeFactory, defineInputTest_InputFactory, - defineNonOptionalFields_OptionalFieldsTypeFactory, + defineNonOptionalDefaultFields_OptionalDefaultFieldsTypeFactory, } from './__generated__/1-basic/fabbrica.js'; import { oneOf } from './test/util.js'; import { definePrefixTypeFactory } from './__generated__/2-typesPrefix/fabbrica.js'; import { defineTypeSuffixFactory } from './__generated__/3-typesSuffix/fabbrica.js'; -import { defineNonOptionalFields_NonOptionalFieldsTypeFactory } from './__generated__/4-non-optional-fields/fabbrica.js'; +import { defineNonOptionalDefaultFields_NonOptionalDefaultFieldsTypeFactory } from './__generated__/4-non-optional-fields/fabbrica.js'; describe('integration test', () => { it('circular dependent type', async () => { @@ -410,9 +410,9 @@ describe('defineTypeFactory', () => { expect(firstNameResolver).toHaveBeenCalledTimes(1); expect(lastNameResolver).toHaveBeenCalledTimes(1); }); - describe('nonOptionalFields', () => { - it('requires to pass all fields if nonOptionalFields is false', async () => { - defineNonOptionalFields_NonOptionalFieldsTypeFactory({ + describe('nonOptionalDefaultFields', () => { + it('requires to pass all fields if nonOptionalDefaultFields is false', async () => { + defineNonOptionalDefaultFields_NonOptionalDefaultFieldsTypeFactory({ // @ts-expect-error -- expects error defaultFields: { field1: 'field1', @@ -420,8 +420,8 @@ describe('defineTypeFactory', () => { }, }); }); - it('requires to pass all fields if nonOptionalFields is true', async () => { - const TypeFactory = defineNonOptionalFields_OptionalFieldsTypeFactory({ + it('requires to pass all fields if nonOptionalDefaultFields is true', async () => { + const TypeFactory = defineNonOptionalDefaultFields_OptionalDefaultFieldsTypeFactory({ defaultFields: { field1: 'field1', // field2: 'field2', diff --git a/src/code-generator.ts b/src/code-generator.ts index 45f5fed..ccd3db0 100644 --- a/src/code-generator.ts +++ b/src/code-generator.ts @@ -43,7 +43,7 @@ function generateFieldNamesDefinitionCode(typeInfo: TypeInfo): string { function generateTypeFactoryCode(config: Config, typeInfo: TypeInfo): string { const { name } = typeInfo; function wrapRequired(str: string) { - return config.nonOptionalFields ? `Required<${str}>` : str; + return config.nonOptionalDefaultFields ? `Required<${str}>` : str; } return ` export type ${name}FactoryDefineOptions< diff --git a/src/config.test.ts b/src/config.test.ts index 2afd6e9..78f79ea 100644 --- a/src/config.test.ts +++ b/src/config.test.ts @@ -26,11 +26,13 @@ describe('validateConfig', () => { '`options.skipIsAbstractType` must be a boolean', ); }); - it('nonOptionalFields', () => { - expect(() => validateConfig({ typesFile: './types', nonOptionalFields: oneOf([true, false]) })).not.toThrow(); + it('nonOptionalDefaultFields', () => { + expect(() => + validateConfig({ typesFile: './types', nonOptionalDefaultFields: oneOf([true, false]) }), + ).not.toThrow(); expect(() => validateConfig({ typesFile: './types' })).not.toThrow(); - expect(() => validateConfig({ typesFile: './types', nonOptionalFields: 1 })).toThrow( - '`options.nonOptionalFields` must be a boolean', + expect(() => validateConfig({ typesFile: './types', nonOptionalDefaultFields: 1 })).toThrow( + '`options.nonOptionalDefaultFields` must be a boolean', ); }); it('typesPrefix', () => { diff --git a/src/config.ts b/src/config.ts index d1ab0ea..9203a85 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,7 +4,7 @@ export type RawConfig = { typesFile: string; skipTypename?: RawTypesConfig['skipTypename']; skipIsAbstractType?: boolean | undefined; - nonOptionalFields?: boolean | undefined; + nonOptionalDefaultFields?: boolean | undefined; namingConvention?: RawTypesConfig['namingConvention']; typesPrefix?: RawTypesConfig['typesPrefix']; typesSuffix?: RawTypesConfig['typesSuffix']; @@ -15,7 +15,7 @@ export type Config = { typesFile: string; skipTypename: Exclude; skipIsAbstractType: boolean; - nonOptionalFields: boolean; + nonOptionalDefaultFields: boolean; typesPrefix: Exclude; typesSuffix: Exclude; convert: ConvertFn; @@ -38,8 +38,8 @@ export function validateConfig(rawConfig: unknown): asserts rawConfig is RawConf if ('skipIsAbstractType' in rawConfig && typeof rawConfig['skipIsAbstractType'] !== 'boolean') { throw new Error('`options.skipIsAbstractType` must be a boolean'); } - if ('nonOptionalFields' in rawConfig && typeof rawConfig['nonOptionalFields'] !== 'boolean') { - throw new Error('`options.nonOptionalFields` must be a boolean'); + if ('nonOptionalDefaultFields' in rawConfig && typeof rawConfig['nonOptionalDefaultFields'] !== 'boolean') { + throw new Error('`options.nonOptionalDefaultFields` must be a boolean'); } if ('typesPrefix' in rawConfig && typeof rawConfig['typesPrefix'] !== 'string') { throw new Error('`options.typesPrefix` must be a string'); @@ -54,7 +54,7 @@ export function normalizeConfig(rawConfig: RawConfig): Config { typesFile: rawConfig.typesFile, skipTypename: rawConfig.skipTypename ?? false, skipIsAbstractType: rawConfig.skipIsAbstractType ?? true, - nonOptionalFields: rawConfig.nonOptionalFields ?? false, + nonOptionalDefaultFields: rawConfig.nonOptionalDefaultFields ?? false, typesPrefix: rawConfig.typesPrefix ?? '', typesSuffix: rawConfig.typesSuffix ?? '', convert: rawConfig.namingConvention diff --git a/src/test/util.ts b/src/test/util.ts index 5f9aa7d..4a98569 100644 --- a/src/test/util.ts +++ b/src/test/util.ts @@ -12,7 +12,7 @@ export function fakeConfig(args: Partial = {}): Config { typesFile: './types', skipTypename: true, skipIsAbstractType: true, - nonOptionalFields: false, + nonOptionalDefaultFields: false, typesPrefix: '', typesSuffix: '', convert: convertFactory({}),