@graphprotocol/graph-cli 0.25.1 → 0.25.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.25.1",
3
+ "version": "0.25.2",
4
4
  "description": "CLI for building for and deploying to The Graph",
5
5
  "dependencies": {
6
6
  "assemblyscript": "0.19.10",
@@ -12,7 +12,7 @@
12
12
  "dockerode": "^2.5.8",
13
13
  "fs-extra": "^9.0.0",
14
14
  "glob": "^7.1.2",
15
- "gluegun": "^4.3.1",
15
+ "gluegun": "https://github.com/edgeandnode/gluegun#v4.3.1-pin-colors-dep",
16
16
  "graphql": "^15.5.0",
17
17
  "immutable": "^3.8.2",
18
18
  "ipfs-http-client": "^34.0.0",
@@ -0,0 +1,34 @@
1
+ const immutable = require('immutable')
2
+
3
+ // TODO: kill me
4
+ const EMPTY_ARRAY = 'new Array(0)'
5
+
6
+ const ASC_DEFAULTS = [
7
+ // Scalar values
8
+
9
+ ['Address', 'Address.zero()'],
10
+ ['Bytes', 'Bytes.empty()'],
11
+ ['boolean', 'false'],
12
+ ['i32', '0'],
13
+ ['string', '""'],
14
+ ['BigInt', 'BigInt.zero()'],
15
+ ['BigDecimal', 'BigDecimal.zero()'],
16
+
17
+ // Arrays
18
+
19
+ ['Array<Address>', EMPTY_ARRAY],
20
+ ['Array<Bytes>', EMPTY_ARRAY],
21
+ ['Array<boolean>', EMPTY_ARRAY],
22
+ ['Array<i32>', EMPTY_ARRAY],
23
+ ['Array<string>', EMPTY_ARRAY],
24
+ ['Array<BigInt>', EMPTY_ARRAY],
25
+ ['Array<BigDecimal>', EMPTY_ARRAY],
26
+ ['Array<string | null>', EMPTY_ARRAY],
27
+ ]
28
+
29
+ module.exports = immutable.fromJS({
30
+ AssemblyScript: ASC_DEFAULTS,
31
+ })
32
+ // TODO: use me:
33
+ // [/Array<.*>/, 'new Array(0)'],
34
+ // [/Array\<.*\>/, 'new Array(0)'],
@@ -279,6 +279,7 @@ const loadAbiFromBlockScout = async (ABI, network, address) =>
279
279
  const getEtherscanLikeAPIUrl = (network) => {
280
280
  switch(network){
281
281
  case "mainnet": return `https://api.etherscan.io/api`;
282
+ case "arbitrum-one": return `https://api.arbiscan.io/api`;
282
283
  case "bsc": return `https://api.bscscan.com/api`;
283
284
  case "matic": return `https://api.polygonscan.com/api`;
284
285
  case "mumbai": return `https://api-testnet.polygonscan.com/api`;
@@ -2,61 +2,125 @@ const { Binary } = require('binary-install-raw')
2
2
  const os = require('os')
3
3
  const chalk = require('chalk')
4
4
  const fetch = require('node-fetch')
5
+ const { filesystem, print } = require('gluegun')
6
+ const { fixParameters } = require('../command-helpers/gluegun')
5
7
  const semver = require('semver')
8
+ const { spawn, exec } = require('child_process')
9
+ const yaml = require('js-yaml')
6
10
 
7
11
  const HELP = `
8
12
  ${chalk.bold('graph test')} ${chalk.dim('[options]')} ${chalk.bold('<datasource>')}
9
13
 
10
14
  ${chalk.dim('Options:')}
11
-
12
- -f --force Overwrite folder + file when downloading
15
+ -c, --coverage Run the tests in coverage mode. Works with v0.2.1 and above
16
+ -d, --docker Run the tests in a docker container(Note: Please execute from the root folder of the subgraph)
17
+ -f --force Binary - overwrites folder + file when downloading. Docker - rebuilds the docker image
13
18
  -h, --help Show usage information
14
19
  -l, --logs Logs to the console information about the OS, CPU model and download url (debugging purposes)
20
+ -r, --recompile Force-recompile tests (Not available in 0.2.2 and earlier versions)
15
21
  -v, --version <tag> Choose the version of the rust binary that you want to be downloaded/used
16
22
  `
17
23
 
18
24
  module.exports = {
19
25
  description: 'Runs rust binary for subgraph testing',
20
26
  run: async toolbox => {
21
- // Obtain tools
22
- let { print } = toolbox
23
-
24
27
  // Read CLI parameters
25
- let { f, force, h, help, l, logs, v, version } = toolbox.parameters.options
26
- let datasource = toolbox.parameters.first
28
+ let {
29
+ c,
30
+ coverage,
31
+ d,
32
+ docker,
33
+ f,
34
+ force,
35
+ h,
36
+ help,
37
+ l,
38
+ logs,
39
+ r,
40
+ recompile,
41
+ v,
42
+ version,
43
+ } = toolbox.parameters.options
27
44
 
45
+ let opts = new Map()
28
46
  // Support both long and short option variants
29
- force = force || f
30
- help = help || h
31
- logs = logs || l
32
- version = version || v
47
+ opts.set("coverage", coverage || c)
48
+ opts.set("docker", docker || d)
49
+ opts.set("force", force || f)
50
+ opts.set("help", help || h)
51
+ opts.set("logs", logs || l)
52
+ opts.set("recompile", recompile || r)
53
+ opts.set("version", version || v)
54
+
55
+ // Fix if a boolean flag (e.g -c, --coverage) has an argument
56
+ try {
57
+ fixParameters(toolbox.parameters, {
58
+ h,
59
+ help,
60
+ c,
61
+ coverage,
62
+ d,
63
+ docker,
64
+ f,
65
+ force,
66
+ l,
67
+ logs,
68
+ r,
69
+ recompile
70
+ })
71
+ } catch (e) {
72
+ print.error(e.message)
73
+ process.exitCode = 1
74
+ return
75
+ }
76
+
77
+ let datasource = toolbox.parameters.first || toolbox.parameters.array[0]
33
78
 
34
79
  // Show help text if requested
35
- if (help) {
80
+ if (opts.get("help")) {
36
81
  print.info(HELP)
37
82
  return
38
83
  }
39
84
 
40
- const platform = getPlatform(logs)
41
- if (!version) {
42
- let result = await fetch('https://api.github.com/repos/LimeChain/matchstick/releases/latest')
43
- let json = await result.json()
44
- version = json.tag_name
85
+ let result = await fetch('https://api.github.com/repos/LimeChain/matchstick/releases/latest')
86
+ let json = await result.json()
87
+ opts.set("latestVersion", json.tag_name)
88
+
89
+ if(opts.get("docker")) {
90
+ runDocker(datasource, opts)
91
+ } else {
92
+ runBinary(datasource, opts)
45
93
  }
94
+ }
95
+ }
46
96
 
47
- const url = `https://github.com/LimeChain/matchstick/releases/download/${version}/${platform}`
97
+ async function runBinary(datasource, opts) {
98
+ let coverageOpt = opts.get("coverage")
99
+ let forceOpt = opts.get("force")
100
+ let logsOpt = opts.get("logs")
101
+ let versionOpt = opts.get("version")
102
+ let latestVersion = opts.get("latestVersion")
103
+ let recompileOpt = opts.get("recompile")
48
104
 
49
- if (logs) {
50
- console.log(`Download link: ${url}`)
51
- }
105
+ const platform = getPlatform(logsOpt)
52
106
 
53
- let binary = new Binary(platform, url, version)
54
- await binary.install(force)
55
- datasource ? binary.run(datasource) : binary.run()
107
+ const url = `https://github.com/LimeChain/matchstick/releases/download/${versionOpt || latestVersion}/${platform}`
108
+
109
+ if (logsOpt) {
110
+ print.info(`Download link: ${url}`)
56
111
  }
112
+
113
+ let binary = new Binary(platform, url, versionOpt || latestVersion)
114
+ forceOpt ? await binary.install(true) : await binary.install(false)
115
+ let args = new Array()
116
+
117
+ if (coverageOpt) args.push('-c')
118
+ if (recompileOpt) args.push('-r')
119
+ if (datasource) args.push(datasource)
120
+ args.length > 0 ? binary.run(...args) : binary.run()
57
121
  }
58
122
 
59
- function getPlatform(logs) {
123
+ function getPlatform(logsOpt) {
60
124
  const type = os.type()
61
125
  const arch = os.arch()
62
126
  const release = os.release()
@@ -64,8 +128,8 @@ function getPlatform(logs) {
64
128
  const majorVersion = semver.major(release)
65
129
  const isM1 = cpuCore.model.includes("Apple M1")
66
130
 
67
- if (logs) {
68
- console.log(`OS type: ${type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
131
+ if (logsOpt) {
132
+ print.info(`OS type: ${type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
69
133
  }
70
134
 
71
135
  if (arch === 'x64' || (arch === 'arm64' && isM1)) {
@@ -90,3 +154,122 @@ function getPlatform(logs) {
90
154
 
91
155
  throw new Error(`Unsupported platform: ${type} ${arch} ${majorVersion}`)
92
156
  }
157
+
158
+ async function runDocker(datasource, opts) {
159
+ let coverageOpt = opts.get("coverage")
160
+ let forceOpt = opts.get("force")
161
+ let versionOpt = opts.get("version")
162
+ let latestVersion = opts.get("latestVersion")
163
+ let recompileOpt = opts.get("recompile")
164
+
165
+ // Remove binary-install-raw binaries, because docker has permission issues
166
+ // when building the docker images
167
+ await filesystem.remove("./node_modules/binary-install-raw/bin")
168
+
169
+ // Get current working directory
170
+ let current_folder = await filesystem.cwd()
171
+
172
+ // Build the Dockerfile location. Defaults to ./tests/.docker if
173
+ // a custom testsFolder is not declared in the subgraph.yaml
174
+ let dockerDir = ""
175
+
176
+ try {
177
+ let doc = await yaml.load(filesystem.read('subgraph.yaml', 'utf8'))
178
+ testsFolder = doc.testsFolder || './tests'
179
+ dockerDir = testsFolder.endsWith('/') ? testsFolder + '.docker' : testsFolder + '/.docker'
180
+ } catch (error) {
181
+ print.error(error.message)
182
+ return
183
+ }
184
+
185
+ // Create the Dockerfile
186
+ try {
187
+ await filesystem.write(`${dockerDir}/Dockerfile`, dockerfile(versionOpt, latestVersion))
188
+ print.info('Successfully generated Dockerfile.')
189
+ } catch (error) {
190
+ print.info('A problem occurred while generating the Dockerfile. Please attend to the errors below:')
191
+ print.error(error.message)
192
+ return
193
+ }
194
+
195
+ // Run a command to check if matchstick image already exists
196
+ exec('docker images -q matchstick', (error, stdout, stderr) => {
197
+ // Collect all(if any) flags and options that have to be passed to the matchstick binary
198
+ let testArgs = ''
199
+ if (coverageOpt) testArgs = testArgs + ' -c'
200
+ if (recompileOpt) testArgs = testArgs + ' -r'
201
+ if (datasource) testArgs = testArgs + ' ' + datasource
202
+
203
+ // Build the `docker run` command options and flags
204
+ let dockerRunOpts = ['run', '-it', '--rm', '--mount', `type=bind,source=${current_folder},target=/matchstick`]
205
+
206
+ if(testArgs !== '') {
207
+ dockerRunOpts.push('-e')
208
+ dockerRunOpts.push(`ARGS=${testArgs.trim()}`)
209
+ }
210
+
211
+ dockerRunOpts.push('matchstick')
212
+
213
+ // If a matchstick image does not exists, the command returns an empty string,
214
+ // else it'll return the image ID. Skip `docker build` if an image already exists
215
+ // If `-v/--version` is specified, delete current image(if any) and rebuild.
216
+ // Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
217
+ if(stdout === '' || versionOpt || forceOpt) {
218
+ if ((stdout !== '' && versionOpt) || forceOpt) {
219
+ exec('docker image rm matchstick', (error, stdout, stderr) => {
220
+ print.info(chalk.bold(`Removing matchstick image\n${stdout}`))
221
+ })
222
+ }
223
+ // Build a docker image. If the process has executed successfully
224
+ // run a container from that image.
225
+ spawn(
226
+ 'docker',
227
+ ['build', '--no-cache', '-f', `${dockerDir}/Dockerfile`, '-t', 'matchstick', '.'],
228
+ { stdio: 'inherit' }
229
+ ).on('close', code => {
230
+ if (code === 0) {
231
+ spawn('docker', dockerRunOpts, { stdio: 'inherit' })
232
+ }
233
+ })
234
+ } else {
235
+ print.info("Docker image already exists. Skipping `docker build` command.")
236
+ // Run the container from the existing matchstick docker image
237
+ spawn('docker', dockerRunOpts, { stdio: 'inherit' })
238
+ }
239
+ })
240
+ }
241
+
242
+ // TODO: Move these in separate file (in a function maybe)
243
+ function dockerfile(versionOpt, latestVersion) {
244
+ return `
245
+ FROM ubuntu:20.04
246
+ ENV ARGS=""
247
+
248
+ # Install necessary packages
249
+ RUN apt update
250
+ RUN apt install -y nodejs
251
+ RUN apt install -y npm
252
+ RUN apt install -y git
253
+ RUN apt install -y postgresql
254
+ RUN apt install -y curl
255
+ RUN apt install -y cmake
256
+ RUN npm install -g @graphprotocol/graph-cli
257
+
258
+ # Download the latest linux binary
259
+ RUN curl -OL https://github.com/LimeChain/matchstick/releases/download/${versionOpt || latestVersion}/binary-linux-20
260
+
261
+ # Make it executable
262
+ RUN chmod a+x binary-linux-20
263
+
264
+ # Create a matchstick dir where the host will be copied
265
+ RUN mkdir matchstick
266
+ WORKDIR matchstick
267
+
268
+ # Copy host to /matchstick
269
+ COPY ../ .
270
+
271
+ RUN graph codegen
272
+ RUN graph build
273
+
274
+ CMD ../binary-linux-20 \${ARGS}`
275
+ }
@@ -57,16 +57,20 @@ module.exports = class Protocol {
57
57
  'arbitrum-rinkeby',
58
58
  'optimism',
59
59
  'optimism-kovan',
60
+ 'aurora',
61
+ 'aurora-testnet',
60
62
  ],
61
63
  near: [
62
64
  'near-mainnet',
65
+ 'near-testnet'
63
66
  ],
64
67
  })
65
68
  }
66
69
 
67
70
  normalizeName(name) {
68
- return Protocol.availableProtocols()
69
- .findKey(possibleNames => possibleNames.includes(name))
71
+ return Protocol.availableProtocols().findKey(possibleNames =>
72
+ possibleNames.includes(name),
73
+ )
70
74
  }
71
75
 
72
76
  displayName() {
@@ -142,9 +146,7 @@ module.exports = class Protocol {
142
146
  case 'near':
143
147
  return new NearSubgraph(optionsWithProtocol)
144
148
  default:
145
- throw new Error(
146
- `Data sources with kind '${this.name}' are not supported yet`,
147
- )
149
+ throw new Error(`Data sources with kind '${this.name}' are not supported yet`)
148
150
  }
149
151
  }
150
152