@depup/graphql-codegen__typescript-operations 5.0.9-depup.0 → 6.1.1-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.js CHANGED
@@ -1,38 +1,57 @@
1
+ import { concatAST } from 'graphql';
1
2
  import { oldVisit } from '@graphql-codegen/plugin-helpers';
3
+ import { transformSchemaAST } from '@graphql-codegen/schema-ast';
2
4
  import { optimizeOperations } from '@graphql-codegen/visitor-plugin-common';
3
- import { concatAST, Kind } from 'graphql';
4
5
  import { TypeScriptDocumentsVisitor } from './visitor.js';
5
- export const plugin = async (inputSchema, rawDocuments, config) => {
6
- const schema = config.nullability?.errorHandlingClient ? await semanticToStrict(inputSchema) : inputSchema;
6
+ export const plugin = async (inputSchema, rawDocuments, config, { outputFile }) => {
7
+ const schema = config.nullability?.errorHandlingClient
8
+ ? await semanticToStrict(inputSchema)
9
+ : inputSchema;
7
10
  const documents = config.flattenGeneratedTypes
8
11
  ? optimizeOperations(schema, rawDocuments, {
9
12
  includeFragments: config.flattenGeneratedTypesIncludeFragments,
10
13
  })
11
14
  : rawDocuments;
12
- const allAst = concatAST(documents.map(v => v.document));
13
- const allFragments = [
14
- ...allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION).map(fragmentDef => ({
15
- node: fragmentDef,
16
- name: fragmentDef.name.value,
17
- onType: fragmentDef.typeCondition.name.value,
18
- isExternal: false,
19
- })),
20
- ...(config.externalFragments || []),
21
- ];
22
- const visitor = new TypeScriptDocumentsVisitor(schema, config, allFragments);
23
- const visitorResult = oldVisit(allAst, {
15
+ const parsedDocuments = documents.reduce((prev, document) => {
16
+ prev.all.documentFiles.push(document);
17
+ prev.all.documentNodes.push(document.document);
18
+ // `!document.type` case could happen in a few scenarios:
19
+ // - the plugin is programmatically triggered
20
+ // - in existing tests
21
+ if (!document.type || document.type === 'standard') {
22
+ prev.standard.documentFiles.push(document);
23
+ prev.standard.documentNodes.push(document.document);
24
+ }
25
+ return prev;
26
+ }, {
27
+ all: { documentFiles: [], documentNodes: [] },
28
+ standard: { documentFiles: [], documentNodes: [] },
29
+ });
30
+ // For Fragment types to resolve correctly, we must get read all docs (`standard` and `external`)
31
+ // Fragment types are usually (but not always) in `external` files in certain setup, like a monorepo.
32
+ const allDocumentsAST = concatAST(parsedDocuments.all.documentNodes);
33
+ const visitor = new TypeScriptDocumentsVisitor(schema, config, allDocumentsAST, outputFile);
34
+ // We only visit `standard` documents to generate types.
35
+ // `external` documents are included as references for typechecking and completeness i.e. only used for reading purposes, no writing.
36
+ const documentsToVisitAST = concatAST(parsedDocuments.standard.documentNodes);
37
+ const operationsResult = oldVisit(documentsToVisitAST, {
24
38
  leave: visitor,
25
39
  });
26
- let content = visitorResult.definitions.join('\n');
40
+ const operationsDefinitions = operationsResult.definitions;
27
41
  if (config.addOperationExport) {
28
- const exportConsts = [];
29
- for (const d of allAst.definitions) {
42
+ for (const d of allDocumentsAST.definitions) {
30
43
  if ('name' in d) {
31
- exportConsts.push(`export declare const ${d.name.value}: import("graphql").DocumentNode;`);
44
+ operationsDefinitions.push(`export declare const ${d.name.value}: import("graphql").DocumentNode;`);
32
45
  }
33
46
  }
34
- content = visitorResult.definitions.concat(exportConsts).join('\n');
35
47
  }
48
+ const schemaTypes = oldVisit(transformSchemaAST(schema, config).ast, { leave: visitor });
49
+ // IMPORTANT: when a visitor leaves a node with no transformation logic,
50
+ // It will leave the node as an object.
51
+ // Here, we filter in nodes that have been turned into strings, i.e. they have been transformed
52
+ // This way, we do not have to explicitly declare a method for every node type to convert them to null
53
+ const schemaTypesDefinitions = schemaTypes.definitions.filter(def => typeof def === 'string');
54
+ let content = [...schemaTypesDefinitions, ...operationsDefinitions].join('\n');
36
55
  if (config.globalNamespace) {
37
56
  content = `
38
57
  declare global {
@@ -40,7 +59,15 @@ export const plugin = async (inputSchema, rawDocuments, config) => {
40
59
  }`;
41
60
  }
42
61
  return {
43
- prepend: [...visitor.getImports(), ...visitor.getGlobalDeclarations(visitor.config.noExport)],
62
+ prepend: [
63
+ ...visitor.getImports(),
64
+ ...visitor.getExternalSchemaTypeImports(),
65
+ ...visitor.getEnumsImports(),
66
+ ...visitor.getScalarsImports(),
67
+ ...visitor.getGlobalDeclarations(visitor.config.noExport),
68
+ visitor.getExactUtilityType(),
69
+ visitor.getIncrementalUtilityType(),
70
+ ],
44
71
  content,
45
72
  };
46
73
  };
@@ -1,6 +1,51 @@
1
- import { TypeScriptOperationVariablesToObject as TSOperationVariablesToObject } from '@graphql-codegen/typescript';
2
- export class TypeScriptOperationVariablesToObject extends TSOperationVariablesToObject {
1
+ import { Kind } from 'graphql';
2
+ import { DEFAULT_INPUT_SCALARS, OperationVariablesToObject, printTypeScriptMaybeType, } from '@graphql-codegen/visitor-plugin-common';
3
+ export class TypeScriptOperationVariablesToObject extends OperationVariablesToObject {
4
+ _config;
5
+ constructor(_config, _scalars, _convertName, _namespacedImportName, _enumNames, _enumPrefix, _enumSuffix, _enumValues, _applyCoercion) {
6
+ super(_scalars, _convertName, _namespacedImportName, _enumNames, _enumPrefix, _enumSuffix, _enumValues, _applyCoercion, {});
7
+ this._config = _config;
8
+ }
9
+ formatFieldString(fieldName, isNonNullType, hasDefaultValue) {
10
+ return `${fieldName}${this.getAvoidOption(isNonNullType, hasDefaultValue) ? '?' : ''}`;
11
+ }
3
12
  formatTypeString(fieldType, _isNonNullType, _hasDefaultValue) {
4
13
  return fieldType;
5
14
  }
15
+ clearOptional(str) {
16
+ const maybeSuffix = this._config.inputMaybeValue.replace('T', ''); // e.g. turns `T | null | undefined` to ` | null | undefined`
17
+ if (str.endsWith(maybeSuffix)) {
18
+ return (str = str.substring(0, str.length - maybeSuffix.length));
19
+ }
20
+ return str;
21
+ }
22
+ getAvoidOption(isNonNullType, hasDefaultValue) {
23
+ const options = this._config.avoidOptionals;
24
+ return (((options.variableValue || !options.defaultValue) && hasDefaultValue) ||
25
+ (!options.variableValue && !isNonNullType));
26
+ }
27
+ getScalar(name) {
28
+ return this._scalars[name]?.input ?? DEFAULT_INPUT_SCALARS[name].input ?? 'unknown';
29
+ }
30
+ getPunctuation() {
31
+ return ';';
32
+ }
33
+ wrapAstTypeWithModifiers(baseType, typeNode, applyCoercion = false) {
34
+ if (typeNode.kind === Kind.NON_NULL_TYPE) {
35
+ const type = this.wrapAstTypeWithModifiers(baseType, typeNode.type, applyCoercion);
36
+ return this.clearOptional(type);
37
+ }
38
+ if (typeNode.kind === Kind.LIST_TYPE) {
39
+ const innerType = this.wrapAstTypeWithModifiers(baseType, typeNode.type, applyCoercion);
40
+ const listInputCoercionExtension = applyCoercion ? ` | ${innerType}` : '';
41
+ return this.wrapMaybe(`${this._config.immutableTypes ? 'ReadonlyArray' : 'Array'}<${innerType}>${listInputCoercionExtension}`);
42
+ }
43
+ return this.wrapMaybe(baseType);
44
+ }
45
+ wrapMaybe(type) {
46
+ return printTypeScriptMaybeType({
47
+ type,
48
+ pattern: this._config.inputMaybeValue,
49
+ });
50
+ }
6
51
  }
@@ -23,15 +23,7 @@ export class TypeScriptSelectionSetProcessor extends BaseSelectionSetProcessor {
23
23
  });
24
24
  let resString = formattedUnionTransform('Pick', parentName, escapedFieldNames);
25
25
  if (hasConditionals) {
26
- const avoidOptional =
27
- // TODO: check type and exec only if relevant
28
- this.config.avoidOptionals === true ||
29
- (typeof this.config.avoidOptionals === 'object' &&
30
- (this.config.avoidOptionals.field ||
31
- this.config.avoidOptionals.inputValue ||
32
- this.config.avoidOptionals.object));
33
- const transform = avoidOptional ? 'MakeMaybe' : 'MakeOptional';
34
- resString = `${this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : ''}${formattedUnionTransform(transform, resString, escapedConditionalsList)}`;
26
+ resString = `${this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : ''}${formattedUnionTransform('MakeOptional', resString, escapedConditionalsList)}`;
35
27
  }
36
28
  return [resString];
37
29
  }
@@ -47,7 +39,9 @@ export class TypeScriptSelectionSetProcessor extends BaseSelectionSetProcessor {
47
39
  useTypesPrefix: true,
48
40
  });
49
41
  const selections = fields.map(aliasedField => {
50
- const value = aliasedField.fieldName === '__typename' ? `'${schemaType.name}'` : `${parentName}['${aliasedField.fieldName}']`;
42
+ const value = aliasedField.fieldName === '__typename'
43
+ ? `'${schemaType.name}'`
44
+ : `${parentName}['${aliasedField.fieldName}']`;
51
45
  return `${aliasedField.alias}: ${value}`;
52
46
  });
53
47
  return [formatSelections(selections)];