@graphprotocol/graph-cli 0.37.3-alpha-20230112170916-36bdc67 → 0.37.3-alpha-20230112190020-19838fd

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,6 +1,6 @@
1
1
  # @graphprotocol/graph-cli
2
2
 
3
- ## 0.37.3-alpha-20230112170916-36bdc67
3
+ ## 0.37.3-alpha-20230112190020-19838fd
4
4
 
5
5
  ### Patch Changes
6
6
 
@@ -1,6 +1,4 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fixParameters = void 0;
4
2
  // Workaround for https://github.com/infinitered/gluegun/pull/464.
5
3
  //
6
4
  // There is currently no way in Gluegun to define command-line options
@@ -26,7 +24,8 @@ exports.fixParameters = void 0;
26
24
  // The `fixParameters` function checks if any of the provided boolean
27
25
  // options has a string value; if so, it pushes it to the front of the
28
26
  // parameters array and returns the result of that.
29
- //
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.fixParameters = void 0;
30
29
  const fixParameters = (parameters, booleanOptions) => {
31
30
  let unexpectedStringOptions = Object.keys(booleanOptions)
32
31
  .filter(key => typeof booleanOptions[key] === 'string')
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createJsonRpcClient = void 0;
7
7
  const jayson_1 = __importDefault(require("jayson"));
8
8
  const gluegun_1 = require("gluegun");
9
- const createJsonRpcClient = (url) => {
9
+ function createJsonRpcClient(url) {
10
10
  const params = {
11
11
  host: url.hostname,
12
12
  port: url.port,
@@ -25,5 +25,5 @@ const createJsonRpcClient = (url) => {
25
25
  gluegun_1.print.error('The Graph Node URL must be of the following format: http(s)://host[:port]/[path]');
26
26
  return null;
27
27
  }
28
- };
28
+ }
29
29
  exports.createJsonRpcClient = createJsonRpcClient;
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const chalk_1 = __importDefault(require("chalk"));
30
- const toolbox = __importStar(require("gluegun/toolbox"));
30
+ const toolbox = __importStar(require("gluegun"));
31
31
  const immutable_1 = __importDefault(require("immutable"));
32
32
  const spinner_1 = require("../command-helpers/spinner");
33
33
  const subgraph_1 = __importDefault(require("../subgraph"));
@@ -55,7 +55,7 @@ exports.default = {
55
55
  // Obtain tools
56
56
  let { print, system } = toolbox;
57
57
  // Read CLI parameters
58
- let { abi, contractName, h, help, mergeEntities, networkFile } = toolbox.parameters.options;
58
+ let { abi, contractName, h, help, mergeEntities, networkFile, } = toolbox.parameters.options;
59
59
  contractName = contractName || 'Contract';
60
60
  try {
61
61
  (0, gluegun_1.fixParameters)(toolbox.parameters, {
@@ -69,8 +69,8 @@ exports.default = {
69
69
  process.exitCode = 1;
70
70
  return;
71
71
  }
72
- let address = toolbox.parameters.first || toolbox.parameters.array[0];
73
- let manifestPath = toolbox.parameters.second || toolbox.parameters.array[1] || './subgraph.yaml';
72
+ let address = toolbox.parameters.first || toolbox.parameters.array?.[0];
73
+ let manifestPath = toolbox.parameters.second || toolbox.parameters.array?.[1] || './subgraph.yaml';
74
74
  // Show help text if requested
75
75
  if (help || h) {
76
76
  print.info(HELP);
@@ -85,7 +85,7 @@ exports.default = {
85
85
  const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifestPath);
86
86
  let protocol = protocols_1.default.fromDataSources(dataSourcesAndTemplates);
87
87
  let manifest = await subgraph_1.default.load(manifestPath, { protocol });
88
- let network = manifest.result.get('dataSources').get(0).get('network');
88
+ let network = manifest.result.getIn(['dataSources', 0, 'network']);
89
89
  let result = manifest.result.asMutable();
90
90
  let entities = getEntities(manifest);
91
91
  let contractNames = getContractNames(manifest);
@@ -130,30 +130,30 @@ exports.default = {
130
130
  const networksFile = networkFile || './networks.json';
131
131
  await (0, network_1.updateNetworksFile)(toolbox, network, contractName, address, networksFile);
132
132
  // Detect Yarn and/or NPM
133
- let yarn = await system.which('yarn');
134
- let npm = await system.which('npm');
133
+ let yarn = system.which('yarn');
134
+ let npm = system.which('npm');
135
135
  if (!yarn && !npm) {
136
136
  print.error(`Neither Yarn nor NPM were found on your system. Please install one of them.`);
137
137
  process.exitCode = 1;
138
138
  return;
139
139
  }
140
- await (0, spinner_1.withSpinner)('Running codegen', 'Failed to run codegen', 'Warning during codegen', async (spinner) => {
140
+ await (0, spinner_1.withSpinner)('Running codegen', 'Failed to run codegen', 'Warning during codegen', async () => {
141
141
  await system.run(yarn ? 'yarn codegen' : 'npm run codegen');
142
142
  });
143
143
  },
144
144
  };
145
- const getEntities = manifest => {
145
+ const getEntities = (manifest) => {
146
146
  let dataSources = manifest.result.get('dataSources', immutable_1.default.List());
147
147
  let templates = manifest.result.get('templates', immutable_1.default.List());
148
148
  return dataSources
149
149
  .concat(templates)
150
- .map(dataSource => dataSource.getIn(['mapping', 'entities']))
150
+ .map((dataSource) => dataSource.getIn(['mapping', 'entities']))
151
151
  .flatten();
152
152
  };
153
- const getContractNames = manifest => {
153
+ const getContractNames = (manifest) => {
154
154
  let dataSources = manifest.result.get('dataSources', immutable_1.default.List());
155
155
  let templates = manifest.result.get('templates', immutable_1.default.List());
156
- return dataSources.concat(templates).map(dataSource => dataSource.get('name'));
156
+ return dataSources.concat(templates).map((dataSource) => dataSource.get('name'));
157
157
  };
158
158
  const updateEventNamesOnCollision = (ethabi, entities, contractName, mergeEntities) => {
159
159
  let abiData = ethabi.data;
@@ -168,7 +168,7 @@ const updateEventNamesOnCollision = (ethabi, entities, contractName, mergeEntiti
168
168
  print.error(`Contract name ('${contractName}')
169
169
  + event name ('${dataRow.get('name')}') entity already exists.`);
170
170
  process.exitCode = 1;
171
- return;
171
+ break;
172
172
  }
173
173
  if (mergeEntities) {
174
174
  collisionEntities.push(dataRow.get('name'));
@@ -48,9 +48,9 @@ exports.default = {
48
48
  description: 'Sets the deploy key to use when deploying to a Graph node',
49
49
  run: async (toolbox) => {
50
50
  // Obtain tools
51
- let { filesystem, print, system } = toolbox;
51
+ const { print } = toolbox;
52
52
  // Read CLI parameters
53
- let { product, studio, h, help } = toolbox.parameters.options;
53
+ const { product, studio, h, help } = toolbox.parameters.options;
54
54
  // Show help text if requested
55
55
  if (help || h) {
56
56
  print.info(HELP);
@@ -21,7 +21,7 @@ exports.default = {
21
21
  description: 'Registers a subgraph name',
22
22
  run: async (toolbox) => {
23
23
  // Obtain tools
24
- let { filesystem, print, system } = toolbox;
24
+ const { print } = toolbox;
25
25
  // Read CLI parameters
26
26
  let { accessToken, g, h, help, node } = toolbox.parameters.options;
27
27
  let subgraphName = toolbox.parameters.first;
@@ -65,10 +65,15 @@ exports.default = {
65
65
  // Use the access token, if one is set
66
66
  accessToken = await (0, auth_1.identifyDeployKey)(node, accessToken);
67
67
  if (accessToken !== undefined && accessToken !== null) {
68
+ // @ts-expect-error options property seems to exist
68
69
  client.options.headers = { Authorization: `Bearer ${accessToken}` };
69
70
  }
70
71
  let spinner = print.spin(`Creating subgraph in Graph node: ${requestUrl}`);
71
- client.request('subgraph_create', { name: subgraphName }, function (requestError, jsonRpcError, res) {
72
+ client.request('subgraph_create', { name: subgraphName }, function (
73
+ // @ts-expect-error TODO: why are the arguments not typed?
74
+ requestError,
75
+ // @ts-expect-error TODO: why are the arguments not typed?
76
+ jsonRpcError) {
72
77
  if (jsonRpcError) {
73
78
  spinner.fail(`Error creating the subgraph: ${jsonRpcError.message}`);
74
79
  process.exitCode = 1;
@@ -29,8 +29,12 @@ exports.default = {
29
29
  description: 'Runs rust binary for subgraph testing',
30
30
  run: async (toolbox) => {
31
31
  // Read CLI parameters
32
- let { c, coverage, d, docker, f, force, h, help, l, logs, r, recompile, v, version } = toolbox.parameters.options;
33
- let opts = {};
32
+ let { c, coverage, d, docker, f, force, h, help, l, logs, r, recompile, v, version, } = toolbox.parameters.options;
33
+ const testsFolder = './tests';
34
+ let opts = {
35
+ testsFolder,
36
+ cachePath: path_1.default.join(testsFolder, '.latest.json'),
37
+ };
34
38
  // Support both long and short option variants
35
39
  opts.coverage = coverage || c;
36
40
  opts.docker = docker || d;
@@ -39,7 +43,6 @@ exports.default = {
39
43
  opts.logs = logs || l;
40
44
  opts.recompile = recompile || r;
41
45
  opts.version = version || v;
42
- opts.testsFolder = './tests';
43
46
  // Fix if a boolean flag (e.g -c, --coverage) has an argument
44
47
  try {
45
48
  (0, gluegun_2.fixParameters)(toolbox.parameters, {
@@ -62,7 +65,7 @@ exports.default = {
62
65
  process.exitCode = 1;
63
66
  return;
64
67
  }
65
- let datasource = toolbox.parameters.first || toolbox.parameters.array[0];
68
+ let datasource = toolbox.parameters.first || toolbox.parameters.array?.[0];
66
69
  // Show help text if requested
67
70
  if (opts.help) {
68
71
  gluegun_1.print.info(HELP);
@@ -85,7 +88,6 @@ exports.default = {
85
88
  process.exit(1);
86
89
  }
87
90
  }
88
- opts.cachePath = path_1.default.join(opts.testsFolder, '.latest.json');
89
91
  setVersionFromCache(opts);
90
92
  // Fetch the latest version tag if version is not specified with -v/--version or if the version is not cached
91
93
  if (opts.force || (!opts.version && !opts.latestVersion)) {
@@ -127,7 +129,8 @@ async function runBinary(datasource, opts) {
127
129
  let latestVersion = opts.latestVersion;
128
130
  let recompileOpt = opts.recompile;
129
131
  const platform = await getPlatform(logsOpt);
130
- const url = `https://github.com/LimeChain/matchstick/releases/download/${versionOpt || latestVersion}/${platform}`;
132
+ const url = `https://github.com/LimeChain/matchstick/releases/download/${versionOpt ||
133
+ latestVersion}/${platform}`;
131
134
  if (logsOpt) {
132
135
  gluegun_1.print.info(`Download link: ${url}`);
133
136
  }
@@ -150,9 +153,10 @@ async function getPlatform(logsOpt) {
150
153
  const linuxInfo = type === 'Linux' ? await getLinuxInfo() : {};
151
154
  const linuxDistro = linuxInfo.name;
152
155
  const release = linuxInfo.version || os_1.default.release();
153
- const majorVersion = parseInt(linuxInfo.version, 10) || semver_1.default.major(release);
156
+ const majorVersion = parseInt(linuxInfo.version || '', 10) || semver_1.default.major(release);
154
157
  if (logsOpt) {
155
- gluegun_1.print.info(`OS type: ${linuxDistro || type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`);
158
+ gluegun_1.print.info(`OS type: ${linuxDistro ||
159
+ type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`);
156
160
  }
157
161
  if (arch === 'x64' || isAppleSilicon) {
158
162
  if (type === 'Darwin') {
@@ -206,9 +210,9 @@ async function runDocker(datasource, opts) {
206
210
  let recompileOpt = opts.recompile;
207
211
  // Remove binary-install-raw binaries, because docker has permission issues
208
212
  // when building the docker images
209
- await gluegun_1.filesystem.remove('./node_modules/binary-install-raw/bin');
213
+ gluegun_1.filesystem.remove('./node_modules/binary-install-raw/bin');
210
214
  // Get current working directory
211
- let current_folder = await gluegun_1.filesystem.cwd();
215
+ let current_folder = gluegun_1.filesystem.cwd();
212
216
  // Declate dockerfilePath with default location
213
217
  let dockerfilePath = path_1.default.join(opts.testsFolder || 'tests', '.docker/Dockerfile');
214
218
  // Check if the Dockerfil already exists
@@ -219,7 +223,7 @@ async function runDocker(datasource, opts) {
219
223
  await dockerfile(dockerfilePath, versionOpt, latestVersion);
220
224
  }
221
225
  // Run a command to check if matchstick image already exists
222
- (0, child_process_1.exec)('docker images -q matchstick', (error, stdout, stderr) => {
226
+ (0, child_process_1.exec)('docker images -q matchstick', (_error, stdout, _stderr) => {
223
227
  // Collect all(if any) flags and options that have to be passed to the matchstick binary
224
228
  let testArgs = '';
225
229
  if (coverageOpt)
@@ -247,7 +251,7 @@ async function runDocker(datasource, opts) {
247
251
  // Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
248
252
  if (!dockerfileExists || stdout === '' || versionOpt || forceOpt) {
249
253
  if (stdout !== '') {
250
- (0, child_process_1.exec)('docker image rm matchstick', (error, stdout, stderr) => {
254
+ (0, child_process_1.exec)('docker image rm matchstick', (_error, stdout, _stderr) => {
251
255
  gluegun_1.print.info(chalk_1.default.bold(`Removing matchstick image\n${stdout}`));
252
256
  });
253
257
  }
@@ -283,9 +287,9 @@ async function dockerfile(dockerfilePath, versionOpt, latestVersion) {
283
287
  }
284
288
  });
285
289
  // Write the Dockerfile
286
- await gluegun_1.filesystem.write(dockerfilePath, content);
290
+ gluegun_1.filesystem.write(dockerfilePath, content);
287
291
  // Replaces the version placeholders
288
- await gluegun_1.patching.replace(dockerfilePath, '<MATCHSTICK_VERSION>', versionOpt || latestVersion);
292
+ await gluegun_1.patching.replace(dockerfilePath, '<MATCHSTICK_VERSION>', versionOpt || latestVersion || 'unknown');
289
293
  }
290
294
  catch (error) {
291
295
  spinner.fail(`A problem occurred while generating the Dockerfile. Please attend to the errors below:\n ${error.message}`);
package/jest.config.js CHANGED
@@ -49,10 +49,10 @@ module.exports = {
49
49
  // forceCoverageMatch: [],
50
50
 
51
51
  // A path to a module which exports an async function that is triggered once before all test suites
52
- globalSetup: './tests/cli/globalSetup',
52
+ globalSetup: './tests/cli/globalSetup.ts',
53
53
 
54
54
  // A path to a module which exports an async function that is triggered once after all test suites
55
- globalTeardown: './tests/cli/globalTeardown',
55
+ globalTeardown: './tests/cli/globalTeardown.ts',
56
56
 
57
57
  // A set of global variables that need to be available in all test environments
58
58
  // globals: {},
@@ -136,7 +136,7 @@ module.exports = {
136
136
  testMatch: ['**/?(*.)+(spec|test).(t|j)s?(x)'],
137
137
 
138
138
  // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
139
- testPathIgnorePatterns: ['/src/commands/test.js', '/node_modules/', '/dist/'],
139
+ testPathIgnorePatterns: ['/src/commands/test.ts', '/node_modules/', '/dist/'],
140
140
 
141
141
  // The regexp pattern Jest uses to detect test files
142
142
  // testRegex: "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.37.3-alpha-20230112170916-36bdc67",
3
+ "version": "0.37.3-alpha-20230112190020-19838fd",
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",
@@ -55,9 +55,9 @@
55
55
  },
56
56
  "scripts": {
57
57
  "test": "jest --verbose",
58
- "test:init": "jest tests/cli/init.test.js --verbose",
59
- "test:validation": "jest tests/cli/validation.test.js --verbose",
58
+ "test:init": "jest tests/cli/init.test.ts --verbose",
59
+ "test:validation": "jest tests/cli/validation.test.ts --verbose",
60
60
  "type-check": "tsc --noEmit",
61
- "build": "tsc --build && copyfiles -u 1 src/**/*.graphql dist/ && chmod +x ./dist/bin.js"
61
+ "build": "tsc -b tsconfig.build.json && copyfiles -u 1 src/**/*.graphql dist/ && chmod +x ./dist/bin.js"
62
62
  }
63
63
  }
@@ -23,8 +23,13 @@
23
23
  // The `fixParameters` function checks if any of the provided boolean
24
24
  // options has a string value; if so, it pushes it to the front of the
25
25
  // parameters array and returns the result of that.
26
- //
27
- export const fixParameters = (parameters: any, booleanOptions: any) => {
26
+
27
+ import { GluegunParameters } from 'gluegun'
28
+
29
+ export const fixParameters = (
30
+ parameters: GluegunParameters,
31
+ booleanOptions: Record<string, string>,
32
+ ) => {
28
33
  let unexpectedStringOptions = Object.keys(booleanOptions)
29
34
  .filter(key => typeof booleanOptions[key] === 'string')
30
35
  .map(key => ({ key, value: booleanOptions[key] }))
@@ -39,9 +44,9 @@ export const fixParameters = (parameters: any, booleanOptions: any) => {
39
44
  )
40
45
  } else if (unexpectedStringOptions.length == 1) {
41
46
  let params = parameters.array
42
- params.unshift(unexpectedStringOptions[0].value)
43
- return params
47
+ params!.unshift(unexpectedStringOptions[0].value)
48
+ return params!
44
49
  } else {
45
- return parameters.array
50
+ return parameters.array!
46
51
  }
47
52
  }
@@ -1,7 +1,7 @@
1
1
  import jayson from 'jayson'
2
2
  import { print } from 'gluegun'
3
3
 
4
- const createJsonRpcClient = (url: URL) => {
4
+ export function createJsonRpcClient(url: URL): jayson.Client | null {
5
5
  const params = {
6
6
  host: url.hostname,
7
7
  port: url.port,
@@ -24,5 +24,3 @@ const createJsonRpcClient = (url: URL) => {
24
24
  return null
25
25
  }
26
26
  }
27
-
28
- export { createJsonRpcClient }
@@ -16,8 +16,8 @@ export function chooseNodeUrl({
16
16
  }: {
17
17
  product: string
18
18
  studio: string
19
- node: string
20
- allowSimpleName: boolean
19
+ node?: string
20
+ allowSimpleName?: boolean
21
21
  }) {
22
22
  if (node) {
23
23
  try {
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk'
2
- import * as toolbox from 'gluegun/toolbox'
2
+ import * as toolbox from 'gluegun'
3
3
  import immutable from 'immutable'
4
4
  import { withSpinner } from '../command-helpers/spinner'
5
5
  import Subgraph from '../subgraph'
@@ -29,15 +29,29 @@ ${chalk.dim('Options:')}
29
29
  -h, --help Show usage information
30
30
  `
31
31
 
32
+ export interface AddOptions {
33
+ abi?: string
34
+ contractName?: string
35
+ mergeEntities?: boolean
36
+ networkFile?: string
37
+ help?: boolean
38
+ }
39
+
32
40
  export default {
33
41
  description: 'Adds a new datasource to a subgraph',
34
- run: async toolbox => {
42
+ run: async (toolbox: toolbox.GluegunToolbox) => {
35
43
  // Obtain tools
36
44
  let { print, system } = toolbox
37
45
 
38
46
  // Read CLI parameters
39
- let { abi, contractName, h, help, mergeEntities, networkFile } =
40
- toolbox.parameters.options
47
+ let {
48
+ abi,
49
+ contractName,
50
+ h,
51
+ help,
52
+ mergeEntities,
53
+ networkFile,
54
+ } = toolbox.parameters.options
41
55
 
42
56
  contractName = contractName || 'Contract'
43
57
 
@@ -53,9 +67,9 @@ export default {
53
67
  return
54
68
  }
55
69
 
56
- let address = toolbox.parameters.first || toolbox.parameters.array[0]
70
+ let address = toolbox.parameters.first || toolbox.parameters.array?.[0]
57
71
  let manifestPath =
58
- toolbox.parameters.second || toolbox.parameters.array[1] || './subgraph.yaml'
72
+ toolbox.parameters.second || toolbox.parameters.array?.[1] || './subgraph.yaml'
59
73
 
60
74
  // Show help text if requested
61
75
  if (help || h) {
@@ -73,7 +87,7 @@ export default {
73
87
  const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifestPath)
74
88
  let protocol = Protocol.fromDataSources(dataSourcesAndTemplates)
75
89
  let manifest = await Subgraph.load(manifestPath, { protocol })
76
- let network = manifest.result.get('dataSources').get(0).get('network')
90
+ let network = manifest.result.getIn(['dataSources', 0, 'network']) as any
77
91
  let result = manifest.result.asMutable()
78
92
 
79
93
  let entities = getEntities(manifest)
@@ -109,7 +123,7 @@ export default {
109
123
  await writeSchema(
110
124
  ethabi,
111
125
  protocol,
112
- result.getIn(['schema', 'file']),
126
+ result.getIn(['schema', 'file']) as any,
113
127
  collisionEntities,
114
128
  )
115
129
  await writeMapping(ethabi, protocol, contractName, collisionEntities)
@@ -127,7 +141,7 @@ export default {
127
141
  // Handle the collisions edge case by copying another data source yaml data
128
142
  if (mergeEntities && onlyCollisions) {
129
143
  let firstDataSource = dataSources.get(0)
130
- let source = dataSource.get('source')
144
+ let source = dataSource.get('source') as any
131
145
  let mapping = firstDataSource.get('mapping').asMutable()
132
146
 
133
147
  // Save the address of the new data source
@@ -146,8 +160,8 @@ export default {
146
160
  await updateNetworksFile(toolbox, network, contractName, address, networksFile)
147
161
 
148
162
  // Detect Yarn and/or NPM
149
- let yarn = await system.which('yarn')
150
- let npm = await system.which('npm')
163
+ let yarn = system.which('yarn')
164
+ let npm = system.which('npm')
151
165
  if (!yarn && !npm) {
152
166
  print.error(
153
167
  `Neither Yarn nor NPM were found on your system. Please install one of them.`,
@@ -160,31 +174,36 @@ export default {
160
174
  'Running codegen',
161
175
  'Failed to run codegen',
162
176
  'Warning during codegen',
163
- async spinner => {
177
+ async () => {
164
178
  await system.run(yarn ? 'yarn codegen' : 'npm run codegen')
165
179
  },
166
180
  )
167
181
  },
168
182
  }
169
183
 
170
- const getEntities = manifest => {
184
+ const getEntities = (manifest: any) => {
171
185
  let dataSources = manifest.result.get('dataSources', immutable.List())
172
186
  let templates = manifest.result.get('templates', immutable.List())
173
187
 
174
188
  return dataSources
175
189
  .concat(templates)
176
- .map(dataSource => dataSource.getIn(['mapping', 'entities']))
190
+ .map((dataSource: any) => dataSource.getIn(['mapping', 'entities']))
177
191
  .flatten()
178
192
  }
179
193
 
180
- const getContractNames = manifest => {
194
+ const getContractNames = (manifest: any) => {
181
195
  let dataSources = manifest.result.get('dataSources', immutable.List())
182
196
  let templates = manifest.result.get('templates', immutable.List())
183
197
 
184
- return dataSources.concat(templates).map(dataSource => dataSource.get('name'))
198
+ return dataSources.concat(templates).map((dataSource: any) => dataSource.get('name'))
185
199
  }
186
200
 
187
- const updateEventNamesOnCollision = (ethabi, entities, contractName, mergeEntities) => {
201
+ const updateEventNamesOnCollision = (
202
+ ethabi: any,
203
+ entities: any,
204
+ contractName: string,
205
+ mergeEntities: boolean,
206
+ ) => {
188
207
  let abiData = ethabi.data
189
208
  let { print } = toolbox
190
209
  let collisionEntities = []
@@ -199,7 +218,7 @@ const updateEventNamesOnCollision = (ethabi, entities, contractName, mergeEntiti
199
218
  print.error(`Contract name ('${contractName}')
200
219
  + event name ('${dataRow.get('name')}') entity already exists.`)
201
220
  process.exitCode = 1
202
- return
221
+ break
203
222
  }
204
223
 
205
224
  if (mergeEntities) {
@@ -1,4 +1,5 @@
1
1
  import chalk from 'chalk'
2
+ import { GluegunToolbox } from 'gluegun'
2
3
  import { saveDeployKey } from '../command-helpers/auth'
3
4
  import { chooseNodeUrl } from '../command-helpers/node'
4
5
  import { fixParameters } from '../command-helpers/gluegun'
@@ -16,7 +17,19 @@ ${chalk.dim('Options:')}
16
17
  -h, --help Show usage information
17
18
  `
18
19
 
19
- const processForm = async (toolbox, { product, studio, node, deployKey }) => {
20
+ export interface AuthOptions {
21
+ product?: 'subgraph-studio' | 'hosted-service'
22
+ studio?: string
23
+ help?: boolean
24
+ // not a cli arg
25
+ node?: string
26
+ deployKey?: string
27
+ }
28
+
29
+ const processForm = async (
30
+ toolbox: GluegunToolbox,
31
+ { product, studio, node, deployKey }: AuthOptions,
32
+ ) => {
20
33
  const questions = [
21
34
  {
22
35
  type: 'select',
@@ -47,12 +60,12 @@ const processForm = async (toolbox, { product, studio, node, deployKey }) => {
47
60
 
48
61
  export default {
49
62
  description: 'Sets the deploy key to use when deploying to a Graph node',
50
- run: async toolbox => {
63
+ run: async (toolbox: GluegunToolbox) => {
51
64
  // Obtain tools
52
- let { filesystem, print, system } = toolbox
65
+ const { print } = toolbox
53
66
 
54
67
  // Read CLI parameters
55
- let { product, studio, h, help } = toolbox.parameters.options
68
+ const { product, studio, h, help } = toolbox.parameters.options
56
69
 
57
70
  // Show help text if requested
58
71
  if (help || h) {
@@ -60,7 +73,7 @@ export default {
60
73
  return
61
74
  }
62
75
 
63
- let firstParam, secondParam
76
+ let firstParam: string, secondParam: string
64
77
  try {
65
78
  ;[firstParam, secondParam] = fixParameters(toolbox.parameters, {
66
79
  h,
@@ -74,7 +87,7 @@ export default {
74
87
  }
75
88
 
76
89
  // if user specifies --product or --studio then deployKey is the first parameter
77
- let node
90
+ let node: string | undefined
78
91
  let deployKey
79
92
  if (product || studio) {
80
93
  ;({ node } = chooseNodeUrl({ product, studio, node }))
@@ -119,7 +132,7 @@ export default {
119
132
  }
120
133
 
121
134
  try {
122
- await saveDeployKey(node, deployKey)
135
+ await saveDeployKey(node!, deployKey)
123
136
  print.success(`Deploy key set for ${node}`)
124
137
  } catch (e) {
125
138
  print.error(e)
@@ -0,0 +1 @@
1
+ declare module 'binary-install-raw'
@@ -1,5 +1,6 @@
1
1
  import { URL } from 'url'
2
2
  import chalk from 'chalk'
3
+ import * as toolbox from 'gluegun'
3
4
  import { validateNodeUrl } from '../command-helpers/node'
4
5
  import { identifyDeployKey as identifyAccessToken } from '../command-helpers/auth'
5
6
  import { createJsonRpcClient } from '../command-helpers/jsonrpc'
@@ -14,11 +15,17 @@ ${chalk.dim('Options:')}
14
15
  -g, --node <url> Graph node to create the subgraph in
15
16
  `
16
17
 
18
+ export interface AddOptions {
19
+ accessToken?: string
20
+ help?: boolean
21
+ node?: string
22
+ }
23
+
17
24
  export default {
18
25
  description: 'Registers a subgraph name',
19
- run: async toolbox => {
26
+ run: async (toolbox: toolbox.GluegunToolbox) => {
20
27
  // Obtain tools
21
- let { filesystem, print, system } = toolbox
28
+ const { print } = toolbox
22
29
 
23
30
  // Read CLI parameters
24
31
  let { accessToken, g, h, help, node } = toolbox.parameters.options
@@ -69,25 +76,27 @@ export default {
69
76
  // Use the access token, if one is set
70
77
  accessToken = await identifyAccessToken(node, accessToken)
71
78
  if (accessToken !== undefined && accessToken !== null) {
79
+ // @ts-expect-error options property seems to exist
72
80
  client.options.headers = { Authorization: `Bearer ${accessToken}` }
73
81
  }
74
82
 
75
83
  let spinner = print.spin(`Creating subgraph in Graph node: ${requestUrl}`)
76
- client.request(
77
- 'subgraph_create',
78
- { name: subgraphName },
79
- function (requestError, jsonRpcError, res) {
80
- if (jsonRpcError) {
81
- spinner.fail(`Error creating the subgraph: ${jsonRpcError.message}`)
82
- process.exitCode = 1
83
- } else if (requestError) {
84
- spinner.fail(`HTTP error creating the subgraph: ${requestError.code}`)
85
- process.exitCode = 1
86
- } else {
87
- spinner.stop()
88
- print.success(`Created subgraph: ${subgraphName}`)
89
- }
90
- },
91
- )
84
+ client.request('subgraph_create', { name: subgraphName }, function(
85
+ // @ts-expect-error TODO: why are the arguments not typed?
86
+ requestError,
87
+ // @ts-expect-error TODO: why are the arguments not typed?
88
+ jsonRpcError,
89
+ ) {
90
+ if (jsonRpcError) {
91
+ spinner.fail(`Error creating the subgraph: ${jsonRpcError.message}`)
92
+ process.exitCode = 1
93
+ } else if (requestError) {
94
+ spinner.fail(`HTTP error creating the subgraph: ${requestError.code}`)
95
+ process.exitCode = 1
96
+ } else {
97
+ spinner.stop()
98
+ print.success(`Created subgraph: ${subgraphName}`)
99
+ }
100
+ })
92
101
  },
93
102
  }
@@ -2,7 +2,7 @@ import { Binary } from 'binary-install-raw'
2
2
  import os from 'os'
3
3
  import chalk from 'chalk'
4
4
  import fetch from 'node-fetch'
5
- import { filesystem, patching, print, system } from 'gluegun'
5
+ import { filesystem, GluegunToolbox, patching, print, system } from 'gluegun'
6
6
  import { fixParameters } from '../command-helpers/gluegun'
7
7
  import path from 'path'
8
8
  import semver from 'semver'
@@ -22,14 +22,46 @@ ${chalk.dim('Options:')}
22
22
  -v, --version <tag> Choose the version of the rust binary that you want to be downloaded/used
23
23
  `
24
24
 
25
+ export interface TestOptions {
26
+ coverage?: boolean
27
+ docker?: boolean
28
+ force?: boolean
29
+ help?: boolean
30
+ logs?: boolean
31
+ recompile?: boolean
32
+ version?: string
33
+ // not a cli arg
34
+ testsFolder: string
35
+ cachePath: string
36
+ latestVersion?: string
37
+ }
38
+
25
39
  export default {
26
40
  description: 'Runs rust binary for subgraph testing',
27
- run: async toolbox => {
41
+ run: async (toolbox: GluegunToolbox) => {
28
42
  // Read CLI parameters
29
- let { c, coverage, d, docker, f, force, h, help, l, logs, r, recompile, v, version } =
30
- toolbox.parameters.options
31
-
32
- let opts = {}
43
+ let {
44
+ c,
45
+ coverage,
46
+ d,
47
+ docker,
48
+ f,
49
+ force,
50
+ h,
51
+ help,
52
+ l,
53
+ logs,
54
+ r,
55
+ recompile,
56
+ v,
57
+ version,
58
+ } = toolbox.parameters.options
59
+
60
+ const testsFolder = './tests'
61
+ let opts: TestOptions = {
62
+ testsFolder,
63
+ cachePath: path.join(testsFolder, '.latest.json'),
64
+ }
33
65
  // Support both long and short option variants
34
66
  opts.coverage = coverage || c
35
67
  opts.docker = docker || d
@@ -38,7 +70,6 @@ export default {
38
70
  opts.logs = logs || l
39
71
  opts.recompile = recompile || r
40
72
  opts.version = version || v
41
- opts.testsFolder = './tests'
42
73
  // Fix if a boolean flag (e.g -c, --coverage) has an argument
43
74
  try {
44
75
  fixParameters(toolbox.parameters, {
@@ -61,7 +92,7 @@ export default {
61
92
  return
62
93
  }
63
94
 
64
- let datasource = toolbox.parameters.first || toolbox.parameters.array[0]
95
+ let datasource = toolbox.parameters.first || toolbox.parameters.array?.[0]
65
96
  // Show help text if requested
66
97
  if (opts.help) {
67
98
  print.info(HELP)
@@ -72,7 +103,7 @@ export default {
72
103
  if (filesystem.exists('matchstick.yaml')) {
73
104
  try {
74
105
  // Load the config
75
- let config = await yaml.load(filesystem.read('matchstick.yaml', 'utf8'))
106
+ let config = await yaml.load(filesystem.read('matchstick.yaml', 'utf8')!)
76
107
 
77
108
  // Check if matchstick.yaml and testsFolder not null
78
109
  if (config && config.testsFolder) {
@@ -88,7 +119,6 @@ export default {
88
119
  }
89
120
  }
90
121
 
91
- opts.cachePath = path.join(opts.testsFolder, '.latest.json')
92
122
  setVersionFromCache(opts)
93
123
 
94
124
  // Fetch the latest version tag if version is not specified with -v/--version or if the version is not cached
@@ -116,7 +146,7 @@ export default {
116
146
  },
117
147
  }
118
148
 
119
- async function setVersionFromCache(opts) {
149
+ async function setVersionFromCache(opts: TestOptions) {
120
150
  if (filesystem.exists(opts.cachePath) == 'file') {
121
151
  let cached = filesystem.read(opts.cachePath, 'json')
122
152
  // Get the cache age in days
@@ -128,7 +158,7 @@ async function setVersionFromCache(opts) {
128
158
  }
129
159
  }
130
160
 
131
- async function runBinary(datasource, opts) {
161
+ async function runBinary(datasource: string | undefined, opts: TestOptions) {
132
162
  let coverageOpt = opts.coverage
133
163
  let forceOpt = opts.force
134
164
  let logsOpt = opts.logs
@@ -138,9 +168,8 @@ async function runBinary(datasource, opts) {
138
168
 
139
169
  const platform = await getPlatform(logsOpt)
140
170
 
141
- const url = `https://github.com/LimeChain/matchstick/releases/download/${
142
- versionOpt || latestVersion
143
- }/${platform}`
171
+ const url = `https://github.com/LimeChain/matchstick/releases/download/${versionOpt ||
172
+ latestVersion}/${platform}`
144
173
 
145
174
  if (logsOpt) {
146
175
  print.info(`Download link: ${url}`)
@@ -156,7 +185,7 @@ async function runBinary(datasource, opts) {
156
185
  args.length > 0 ? binary.run(...args) : binary.run()
157
186
  }
158
187
 
159
- async function getPlatform(logsOpt) {
188
+ async function getPlatform(logsOpt: boolean | undefined) {
160
189
  const type = os.type()
161
190
  const arch = os.arch()
162
191
  const cpuCore = os.cpus()[0]
@@ -164,13 +193,12 @@ async function getPlatform(logsOpt) {
164
193
  const linuxInfo = type === 'Linux' ? await getLinuxInfo() : {}
165
194
  const linuxDistro = linuxInfo.name
166
195
  const release = linuxInfo.version || os.release()
167
- const majorVersion = parseInt(linuxInfo.version, 10) || semver.major(release)
196
+ const majorVersion = parseInt(linuxInfo.version || '', 10) || semver.major(release)
168
197
 
169
198
  if (logsOpt) {
170
199
  print.info(
171
- `OS type: ${
172
- linuxDistro || type
173
- }\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${
200
+ `OS type: ${linuxDistro ||
201
+ type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${
174
202
  cpuCore.model
175
203
  }`,
176
204
  )
@@ -199,7 +227,21 @@ async function getPlatform(logsOpt) {
199
227
  throw new Error(`Unsupported platform: ${type} ${arch} ${majorVersion}`)
200
228
  }
201
229
 
202
- async function getLinuxInfo() {
230
+ /**
231
+ * The result of running `cat /etc/*-release | grep -E '(^VERSION|^NAME)='`
232
+ *
233
+ * May look like this:
234
+ * ```sh
235
+ * NAME="Ubuntu"
236
+ * VERSION="16.04.7 LTS (Xenial Xerus)"
237
+ * ```
238
+ */
239
+ interface LinuxInfo {
240
+ name?: string
241
+ version?: string
242
+ }
243
+
244
+ async function getLinuxInfo(): Promise<LinuxInfo> {
203
245
  try {
204
246
  let result = await system.run("cat /etc/*-release | grep -E '(^VERSION|^NAME)='", {
205
247
  trim: true,
@@ -208,10 +250,10 @@ async function getLinuxInfo() {
208
250
  .replace(/['"]+/g, '')
209
251
  .split('\n')
210
252
  .map(p => p.split('='))
211
- let linuxInfo = {}
253
+ let linuxInfo: LinuxInfo = {}
212
254
 
213
255
  infoArray.forEach(val => {
214
- linuxInfo[val[0].toLowerCase()] = val[1]
256
+ linuxInfo[val[0].toLowerCase() as keyof LinuxInfo] = val[1]
215
257
  })
216
258
 
217
259
  return linuxInfo
@@ -221,7 +263,7 @@ async function getLinuxInfo() {
221
263
  }
222
264
  }
223
265
 
224
- async function runDocker(datasource, opts) {
266
+ async function runDocker(datasource: string | undefined, opts: TestOptions) {
225
267
  let coverageOpt = opts.coverage
226
268
  let forceOpt = opts.force
227
269
  let versionOpt = opts.version
@@ -230,10 +272,10 @@ async function runDocker(datasource, opts) {
230
272
 
231
273
  // Remove binary-install-raw binaries, because docker has permission issues
232
274
  // when building the docker images
233
- await filesystem.remove('./node_modules/binary-install-raw/bin')
275
+ filesystem.remove('./node_modules/binary-install-raw/bin')
234
276
 
235
277
  // Get current working directory
236
- let current_folder = await filesystem.cwd()
278
+ let current_folder = filesystem.cwd()
237
279
 
238
280
  // Declate dockerfilePath with default location
239
281
  let dockerfilePath = path.join(opts.testsFolder || 'tests', '.docker/Dockerfile')
@@ -248,7 +290,7 @@ async function runDocker(datasource, opts) {
248
290
  }
249
291
 
250
292
  // Run a command to check if matchstick image already exists
251
- exec('docker images -q matchstick', (error, stdout, stderr) => {
293
+ exec('docker images -q matchstick', (_error, stdout, _stderr) => {
252
294
  // Collect all(if any) flags and options that have to be passed to the matchstick binary
253
295
  let testArgs = ''
254
296
  if (coverageOpt) testArgs = testArgs + ' -c'
@@ -277,7 +319,7 @@ async function runDocker(datasource, opts) {
277
319
  // Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
278
320
  if (!dockerfileExists || stdout === '' || versionOpt || forceOpt) {
279
321
  if (stdout !== '') {
280
- exec('docker image rm matchstick', (error, stdout, stderr) => {
322
+ exec('docker image rm matchstick', (_error, stdout, _stderr) => {
281
323
  print.info(chalk.bold(`Removing matchstick image\n${stdout}`))
282
324
  })
283
325
  }
@@ -300,7 +342,11 @@ async function runDocker(datasource, opts) {
300
342
 
301
343
  // Downloads Dockerfile template from the demo-subgraph repo
302
344
  // Replaces the placeholders with their respective values
303
- async function dockerfile(dockerfilePath, versionOpt, latestVersion) {
345
+ async function dockerfile(
346
+ dockerfilePath: string,
347
+ versionOpt: string | undefined,
348
+ latestVersion: string | undefined,
349
+ ) {
304
350
  let spinner = print.spin('Generating Dockerfile...')
305
351
 
306
352
  try {
@@ -318,13 +364,13 @@ async function dockerfile(dockerfilePath, versionOpt, latestVersion) {
318
364
  })
319
365
 
320
366
  // Write the Dockerfile
321
- await filesystem.write(dockerfilePath, content)
367
+ filesystem.write(dockerfilePath, content)
322
368
 
323
369
  // Replaces the version placeholders
324
370
  await patching.replace(
325
371
  dockerfilePath,
326
372
  '<MATCHSTICK_VERSION>',
327
- versionOpt || latestVersion,
373
+ versionOpt || latestVersion || 'unknown',
328
374
  )
329
375
  } catch (error) {
330
376
  spinner.fail(
package/src/subgraph.ts CHANGED
@@ -275,7 +275,7 @@ More than one template named '${name}', template names must be unique.`,
275
275
  }
276
276
  }
277
277
 
278
- let manifest = immutable.fromJS(data)
278
+ let manifest = immutable.fromJS(data) as immutable.Map<any, any>
279
279
 
280
280
  // Validate the schema
281
281
  Subgraph.validateSchema(manifest, { resolveFile })
File without changes
File without changes
@@ -0,0 +1,6 @@
1
+ declare module 'spawn-command' {
2
+ import { spawn, SpawnOptions, ChildProcessByStdio, StdioPipe } from 'child_process'
3
+ type SpawnResult = ChildProcessByStdio<Writable, Readable, Readable>
4
+ export { SpawnOptions, SpawnResult }
5
+ export default function spawn(command: string, options: SpawnOptions): SpawnResult
6
+ }
@@ -6,20 +6,30 @@ import stripAnsi from 'strip-ansi'
6
6
  // Deletes folder if:
7
7
  // - flag is true
8
8
  // - folder exists
9
- const deleteDir = (dir, flag) => {
9
+ const deleteDir = (dir: string, flag: boolean) => {
10
10
  if (flag && fs.existsSync(dir)) {
11
11
  fs.removeSync(dir)
12
12
  }
13
13
  }
14
14
 
15
- const resolvePath = p => path.join(__dirname, p)
16
-
17
- const cliTest = (title, args, testPath, options = {}) => {
15
+ const resolvePath = (p: string) => path.join(__dirname, p)
16
+
17
+ export function cliTest(
18
+ title: string,
19
+ args: string[],
20
+ testPath: string,
21
+ options: {
22
+ cwd?: string
23
+ deleteDir?: boolean
24
+ exitCode?: number
25
+ timeout?: number
26
+ } = {},
27
+ ) {
18
28
  test(
19
29
  title,
20
30
  async () => {
21
31
  try {
22
- deleteDir(resolvePath(`./${testPath}`), options.deleteDir)
32
+ deleteDir(resolvePath(`./${testPath}`), !!options.deleteDir)
23
33
 
24
34
  // Use the provided cwd if desired
25
35
  let cwd = options.cwd ? options.cwd : resolvePath(`./${testPath}`)
@@ -62,14 +72,24 @@ const cliTest = (title, args, testPath, options = {}) => {
62
72
  expect(stripAnsi(stdout)).toBe(expectedStdout)
63
73
  }
64
74
  } finally {
65
- deleteDir(resolvePath(`./${testPath}`), options.deleteDir)
75
+ deleteDir(resolvePath(`./${testPath}`), !!options.deleteDir)
66
76
  }
67
77
  },
68
78
  options.timeout || undefined,
69
79
  )
70
80
  }
71
81
 
72
- const runCommand = async (command, args = [], cwd = process.cwd()) => {
82
+ function runCommand(
83
+ command: string,
84
+ args: string[] = [],
85
+ cwd = process.cwd(),
86
+ ): Promise<
87
+ [
88
+ number | null, // exitCode
89
+ string, // stdout
90
+ string, // stderr
91
+ ]
92
+ > {
73
93
  // Make sure to set an absolute working directory
74
94
  cwd = cwd[0] !== '/' ? path.resolve(__dirname, cwd) : cwd
75
95
 
@@ -82,11 +102,11 @@ const runCommand = async (command, args = [], cwd = process.cwd()) => {
82
102
  reject(error)
83
103
  })
84
104
 
85
- child.stdout.on('data', data => {
105
+ child.stdout.on('data', (data: Buffer) => {
86
106
  stdout += data.toString()
87
107
  })
88
108
 
89
- child.stderr.on('data', data => {
109
+ child.stderr.on('data', (data: Buffer) => {
90
110
  stderr += data.toString()
91
111
  })
92
112
 
@@ -96,15 +116,13 @@ const runCommand = async (command, args = [], cwd = process.cwd()) => {
96
116
  })
97
117
  }
98
118
 
99
- const runGraphCli = async (args, cwd) => {
119
+ export function runGraphCli(args: string[], cwd: string) {
100
120
  // Resolve the path to graph.js
101
121
  let graphCli = path.join(__dirname, '..', '..', 'dist', 'bin.js')
102
122
 
103
- return await runCommand(graphCli, args, cwd)
123
+ return runCommand(graphCli, args, cwd)
104
124
  }
105
125
 
106
- const npmLinkCli = () => runCommand('npm', ['link'])
107
-
108
- const npmUnlinkCli = () => runCommand('npm', ['unlink'])
126
+ export const npmLinkCli = () => runCommand('npm', ['link'])
109
127
 
110
- export { cliTest, npmLinkCli, npmUnlinkCli, runGraphCli }
128
+ export const npmUnlinkCli = () => runCommand('npm', ['unlink'])
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["./src"]
4
+ }
package/tsconfig.json CHANGED
@@ -14,5 +14,6 @@
14
14
  "skipLibCheck": true,
15
15
  "allowJs": true
16
16
  },
17
- "include": ["./src"]
17
+ "include": ["./src", "./tests"],
18
+ "exclude": ["./tests/cli/init", "./tests/cli/validation"]
18
19
  }