@graphql-codegen/cli 2.5.0-alpha-bc33c031d.0 → 2.5.0-alpha-fc06eb8e7.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/bin.js CHANGED
@@ -505,30 +505,20 @@ async function loadSchema(schemaPointers, config) {
505
505
 
506
506
  ${e.message || e}
507
507
  ${e.stack || ''}
508
-
508
+
509
509
  GraphQL Code Generator supports:
510
510
  - ES Modules and CommonJS exports (export as default or named export "schema")
511
511
  - Introspection JSON File
512
512
  - URL of GraphQL endpoint
513
513
  - Multiple files with type definitions (glob expression)
514
514
  - String in config file
515
-
515
+
516
516
  Try to use one of above options and run codegen again.
517
-
517
+
518
518
  `);
519
519
  }
520
520
  }
521
- const requiredLoader = async (pointers, schema) => {
522
- return Promise.all(pointers.map(async (pointer) => {
523
- const userLoader = (await makeDefaultLoader(process.cwd())(pointer.require)).default;
524
- const documents = userLoader(pointer.config || {}, schema);
525
- return documents;
526
- })).then(results => [].concat(...results));
527
- };
528
- const isRequirePointer = (pointer) => {
529
- return typeof pointer === 'object' && 'require' in pointer;
530
- };
531
- async function loadDocuments(documentPointers, config, schema) {
521
+ async function loadDocuments(documentPointers, config) {
532
522
  const loaders = [
533
523
  new codeFileLoader.CodeFileLoader({
534
524
  pluckConfig: {
@@ -547,35 +537,14 @@ async function loadDocuments(documentPointers, config, schema) {
547
537
  }
548
538
  ignore.push(path.join(process.cwd(), generatePath));
549
539
  }
550
- const loaderPointers = [];
551
- const requestPointers = [];
552
- if (Array.isArray(documentPointers)) {
553
- documentPointers.forEach(pointer => {
554
- if (isRequirePointer(pointer)) {
555
- requestPointers.push(pointer);
556
- }
557
- else {
558
- loaderPointers.push(pointer);
559
- }
560
- });
561
- }
562
- else {
563
- if (isRequirePointer(documentPointers)) {
564
- requestPointers.push(documentPointers);
565
- }
566
- else {
567
- loaderPointers.push(documentPointers);
568
- }
569
- }
570
- const loadedFromToolkit = await load.loadDocuments(loaderPointers, {
540
+ const loadedFromToolkit = await load.loadDocuments(documentPointers, {
571
541
  ...defaultDocumentsLoadOptions,
572
542
  ignore,
573
543
  loaders,
574
544
  ...config,
575
545
  ...config.config,
576
546
  });
577
- const loadedAlterantively = await requiredLoader(requestPointers, schema);
578
- return [...loadedFromToolkit, ...loadedAlterantively];
547
+ return loadedFromToolkit;
579
548
  }
580
549
 
581
550
  const { lstat } = fs.promises;
@@ -707,6 +676,10 @@ function buildOptions() {
707
676
  describe: 'Only print errors',
708
677
  type: 'boolean',
709
678
  },
679
+ profile: {
680
+ describe: 'Use profiler to measure performance',
681
+ type: 'boolean',
682
+ },
710
683
  p: {
711
684
  alias: 'project',
712
685
  describe: 'Name of a project in GraphQL Config',
@@ -748,6 +721,9 @@ function updateContextWithCliFlags(context, cliFlags) {
748
721
  if (cliFlags.project) {
749
722
  context.useProject(cliFlags.project);
750
723
  }
724
+ if (cliFlags.profile === true) {
725
+ context.useProfiler();
726
+ }
751
727
  context.updateConfig(config);
752
728
  }
753
729
  class CodegenContext {
@@ -757,6 +733,7 @@ class CodegenContext {
757
733
  this._graphqlConfig = graphqlConfig;
758
734
  this.filepath = this._graphqlConfig ? this._graphqlConfig.filepath : filepath;
759
735
  this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : process.cwd();
736
+ this.profiler = pluginHelpers.createNoopProfiler();
760
737
  }
761
738
  useProject(name) {
762
739
  this._project = name;
@@ -787,6 +764,13 @@ class CodegenContext {
787
764
  ...config,
788
765
  };
789
766
  }
767
+ useProfiler() {
768
+ this.profiler = pluginHelpers.createProfiler();
769
+ const now = new Date(); // 2011-10-05T14:48:00.000Z
770
+ const datetime = now.toISOString().split('.')[0]; // 2011-10-05T14:48:00
771
+ const datetimeNormalized = datetime.replace(/-|:/g, ''); // 20111005T144800
772
+ this.profilerOutput = `codegen-${datetimeNormalized}.json`;
773
+ }
790
774
  getPluginContext() {
791
775
  return this._pluginContext;
792
776
  }
@@ -798,14 +782,14 @@ class CodegenContext {
798
782
  }
799
783
  return loadSchema(pointer, config);
800
784
  }
801
- async loadDocuments(input) {
785
+ async loadDocuments(pointer) {
802
786
  const config = this.getConfig(defaultDocumentsLoadOptions);
803
787
  if (this._graphqlConfig) {
804
788
  // TODO: pointer won't work here
805
- const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(input.pointer, config);
789
+ const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config);
806
790
  return documents;
807
791
  }
808
- return loadDocuments(input.pointer, config, input.schema);
792
+ return loadDocuments(pointer, config);
809
793
  }
810
794
  }
811
795
  function ensureContext(input) {
@@ -836,19 +820,6 @@ function createCache(loader) {
836
820
  };
837
821
  }
838
822
  async function executeCodegen(input) {
839
- function wrapTask(task, source) {
840
- return async () => {
841
- try {
842
- await Promise.resolve().then(() => task());
843
- }
844
- catch (error) {
845
- if (source && !(error instanceof graphql.GraphQLError)) {
846
- error.source = source;
847
- }
848
- throw error;
849
- }
850
- };
851
- }
852
823
  const context = ensureContext(input);
853
824
  const config = context.getConfig();
854
825
  const pluginContext = context.getPluginContext();
@@ -895,9 +866,24 @@ async function executeCodegen(input) {
895
866
  const documentsLoadingCache = createCache(async function (hash) {
896
867
  const documents = await context.loadDocuments(JSON.parse(hash));
897
868
  return {
898
- documents,
869
+ documents: documents,
899
870
  };
900
871
  });
872
+ function wrapTask(task, source, taskName) {
873
+ return () => {
874
+ return context.profiler.run(async () => {
875
+ try {
876
+ await Promise.resolve().then(() => task());
877
+ }
878
+ catch (error) {
879
+ if (source && !(error instanceof graphql.GraphQLError)) {
880
+ error.source = source;
881
+ }
882
+ throw error;
883
+ }
884
+ }, taskName);
885
+ };
886
+ }
901
887
  async function normalize() {
902
888
  /* Load Require extensions */
903
889
  const requireExtensions = pluginHelpers.normalizeInstanceOrArray(config.require);
@@ -1003,20 +989,20 @@ async function executeCodegen(input) {
1003
989
  const result = await schemaLoadingCache.load(hash);
1004
990
  outputSchemaAst = await result.outputSchemaAst;
1005
991
  outputSchema = result.outputSchema;
1006
- }, filename),
992
+ }, filename, `Load GraphQL schemas: ${filename}`),
1007
993
  },
1008
994
  {
1009
995
  title: 'Load GraphQL documents',
1010
996
  task: wrapTask(async () => {
1011
997
  debugLog(`[CLI] Loading Documents`);
1012
998
  const allDocuments = [...rootDocuments, ...outputSpecificDocuments];
1013
- const hash = JSON.stringify({ pointer: allDocuments, schema: outputSchema });
999
+ const hash = JSON.stringify(allDocuments);
1014
1000
  const result = await documentsLoadingCache.load(hash);
1015
1001
  const documents = result.documents;
1016
1002
  if (documents.length > 0) {
1017
1003
  outputDocuments.push(...documents);
1018
1004
  }
1019
- }, filename),
1005
+ }, filename, `Load GraphQL documents: ${filename}`),
1020
1006
  },
1021
1007
  {
1022
1008
  title: 'Generate',
@@ -1044,7 +1030,7 @@ async function executeCodegen(input) {
1044
1030
  };
1045
1031
  let outputs = [];
1046
1032
  if (hasPreset) {
1047
- outputs = await preset.buildGeneratesSection({
1033
+ outputs = await context.profiler.run(async () => preset.buildGeneratesSection({
1048
1034
  baseOutputDir: filename,
1049
1035
  presetConfig: outputConfig.presetConfig || {},
1050
1036
  plugins: normalizedPluginsArray,
@@ -1054,7 +1040,8 @@ async function executeCodegen(input) {
1054
1040
  config: mergedConfig,
1055
1041
  pluginMap,
1056
1042
  pluginContext,
1057
- });
1043
+ profiler: context.profiler,
1044
+ }), `Build Generates Section: ${filename}`);
1058
1045
  }
1059
1046
  else {
1060
1047
  outputs = [
@@ -1067,6 +1054,7 @@ async function executeCodegen(input) {
1067
1054
  config: mergedConfig,
1068
1055
  pluginMap,
1069
1056
  pluginContext,
1057
+ profiler: context.profiler,
1070
1058
  },
1071
1059
  ];
1072
1060
  }
@@ -1078,8 +1066,8 @@ async function executeCodegen(input) {
1078
1066
  hooks: outputConfig.hooks || {},
1079
1067
  });
1080
1068
  };
1081
- await Promise.all(outputs.map(process));
1082
- }, filename),
1069
+ await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
1070
+ }, filename, `Generate: ${filename}`),
1083
1071
  },
1084
1072
  ], {
1085
1073
  // it stops when one of tasks failed
@@ -1246,7 +1234,7 @@ const hash = (content) => crypto.createHash('sha1').update(content).digest('base
1246
1234
  async function generate(input, saveToFile = true) {
1247
1235
  const context = ensureContext(input);
1248
1236
  const config = context.getConfig();
1249
- await lifecycleHooks(config.hooks).afterStart();
1237
+ await context.profiler.run(() => lifecycleHooks(config.hooks).afterStart(), 'Lifecycle: afterStart');
1250
1238
  let previouslyGeneratedFilenames = [];
1251
1239
  function removeStaleFiles(config, generationResult) {
1252
1240
  const filenames = generationResult.map(o => o.filename);
@@ -1275,8 +1263,8 @@ async function generate(input, saveToFile = true) {
1275
1263
  if (config.watch) {
1276
1264
  removeStaleFiles(config, generationResult);
1277
1265
  }
1278
- await lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
1279
- await Promise.all(generationResult.map(async (result) => {
1266
+ await context.profiler.run(() => lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: beforeAllFileWrite');
1267
+ await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
1280
1268
  const exists = fileExists(result.filename);
1281
1269
  if (!shouldOverwrite(config, result.filename) && exists) {
1282
1270
  return;
@@ -1288,7 +1276,7 @@ async function generate(input, saveToFile = true) {
1288
1276
  previousHash = hash(readSync(result.filename));
1289
1277
  }
1290
1278
  if (previousHash && currentHash === previousHash) {
1291
- debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1279
+ debugLog(`Skipping file (${result.filename}) writing due to identical hash...`);
1292
1280
  return;
1293
1281
  }
1294
1282
  if (content.length === 0) {
@@ -1305,17 +1293,20 @@ async function generate(input, saveToFile = true) {
1305
1293
  writeSync(absolutePath, result.content);
1306
1294
  await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename);
1307
1295
  await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename);
1308
- }));
1309
- await lifecycleHooks(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename));
1296
+ })), 'Write files');
1297
+ await context.profiler.run(() => lifecycleHooks(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: afterAllFileWrite');
1310
1298
  return generationResult;
1311
1299
  }
1312
1300
  // watch mode
1313
1301
  if (config.watch) {
1314
1302
  return createWatcher(context, writeOutput);
1315
1303
  }
1316
- const outputFiles = await executeCodegen(context);
1317
- await writeOutput(outputFiles);
1318
- lifecycleHooks(config.hooks).beforeDone();
1304
+ const outputFiles = await context.profiler.run(() => executeCodegen(context), 'executeCodegen');
1305
+ await context.profiler.run(() => writeOutput(outputFiles), 'writeOutput');
1306
+ await context.profiler.run(() => lifecycleHooks(config.hooks).beforeDone(), 'Lifecycle: beforeDone');
1307
+ if (context.profilerOutput) {
1308
+ writeSync(path.join(context.cwd, context.profilerOutput), JSON.stringify(context.profiler.collect()));
1309
+ }
1319
1310
  return outputFiles;
1320
1311
  }
1321
1312
  function shouldOverwrite(config, outputPath) {
package/codegen.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  import { Types } from '@graphql-codegen/plugin-helpers';
2
2
  import { CodegenContext } from './config';
3
- export declare const makeDefaultLoader: (from: string) => (mod: string) => Promise<any>;
4
3
  export declare function executeCodegen(input: CodegenContext | Types.Config): Promise<Types.FileOutput[]>;
package/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Types } from '@graphql-codegen/plugin-helpers';
1
+ import { Types, Profiler } from '@graphql-codegen/plugin-helpers';
2
2
  import { GraphQLConfig } from 'graphql-config';
3
3
  import { GraphQLSchema } from 'graphql';
4
4
  export declare type YamlCliFlags = {
@@ -9,6 +9,7 @@ export declare type YamlCliFlags = {
9
9
  project: string;
10
10
  silent: boolean;
11
11
  errorsOnly: boolean;
12
+ profile: boolean;
12
13
  };
13
14
  export declare function generateSearchPlaces(moduleName: string): string[];
14
15
  export interface LoadCodegenConfigOptions {
@@ -74,6 +75,10 @@ export declare function buildOptions(): {
74
75
  describe: string;
75
76
  type: "boolean";
76
77
  };
78
+ profile: {
79
+ describe: string;
80
+ type: "boolean";
81
+ };
77
82
  p: {
78
83
  alias: string;
79
84
  describe: string;
@@ -91,6 +96,8 @@ export declare class CodegenContext {
91
96
  private _pluginContext;
92
97
  cwd: string;
93
98
  filepath: string;
99
+ profiler: Profiler;
100
+ profilerOutput?: string;
94
101
  constructor({ config, graphqlConfig, filepath, }: {
95
102
  config?: Types.Config;
96
103
  graphqlConfig?: GraphQLConfig;
@@ -99,13 +106,11 @@ export declare class CodegenContext {
99
106
  useProject(name?: string): void;
100
107
  getConfig<T>(extraConfig?: T): T & Types.Config;
101
108
  updateConfig(config: Partial<Types.Config>): void;
109
+ useProfiler(): void;
102
110
  getPluginContext(): {
103
111
  [key: string]: any;
104
112
  };
105
113
  loadSchema(pointer: Types.Schema): Promise<GraphQLSchema>;
106
- loadDocuments(input: {
107
- pointer: Types.OperationDocument[];
108
- schema: GraphQLSchema;
109
- }): Promise<Types.DocumentFile[]>;
114
+ loadDocuments(pointer: Types.OperationDocument[]): Promise<Types.DocumentFile[]>;
110
115
  }
111
116
  export declare function ensureContext(input: CodegenContext | Types.Config): CodegenContext;
package/index.js CHANGED
@@ -423,30 +423,20 @@ async function loadSchema(schemaPointers, config) {
423
423
 
424
424
  ${e.message || e}
425
425
  ${e.stack || ''}
426
-
426
+
427
427
  GraphQL Code Generator supports:
428
428
  - ES Modules and CommonJS exports (export as default or named export "schema")
429
429
  - Introspection JSON File
430
430
  - URL of GraphQL endpoint
431
431
  - Multiple files with type definitions (glob expression)
432
432
  - String in config file
433
-
433
+
434
434
  Try to use one of above options and run codegen again.
435
-
435
+
436
436
  `);
437
437
  }
438
438
  }
439
- const requiredLoader = async (pointers, schema) => {
440
- return Promise.all(pointers.map(async (pointer) => {
441
- const userLoader = (await makeDefaultLoader(process.cwd())(pointer.require)).default;
442
- const documents = userLoader(pointer.config || {}, schema);
443
- return documents;
444
- })).then(results => [].concat(...results));
445
- };
446
- const isRequirePointer = (pointer) => {
447
- return typeof pointer === 'object' && 'require' in pointer;
448
- };
449
- async function loadDocuments(documentPointers, config, schema) {
439
+ async function loadDocuments(documentPointers, config) {
450
440
  const loaders = [
451
441
  new codeFileLoader.CodeFileLoader({
452
442
  pluckConfig: {
@@ -465,35 +455,14 @@ async function loadDocuments(documentPointers, config, schema) {
465
455
  }
466
456
  ignore.push(path.join(process.cwd(), generatePath));
467
457
  }
468
- const loaderPointers = [];
469
- const requestPointers = [];
470
- if (Array.isArray(documentPointers)) {
471
- documentPointers.forEach(pointer => {
472
- if (isRequirePointer(pointer)) {
473
- requestPointers.push(pointer);
474
- }
475
- else {
476
- loaderPointers.push(pointer);
477
- }
478
- });
479
- }
480
- else {
481
- if (isRequirePointer(documentPointers)) {
482
- requestPointers.push(documentPointers);
483
- }
484
- else {
485
- loaderPointers.push(documentPointers);
486
- }
487
- }
488
- const loadedFromToolkit = await load.loadDocuments(loaderPointers, {
458
+ const loadedFromToolkit = await load.loadDocuments(documentPointers, {
489
459
  ...defaultDocumentsLoadOptions,
490
460
  ignore,
491
461
  loaders,
492
462
  ...config,
493
463
  ...config.config,
494
464
  });
495
- const loadedAlterantively = await requiredLoader(requestPointers, schema);
496
- return [...loadedFromToolkit, ...loadedAlterantively];
465
+ return loadedFromToolkit;
497
466
  }
498
467
 
499
468
  const { lstat } = fs.promises;
@@ -625,6 +594,10 @@ function buildOptions() {
625
594
  describe: 'Only print errors',
626
595
  type: 'boolean',
627
596
  },
597
+ profile: {
598
+ describe: 'Use profiler to measure performance',
599
+ type: 'boolean',
600
+ },
628
601
  p: {
629
602
  alias: 'project',
630
603
  describe: 'Name of a project in GraphQL Config',
@@ -666,6 +639,9 @@ function updateContextWithCliFlags(context, cliFlags) {
666
639
  if (cliFlags.project) {
667
640
  context.useProject(cliFlags.project);
668
641
  }
642
+ if (cliFlags.profile === true) {
643
+ context.useProfiler();
644
+ }
669
645
  context.updateConfig(config);
670
646
  }
671
647
  class CodegenContext {
@@ -675,6 +651,7 @@ class CodegenContext {
675
651
  this._graphqlConfig = graphqlConfig;
676
652
  this.filepath = this._graphqlConfig ? this._graphqlConfig.filepath : filepath;
677
653
  this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : process.cwd();
654
+ this.profiler = pluginHelpers.createNoopProfiler();
678
655
  }
679
656
  useProject(name) {
680
657
  this._project = name;
@@ -705,6 +682,13 @@ class CodegenContext {
705
682
  ...config,
706
683
  };
707
684
  }
685
+ useProfiler() {
686
+ this.profiler = pluginHelpers.createProfiler();
687
+ const now = new Date(); // 2011-10-05T14:48:00.000Z
688
+ const datetime = now.toISOString().split('.')[0]; // 2011-10-05T14:48:00
689
+ const datetimeNormalized = datetime.replace(/-|:/g, ''); // 20111005T144800
690
+ this.profilerOutput = `codegen-${datetimeNormalized}.json`;
691
+ }
708
692
  getPluginContext() {
709
693
  return this._pluginContext;
710
694
  }
@@ -716,14 +700,14 @@ class CodegenContext {
716
700
  }
717
701
  return loadSchema(pointer, config);
718
702
  }
719
- async loadDocuments(input) {
703
+ async loadDocuments(pointer) {
720
704
  const config = this.getConfig(defaultDocumentsLoadOptions);
721
705
  if (this._graphqlConfig) {
722
706
  // TODO: pointer won't work here
723
- const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(input.pointer, config);
707
+ const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config);
724
708
  return documents;
725
709
  }
726
- return loadDocuments(input.pointer, config, input.schema);
710
+ return loadDocuments(pointer, config);
727
711
  }
728
712
  }
729
713
  function ensureContext(input) {
@@ -754,19 +738,6 @@ function createCache(loader) {
754
738
  };
755
739
  }
756
740
  async function executeCodegen(input) {
757
- function wrapTask(task, source) {
758
- return async () => {
759
- try {
760
- await Promise.resolve().then(() => task());
761
- }
762
- catch (error) {
763
- if (source && !(error instanceof graphql.GraphQLError)) {
764
- error.source = source;
765
- }
766
- throw error;
767
- }
768
- };
769
- }
770
741
  const context = ensureContext(input);
771
742
  const config = context.getConfig();
772
743
  const pluginContext = context.getPluginContext();
@@ -813,9 +784,24 @@ async function executeCodegen(input) {
813
784
  const documentsLoadingCache = createCache(async function (hash) {
814
785
  const documents = await context.loadDocuments(JSON.parse(hash));
815
786
  return {
816
- documents,
787
+ documents: documents,
817
788
  };
818
789
  });
790
+ function wrapTask(task, source, taskName) {
791
+ return () => {
792
+ return context.profiler.run(async () => {
793
+ try {
794
+ await Promise.resolve().then(() => task());
795
+ }
796
+ catch (error) {
797
+ if (source && !(error instanceof graphql.GraphQLError)) {
798
+ error.source = source;
799
+ }
800
+ throw error;
801
+ }
802
+ }, taskName);
803
+ };
804
+ }
819
805
  async function normalize() {
820
806
  /* Load Require extensions */
821
807
  const requireExtensions = pluginHelpers.normalizeInstanceOrArray(config.require);
@@ -921,20 +907,20 @@ async function executeCodegen(input) {
921
907
  const result = await schemaLoadingCache.load(hash);
922
908
  outputSchemaAst = await result.outputSchemaAst;
923
909
  outputSchema = result.outputSchema;
924
- }, filename),
910
+ }, filename, `Load GraphQL schemas: ${filename}`),
925
911
  },
926
912
  {
927
913
  title: 'Load GraphQL documents',
928
914
  task: wrapTask(async () => {
929
915
  debugLog(`[CLI] Loading Documents`);
930
916
  const allDocuments = [...rootDocuments, ...outputSpecificDocuments];
931
- const hash = JSON.stringify({ pointer: allDocuments, schema: outputSchema });
917
+ const hash = JSON.stringify(allDocuments);
932
918
  const result = await documentsLoadingCache.load(hash);
933
919
  const documents = result.documents;
934
920
  if (documents.length > 0) {
935
921
  outputDocuments.push(...documents);
936
922
  }
937
- }, filename),
923
+ }, filename, `Load GraphQL documents: ${filename}`),
938
924
  },
939
925
  {
940
926
  title: 'Generate',
@@ -962,7 +948,7 @@ async function executeCodegen(input) {
962
948
  };
963
949
  let outputs = [];
964
950
  if (hasPreset) {
965
- outputs = await preset.buildGeneratesSection({
951
+ outputs = await context.profiler.run(async () => preset.buildGeneratesSection({
966
952
  baseOutputDir: filename,
967
953
  presetConfig: outputConfig.presetConfig || {},
968
954
  plugins: normalizedPluginsArray,
@@ -972,7 +958,8 @@ async function executeCodegen(input) {
972
958
  config: mergedConfig,
973
959
  pluginMap,
974
960
  pluginContext,
975
- });
961
+ profiler: context.profiler,
962
+ }), `Build Generates Section: ${filename}`);
976
963
  }
977
964
  else {
978
965
  outputs = [
@@ -985,6 +972,7 @@ async function executeCodegen(input) {
985
972
  config: mergedConfig,
986
973
  pluginMap,
987
974
  pluginContext,
975
+ profiler: context.profiler,
988
976
  },
989
977
  ];
990
978
  }
@@ -996,8 +984,8 @@ async function executeCodegen(input) {
996
984
  hooks: outputConfig.hooks || {},
997
985
  });
998
986
  };
999
- await Promise.all(outputs.map(process));
1000
- }, filename),
987
+ await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
988
+ }, filename, `Generate: ${filename}`),
1001
989
  },
1002
990
  ], {
1003
991
  // it stops when one of tasks failed
@@ -1247,7 +1235,7 @@ const hash = (content) => crypto.createHash('sha1').update(content).digest('base
1247
1235
  async function generate(input, saveToFile = true) {
1248
1236
  const context = ensureContext(input);
1249
1237
  const config = context.getConfig();
1250
- await lifecycleHooks(config.hooks).afterStart();
1238
+ await context.profiler.run(() => lifecycleHooks(config.hooks).afterStart(), 'Lifecycle: afterStart');
1251
1239
  let previouslyGeneratedFilenames = [];
1252
1240
  function removeStaleFiles(config, generationResult) {
1253
1241
  const filenames = generationResult.map(o => o.filename);
@@ -1276,8 +1264,8 @@ async function generate(input, saveToFile = true) {
1276
1264
  if (config.watch) {
1277
1265
  removeStaleFiles(config, generationResult);
1278
1266
  }
1279
- await lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
1280
- await Promise.all(generationResult.map(async (result) => {
1267
+ await context.profiler.run(() => lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: beforeAllFileWrite');
1268
+ await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
1281
1269
  const exists = fileExists(result.filename);
1282
1270
  if (!shouldOverwrite(config, result.filename) && exists) {
1283
1271
  return;
@@ -1289,7 +1277,7 @@ async function generate(input, saveToFile = true) {
1289
1277
  previousHash = hash(readSync(result.filename));
1290
1278
  }
1291
1279
  if (previousHash && currentHash === previousHash) {
1292
- debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1280
+ debugLog(`Skipping file (${result.filename}) writing due to identical hash...`);
1293
1281
  return;
1294
1282
  }
1295
1283
  if (content.length === 0) {
@@ -1306,17 +1294,20 @@ async function generate(input, saveToFile = true) {
1306
1294
  writeSync(absolutePath, result.content);
1307
1295
  await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename);
1308
1296
  await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename);
1309
- }));
1310
- await lifecycleHooks(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename));
1297
+ })), 'Write files');
1298
+ await context.profiler.run(() => lifecycleHooks(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: afterAllFileWrite');
1311
1299
  return generationResult;
1312
1300
  }
1313
1301
  // watch mode
1314
1302
  if (config.watch) {
1315
1303
  return createWatcher(context, writeOutput);
1316
1304
  }
1317
- const outputFiles = await executeCodegen(context);
1318
- await writeOutput(outputFiles);
1319
- lifecycleHooks(config.hooks).beforeDone();
1305
+ const outputFiles = await context.profiler.run(() => executeCodegen(context), 'executeCodegen');
1306
+ await context.profiler.run(() => writeOutput(outputFiles), 'writeOutput');
1307
+ await context.profiler.run(() => lifecycleHooks(config.hooks).beforeDone(), 'Lifecycle: beforeDone');
1308
+ if (context.profilerOutput) {
1309
+ writeSync(path.join(context.cwd, context.profilerOutput), JSON.stringify(context.profiler.collect()));
1310
+ }
1320
1311
  return outputFiles;
1321
1312
  }
1322
1313
  function shouldOverwrite(config, outputPath) {
package/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { isDetailedError, DetailedError, normalizeInstanceOrArray, normalizeConfig, normalizeOutputParam, getCachedDocumentNodeFromSchema } from '@graphql-codegen/plugin-helpers';
1
+ import { isDetailedError, DetailedError, createNoopProfiler, createProfiler, normalizeInstanceOrArray, normalizeConfig, normalizeOutputParam, getCachedDocumentNodeFromSchema } from '@graphql-codegen/plugin-helpers';
2
2
  import { codegen } from '@graphql-codegen/core';
3
3
  import chalk from 'chalk';
4
4
  import logSymbols from 'log-symbols';
@@ -24,7 +24,7 @@ import { JsonFileLoader } from '@graphql-tools/json-file-loader';
24
24
  import { UrlLoader } from '@graphql-tools/url-loader';
25
25
  import yaml from 'yaml';
26
26
  import { createRequire } from 'module';
27
- import fs, { promises, readFileSync, writeFileSync, statSync, unlink } from 'fs';
27
+ import fs, { promises, writeFileSync, readFileSync, statSync, unlink } from 'fs';
28
28
  import Listr from 'listr';
29
29
  import { exec } from 'child_process';
30
30
  import isGlob from 'is-glob';
@@ -396,30 +396,20 @@ async function loadSchema(schemaPointers, config) {
396
396
 
397
397
  ${e.message || e}
398
398
  ${e.stack || ''}
399
-
399
+
400
400
  GraphQL Code Generator supports:
401
401
  - ES Modules and CommonJS exports (export as default or named export "schema")
402
402
  - Introspection JSON File
403
403
  - URL of GraphQL endpoint
404
404
  - Multiple files with type definitions (glob expression)
405
405
  - String in config file
406
-
406
+
407
407
  Try to use one of above options and run codegen again.
408
-
408
+
409
409
  `);
410
410
  }
411
411
  }
412
- const requiredLoader = async (pointers, schema) => {
413
- return Promise.all(pointers.map(async (pointer) => {
414
- const userLoader = (await makeDefaultLoader(process.cwd())(pointer.require)).default;
415
- const documents = userLoader(pointer.config || {}, schema);
416
- return documents;
417
- })).then(results => [].concat(...results));
418
- };
419
- const isRequirePointer = (pointer) => {
420
- return typeof pointer === 'object' && 'require' in pointer;
421
- };
422
- async function loadDocuments(documentPointers, config, schema) {
412
+ async function loadDocuments(documentPointers, config) {
423
413
  const loaders = [
424
414
  new CodeFileLoader({
425
415
  pluckConfig: {
@@ -438,35 +428,14 @@ async function loadDocuments(documentPointers, config, schema) {
438
428
  }
439
429
  ignore.push(join(process.cwd(), generatePath));
440
430
  }
441
- const loaderPointers = [];
442
- const requestPointers = [];
443
- if (Array.isArray(documentPointers)) {
444
- documentPointers.forEach(pointer => {
445
- if (isRequirePointer(pointer)) {
446
- requestPointers.push(pointer);
447
- }
448
- else {
449
- loaderPointers.push(pointer);
450
- }
451
- });
452
- }
453
- else {
454
- if (isRequirePointer(documentPointers)) {
455
- requestPointers.push(documentPointers);
456
- }
457
- else {
458
- loaderPointers.push(documentPointers);
459
- }
460
- }
461
- const loadedFromToolkit = await loadDocuments$1(loaderPointers, {
431
+ const loadedFromToolkit = await loadDocuments$1(documentPointers, {
462
432
  ...defaultDocumentsLoadOptions,
463
433
  ignore,
464
434
  loaders,
465
435
  ...config,
466
436
  ...config.config,
467
437
  });
468
- const loadedAlterantively = await requiredLoader(requestPointers, schema);
469
- return [...loadedFromToolkit, ...loadedAlterantively];
438
+ return loadedFromToolkit;
470
439
  }
471
440
 
472
441
  const { lstat } = promises;
@@ -598,6 +567,10 @@ function buildOptions() {
598
567
  describe: 'Only print errors',
599
568
  type: 'boolean',
600
569
  },
570
+ profile: {
571
+ describe: 'Use profiler to measure performance',
572
+ type: 'boolean',
573
+ },
601
574
  p: {
602
575
  alias: 'project',
603
576
  describe: 'Name of a project in GraphQL Config',
@@ -639,6 +612,9 @@ function updateContextWithCliFlags(context, cliFlags) {
639
612
  if (cliFlags.project) {
640
613
  context.useProject(cliFlags.project);
641
614
  }
615
+ if (cliFlags.profile === true) {
616
+ context.useProfiler();
617
+ }
642
618
  context.updateConfig(config);
643
619
  }
644
620
  class CodegenContext {
@@ -648,6 +624,7 @@ class CodegenContext {
648
624
  this._graphqlConfig = graphqlConfig;
649
625
  this.filepath = this._graphqlConfig ? this._graphqlConfig.filepath : filepath;
650
626
  this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : process.cwd();
627
+ this.profiler = createNoopProfiler();
651
628
  }
652
629
  useProject(name) {
653
630
  this._project = name;
@@ -678,6 +655,13 @@ class CodegenContext {
678
655
  ...config,
679
656
  };
680
657
  }
658
+ useProfiler() {
659
+ this.profiler = createProfiler();
660
+ const now = new Date(); // 2011-10-05T14:48:00.000Z
661
+ const datetime = now.toISOString().split('.')[0]; // 2011-10-05T14:48:00
662
+ const datetimeNormalized = datetime.replace(/-|:/g, ''); // 20111005T144800
663
+ this.profilerOutput = `codegen-${datetimeNormalized}.json`;
664
+ }
681
665
  getPluginContext() {
682
666
  return this._pluginContext;
683
667
  }
@@ -689,14 +673,14 @@ class CodegenContext {
689
673
  }
690
674
  return loadSchema(pointer, config);
691
675
  }
692
- async loadDocuments(input) {
676
+ async loadDocuments(pointer) {
693
677
  const config = this.getConfig(defaultDocumentsLoadOptions);
694
678
  if (this._graphqlConfig) {
695
679
  // TODO: pointer won't work here
696
- const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(input.pointer, config);
680
+ const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config);
697
681
  return documents;
698
682
  }
699
- return loadDocuments(input.pointer, config, input.schema);
683
+ return loadDocuments(pointer, config);
700
684
  }
701
685
  }
702
686
  function ensureContext(input) {
@@ -727,19 +711,6 @@ function createCache(loader) {
727
711
  };
728
712
  }
729
713
  async function executeCodegen(input) {
730
- function wrapTask(task, source) {
731
- return async () => {
732
- try {
733
- await Promise.resolve().then(() => task());
734
- }
735
- catch (error) {
736
- if (source && !(error instanceof GraphQLError)) {
737
- error.source = source;
738
- }
739
- throw error;
740
- }
741
- };
742
- }
743
714
  const context = ensureContext(input);
744
715
  const config = context.getConfig();
745
716
  const pluginContext = context.getPluginContext();
@@ -786,9 +757,24 @@ async function executeCodegen(input) {
786
757
  const documentsLoadingCache = createCache(async function (hash) {
787
758
  const documents = await context.loadDocuments(JSON.parse(hash));
788
759
  return {
789
- documents,
760
+ documents: documents,
790
761
  };
791
762
  });
763
+ function wrapTask(task, source, taskName) {
764
+ return () => {
765
+ return context.profiler.run(async () => {
766
+ try {
767
+ await Promise.resolve().then(() => task());
768
+ }
769
+ catch (error) {
770
+ if (source && !(error instanceof GraphQLError)) {
771
+ error.source = source;
772
+ }
773
+ throw error;
774
+ }
775
+ }, taskName);
776
+ };
777
+ }
792
778
  async function normalize() {
793
779
  /* Load Require extensions */
794
780
  const requireExtensions = normalizeInstanceOrArray(config.require);
@@ -894,20 +880,20 @@ async function executeCodegen(input) {
894
880
  const result = await schemaLoadingCache.load(hash);
895
881
  outputSchemaAst = await result.outputSchemaAst;
896
882
  outputSchema = result.outputSchema;
897
- }, filename),
883
+ }, filename, `Load GraphQL schemas: ${filename}`),
898
884
  },
899
885
  {
900
886
  title: 'Load GraphQL documents',
901
887
  task: wrapTask(async () => {
902
888
  debugLog(`[CLI] Loading Documents`);
903
889
  const allDocuments = [...rootDocuments, ...outputSpecificDocuments];
904
- const hash = JSON.stringify({ pointer: allDocuments, schema: outputSchema });
890
+ const hash = JSON.stringify(allDocuments);
905
891
  const result = await documentsLoadingCache.load(hash);
906
892
  const documents = result.documents;
907
893
  if (documents.length > 0) {
908
894
  outputDocuments.push(...documents);
909
895
  }
910
- }, filename),
896
+ }, filename, `Load GraphQL documents: ${filename}`),
911
897
  },
912
898
  {
913
899
  title: 'Generate',
@@ -935,7 +921,7 @@ async function executeCodegen(input) {
935
921
  };
936
922
  let outputs = [];
937
923
  if (hasPreset) {
938
- outputs = await preset.buildGeneratesSection({
924
+ outputs = await context.profiler.run(async () => preset.buildGeneratesSection({
939
925
  baseOutputDir: filename,
940
926
  presetConfig: outputConfig.presetConfig || {},
941
927
  plugins: normalizedPluginsArray,
@@ -945,7 +931,8 @@ async function executeCodegen(input) {
945
931
  config: mergedConfig,
946
932
  pluginMap,
947
933
  pluginContext,
948
- });
934
+ profiler: context.profiler,
935
+ }), `Build Generates Section: ${filename}`);
949
936
  }
950
937
  else {
951
938
  outputs = [
@@ -958,6 +945,7 @@ async function executeCodegen(input) {
958
945
  config: mergedConfig,
959
946
  pluginMap,
960
947
  pluginContext,
948
+ profiler: context.profiler,
961
949
  },
962
950
  ];
963
951
  }
@@ -969,8 +957,8 @@ async function executeCodegen(input) {
969
957
  hooks: outputConfig.hooks || {},
970
958
  });
971
959
  };
972
- await Promise.all(outputs.map(process));
973
- }, filename),
960
+ await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
961
+ }, filename, `Generate: ${filename}`),
974
962
  },
975
963
  ], {
976
964
  // it stops when one of tasks failed
@@ -1220,7 +1208,7 @@ const hash = (content) => createHash('sha1').update(content).digest('base64');
1220
1208
  async function generate(input, saveToFile = true) {
1221
1209
  const context = ensureContext(input);
1222
1210
  const config = context.getConfig();
1223
- await lifecycleHooks(config.hooks).afterStart();
1211
+ await context.profiler.run(() => lifecycleHooks(config.hooks).afterStart(), 'Lifecycle: afterStart');
1224
1212
  let previouslyGeneratedFilenames = [];
1225
1213
  function removeStaleFiles(config, generationResult) {
1226
1214
  const filenames = generationResult.map(o => o.filename);
@@ -1249,8 +1237,8 @@ async function generate(input, saveToFile = true) {
1249
1237
  if (config.watch) {
1250
1238
  removeStaleFiles(config, generationResult);
1251
1239
  }
1252
- await lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
1253
- await Promise.all(generationResult.map(async (result) => {
1240
+ await context.profiler.run(() => lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: beforeAllFileWrite');
1241
+ await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
1254
1242
  const exists = fileExists(result.filename);
1255
1243
  if (!shouldOverwrite(config, result.filename) && exists) {
1256
1244
  return;
@@ -1262,7 +1250,7 @@ async function generate(input, saveToFile = true) {
1262
1250
  previousHash = hash(readSync(result.filename));
1263
1251
  }
1264
1252
  if (previousHash && currentHash === previousHash) {
1265
- debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1253
+ debugLog(`Skipping file (${result.filename}) writing due to identical hash...`);
1266
1254
  return;
1267
1255
  }
1268
1256
  if (content.length === 0) {
@@ -1279,17 +1267,20 @@ async function generate(input, saveToFile = true) {
1279
1267
  writeSync(absolutePath, result.content);
1280
1268
  await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename);
1281
1269
  await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename);
1282
- }));
1283
- await lifecycleHooks(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename));
1270
+ })), 'Write files');
1271
+ await context.profiler.run(() => lifecycleHooks(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: afterAllFileWrite');
1284
1272
  return generationResult;
1285
1273
  }
1286
1274
  // watch mode
1287
1275
  if (config.watch) {
1288
1276
  return createWatcher(context, writeOutput);
1289
1277
  }
1290
- const outputFiles = await executeCodegen(context);
1291
- await writeOutput(outputFiles);
1292
- lifecycleHooks(config.hooks).beforeDone();
1278
+ const outputFiles = await context.profiler.run(() => executeCodegen(context), 'executeCodegen');
1279
+ await context.profiler.run(() => writeOutput(outputFiles), 'writeOutput');
1280
+ await context.profiler.run(() => lifecycleHooks(config.hooks).beforeDone(), 'Lifecycle: beforeDone');
1281
+ if (context.profilerOutput) {
1282
+ writeSync(join(context.cwd, context.profilerOutput), JSON.stringify(context.profiler.collect()));
1283
+ }
1293
1284
  return outputFiles;
1294
1285
  }
1295
1286
  function shouldOverwrite(config, outputPath) {
package/load.d.ts CHANGED
@@ -12,4 +12,4 @@ export declare const defaultDocumentsLoadOptions: {
12
12
  skipGraphQLImport: boolean;
13
13
  };
14
14
  export declare function loadSchema(schemaPointers: UnnormalizedTypeDefPointer, config: Types.Config): Promise<GraphQLSchema>;
15
- export declare function loadDocuments(documentPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], config: Types.Config, schema: GraphQLSchema): Promise<Types.DocumentFile[]>;
15
+ export declare function loadDocuments(documentPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], config: Types.Config): Promise<Types.DocumentFile[]>;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@graphql-codegen/cli",
3
- "version": "2.5.0-alpha-bc33c031d.0",
3
+ "version": "2.5.0-alpha-fc06eb8e7.0",
4
4
  "peerDependencies": {
5
5
  "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
6
6
  },
7
7
  "dependencies": {
8
- "@graphql-codegen/core": "2.4.1-alpha-bc33c031d.0",
9
- "@graphql-codegen/plugin-helpers": "2.3.3-alpha-bc33c031d.0",
8
+ "@graphql-codegen/core": "2.5.0-alpha-fc06eb8e7.0",
9
+ "@graphql-codegen/plugin-helpers": "2.4.0-alpha-fc06eb8e7.0",
10
10
  "@graphql-tools/apollo-engine-loader": "^7.0.5",
11
11
  "@graphql-tools/code-file-loader": "^7.0.6",
12
12
  "@graphql-tools/git-loader": "^7.0.5",