@graphql-codegen/cli 2.6.0-alpha-dfbea14f8.0 → 2.6.0-alpha-cb6ec4365.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.
Files changed (4) hide show
  1. package/bin.js +67 -67
  2. package/index.js +67 -67
  3. package/index.mjs +69 -69
  4. package/package.json +3 -3
package/bin.js CHANGED
@@ -53,12 +53,12 @@ const yaml = _interopDefault(require('yaml'));
53
53
  const module$1 = require('module');
54
54
  const fs = require('fs');
55
55
  const fs__default = _interopDefault(fs);
56
+ const crypto = require('crypto');
56
57
  const os = require('os');
57
58
  const Listr = _interopDefault(require('listr'));
58
59
  const isGlob = _interopDefault(require('is-glob'));
59
60
  const debounce = _interopDefault(require('debounce'));
60
61
  const mkdirp = _interopDefault(require('mkdirp'));
61
- const crypto = require('crypto');
62
62
  const inquirer = _interopDefault(require('inquirer'));
63
63
  const detectIndent = _interopDefault(require('detect-indent'));
64
64
  const getLatestVersion = _interopDefault(require('latest-version'));
@@ -779,23 +779,52 @@ class CodegenContext {
779
779
  const config = this.getConfig(defaultSchemaLoadOptions);
780
780
  if (this._graphqlConfig) {
781
781
  // TODO: SchemaWithLoader won't work here
782
- return this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config);
782
+ return addHashToSchema(this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config));
783
783
  }
784
- return loadSchema(pointer, config);
784
+ return addHashToSchema(loadSchema(pointer, config));
785
785
  }
786
786
  async loadDocuments(pointer) {
787
787
  const config = this.getConfig(defaultDocumentsLoadOptions);
788
788
  if (this._graphqlConfig) {
789
789
  // TODO: pointer won't work here
790
- const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config);
791
- return documents;
790
+ return addHashToDocumentFiles(this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config));
792
791
  }
793
- return loadDocuments(pointer, config);
792
+ return addHashToDocumentFiles(loadDocuments(pointer, config));
794
793
  }
795
794
  }
796
795
  function ensureContext(input) {
797
796
  return input instanceof CodegenContext ? input : new CodegenContext({ config: input });
798
797
  }
798
+ function hashContent(content) {
799
+ return crypto.createHash('sha256').update(content).digest('hex');
800
+ }
801
+ function hashSchema(schema) {
802
+ return hashContent(utils.printSchemaWithDirectives(schema, {
803
+ assumeValid: true,
804
+ }));
805
+ }
806
+ function addHashToSchema(schemaPromise) {
807
+ return schemaPromise.then(schema => {
808
+ // It's consumed later on. The general purpose is to use it for caching.
809
+ schema.extensions['hash'] = hashSchema(schema);
810
+ return schema;
811
+ });
812
+ }
813
+ function hashDocument(doc) {
814
+ if (doc.rawSDL) {
815
+ return hashContent(doc.rawSDL);
816
+ }
817
+ if (doc.document) {
818
+ return hashContent(graphql.print(doc.document));
819
+ }
820
+ return null;
821
+ }
822
+ function addHashToDocumentFiles(documentFilesPromise) {
823
+ return documentFilesPromise.then(documentFiles => documentFiles.map(doc => {
824
+ doc.hash = hashDocument(doc);
825
+ return doc;
826
+ }));
827
+ }
799
828
 
800
829
  const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
801
830
  const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
@@ -833,18 +862,17 @@ const makeDefaultLoader = (from) => {
833
862
  return new Promise(function (resolve) { resolve(_interopNamespace(require(relativeRequire.resolve(mod)))); });
834
863
  };
835
864
  };
836
- // TODO: Replace any with types
837
- function createCache(loader) {
865
+ function createCache() {
838
866
  const cache = new Map();
839
- return {
840
- load(key) {
841
- if (cache.has(key)) {
842
- return cache.get(key);
843
- }
844
- const value = loader(key);
845
- cache.set(key, value);
846
- return value;
847
- },
867
+ return function ensure(namespace, key, factory) {
868
+ const cacheKey = `${namespace}:${key}`;
869
+ const cachedValue = cache.get(cacheKey);
870
+ if (cachedValue) {
871
+ return cachedValue;
872
+ }
873
+ const value = factory();
874
+ cache.set(cacheKey, value);
875
+ return value;
848
876
  };
849
877
  }
850
878
  async function executeCodegen(input) {
@@ -883,20 +911,7 @@ async function executeCodegen(input) {
883
911
  let rootSchemas;
884
912
  let rootDocuments;
885
913
  const generates = {};
886
- const schemaLoadingCache = createCache(async function (hash) {
887
- const outputSchemaAst = await context.loadSchema(JSON.parse(hash));
888
- const outputSchema = pluginHelpers.getCachedDocumentNodeFromSchema(outputSchemaAst);
889
- return {
890
- outputSchemaAst: outputSchemaAst,
891
- outputSchema: outputSchema,
892
- };
893
- });
894
- const documentsLoadingCache = createCache(async function (hash) {
895
- const documents = await context.loadDocuments(JSON.parse(hash));
896
- return {
897
- documents: documents,
898
- };
899
- });
914
+ const cache = createCache();
900
915
  function wrapTask(task, source, taskName) {
901
916
  return () => {
902
917
  return context.profiler.run(async () => {
@@ -1014,7 +1029,14 @@ async function executeCodegen(input) {
1014
1029
  }
1015
1030
  }
1016
1031
  const hash = JSON.stringify(schemaPointerMap);
1017
- const result = await schemaLoadingCache.load(hash);
1032
+ const result = await cache('schema', hash, async () => {
1033
+ const outputSchemaAst = await context.loadSchema(schemaPointerMap);
1034
+ const outputSchema = pluginHelpers.getCachedDocumentNodeFromSchema(outputSchemaAst);
1035
+ return {
1036
+ outputSchemaAst: outputSchemaAst,
1037
+ outputSchema: outputSchema,
1038
+ };
1039
+ });
1018
1040
  outputSchemaAst = await result.outputSchemaAst;
1019
1041
  outputSchema = result.outputSchema;
1020
1042
  }, filename, `Load GraphQL schemas: ${filename}`),
@@ -1026,7 +1048,12 @@ async function executeCodegen(input) {
1026
1048
  // get different cache for shared docs and output specific docs
1027
1049
  const results = await Promise.all([rootDocuments, outputSpecificDocuments].map(docs => {
1028
1050
  const hash = JSON.stringify(docs);
1029
- return documentsLoadingCache.load(hash);
1051
+ return cache('documents', hash, async () => {
1052
+ const documents = await context.loadDocuments(docs);
1053
+ return {
1054
+ documents: documents,
1055
+ };
1056
+ });
1030
1057
  }));
1031
1058
  const documents = [];
1032
1059
  results.forEach(source => documents.push(...source.documents));
@@ -1090,7 +1117,10 @@ async function executeCodegen(input) {
1090
1117
  ];
1091
1118
  }
1092
1119
  const process = async (outputArgs) => {
1093
- const output = await core.codegen(outputArgs);
1120
+ const output = await core.codegen({
1121
+ ...outputArgs,
1122
+ cache,
1123
+ });
1094
1124
  result.push({
1095
1125
  filename: outputArgs.filename,
1096
1126
  content: output,
@@ -1310,39 +1340,9 @@ async function generate(input, saveToFile = true) {
1310
1340
  }
1311
1341
  await context.profiler.run(async () => {
1312
1342
  await lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
1313
- await Promise.all(generationResult.map(async (result) => {
1314
- const exists = await fileExists(result.filename);
1315
- if (!shouldOverwrite(config, result.filename) && exists) {
1316
- return;
1317
- }
1318
- const content = result.content || '';
1319
- const currentHash = hash(content);
1320
- let previousHash = recentOutputHash.get(result.filename);
1321
- if (!previousHash && exists) {
1322
- previousHash = hash(await readFile(result.filename));
1323
- }
1324
- if (previousHash && currentHash === previousHash) {
1325
- debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1326
- return;
1327
- }
1328
- if (content.length === 0) {
1329
- return;
1330
- }
1331
- recentOutputHash.set(result.filename, currentHash);
1332
- const basedir = path.dirname(result.filename);
1333
- await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename);
1334
- await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename);
1335
- await mkdirp(basedir);
1336
- const absolutePath = path.isAbsolute(result.filename)
1337
- ? result.filename
1338
- : path.join(input.cwd || process.cwd(), result.filename);
1339
- await writeFile(absolutePath, result.content);
1340
- await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename);
1341
- await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename);
1342
- }));
1343
1343
  }, 'Lifecycle: beforeAllFileWrite');
1344
1344
  await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
1345
- const exists = fileExists(result.filename);
1345
+ const exists = await fileExists(result.filename);
1346
1346
  if (!shouldOverwrite(config, result.filename) && exists) {
1347
1347
  return;
1348
1348
  }
@@ -1353,7 +1353,7 @@ async function generate(input, saveToFile = true) {
1353
1353
  previousHash = hash(await readFile(result.filename));
1354
1354
  }
1355
1355
  if (previousHash && currentHash === previousHash) {
1356
- debugLog(`Skipping file (${result.filename}) writing due to identical hash...`);
1356
+ debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1357
1357
  return;
1358
1358
  }
1359
1359
  if (content.length === 0) {
@@ -1363,7 +1363,7 @@ async function generate(input, saveToFile = true) {
1363
1363
  const basedir = path.dirname(result.filename);
1364
1364
  await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename);
1365
1365
  await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename);
1366
- mkdirp.sync(basedir);
1366
+ await mkdirp(basedir);
1367
1367
  const absolutePath = path.isAbsolute(result.filename)
1368
1368
  ? result.filename
1369
1369
  : path.join(input.cwd || process.cwd(), result.filename);
package/index.js CHANGED
@@ -53,13 +53,13 @@ const yaml = _interopDefault(require('yaml'));
53
53
  const module$1 = require('module');
54
54
  const fs = require('fs');
55
55
  const fs__default = _interopDefault(fs);
56
+ const crypto = require('crypto');
56
57
  const os = require('os');
57
58
  const Listr = _interopDefault(require('listr'));
58
59
  const child_process = require('child_process');
59
60
  const isGlob = _interopDefault(require('is-glob'));
60
61
  const debounce = _interopDefault(require('debounce'));
61
62
  const mkdirp = _interopDefault(require('mkdirp'));
62
- const crypto = require('crypto');
63
63
  const inquirer = _interopDefault(require('inquirer'));
64
64
  const detectIndent = _interopDefault(require('detect-indent'));
65
65
  const getLatestVersion = _interopDefault(require('latest-version'));
@@ -697,23 +697,52 @@ class CodegenContext {
697
697
  const config = this.getConfig(defaultSchemaLoadOptions);
698
698
  if (this._graphqlConfig) {
699
699
  // TODO: SchemaWithLoader won't work here
700
- return this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config);
700
+ return addHashToSchema(this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config));
701
701
  }
702
- return loadSchema(pointer, config);
702
+ return addHashToSchema(loadSchema(pointer, config));
703
703
  }
704
704
  async loadDocuments(pointer) {
705
705
  const config = this.getConfig(defaultDocumentsLoadOptions);
706
706
  if (this._graphqlConfig) {
707
707
  // TODO: pointer won't work here
708
- const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config);
709
- return documents;
708
+ return addHashToDocumentFiles(this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config));
710
709
  }
711
- return loadDocuments(pointer, config);
710
+ return addHashToDocumentFiles(loadDocuments(pointer, config));
712
711
  }
713
712
  }
714
713
  function ensureContext(input) {
715
714
  return input instanceof CodegenContext ? input : new CodegenContext({ config: input });
716
715
  }
716
+ function hashContent(content) {
717
+ return crypto.createHash('sha256').update(content).digest('hex');
718
+ }
719
+ function hashSchema(schema) {
720
+ return hashContent(utils.printSchemaWithDirectives(schema, {
721
+ assumeValid: true,
722
+ }));
723
+ }
724
+ function addHashToSchema(schemaPromise) {
725
+ return schemaPromise.then(schema => {
726
+ // It's consumed later on. The general purpose is to use it for caching.
727
+ schema.extensions['hash'] = hashSchema(schema);
728
+ return schema;
729
+ });
730
+ }
731
+ function hashDocument(doc) {
732
+ if (doc.rawSDL) {
733
+ return hashContent(doc.rawSDL);
734
+ }
735
+ if (doc.document) {
736
+ return hashContent(graphql.print(doc.document));
737
+ }
738
+ return null;
739
+ }
740
+ function addHashToDocumentFiles(documentFilesPromise) {
741
+ return documentFilesPromise.then(documentFiles => documentFiles.map(doc => {
742
+ doc.hash = hashDocument(doc);
743
+ return doc;
744
+ }));
745
+ }
717
746
 
718
747
  const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
719
748
  const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
@@ -751,18 +780,17 @@ const makeDefaultLoader = (from) => {
751
780
  return new Promise(function (resolve) { resolve(_interopNamespace(require(relativeRequire.resolve(mod)))); });
752
781
  };
753
782
  };
754
- // TODO: Replace any with types
755
- function createCache(loader) {
783
+ function createCache() {
756
784
  const cache = new Map();
757
- return {
758
- load(key) {
759
- if (cache.has(key)) {
760
- return cache.get(key);
761
- }
762
- const value = loader(key);
763
- cache.set(key, value);
764
- return value;
765
- },
785
+ return function ensure(namespace, key, factory) {
786
+ const cacheKey = `${namespace}:${key}`;
787
+ const cachedValue = cache.get(cacheKey);
788
+ if (cachedValue) {
789
+ return cachedValue;
790
+ }
791
+ const value = factory();
792
+ cache.set(cacheKey, value);
793
+ return value;
766
794
  };
767
795
  }
768
796
  async function executeCodegen(input) {
@@ -801,20 +829,7 @@ async function executeCodegen(input) {
801
829
  let rootSchemas;
802
830
  let rootDocuments;
803
831
  const generates = {};
804
- const schemaLoadingCache = createCache(async function (hash) {
805
- const outputSchemaAst = await context.loadSchema(JSON.parse(hash));
806
- const outputSchema = pluginHelpers.getCachedDocumentNodeFromSchema(outputSchemaAst);
807
- return {
808
- outputSchemaAst: outputSchemaAst,
809
- outputSchema: outputSchema,
810
- };
811
- });
812
- const documentsLoadingCache = createCache(async function (hash) {
813
- const documents = await context.loadDocuments(JSON.parse(hash));
814
- return {
815
- documents: documents,
816
- };
817
- });
832
+ const cache = createCache();
818
833
  function wrapTask(task, source, taskName) {
819
834
  return () => {
820
835
  return context.profiler.run(async () => {
@@ -932,7 +947,14 @@ async function executeCodegen(input) {
932
947
  }
933
948
  }
934
949
  const hash = JSON.stringify(schemaPointerMap);
935
- const result = await schemaLoadingCache.load(hash);
950
+ const result = await cache('schema', hash, async () => {
951
+ const outputSchemaAst = await context.loadSchema(schemaPointerMap);
952
+ const outputSchema = pluginHelpers.getCachedDocumentNodeFromSchema(outputSchemaAst);
953
+ return {
954
+ outputSchemaAst: outputSchemaAst,
955
+ outputSchema: outputSchema,
956
+ };
957
+ });
936
958
  outputSchemaAst = await result.outputSchemaAst;
937
959
  outputSchema = result.outputSchema;
938
960
  }, filename, `Load GraphQL schemas: ${filename}`),
@@ -944,7 +966,12 @@ async function executeCodegen(input) {
944
966
  // get different cache for shared docs and output specific docs
945
967
  const results = await Promise.all([rootDocuments, outputSpecificDocuments].map(docs => {
946
968
  const hash = JSON.stringify(docs);
947
- return documentsLoadingCache.load(hash);
969
+ return cache('documents', hash, async () => {
970
+ const documents = await context.loadDocuments(docs);
971
+ return {
972
+ documents: documents,
973
+ };
974
+ });
948
975
  }));
949
976
  const documents = [];
950
977
  results.forEach(source => documents.push(...source.documents));
@@ -1008,7 +1035,10 @@ async function executeCodegen(input) {
1008
1035
  ];
1009
1036
  }
1010
1037
  const process = async (outputArgs) => {
1011
- const output = await core.codegen(outputArgs);
1038
+ const output = await core.codegen({
1039
+ ...outputArgs,
1040
+ cache,
1041
+ });
1012
1042
  result.push({
1013
1043
  filename: outputArgs.filename,
1014
1044
  content: output,
@@ -1311,39 +1341,9 @@ async function generate(input, saveToFile = true) {
1311
1341
  }
1312
1342
  await context.profiler.run(async () => {
1313
1343
  await lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
1314
- await Promise.all(generationResult.map(async (result) => {
1315
- const exists = await fileExists(result.filename);
1316
- if (!shouldOverwrite(config, result.filename) && exists) {
1317
- return;
1318
- }
1319
- const content = result.content || '';
1320
- const currentHash = hash(content);
1321
- let previousHash = recentOutputHash.get(result.filename);
1322
- if (!previousHash && exists) {
1323
- previousHash = hash(await readFile(result.filename));
1324
- }
1325
- if (previousHash && currentHash === previousHash) {
1326
- debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1327
- return;
1328
- }
1329
- if (content.length === 0) {
1330
- return;
1331
- }
1332
- recentOutputHash.set(result.filename, currentHash);
1333
- const basedir = path.dirname(result.filename);
1334
- await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename);
1335
- await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename);
1336
- await mkdirp(basedir);
1337
- const absolutePath = path.isAbsolute(result.filename)
1338
- ? result.filename
1339
- : path.join(input.cwd || process.cwd(), result.filename);
1340
- await writeFile(absolutePath, result.content);
1341
- await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename);
1342
- await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename);
1343
- }));
1344
1344
  }, 'Lifecycle: beforeAllFileWrite');
1345
1345
  await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
1346
- const exists = fileExists(result.filename);
1346
+ const exists = await fileExists(result.filename);
1347
1347
  if (!shouldOverwrite(config, result.filename) && exists) {
1348
1348
  return;
1349
1349
  }
@@ -1354,7 +1354,7 @@ async function generate(input, saveToFile = true) {
1354
1354
  previousHash = hash(await readFile(result.filename));
1355
1355
  }
1356
1356
  if (previousHash && currentHash === previousHash) {
1357
- debugLog(`Skipping file (${result.filename}) writing due to identical hash...`);
1357
+ debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1358
1358
  return;
1359
1359
  }
1360
1360
  if (content.length === 0) {
@@ -1364,7 +1364,7 @@ async function generate(input, saveToFile = true) {
1364
1364
  const basedir = path.dirname(result.filename);
1365
1365
  await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename);
1366
1366
  await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename);
1367
- mkdirp.sync(basedir);
1367
+ await mkdirp(basedir);
1368
1368
  const absolutePath = path.isAbsolute(result.filename)
1369
1369
  ? result.filename
1370
1370
  : path.join(input.cwd || process.cwd(), result.filename);
package/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isDetailedError, DetailedError, createNoopProfiler, createProfiler, normalizeInstanceOrArray, normalizeConfig, normalizeOutputParam, getCachedDocumentNodeFromSchema } from '@graphql-codegen/plugin-helpers';
2
2
  import { codegen } from '@graphql-codegen/core';
3
- import { AggregateError, isValidPath } from '@graphql-tools/utils';
3
+ import { printSchemaWithDirectives, AggregateError, isValidPath } from '@graphql-tools/utils';
4
4
  import chalk from 'chalk';
5
5
  import logSymbols from 'log-symbols';
6
6
  import ansiEscapes from 'ansi-escapes';
@@ -8,7 +8,7 @@ import wrapAnsi from 'wrap-ansi';
8
8
  import { stripIndent } from 'common-tags';
9
9
  import { dummyLogger } from 'ts-log';
10
10
  import UpdateRenderer from 'listr-update-renderer';
11
- import { GraphQLError } from 'graphql';
11
+ import { print, GraphQLError } from 'graphql';
12
12
  import path, { resolve, extname, join, delimiter, sep, dirname, isAbsolute, relative } from 'path';
13
13
  import { cosmiconfig, defaultLoaders } from 'cosmiconfig';
14
14
  import { env } from 'string-env-interpolation';
@@ -26,13 +26,13 @@ import { UrlLoader } from '@graphql-tools/url-loader';
26
26
  import yaml from 'yaml';
27
27
  import { createRequire } from 'module';
28
28
  import fs, { promises, unlink, writeFileSync, readFileSync } from 'fs';
29
+ import { createHash } from 'crypto';
29
30
  import { cpus } from 'os';
30
31
  import Listr from 'listr';
31
32
  import { exec } from 'child_process';
32
33
  import isGlob from 'is-glob';
33
34
  import debounce from 'debounce';
34
35
  import mkdirp from 'mkdirp';
35
- import { createHash } from 'crypto';
36
36
  import inquirer from 'inquirer';
37
37
  import detectIndent from 'detect-indent';
38
38
  import getLatestVersion from 'latest-version';
@@ -670,23 +670,52 @@ class CodegenContext {
670
670
  const config = this.getConfig(defaultSchemaLoadOptions);
671
671
  if (this._graphqlConfig) {
672
672
  // TODO: SchemaWithLoader won't work here
673
- return this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config);
673
+ return addHashToSchema(this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config));
674
674
  }
675
- return loadSchema(pointer, config);
675
+ return addHashToSchema(loadSchema(pointer, config));
676
676
  }
677
677
  async loadDocuments(pointer) {
678
678
  const config = this.getConfig(defaultDocumentsLoadOptions);
679
679
  if (this._graphqlConfig) {
680
680
  // TODO: pointer won't work here
681
- const documents = await this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config);
682
- return documents;
681
+ return addHashToDocumentFiles(this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config));
683
682
  }
684
- return loadDocuments(pointer, config);
683
+ return addHashToDocumentFiles(loadDocuments(pointer, config));
685
684
  }
686
685
  }
687
686
  function ensureContext(input) {
688
687
  return input instanceof CodegenContext ? input : new CodegenContext({ config: input });
689
688
  }
689
+ function hashContent(content) {
690
+ return createHash('sha256').update(content).digest('hex');
691
+ }
692
+ function hashSchema(schema) {
693
+ return hashContent(printSchemaWithDirectives(schema, {
694
+ assumeValid: true,
695
+ }));
696
+ }
697
+ function addHashToSchema(schemaPromise) {
698
+ return schemaPromise.then(schema => {
699
+ // It's consumed later on. The general purpose is to use it for caching.
700
+ schema.extensions['hash'] = hashSchema(schema);
701
+ return schema;
702
+ });
703
+ }
704
+ function hashDocument(doc) {
705
+ if (doc.rawSDL) {
706
+ return hashContent(doc.rawSDL);
707
+ }
708
+ if (doc.document) {
709
+ return hashContent(print(doc.document));
710
+ }
711
+ return null;
712
+ }
713
+ function addHashToDocumentFiles(documentFilesPromise) {
714
+ return documentFilesPromise.then(documentFiles => documentFiles.map(doc => {
715
+ doc.hash = hashDocument(doc);
716
+ return doc;
717
+ }));
718
+ }
690
719
 
691
720
  const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
692
721
  const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
@@ -724,18 +753,17 @@ const makeDefaultLoader = (from) => {
724
753
  return import(relativeRequire.resolve(mod));
725
754
  };
726
755
  };
727
- // TODO: Replace any with types
728
- function createCache(loader) {
756
+ function createCache() {
729
757
  const cache = new Map();
730
- return {
731
- load(key) {
732
- if (cache.has(key)) {
733
- return cache.get(key);
734
- }
735
- const value = loader(key);
736
- cache.set(key, value);
737
- return value;
738
- },
758
+ return function ensure(namespace, key, factory) {
759
+ const cacheKey = `${namespace}:${key}`;
760
+ const cachedValue = cache.get(cacheKey);
761
+ if (cachedValue) {
762
+ return cachedValue;
763
+ }
764
+ const value = factory();
765
+ cache.set(cacheKey, value);
766
+ return value;
739
767
  };
740
768
  }
741
769
  async function executeCodegen(input) {
@@ -774,20 +802,7 @@ async function executeCodegen(input) {
774
802
  let rootSchemas;
775
803
  let rootDocuments;
776
804
  const generates = {};
777
- const schemaLoadingCache = createCache(async function (hash) {
778
- const outputSchemaAst = await context.loadSchema(JSON.parse(hash));
779
- const outputSchema = getCachedDocumentNodeFromSchema(outputSchemaAst);
780
- return {
781
- outputSchemaAst: outputSchemaAst,
782
- outputSchema: outputSchema,
783
- };
784
- });
785
- const documentsLoadingCache = createCache(async function (hash) {
786
- const documents = await context.loadDocuments(JSON.parse(hash));
787
- return {
788
- documents: documents,
789
- };
790
- });
805
+ const cache = createCache();
791
806
  function wrapTask(task, source, taskName) {
792
807
  return () => {
793
808
  return context.profiler.run(async () => {
@@ -905,7 +920,14 @@ async function executeCodegen(input) {
905
920
  }
906
921
  }
907
922
  const hash = JSON.stringify(schemaPointerMap);
908
- const result = await schemaLoadingCache.load(hash);
923
+ const result = await cache('schema', hash, async () => {
924
+ const outputSchemaAst = await context.loadSchema(schemaPointerMap);
925
+ const outputSchema = getCachedDocumentNodeFromSchema(outputSchemaAst);
926
+ return {
927
+ outputSchemaAst: outputSchemaAst,
928
+ outputSchema: outputSchema,
929
+ };
930
+ });
909
931
  outputSchemaAst = await result.outputSchemaAst;
910
932
  outputSchema = result.outputSchema;
911
933
  }, filename, `Load GraphQL schemas: ${filename}`),
@@ -917,7 +939,12 @@ async function executeCodegen(input) {
917
939
  // get different cache for shared docs and output specific docs
918
940
  const results = await Promise.all([rootDocuments, outputSpecificDocuments].map(docs => {
919
941
  const hash = JSON.stringify(docs);
920
- return documentsLoadingCache.load(hash);
942
+ return cache('documents', hash, async () => {
943
+ const documents = await context.loadDocuments(docs);
944
+ return {
945
+ documents: documents,
946
+ };
947
+ });
921
948
  }));
922
949
  const documents = [];
923
950
  results.forEach(source => documents.push(...source.documents));
@@ -981,7 +1008,10 @@ async function executeCodegen(input) {
981
1008
  ];
982
1009
  }
983
1010
  const process = async (outputArgs) => {
984
- const output = await codegen(outputArgs);
1011
+ const output = await codegen({
1012
+ ...outputArgs,
1013
+ cache,
1014
+ });
985
1015
  result.push({
986
1016
  filename: outputArgs.filename,
987
1017
  content: output,
@@ -1284,39 +1314,9 @@ async function generate(input, saveToFile = true) {
1284
1314
  }
1285
1315
  await context.profiler.run(async () => {
1286
1316
  await lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
1287
- await Promise.all(generationResult.map(async (result) => {
1288
- const exists = await fileExists(result.filename);
1289
- if (!shouldOverwrite(config, result.filename) && exists) {
1290
- return;
1291
- }
1292
- const content = result.content || '';
1293
- const currentHash = hash(content);
1294
- let previousHash = recentOutputHash.get(result.filename);
1295
- if (!previousHash && exists) {
1296
- previousHash = hash(await readFile(result.filename));
1297
- }
1298
- if (previousHash && currentHash === previousHash) {
1299
- debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1300
- return;
1301
- }
1302
- if (content.length === 0) {
1303
- return;
1304
- }
1305
- recentOutputHash.set(result.filename, currentHash);
1306
- const basedir = dirname(result.filename);
1307
- await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename);
1308
- await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename);
1309
- await mkdirp(basedir);
1310
- const absolutePath = isAbsolute(result.filename)
1311
- ? result.filename
1312
- : join(input.cwd || process.cwd(), result.filename);
1313
- await writeFile(absolutePath, result.content);
1314
- await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename);
1315
- await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename);
1316
- }));
1317
1317
  }, 'Lifecycle: beforeAllFileWrite');
1318
1318
  await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
1319
- const exists = fileExists(result.filename);
1319
+ const exists = await fileExists(result.filename);
1320
1320
  if (!shouldOverwrite(config, result.filename) && exists) {
1321
1321
  return;
1322
1322
  }
@@ -1327,7 +1327,7 @@ async function generate(input, saveToFile = true) {
1327
1327
  previousHash = hash(await readFile(result.filename));
1328
1328
  }
1329
1329
  if (previousHash && currentHash === previousHash) {
1330
- debugLog(`Skipping file (${result.filename}) writing due to identical hash...`);
1330
+ debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1331
1331
  return;
1332
1332
  }
1333
1333
  if (content.length === 0) {
@@ -1337,7 +1337,7 @@ async function generate(input, saveToFile = true) {
1337
1337
  const basedir = dirname(result.filename);
1338
1338
  await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename);
1339
1339
  await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename);
1340
- mkdirp.sync(basedir);
1340
+ await mkdirp(basedir);
1341
1341
  const absolutePath = isAbsolute(result.filename)
1342
1342
  ? result.filename
1343
1343
  : join(input.cwd || process.cwd(), result.filename);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@graphql-codegen/cli",
3
- "version": "2.6.0-alpha-dfbea14f8.0",
3
+ "version": "2.6.0-alpha-cb6ec4365.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.5.0",
9
- "@graphql-codegen/plugin-helpers": "^2.4.0",
8
+ "@graphql-codegen/core": "2.6.0-alpha-cb6ec4365.0",
9
+ "@graphql-codegen/plugin-helpers": "2.5.0-alpha-cb6ec4365.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",