@graphprotocol/graph-cli 0.37.3-alpha-20230112195908-6a078ea → 0.37.3-alpha-20230112205341-caa8660

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/CHANGELOG.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # @graphprotocol/graph-cli
2
2
 
3
- ## 0.37.3-alpha-20230112195908-6a078ea
3
+ ## 0.37.3-alpha-20230112205341-caa8660
4
4
 
5
5
  ### Patch Changes
6
6
 
7
7
  - [#1020](https://github.com/graphprotocol/graph-cli/pull/1020) [`6184688`](https://github.com/graphprotocol/graph-cli/commit/6184688d7e6efaae49a722410befd28da0af87b0) Thanks [@saihaj](https://github.com/saihaj)! - dependencies updates:
8
8
  - Updated dependency [`immutable@4.2.1` ↗︎](https://www.npmjs.com/package/immutable/v/4.2.1) (from `3.8.2`, in `dependencies`)
9
+ - Removed dependency [`dockerode@2.5.8` ↗︎](https://www.npmjs.com/package/dockerode/v/2.5.8) (from `dependencies`)
9
10
 
10
11
  ## 0.37.2
11
12
 
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateStudioNetwork = exports.allowedStudioNetworks = void 0;
4
- const allowedStudioNetworks = ['mainnet', 'rinkeby', 'goerli', 'gnosis'];
5
- exports.allowedStudioNetworks = allowedStudioNetworks;
6
- const validateStudioNetwork = ({ studio, product, network }) => {
4
+ exports.allowedStudioNetworks = ['mainnet', 'rinkeby', 'goerli', 'gnosis'];
5
+ const validateStudioNetwork = ({ studio, product, network, }) => {
7
6
  let isStudio = studio || product === 'subgraph-studio';
8
- let isAllowedNetwork = allowedStudioNetworks.includes(network);
7
+ let isAllowedNetwork = exports.allowedStudioNetworks.includes(
8
+ // @ts-expect-error we're checking if the network is allowed
9
+ network);
9
10
  if (isStudio && !isAllowedNetwork) {
10
- throw new Error(`The Subgraph Studio only allows subgraphs for these networks: ${allowedStudioNetworks.join(', ')}`);
11
+ throw new Error(`The Subgraph Studio only allows subgraphs for these networks: ${exports.allowedStudioNetworks.join(', ')}`);
11
12
  }
12
13
  };
13
14
  exports.validateStudioNetwork = validateStudioNetwork;
@@ -19,7 +19,6 @@ describe('Version Command Helpers', () => {
19
19
  test("And it's NOT an allowed network", () => {
20
20
  expect(() => (0, studio_1.validateStudioNetwork)({
21
21
  product: 'subgraph-studio',
22
- // @ts-expect-error for tests sake
23
22
  network: 'celo',
24
23
  })).toThrow(new Error(`The Subgraph Studio only allows subgraphs for these networks: ${studio_1.allowedStudioNetworks.join(', ')}`));
25
24
  });
@@ -33,9 +32,7 @@ describe('Version Command Helpers', () => {
33
32
  });
34
33
  test("And it's NOT an allowed network", () => {
35
34
  expect(() => (0, studio_1.validateStudioNetwork)({
36
- // @ts-expect-error for tests sake
37
35
  product: 'hosted-service',
38
- // @ts-expect-error for tests sake
39
36
  network: 'celo',
40
37
  })).not.toThrow(new Error(`The Subgraph Studio only allows subgraphs for these networks: ${studio_1.allowedStudioNetworks.join(', ')}`));
41
38
  });
@@ -29,9 +29,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const chalk_1 = __importDefault(require("chalk"));
30
30
  const os_1 = __importDefault(require("os"));
31
31
  const path_1 = __importDefault(require("path"));
32
- const toolbox = __importStar(require("gluegun/toolbox"));
33
32
  const fs_1 = __importDefault(require("fs"));
34
- const cli_1 = __importDefault(require("../cli"));
33
+ const graphCli = __importStar(require("../cli"));
35
34
  const subgraph_1 = require("../command-helpers/subgraph");
36
35
  const DataSourcesExtractor = __importStar(require("../command-helpers/data-sources"));
37
36
  const studio_1 = require("../command-helpers/studio");
@@ -101,7 +100,7 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
101
100
  message: 'Protocol',
102
101
  choices: protocolChoices,
103
102
  skip: protocolChoices.includes(protocol),
104
- result: value => {
103
+ result: (value) => {
105
104
  protocol = protocol || value;
106
105
  protocolInstance = new protocols_1.default(protocol);
107
106
  return protocol;
@@ -119,7 +118,7 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
119
118
  product === 'hosted-service' ||
120
119
  studio !== undefined ||
121
120
  node !== undefined,
122
- result: value => {
121
+ result: (value) => {
123
122
  // For now we only support NEAR subgraphs in the Hosted Service
124
123
  if (protocol === 'near') {
125
124
  // Can be overwritten because the question will be skipped (product === undefined)
@@ -138,7 +137,7 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
138
137
  name: 'subgraphName',
139
138
  message: () => product == 'subgraph-studio' || studio ? 'Subgraph slug' : 'Subgraph name',
140
139
  initial: subgraphName,
141
- validate: name => {
140
+ validate: (name) => {
142
141
  try {
143
142
  (0, subgraph_1.validateSubgraphName)(name, { allowSimpleName });
144
143
  return true;
@@ -152,7 +151,7 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
152
151
  $ graph init ${name} --allow-simple-name`;
153
152
  }
154
153
  },
155
- result: value => {
154
+ result: (value) => {
156
155
  subgraphName = value;
157
156
  return value;
158
157
  },
@@ -162,7 +161,7 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
162
161
  name: 'directory',
163
162
  message: 'Directory to create the subgraph in',
164
163
  initial: () => directory || (0, subgraph_1.getSubgraphBasename)(subgraphName),
165
- validate: value => toolbox.filesystem.exists(value || directory || (0, subgraph_1.getSubgraphBasename)(subgraphName))
164
+ validate: (value) => toolbox.filesystem.exists(value || directory || (0, subgraph_1.getSubgraphBasename)(subgraphName))
166
165
  ? 'Directory already exists'
167
166
  : true,
168
167
  },
@@ -172,13 +171,16 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
172
171
  message: () => `${protocolInstance.displayName()} network`,
173
172
  choices: () => {
174
173
  initDebug('Generating list of available networks for protocol "%s" (%M)', protocol, availableNetworks.get(protocol));
175
- return availableNetworks
174
+ return (
175
+ // @ts-expect-error TODO: wait what?
176
+ availableNetworks
176
177
  .get(protocol) // Get networks related to the chosen protocol.
177
- .toArray(); // Needed because of gluegun. It can't even receive a JS iterable.
178
+ // @ts-expect-error TODO: wait what?
179
+ .toArray()); // Needed because of gluegun. It can't even receive a JS iterable.
178
180
  },
179
181
  skip: fromExample !== undefined,
180
182
  initial: network || 'mainnet',
181
- result: value => {
183
+ result: (value) => {
182
184
  network = value;
183
185
  return value;
184
186
  },
@@ -214,7 +216,8 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
214
216
  if (protocolInstance.hasABIs() && !abi) {
215
217
  try {
216
218
  if (network === 'poa-core') {
217
- abiFromBlockScout = await (0, abi_1.loadAbiFromBlockScout)(ABI, network, value);
219
+ // TODO: this variable is never used anywhere, what happens?
220
+ // abiFromBlockScout = await loadAbiFromBlockScout(ABI, network, value)
218
221
  }
219
222
  else {
220
223
  abiFromEtherscan = await (0, abi_1.loadAbiFromEtherscan)(ABI, network, value);
@@ -238,7 +241,7 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
238
241
  return true;
239
242
  }
240
243
  try {
241
- abiFromFile = await loadAbiFromFile(ABI, value);
244
+ abiFromFile = loadAbiFromFile(toolbox, ABI, value);
242
245
  return true;
243
246
  }
244
247
  catch (e) {
@@ -252,8 +255,8 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
252
255
  message: 'Contract Name',
253
256
  initial: contractName || 'Contract',
254
257
  skip: () => fromExample !== undefined || !protocolInstance.hasContract(),
255
- validate: value => value && value.length > 0,
256
- result: value => {
258
+ validate: (value) => value && value.length > 0,
259
+ result: (value) => {
257
260
  contractName = value;
258
261
  return value;
259
262
  },
@@ -264,22 +267,28 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
264
267
  message: 'Index contract events as entities',
265
268
  initial: true,
266
269
  skip: () => !!indexEvents,
267
- result: value => {
270
+ result: (value) => {
268
271
  indexEvents = value;
269
272
  return value;
270
273
  },
271
274
  },
272
275
  ];
273
276
  try {
274
- let answers = await toolbox.prompt.ask(questions);
275
- return { ...answers, abi: abiFromEtherscan || abiFromFile, protocolInstance };
277
+ let answers = await toolbox.prompt.ask(
278
+ // @ts-expect-error questions do somehow fit
279
+ questions);
280
+ return {
281
+ ...answers,
282
+ abi: (abiFromEtherscan || abiFromFile),
283
+ protocolInstance,
284
+ };
276
285
  }
277
286
  catch (e) {
278
287
  return undefined;
279
288
  }
280
289
  };
281
- const loadAbiFromFile = async (ABI, filename) => {
282
- let exists = await toolbox.filesystem.exists(filename);
290
+ const loadAbiFromFile = (toolbox, ABI, filename) => {
291
+ let exists = toolbox.filesystem.exists(filename);
283
292
  if (!exists) {
284
293
  throw Error('File does not exist.');
285
294
  }
@@ -290,14 +299,14 @@ const loadAbiFromFile = async (ABI, filename) => {
290
299
  throw Error('Not sure what this path points to.');
291
300
  }
292
301
  else {
293
- return await ABI.load('Contract', filename);
302
+ return ABI.load('Contract', filename);
294
303
  }
295
304
  };
296
305
  exports.default = {
297
306
  description: 'Creates a new subgraph with basic scaffolding',
298
307
  run: async (toolbox) => {
299
308
  // Obtain tools
300
- let { print, system } = toolbox;
309
+ const { print, system } = toolbox;
301
310
  // Read CLI parameters
302
311
  let { protocol, product, studio, node, g, abi, allowSimpleName, fromContract, contractName, fromExample, h, help, indexEvents, network, } = toolbox.parameters.options;
303
312
  node = node || g;
@@ -334,15 +343,15 @@ exports.default = {
334
343
  return;
335
344
  }
336
345
  // Detect git
337
- let git = await system.which('git');
346
+ let git = system.which('git');
338
347
  if (git === null) {
339
348
  print.error(`Git was not found on your system. Please install 'git' so it is in $PATH.`);
340
349
  process.exitCode = 1;
341
350
  return;
342
351
  }
343
352
  // Detect Yarn and/or NPM
344
- let yarn = await system.which('yarn');
345
- let npm = await system.which('npm');
353
+ let yarn = system.which('yarn');
354
+ let npm = system.which('npm');
346
355
  if (!yarn && !npm) {
347
356
  print.error(`Neither Yarn nor NPM were found on your system. Please install one of them.`);
348
357
  process.exitCode = 1;
@@ -371,7 +380,8 @@ exports.default = {
371
380
  const ABI = protocolInstance.getABI();
372
381
  if (abi) {
373
382
  try {
374
- abi = await loadAbiFromFile(ABI, abi);
383
+ // @ts-expect-error TODO: how does this even work when the filename is expected?
384
+ abi = loadAbiFromFile(ABI, abi);
375
385
  }
376
386
  catch (e) {
377
387
  print.error(`Failed to load ABI: ${e.message}`);
@@ -480,12 +490,12 @@ const revalidateSubgraphName = async (toolbox, subgraphName, { allowSimpleName }
480
490
  return false;
481
491
  }
482
492
  };
483
- const initRepository = async (toolbox, directory) => await (0, spinner_1.withSpinner)(`Initialize subgraph repository`, `Failed to initialize subgraph repository`, `Warnings while initializing subgraph repository`, async (spinner) => {
493
+ const initRepository = async (toolbox, directory) => await (0, spinner_1.withSpinner)(`Initialize subgraph repository`, `Failed to initialize subgraph repository`, `Warnings while initializing subgraph repository`, async () => {
484
494
  // Remove .git dir in --from-example mode; in --from-contract, we're
485
495
  // starting from an empty directory
486
496
  let gitDir = path_1.default.join(directory, '.git');
487
497
  if (toolbox.filesystem.exists(gitDir)) {
488
- await toolbox.filesystem.remove(gitDir);
498
+ toolbox.filesystem.remove(gitDir);
489
499
  }
490
500
  await toolbox.system.run('git init', { cwd: directory });
491
501
  await toolbox.system.run('git add --all', { cwd: directory });
@@ -504,18 +514,18 @@ const npmLinkToLocalCli = async (toolbox, directory) => {
504
514
  await toolbox.system.run('npm link @graphprotocol/graph-cli', { cwd: directory });
505
515
  }
506
516
  };
507
- const installDependencies = async (toolbox, directory, installCommand) => await (0, spinner_1.withSpinner)(`Install dependencies with ${toolbox.print.colors.muted(installCommand)}`, `Failed to install dependencies`, `Warnings while installing dependencies`, async (spinner) => {
517
+ const installDependencies = async (toolbox, directory, installCommand) => await (0, spinner_1.withSpinner)(`Install dependencies with ${toolbox.print.colors.muted(installCommand)}`, `Failed to install dependencies`, `Warnings while installing dependencies`, async () => {
508
518
  // Links to local graph-cli if we're running the automated tests
509
519
  await npmLinkToLocalCli(toolbox, directory);
510
520
  await toolbox.system.run(installCommand, { cwd: directory });
511
521
  return true;
512
522
  });
513
- const runCodegen = async (toolbox, directory, codegenCommand) => await (0, spinner_1.withSpinner)(`Generate ABI and schema types with ${toolbox.print.colors.muted(codegenCommand)}`, `Failed to generate code from ABI and GraphQL schema`, `Warnings while generating code from ABI and GraphQL schema`, async (spinner) => {
523
+ const runCodegen = async (toolbox, directory, codegenCommand) => await (0, spinner_1.withSpinner)(`Generate ABI and schema types with ${toolbox.print.colors.muted(codegenCommand)}`, `Failed to generate code from ABI and GraphQL schema`, `Warnings while generating code from ABI and GraphQL schema`, async () => {
514
524
  await toolbox.system.run(codegenCommand, { cwd: directory });
515
525
  return true;
516
526
  });
517
- const printNextSteps = (toolbox, { subgraphName, directory }, { commands }) => {
518
- let { print } = toolbox;
527
+ const printNextSteps = (toolbox, { subgraphName, directory }, { commands, }) => {
528
+ const { print } = toolbox;
519
529
  let relativeDir = path_1.default.relative(process.cwd(), directory);
520
530
  // Print instructions
521
531
  print.success(`
@@ -531,10 +541,10 @@ Subgraph ${print.colors.blue(subgraphName)} created in ${print.colors.blue(relat
531
541
 
532
542
  Make sure to visit the documentation on https://thegraph.com/docs/ for further information.`);
533
543
  };
534
- const initSubgraphFromExample = async (toolbox, { fromExample, allowSimpleName, subgraphName, directory, studio, product }, { commands }) => {
544
+ const initSubgraphFromExample = async (toolbox, { fromExample, allowSimpleName, subgraphName, directory, studio, product, }, { commands, }) => {
535
545
  let { filesystem, print, system } = toolbox;
536
546
  // Fail if the subgraph name is invalid
537
- if (!revalidateSubgraphName(toolbox, subgraphName, { allowSimpleName })) {
547
+ if (!revalidateSubgraphName(toolbox, subgraphName, { allowSimpleName: !!allowSimpleName })) {
538
548
  process.exitCode = 1;
539
549
  return;
540
550
  }
@@ -545,7 +555,7 @@ const initSubgraphFromExample = async (toolbox, { fromExample, allowSimpleName,
545
555
  return;
546
556
  }
547
557
  // Clone the example subgraph repository
548
- let cloned = await (0, spinner_1.withSpinner)(`Cloning example subgraph`, `Failed to clone example subgraph`, `Warnings while cloning example subgraph`, async (spinner) => {
558
+ let cloned = await (0, spinner_1.withSpinner)(`Cloning example subgraph`, `Failed to clone example subgraph`, `Warnings while cloning example subgraph`, async () => {
549
559
  // Create a temporary directory
550
560
  const prefix = path_1.default.join(os_1.default.tmpdir(), 'example-subgraph-');
551
561
  const tmpDir = fs_1.default.mkdtempSync(prefix);
@@ -555,7 +565,7 @@ const initSubgraphFromExample = async (toolbox, { fromExample, allowSimpleName,
555
565
  if (fromExample === undefined || fromExample === true) {
556
566
  fromExample = DEFAULT_EXAMPLE_SUBGRAPH;
557
567
  }
558
- const exampleSubgraphPath = path_1.default.join(tmpDir, fromExample);
568
+ const exampleSubgraphPath = path_1.default.join(tmpDir, String(fromExample));
559
569
  if (!filesystem.exists(exampleSubgraphPath)) {
560
570
  return { result: false, error: `Example not found: ${fromExample}` };
561
571
  }
@@ -589,7 +599,7 @@ const initSubgraphFromExample = async (toolbox, { fromExample, allowSimpleName,
589
599
  return;
590
600
  }
591
601
  // Update package.json to match the subgraph name
592
- let prepared = await (0, spinner_1.withSpinner)(`Update subgraph name and commands in package.json`, `Failed to update subgraph name and commands in package.json`, `Warnings while updating subgraph name and commands in package.json`, async (spinner) => {
602
+ let prepared = await (0, spinner_1.withSpinner)(`Update subgraph name and commands in package.json`, `Failed to update subgraph name and commands in package.json`, `Warnings while updating subgraph name and commands in package.json`, async () => {
593
603
  try {
594
604
  // Load package.json
595
605
  let pkgJsonFilename = filesystem.path(directory, 'package.json');
@@ -638,7 +648,7 @@ const initSubgraphFromExample = async (toolbox, { fromExample, allowSimpleName,
638
648
  }
639
649
  printNextSteps(toolbox, { subgraphName, directory }, { commands });
640
650
  };
641
- const initSubgraphFromContract = async (toolbox, { protocolInstance, allowSimpleName, subgraphName, directory, abi, network, contract, indexEvents, contractName, node, studio, product, }, { commands, addContract }) => {
651
+ const initSubgraphFromContract = async (toolbox, { protocolInstance, allowSimpleName, subgraphName, directory, abi, network, contract, indexEvents, contractName, node, studio, product, }, { commands, addContract, }) => {
642
652
  let { print } = toolbox;
643
653
  // Fail if the subgraph name is invalid
644
654
  if (!revalidateSubgraphName(toolbox, subgraphName, { allowSimpleName })) {
@@ -651,7 +661,10 @@ const initSubgraphFromContract = async (toolbox, { protocolInstance, allowSimple
651
661
  process.exitCode = 1;
652
662
  return;
653
663
  }
654
- if (protocolInstance.hasABIs() && (0, schema_1.abiEvents)(abi).length === 0) {
664
+ if (protocolInstance.hasABIs() &&
665
+ ((0, schema_1.abiEvents)(abi).size === 0 ||
666
+ // @ts-expect-error TODO: the abiEvents result is expected to be a List, how's it an array?
667
+ (0, schema_1.abiEvents)(abi).length === 0)) {
655
668
  // Fail if the ABI does not contain any events
656
669
  print.error(`ABI does not contain any events`);
657
670
  process.exitCode = 1;
@@ -721,7 +734,7 @@ const initSubgraphFromContract = async (toolbox, { protocolInstance, allowSimple
721
734
  const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
722
735
  const addContractConfirmation = await toolbox.prompt.confirm('Add another contract?');
723
736
  if (addContractConfirmation) {
724
- let abiFromFile;
737
+ let abiFromFile = false;
725
738
  let ProtocolContract = protocolInstance.getContract();
726
739
  let questions = [
727
740
  {
@@ -739,7 +752,7 @@ const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
739
752
  name: 'localAbi',
740
753
  message: 'Provide local ABI path?',
741
754
  choices: ['yes', 'no'],
742
- result: value => {
755
+ result: (value) => {
743
756
  abiFromFile = value === 'yes' ? true : false;
744
757
  return abiFromFile;
745
758
  },
@@ -755,13 +768,15 @@ const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
755
768
  name: 'contractName',
756
769
  message: 'Contract Name',
757
770
  initial: 'Contract',
758
- validate: value => value && value.length > 0,
771
+ validate: (value) => value && value.length > 0,
759
772
  },
760
773
  ];
761
774
  // Get the cwd before process.chdir in order to switch back in the end of command execution
762
775
  const cwd = process.cwd();
763
776
  try {
764
- let { abi, contract, contractName } = await toolbox.prompt.ask(questions);
777
+ let { abi, contract, contractName } = await toolbox.prompt.ask(
778
+ // @ts-expect-error questions do somehow fit
779
+ questions);
765
780
  if (fs_1.default.existsSync(directory)) {
766
781
  process.chdir(directory);
767
782
  }
@@ -774,7 +789,7 @@ const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
774
789
  commandLine.push('--abi', abi);
775
790
  }
776
791
  }
777
- await cli_1.default.run(commandLine);
792
+ await graphCli.run(commandLine);
778
793
  }
779
794
  catch (e) {
780
795
  toolbox.print.error(e);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -10,6 +10,7 @@ class NearContract {
10
10
  }
11
11
  constructor(account) {
12
12
  this.account = account;
13
+ this.account = account;
13
14
  }
14
15
  validateLength(value) {
15
16
  return (value.length >= MINIMUM_ACCOUNT_ID_LENGTH &&
package/dist/subgraph.js CHANGED
@@ -32,7 +32,7 @@ const path_1 = __importDefault(require("path"));
32
32
  const yaml_1 = __importDefault(require("yaml"));
33
33
  const types_1 = require("yaml/types");
34
34
  const graphql = __importStar(require("graphql/language"));
35
- const validation_1 = __importDefault(require("./validation"));
35
+ const validation = __importStar(require("./validation"));
36
36
  const debug_1 = __importDefault(require("./debug"));
37
37
  let subgraphDebug = (0, debug_1.default)('graph-cli:subgraph');
38
38
  const throwCombinedError = (filename, errors) => {
@@ -72,11 +72,11 @@ class Subgraph {
72
72
  return definition.name.value === 'SubgraphManifest';
73
73
  });
74
74
  // Validate the subgraph manifest using this schema
75
- return validation_1.default.validateManifest(data, rootType, schema, protocol, { resolveFile });
75
+ return validation.validateManifest(data, rootType, schema, protocol, { resolveFile });
76
76
  }
77
77
  static validateSchema(manifest, { resolveFile }) {
78
78
  let filename = resolveFile(manifest.getIn(['schema', 'file']));
79
- const validationErrors = validation_1.default.validateSchema(filename);
79
+ const validationErrors = validation.validateSchema(filename);
80
80
  let errors;
81
81
  if (validationErrors.size > 0) {
82
82
  errors = validationErrors.groupBy(error => error.get('entity')).sort();
@@ -154,7 +154,7 @@ At least one such handler must be defined.`,
154
154
  if (!protocol.hasContract()) {
155
155
  return immutable_1.default.List();
156
156
  }
157
- return validation_1.default.validateContractValues(manifest, protocol);
157
+ return validation.validateContractValues(manifest, protocol);
158
158
  }
159
159
  // Validate that data source names are unique, so they don't overwrite each other.
160
160
  static validateUniqueDataSourceNames(manifest) {
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateContract = exports.validateContractValues = exports.validateManifest = exports.validateSchema = void 0;
3
4
  const schema_1 = require("./schema");
5
+ Object.defineProperty(exports, "validateSchema", { enumerable: true, get: function () { return schema_1.validateSchema; } });
4
6
  const manifest_1 = require("./manifest");
7
+ Object.defineProperty(exports, "validateManifest", { enumerable: true, get: function () { return manifest_1.validateManifest; } });
5
8
  const contract_1 = require("./contract");
6
- exports.default = {
7
- validateSchema: schema_1.validateSchema,
8
- validateManifest: manifest_1.validateManifest,
9
- validateContractValues: contract_1.validateContractValues,
10
- validateContract: contract_1.validateContract,
11
- };
9
+ Object.defineProperty(exports, "validateContractValues", { enumerable: true, get: function () { return contract_1.validateContractValues; } });
10
+ Object.defineProperty(exports, "validateContract", { enumerable: true, get: function () { return contract_1.validateContract; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.37.3-alpha-20230112195908-6a078ea",
3
+ "version": "0.37.3-alpha-20230112205341-caa8660",
4
4
  "license": "(Apache-2.0 OR MIT)",
5
5
  "description": "CLI for building for and deploying to The Graph",
6
6
  "main": "dist/cli.js",
@@ -7,7 +7,7 @@ export const loadAbiFromEtherscan = async (
7
7
  ABICtor: typeof ABI,
8
8
  network: string,
9
9
  address: string,
10
- ) =>
10
+ ): Promise<ABI> =>
11
11
  await withSpinner(
12
12
  `Fetching ABI from Etherscan`,
13
13
  `Failed to fetch ABI from Etherscan`,
@@ -37,7 +37,6 @@ describe('Version Command Helpers', () => {
37
37
  expect(() =>
38
38
  validateStudioNetwork({
39
39
  product: 'subgraph-studio',
40
- // @ts-expect-error for tests sake
41
40
  network: 'celo',
42
41
  }),
43
42
  ).toThrow(
@@ -69,9 +68,7 @@ describe('Version Command Helpers', () => {
69
68
  test("And it's NOT an allowed network", () => {
70
69
  expect(() =>
71
70
  validateStudioNetwork({
72
- // @ts-expect-error for tests sake
73
71
  product: 'hosted-service',
74
- // @ts-expect-error for tests sake
75
72
  network: 'celo',
76
73
  }),
77
74
  ).not.toThrow(
@@ -1,12 +1,19 @@
1
- const allowedStudioNetworks = ['mainnet', 'rinkeby', 'goerli', 'gnosis'] as const
1
+ export const allowedStudioNetworks = ['mainnet', 'rinkeby', 'goerli', 'gnosis'] as const
2
2
 
3
- const validateStudioNetwork = ({ studio, product, network }:{
4
- studio?: boolean
5
- product?: 'subgraph-studio'
6
- network: typeof allowedStudioNetworks[number]
3
+ export const validateStudioNetwork = ({
4
+ studio,
5
+ product,
6
+ network,
7
+ }: {
8
+ studio?: string | boolean
9
+ product?: string
10
+ network: string
7
11
  }) => {
8
12
  let isStudio = studio || product === 'subgraph-studio'
9
- let isAllowedNetwork = allowedStudioNetworks.includes(network)
13
+ let isAllowedNetwork = allowedStudioNetworks.includes(
14
+ // @ts-expect-error we're checking if the network is allowed
15
+ network,
16
+ )
10
17
 
11
18
  if (isStudio && !isAllowedNetwork) {
12
19
  throw new Error(
@@ -16,5 +23,3 @@ const validateStudioNetwork = ({ studio, product, network }:{
16
23
  )
17
24
  }
18
25
  }
19
-
20
- export { allowedStudioNetworks, validateStudioNetwork }
@@ -1,6 +1,6 @@
1
- const validateSubgraphName = (
1
+ export const validateSubgraphName = (
2
2
  name: string,
3
- { allowSimpleName }: { allowSimpleName: string },
3
+ { allowSimpleName }: { allowSimpleName?: boolean },
4
4
  ) => {
5
5
  if (allowSimpleName) {
6
6
  return name
@@ -16,9 +16,7 @@ You can bypass this check with --allow-simple-name.`)
16
16
  }
17
17
  }
18
18
 
19
- const getSubgraphBasename = (name: string) => {
19
+ export const getSubgraphBasename = (name: string) => {
20
20
  let segments = name.split('/', 2)
21
21
  return segments[segments.length - 1]
22
22
  }
23
-
24
- export { validateSubgraphName, getSubgraphBasename }
@@ -118,7 +118,7 @@ export default {
118
118
  }
119
119
 
120
120
  if (network) {
121
- let identifierName = protocol.getContract().identifierName()
121
+ let identifierName = protocol.getContract()!.identifierName()
122
122
  await updateSubgraphNetwork(toolbox, manifest, network, networkFile, identifierName)
123
123
  }
124
124
 
@@ -252,7 +252,7 @@ export default {
252
252
  }
253
253
 
254
254
  if (network) {
255
- let identifierName = protocol.getContract().identifierName()
255
+ let identifierName = protocol.getContract()!.identifierName()
256
256
  await updateSubgraphNetwork(toolbox, manifest, network, networkFile, identifierName)
257
257
  }
258
258
 
@@ -1,22 +1,24 @@
1
1
  import chalk from 'chalk'
2
2
  import os from 'os'
3
3
  import path from 'path'
4
- import * as toolbox from 'gluegun/toolbox'
4
+ import { GluegunToolbox } from 'gluegun'
5
5
  import fs from 'fs'
6
- import graphCli from '../cli'
6
+ import * as graphCli from '../cli'
7
7
  import { getSubgraphBasename, validateSubgraphName } from '../command-helpers/subgraph'
8
8
  import * as DataSourcesExtractor from '../command-helpers/data-sources'
9
9
  import { validateStudioNetwork } from '../command-helpers/studio'
10
10
  import { initNetworksConfig } from '../command-helpers/network'
11
- import { withSpinner, step } from '../command-helpers/spinner'
11
+ import { withSpinner } from '../command-helpers/spinner'
12
12
  import { fixParameters } from '../command-helpers/gluegun'
13
13
  import { chooseNodeUrl } from '../command-helpers/node'
14
14
  import { loadAbiFromEtherscan, loadAbiFromBlockScout } from '../command-helpers/abi'
15
15
  import { generateScaffold, writeScaffold } from '../command-helpers/scaffold'
16
16
  import { abiEvents } from '../scaffold/schema'
17
17
  import { validateContract } from '../validation'
18
- import Protocol from '../protocols'
18
+ import Protocol, { ProtocolName } from '../protocols'
19
19
  import debug from '../debug'
20
+ import EthereumABI from '../protocols/ethereum/abi'
21
+ import { ContractCtor } from '../protocols/contract'
20
22
 
21
23
  const protocolChoices = Array.from(Protocol.availableProtocols().keys())
22
24
  const availableNetworks = Protocol.availableNetworks()
@@ -51,22 +53,22 @@ ${chalk.dim('Options for --from-contract:')}
51
53
  ${chalk.dim.underline('Ethereum:')}
52
54
 
53
55
  --abi <path> Path to the contract ABI (default: download from Etherscan)
54
- --network <${availableNetworks.get('ethereum').join('|')}>
56
+ --network <${availableNetworks.get('ethereum')!.join('|')}>
55
57
  Selects the network the contract is deployed to
56
58
 
57
59
  ${chalk.dim.underline('NEAR:')}
58
60
 
59
- --network <${availableNetworks.get('near').join('|')}>
61
+ --network <${availableNetworks.get('near')!.join('|')}>
60
62
  Selects the network the contract is deployed to
61
63
 
62
64
  ${chalk.dim.underline('Cosmos:')}
63
65
 
64
- --network <${availableNetworks.get('cosmos').join('|')}>
66
+ --network <${availableNetworks.get('cosmos')!.join('|')}>
65
67
  Selects the network the contract is deployed to
66
68
  `
67
69
 
68
70
  const processInitForm = async (
69
- toolbox,
71
+ toolbox: GluegunToolbox,
70
72
  {
71
73
  protocol,
72
74
  product,
@@ -81,13 +83,41 @@ const processInitForm = async (
81
83
  network,
82
84
  subgraphName,
83
85
  contractName,
86
+ }: {
87
+ protocol: ProtocolName
88
+ product: string
89
+ studio: string
90
+ node: string
91
+ abi: EthereumABI
92
+ allowSimpleName: boolean
93
+ directory: string
94
+ contract: string
95
+ indexEvents: boolean
96
+ fromExample: string | boolean
97
+ network: string
98
+ subgraphName: string
99
+ contractName: string
84
100
  },
85
- ) => {
86
- let abiFromEtherscan = undefined
101
+ ): Promise<
102
+ | {
103
+ abi: EthereumABI
104
+ protocolInstance: Protocol
105
+ subgraphName: string
106
+ directory: string
107
+ studio: string
108
+ product: string
109
+ network: string
110
+ contract: string
111
+ indexEvents: boolean
112
+ contractName: string
113
+ }
114
+ | undefined
115
+ > => {
116
+ let abiFromEtherscan: EthereumABI | undefined = undefined
87
117
  let abiFromFile = undefined
88
- let protocolInstance
89
- let ProtocolContract
90
- let ABI
118
+ let protocolInstance!: Protocol
119
+ let ProtocolContract: ContractCtor
120
+ let ABI: typeof EthereumABI
91
121
 
92
122
  let questions = [
93
123
  {
@@ -96,7 +126,7 @@ const processInitForm = async (
96
126
  message: 'Protocol',
97
127
  choices: protocolChoices,
98
128
  skip: protocolChoices.includes(protocol),
99
- result: value => {
129
+ result: (value: string) => {
100
130
  protocol = protocol || value
101
131
  protocolInstance = new Protocol(protocol)
102
132
  return protocol
@@ -115,7 +145,7 @@ const processInitForm = async (
115
145
  product === 'hosted-service' ||
116
146
  studio !== undefined ||
117
147
  node !== undefined,
118
- result: value => {
148
+ result: (value: string | undefined) => {
119
149
  // For now we only support NEAR subgraphs in the Hosted Service
120
150
  if (protocol === 'near') {
121
151
  // Can be overwritten because the question will be skipped (product === undefined)
@@ -127,7 +157,7 @@ const processInitForm = async (
127
157
  allowSimpleName = true
128
158
  }
129
159
 
130
- product = value
160
+ product = value as any
131
161
  return value
132
162
  },
133
163
  },
@@ -137,7 +167,7 @@ const processInitForm = async (
137
167
  message: () =>
138
168
  product == 'subgraph-studio' || studio ? 'Subgraph slug' : 'Subgraph name',
139
169
  initial: subgraphName,
140
- validate: name => {
170
+ validate: (name: string) => {
141
171
  try {
142
172
  validateSubgraphName(name, { allowSimpleName })
143
173
  return true
@@ -150,7 +180,7 @@ const processInitForm = async (
150
180
  $ graph init ${name} --allow-simple-name`
151
181
  }
152
182
  },
153
- result: value => {
183
+ result: (value: string) => {
154
184
  subgraphName = value
155
185
  return value
156
186
  },
@@ -160,7 +190,7 @@ const processInitForm = async (
160
190
  name: 'directory',
161
191
  message: 'Directory to create the subgraph in',
162
192
  initial: () => directory || getSubgraphBasename(subgraphName),
163
- validate: value =>
193
+ validate: (value: string) =>
164
194
  toolbox.filesystem.exists(value || directory || getSubgraphBasename(subgraphName))
165
195
  ? 'Directory already exists'
166
196
  : true,
@@ -173,16 +203,20 @@ const processInitForm = async (
173
203
  initDebug(
174
204
  'Generating list of available networks for protocol "%s" (%M)',
175
205
  protocol,
176
- availableNetworks.get(protocol),
206
+ availableNetworks.get(protocol as any),
177
207
  )
178
- return availableNetworks
179
- .get(protocol) // Get networks related to the chosen protocol.
180
- .toArray() // Needed because of gluegun. It can't even receive a JS iterable.
208
+ return (
209
+ // @ts-expect-error TODO: wait what?
210
+ availableNetworks
211
+ .get(protocol) // Get networks related to the chosen protocol.
212
+ // @ts-expect-error TODO: wait what?
213
+ .toArray()
214
+ ) // Needed because of gluegun. It can't even receive a JS iterable.
181
215
  },
182
216
 
183
217
  skip: fromExample !== undefined,
184
218
  initial: network || 'mainnet',
185
- result: value => {
219
+ result: (value: string) => {
186
220
  network = value
187
221
  return value
188
222
  },
@@ -196,12 +230,12 @@ const processInitForm = async (
196
230
  type: 'input',
197
231
  name: 'contract',
198
232
  message: () => {
199
- ProtocolContract = protocolInstance.getContract()
233
+ ProtocolContract = protocolInstance.getContract()!
200
234
  return `Contract ${ProtocolContract.identifierName()}`
201
235
  },
202
236
  skip: () => fromExample !== undefined || !protocolInstance.hasContract(),
203
237
  initial: contract,
204
- validate: async value => {
238
+ validate: async (value: string) => {
205
239
  if (fromExample !== undefined || !protocolInstance.hasContract()) {
206
240
  return true
207
241
  }
@@ -211,7 +245,7 @@ const processInitForm = async (
211
245
 
212
246
  return valid ? true : error
213
247
  },
214
- result: async value => {
248
+ result: async (value: string) => {
215
249
  if (fromExample !== undefined) {
216
250
  return value
217
251
  }
@@ -222,9 +256,10 @@ const processInitForm = async (
222
256
  if (protocolInstance.hasABIs() && !abi) {
223
257
  try {
224
258
  if (network === 'poa-core') {
225
- abiFromBlockScout = await loadAbiFromBlockScout(ABI, network, value)
259
+ // TODO: this variable is never used anywhere, what happens?
260
+ // abiFromBlockScout = await loadAbiFromBlockScout(ABI, network, value)
226
261
  } else {
227
- abiFromEtherscan = await loadAbiFromEtherscan(ABI, network, value)
262
+ abiFromEtherscan = await loadAbiFromEtherscan(ABI, network!, value)
228
263
  }
229
264
  } catch (e) {}
230
265
  }
@@ -240,13 +275,13 @@ const processInitForm = async (
240
275
  !protocolInstance.hasABIs() ||
241
276
  fromExample !== undefined ||
242
277
  abiFromEtherscan !== undefined,
243
- validate: async value => {
278
+ validate: async (value: string) => {
244
279
  if (fromExample || abiFromEtherscan || !protocolInstance.hasABIs()) {
245
280
  return true
246
281
  }
247
282
 
248
283
  try {
249
- abiFromFile = await loadAbiFromFile(ABI, value)
284
+ abiFromFile = loadAbiFromFile(toolbox, ABI, value)
250
285
  return true
251
286
  } catch (e) {
252
287
  return e.message
@@ -259,8 +294,8 @@ const processInitForm = async (
259
294
  message: 'Contract Name',
260
295
  initial: contractName || 'Contract',
261
296
  skip: () => fromExample !== undefined || !protocolInstance.hasContract(),
262
- validate: value => value && value.length > 0,
263
- result: value => {
297
+ validate: (value: string) => value && value.length > 0,
298
+ result: (value: string) => {
264
299
  contractName = value
265
300
  return value
266
301
  },
@@ -271,7 +306,7 @@ const processInitForm = async (
271
306
  message: 'Index contract events as entities',
272
307
  initial: true,
273
308
  skip: () => !!indexEvents,
274
- result: value => {
309
+ result: (value: boolean) => {
275
310
  indexEvents = value
276
311
  return value
277
312
  },
@@ -279,15 +314,26 @@ const processInitForm = async (
279
314
  ]
280
315
 
281
316
  try {
282
- let answers = await toolbox.prompt.ask(questions)
283
- return { ...answers, abi: abiFromEtherscan || abiFromFile, protocolInstance }
317
+ let answers = await toolbox.prompt.ask(
318
+ // @ts-expect-error questions do somehow fit
319
+ questions,
320
+ )
321
+ return {
322
+ ...(answers as any), // necessary answers are here
323
+ abi: (abiFromEtherscan || abiFromFile)!,
324
+ protocolInstance,
325
+ }
284
326
  } catch (e) {
285
327
  return undefined
286
328
  }
287
329
  }
288
330
 
289
- const loadAbiFromFile = async (ABI, filename) => {
290
- let exists = await toolbox.filesystem.exists(filename)
331
+ const loadAbiFromFile = (
332
+ toolbox: GluegunToolbox,
333
+ ABI: typeof EthereumABI,
334
+ filename: string,
335
+ ) => {
336
+ let exists = toolbox.filesystem.exists(filename)
291
337
 
292
338
  if (!exists) {
293
339
  throw Error('File does not exist.')
@@ -296,15 +342,15 @@ const loadAbiFromFile = async (ABI, filename) => {
296
342
  } else if (exists === 'other') {
297
343
  throw Error('Not sure what this path points to.')
298
344
  } else {
299
- return await ABI.load('Contract', filename)
345
+ return ABI.load('Contract', filename)
300
346
  }
301
347
  }
302
348
 
303
349
  export default {
304
350
  description: 'Creates a new subgraph with basic scaffolding',
305
- run: async toolbox => {
351
+ run: async (toolbox: GluegunToolbox) => {
306
352
  // Obtain tools
307
- let { print, system } = toolbox
353
+ const { print, system } = toolbox
308
354
 
309
355
  // Read CLI parameters
310
356
  let {
@@ -360,7 +406,7 @@ export default {
360
406
  }
361
407
 
362
408
  // Detect git
363
- let git = await system.which('git')
409
+ let git = system.which('git')
364
410
  if (git === null) {
365
411
  print.error(
366
412
  `Git was not found on your system. Please install 'git' so it is in $PATH.`,
@@ -370,8 +416,8 @@ export default {
370
416
  }
371
417
 
372
418
  // Detect Yarn and/or NPM
373
- let yarn = await system.which('yarn')
374
- let npm = await system.which('npm')
419
+ let yarn = system.which('yarn')
420
+ let npm = system.which('npm')
375
421
  if (!yarn && !npm) {
376
422
  print.error(
377
423
  `Neither Yarn nor NPM were found on your system. Please install one of them.`,
@@ -415,7 +461,8 @@ export default {
415
461
  const ABI = protocolInstance.getABI()
416
462
  if (abi) {
417
463
  try {
418
- abi = await loadAbiFromFile(ABI, abi)
464
+ // @ts-expect-error TODO: how does this even work when the filename is expected?
465
+ abi = loadAbiFromFile(ABI, abi)
419
466
  } catch (e) {
420
467
  print.error(`Failed to load ABI: ${e.message}`)
421
468
  process.exitCode = 1
@@ -520,7 +567,11 @@ export default {
520
567
  },
521
568
  }
522
569
 
523
- const revalidateSubgraphName = async (toolbox, subgraphName, { allowSimpleName }) => {
570
+ const revalidateSubgraphName = async (
571
+ toolbox: GluegunToolbox,
572
+ subgraphName: string,
573
+ { allowSimpleName }: { allowSimpleName: boolean },
574
+ ) => {
524
575
  // Fail if the subgraph name is invalid
525
576
  try {
526
577
  validateSubgraphName(subgraphName, { allowSimpleName })
@@ -536,17 +587,17 @@ const revalidateSubgraphName = async (toolbox, subgraphName, { allowSimpleName }
536
587
  }
537
588
  }
538
589
 
539
- const initRepository = async (toolbox, directory) =>
590
+ const initRepository = async (toolbox: GluegunToolbox, directory: string) =>
540
591
  await withSpinner(
541
592
  `Initialize subgraph repository`,
542
593
  `Failed to initialize subgraph repository`,
543
594
  `Warnings while initializing subgraph repository`,
544
- async spinner => {
595
+ async () => {
545
596
  // Remove .git dir in --from-example mode; in --from-contract, we're
546
597
  // starting from an empty directory
547
598
  let gitDir = path.join(directory, '.git')
548
599
  if (toolbox.filesystem.exists(gitDir)) {
549
- await toolbox.filesystem.remove(gitDir)
600
+ toolbox.filesystem.remove(gitDir)
550
601
  }
551
602
  await toolbox.system.run('git init', { cwd: directory })
552
603
  await toolbox.system.run('git add --all', { cwd: directory })
@@ -562,18 +613,22 @@ const initRepository = async (toolbox, directory) =>
562
613
  // This requires that the command `npm link` is called
563
614
  // on the root directory of this repository, as described here:
564
615
  // https://docs.npmjs.com/cli/v7/commands/npm-link.
565
- const npmLinkToLocalCli = async (toolbox, directory) => {
616
+ const npmLinkToLocalCli = async (toolbox: GluegunToolbox, directory: string) => {
566
617
  if (process.env.GRAPH_CLI_TESTS) {
567
618
  await toolbox.system.run('npm link @graphprotocol/graph-cli', { cwd: directory })
568
619
  }
569
620
  }
570
621
 
571
- const installDependencies = async (toolbox, directory, installCommand) =>
622
+ const installDependencies = async (
623
+ toolbox: GluegunToolbox,
624
+ directory: string,
625
+ installCommand: string,
626
+ ) =>
572
627
  await withSpinner(
573
628
  `Install dependencies with ${toolbox.print.colors.muted(installCommand)}`,
574
629
  `Failed to install dependencies`,
575
630
  `Warnings while installing dependencies`,
576
- async spinner => {
631
+ async () => {
577
632
  // Links to local graph-cli if we're running the automated tests
578
633
  await npmLinkToLocalCli(toolbox, directory)
579
634
 
@@ -582,19 +637,35 @@ const installDependencies = async (toolbox, directory, installCommand) =>
582
637
  },
583
638
  )
584
639
 
585
- const runCodegen = async (toolbox, directory, codegenCommand) =>
640
+ const runCodegen = async (
641
+ toolbox: GluegunToolbox,
642
+ directory: string,
643
+ codegenCommand: string,
644
+ ) =>
586
645
  await withSpinner(
587
646
  `Generate ABI and schema types with ${toolbox.print.colors.muted(codegenCommand)}`,
588
647
  `Failed to generate code from ABI and GraphQL schema`,
589
648
  `Warnings while generating code from ABI and GraphQL schema`,
590
- async spinner => {
649
+ async () => {
591
650
  await toolbox.system.run(codegenCommand, { cwd: directory })
592
651
  return true
593
652
  },
594
653
  )
595
654
 
596
- const printNextSteps = (toolbox, { subgraphName, directory }, { commands }) => {
597
- let { print } = toolbox
655
+ const printNextSteps = (
656
+ toolbox: GluegunToolbox,
657
+ { subgraphName, directory }: { subgraphName: string; directory: string },
658
+ {
659
+ commands,
660
+ }: {
661
+ commands: {
662
+ install: string
663
+ codegen: string
664
+ deploy: string
665
+ }
666
+ },
667
+ ) => {
668
+ const { print } = toolbox
598
669
 
599
670
  let relativeDir = path.relative(process.cwd(), directory)
600
671
 
@@ -616,14 +687,38 @@ Make sure to visit the documentation on https://thegraph.com/docs/ for further i
616
687
  }
617
688
 
618
689
  const initSubgraphFromExample = async (
619
- toolbox,
620
- { fromExample, allowSimpleName, subgraphName, directory, studio, product },
621
- { commands },
690
+ toolbox: GluegunToolbox,
691
+ {
692
+ fromExample,
693
+ allowSimpleName,
694
+ subgraphName,
695
+ directory,
696
+ studio,
697
+ product,
698
+ }: {
699
+ fromExample: string | boolean
700
+ allowSimpleName?: boolean
701
+ subgraphName: string
702
+ directory: string
703
+ studio: string
704
+ product: string
705
+ },
706
+ {
707
+ commands,
708
+ }: {
709
+ commands: {
710
+ install: string
711
+ codegen: string
712
+ deploy: string
713
+ }
714
+ },
622
715
  ) => {
623
716
  let { filesystem, print, system } = toolbox
624
717
 
625
718
  // Fail if the subgraph name is invalid
626
- if (!revalidateSubgraphName(toolbox, subgraphName, { allowSimpleName })) {
719
+ if (
720
+ !revalidateSubgraphName(toolbox, subgraphName, { allowSimpleName: !!allowSimpleName })
721
+ ) {
627
722
  process.exitCode = 1
628
723
  return
629
724
  }
@@ -640,7 +735,7 @@ const initSubgraphFromExample = async (
640
735
  `Cloning example subgraph`,
641
736
  `Failed to clone example subgraph`,
642
737
  `Warnings while cloning example subgraph`,
643
- async spinner => {
738
+ async () => {
644
739
  // Create a temporary directory
645
740
  const prefix = path.join(os.tmpdir(), 'example-subgraph-')
646
741
  const tmpDir = fs.mkdtempSync(prefix)
@@ -655,7 +750,7 @@ const initSubgraphFromExample = async (
655
750
  fromExample = DEFAULT_EXAMPLE_SUBGRAPH
656
751
  }
657
752
 
658
- const exampleSubgraphPath = path.join(tmpDir, fromExample)
753
+ const exampleSubgraphPath = path.join(tmpDir, String(fromExample))
659
754
 
660
755
  if (!filesystem.exists(exampleSubgraphPath)) {
661
756
  return { result: false, error: `Example not found: ${fromExample}` }
@@ -700,7 +795,7 @@ const initSubgraphFromExample = async (
700
795
  `Update subgraph name and commands in package.json`,
701
796
  `Failed to update subgraph name and commands in package.json`,
702
797
  `Warnings while updating subgraph name and commands in package.json`,
703
- async spinner => {
798
+ async () => {
704
799
  try {
705
800
  // Load package.json
706
801
  let pkgJsonFilename = filesystem.path(directory, 'package.json')
@@ -758,7 +853,7 @@ const initSubgraphFromExample = async (
758
853
  }
759
854
 
760
855
  const initSubgraphFromContract = async (
761
- toolbox,
856
+ toolbox: GluegunToolbox,
762
857
  {
763
858
  protocolInstance,
764
859
  allowSimpleName,
@@ -772,8 +867,31 @@ const initSubgraphFromContract = async (
772
867
  node,
773
868
  studio,
774
869
  product,
870
+ }: {
871
+ protocolInstance: Protocol
872
+ allowSimpleName: boolean
873
+ subgraphName: string
874
+ directory: string
875
+ abi: EthereumABI
876
+ network: string
877
+ contract: string
878
+ indexEvents: boolean
879
+ contractName: string
880
+ node: string
881
+ studio: string
882
+ product: string
883
+ },
884
+ {
885
+ commands,
886
+ addContract,
887
+ }: {
888
+ commands: {
889
+ install: string
890
+ codegen: string
891
+ deploy: string
892
+ }
893
+ addContract: boolean
775
894
  },
776
- { commands, addContract },
777
895
  ) => {
778
896
  let { print } = toolbox
779
897
 
@@ -790,7 +908,12 @@ const initSubgraphFromContract = async (
790
908
  return
791
909
  }
792
910
 
793
- if (protocolInstance.hasABIs() && abiEvents(abi).length === 0) {
911
+ if (
912
+ protocolInstance.hasABIs() &&
913
+ (abiEvents(abi).size === 0 ||
914
+ // @ts-expect-error TODO: the abiEvents result is expected to be a List, how's it an array?
915
+ abiEvents(abi).length === 0)
916
+ ) {
794
917
  // Fail if the ABI does not contain any events
795
918
  print.error(`ABI does not contain any events`)
796
919
  process.exitCode = 1
@@ -837,7 +960,7 @@ const initSubgraphFromContract = async (
837
960
  }
838
961
 
839
962
  if (protocolInstance.hasContract()) {
840
- let identifierName = protocolInstance.getContract().identifierName()
963
+ let identifierName = protocolInstance.getContract()!.identifierName()
841
964
  let networkConf = await initNetworksConfig(toolbox, directory, identifierName)
842
965
  if (networkConf !== true) {
843
966
  process.exitCode = 1
@@ -873,19 +996,22 @@ const initSubgraphFromContract = async (
873
996
  printNextSteps(toolbox, { subgraphName, directory }, { commands })
874
997
  }
875
998
 
876
- const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
999
+ const addAnotherContract = async (
1000
+ toolbox: GluegunToolbox,
1001
+ { protocolInstance, directory }: { protocolInstance: Protocol; directory: string },
1002
+ ) => {
877
1003
  const addContractConfirmation = await toolbox.prompt.confirm('Add another contract?')
878
1004
 
879
1005
  if (addContractConfirmation) {
880
- let abiFromFile
881
- let ProtocolContract = protocolInstance.getContract()
1006
+ let abiFromFile: boolean = false
1007
+ let ProtocolContract = protocolInstance.getContract()!
882
1008
 
883
1009
  let questions = [
884
1010
  {
885
1011
  type: 'input',
886
1012
  name: 'contract',
887
1013
  message: () => `Contract ${ProtocolContract.identifierName()}`,
888
- validate: async value => {
1014
+ validate: async (value: string) => {
889
1015
  // Validate whether the contract is valid
890
1016
  const { valid, error } = validateContract(value, ProtocolContract)
891
1017
  return valid ? true : error
@@ -896,7 +1022,7 @@ const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
896
1022
  name: 'localAbi',
897
1023
  message: 'Provide local ABI path?',
898
1024
  choices: ['yes', 'no'],
899
- result: value => {
1025
+ result: (value: string) => {
900
1026
  abiFromFile = value === 'yes' ? true : false
901
1027
  return abiFromFile
902
1028
  },
@@ -912,7 +1038,7 @@ const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
912
1038
  name: 'contractName',
913
1039
  message: 'Contract Name',
914
1040
  initial: 'Contract',
915
- validate: value => value && value.length > 0,
1041
+ validate: (value: string) => value && value.length > 0,
916
1042
  },
917
1043
  ]
918
1044
 
@@ -920,7 +1046,10 @@ const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
920
1046
  const cwd = process.cwd()
921
1047
 
922
1048
  try {
923
- let { abi, contract, contractName } = await toolbox.prompt.ask(questions)
1049
+ let { abi, contract, contractName } = await toolbox.prompt.ask(
1050
+ // @ts-expect-error questions do somehow fit
1051
+ questions,
1052
+ )
924
1053
 
925
1054
  if (fs.existsSync(directory)) {
926
1055
  process.chdir(directory)
@@ -0,0 +1,9 @@
1
+ // TODO: make sure the classes implement this type
2
+ export interface ContractCtor {
3
+ new (account: string): Contract
4
+ identifierName(): string
5
+ }
6
+
7
+ export interface Contract {
8
+ validate(): { valid: boolean; error: string | null }
9
+ }
@@ -1,4 +1,6 @@
1
- export default class EthereumContract {
1
+ import { Contract } from '../contract'
2
+
3
+ export default class EthereumContract implements Contract {
2
4
  static identifierName() {
3
5
  return 'address'
4
6
  }
@@ -21,6 +21,7 @@ import * as CosmosMappingScaffold from './cosmos/scaffold/mapping'
21
21
  import debug from '../debug'
22
22
  import Subgraph from '../subgraph'
23
23
  import { SubgraphOptions } from './subgraph'
24
+ import { ContractCtor } from './contract'
24
25
 
25
26
  let protocolDebug = debug('graph-cli:protocol')
26
27
 
@@ -113,7 +114,10 @@ export default class Protocol {
113
114
  'juno-1',
114
115
  'uni-3', // Juno testnet
115
116
  ],
116
- }) as immutable.Map<string, string[]>
117
+ }) as immutable.Map<
118
+ 'arweave' | 'ethereum' | 'near' | 'cosmos' | 'substreams',
119
+ string[]
120
+ >
117
121
 
118
122
  let allNetworks: string[] = []
119
123
  networks.forEach(value => {
@@ -210,7 +214,7 @@ export type ProtocolName = 'arweave' | 'ethereum' | 'near' | 'cosmos' | 'substre
210
214
  export interface ProtocolConfig {
211
215
  displayName: string
212
216
  abi?: any
213
- contract?: any
217
+ contract?: ContractCtor
214
218
  getTemplateCodeGen?: (template: any) => any
215
219
  getTypeGenerator?: (options: any) => any
216
220
  getSubgraph(options: SubgraphOptions): Subgraph
@@ -1,16 +1,16 @@
1
+ import { Contract } from '../contract'
2
+
1
3
  const MINIMUM_ACCOUNT_ID_LENGTH = 2 as const
2
4
  const MAXIMUM_ACCOUNT_ID_LENGTH = 64 as const
3
5
 
4
6
  const RULES_URL = 'https://docs.near.org/docs/concepts/account#account-id-rules' as const
5
7
 
6
- export default class NearContract {
7
- private account: string
8
-
8
+ export default class NearContract implements Contract {
9
9
  static identifierName() {
10
10
  return 'account'
11
11
  }
12
12
 
13
- constructor(account: string) {
13
+ constructor(private account: string) {
14
14
  this.account = account
15
15
  }
16
16
 
package/src/subgraph.ts CHANGED
@@ -4,7 +4,7 @@ import path from 'path'
4
4
  import yaml from 'yaml'
5
5
  import { strOptions } from 'yaml/types'
6
6
  import * as graphql from 'graphql/language'
7
- import validation from './validation'
7
+ import * as validation from './validation'
8
8
  import debug from './debug'
9
9
  import { Subgraph as ISubgraph } from './protocols/subgraph'
10
10
 
@@ -1,7 +1,8 @@
1
1
  import immutable from 'immutable'
2
2
  import Protocol from '../protocols'
3
+ import { ContractCtor } from '../protocols/contract'
3
4
 
4
- export const validateContract = (value: any, ProtocolContract: any) => {
5
+ export const validateContract = (value: string, ProtocolContract: ContractCtor) => {
5
6
  const contract = new ProtocolContract(value)
6
7
 
7
8
  const { valid, error } = contract.validate()
@@ -20,7 +21,7 @@ export const validateContractValues = (
20
21
  manifest: immutable.Map<any, any>,
21
22
  protocol: Protocol,
22
23
  ) => {
23
- const ProtocolContract = protocol.getContract()
24
+ const ProtocolContract = protocol.getContract()!
24
25
 
25
26
  const fieldName = ProtocolContract.identifierName()
26
27
 
@@ -2,9 +2,4 @@ import { validateSchema } from './schema'
2
2
  import { validateManifest } from './manifest'
3
3
  import { validateContractValues, validateContract } from './contract'
4
4
 
5
- export default {
6
- validateSchema,
7
- validateManifest,
8
- validateContractValues,
9
- validateContract,
10
- }
5
+ export { validateSchema, validateManifest, validateContractValues, validateContract }