@graphprotocol/graph-cli 0.25.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/chain/ethereum.ts +1 -1
  2. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/package.json +1 -1
  3. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/index.js +50 -0
  4. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/license +21 -0
  5. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/package.json +49 -0
  6. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/readme.md +36 -0
  7. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/index.js +10 -0
  8. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/license +9 -0
  9. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/package.json +53 -0
  10. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/readme.md +46 -0
  11. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/index.js +4 -0
  12. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/license +9 -0
  13. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/package.json +52 -0
  14. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/readme.md +39 -0
  15. package/examples/basic-event-handlers/node_modules/keccak/build/Makefile +342 -0
  16. package/examples/basic-event-handlers/node_modules/keccak/build/Release/.deps/Release/obj.target/keccak/src/addon.o.d.raw +27 -0
  17. package/examples/basic-event-handlers/node_modules/keccak/build/binding.Makefile +6 -0
  18. package/examples/basic-event-handlers/node_modules/keccak/build/config.gypi +207 -0
  19. package/examples/basic-event-handlers/node_modules/keccak/build/gyp-mac-tool +615 -0
  20. package/examples/basic-event-handlers/node_modules/keccak/build/keccak.target.mk +209 -0
  21. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.coveralls.yml +1 -0
  22. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.eslintrc +14 -0
  23. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.travis.yml +20 -0
  24. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/CHANGELOG.md +395 -0
  25. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/LICENSE +19 -0
  26. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/Makefile +58 -0
  27. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/README.md +368 -0
  28. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/karma.conf.js +70 -0
  29. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/node.js +1 -0
  30. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/package.json +43 -0
  31. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/browser.js +195 -0
  32. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/debug.js +225 -0
  33. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/index.js +10 -0
  34. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/node.js +186 -0
  35. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/LICENSE +15 -0
  36. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/README.md +368 -0
  37. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/changelog.md +67 -0
  38. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/common.js +240 -0
  39. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/glob.js +790 -0
  40. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/package.json +43 -0
  41. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/sync.js +486 -0
  42. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/index.js +10 -0
  43. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/license +9 -0
  44. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/package.json +53 -0
  45. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/readme.md +46 -0
  46. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/index.js +4 -0
  47. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/license +9 -0
  48. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/package.json +52 -0
  49. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/readme.md +39 -0
  50. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/index.js +46 -0
  51. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/license +21 -0
  52. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/package.json +45 -0
  53. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/readme.md +39 -0
  54. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/index.js +37 -0
  55. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/license +21 -0
  56. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/package.json +56 -0
  57. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/readme.md +42 -0
  58. package/examples/basic-event-handlers/package.json +4 -4
  59. package/examples/basic-event-handlers/yarn.lock +8 -8
  60. package/package.json +27 -24
  61. package/src/codegen/schema.js +12 -9
  62. package/src/codegen/schema.test.js +368 -0
  63. package/src/codegen/typescript.js +7 -11
  64. package/src/commands/deploy.js +3 -1
  65. package/src/commands/init.js +2 -0
  66. package/src/commands/test.js +82 -59
  67. package/src/protocols/ethereum/codegen/abi.js +72 -2
  68. package/src/protocols/ethereum/manifest.graphql +92 -0
  69. package/src/protocols/index.js +17 -7
  70. package/src/protocols/near/manifest.graphql +57 -0
  71. package/src/subgraph.js +18 -13
  72. package/src/validation/manifest.js +12 -8
  73. package/tests/cli/validation/example-values-found.stderr +2 -2
  74. package/tests/cli/validation/invalid-manifest/subgraph.yaml +2 -1
  75. package/tests/cli/validation/invalid-manifest-cannot-infer-protocol/subgraph.yaml +12 -0
  76. package/tests/cli/validation/invalid-manifest-cannot-infer-protocol.stderr +5 -0
  77. package/tests/cli/validation/invalid-manifest.stderr +0 -3
  78. package/tests/cli/validation.test.js +8 -0
  79. package/examples/basic-event-handlers/node_modules/mocha/lib/reporters/base.js.orig +0 -498
  80. package/examples/basic-event-handlers/node_modules/node-fetch/lib/index.js +0 -1416
  81. package/manifest-schema.graphql +0 -122
@@ -0,0 +1,368 @@
1
+ const prettier = require('prettier')
2
+ const graphql = require('graphql/language')
3
+ const immutable = require('immutable')
4
+ const SchemaCodeGenerator = require('./schema')
5
+ const {
6
+ Class,
7
+ Method,
8
+ StaticMethod,
9
+ Param,
10
+ NamedType,
11
+ NullableType,
12
+ ArrayType,
13
+ } = require('./typescript')
14
+
15
+ const formatTS = code =>
16
+ prettier.format(
17
+ code,
18
+ { parser: 'typescript', semi: false }
19
+ )
20
+
21
+ const createSchemaCodeGen = schema =>
22
+ new SchemaCodeGenerator({
23
+ ast: immutable.fromJS(graphql.parse(schema)),
24
+ })
25
+
26
+ const testEntity = (generatedTypes, expectedEntity) => {
27
+ const entity = generatedTypes.find(type => type.name === expectedEntity.name)
28
+
29
+ expect(entity instanceof Class).toBe(true)
30
+ expect(entity.extends).toBe('Entity')
31
+ expect(entity.export).toBe(true)
32
+
33
+ const { members, methods } = entity
34
+
35
+ expect(members).toStrictEqual(expectedEntity.members)
36
+
37
+ for (const expectedMethod of expectedEntity.methods) {
38
+ const method = methods.find(method => method.name === expectedMethod.name)
39
+
40
+ expectedMethod.static
41
+ ? expect(method instanceof StaticMethod).toBe(true)
42
+ : expect(method instanceof Method).toBe(true)
43
+
44
+ expect(method.params).toStrictEqual(expectedMethod.params)
45
+ expect(method.returnType).toStrictEqual(expectedMethod.returnType)
46
+ expect(formatTS(method.body)).toBe(formatTS(expectedMethod.body))
47
+ }
48
+
49
+ expect(methods.length).toBe(expectedEntity.methods.length)
50
+ }
51
+
52
+ describe('Schema code generator', () => {
53
+ test('Should generate nothing for non entity types', () => {
54
+ const codegen = createSchemaCodeGen(`
55
+ type Foo {
56
+ foobar: Int
57
+ }
58
+
59
+ type Bar {
60
+ barfoo: Int
61
+ }
62
+ `)
63
+
64
+ expect(codegen.generateTypes().size).toBe(0)
65
+ })
66
+
67
+ describe('Should generate correct classes for each entity', () => {
68
+ const codegen = createSchemaCodeGen(`
69
+ # just to be sure nothing will be generated from non-entity types alongside regular ones
70
+ type Foo {
71
+ foobar: Int
72
+ }
73
+
74
+ type Account @entity {
75
+ id: ID!
76
+
77
+ # two non primitive types
78
+ description: String
79
+ name: String!
80
+
81
+ # two primitive types (i32)
82
+ age: Int
83
+ count: Int!
84
+
85
+ # derivedFrom
86
+ wallets: [Wallet!] @derivedFrom(field: "account")
87
+ }
88
+
89
+ type Wallet @entity {
90
+ id: ID!
91
+ amount: BigInt!
92
+ account: Account!
93
+ }
94
+ `)
95
+
96
+ const generatedTypes = codegen.generateTypes()
97
+
98
+ test('Foo is NOT an entity', () => {
99
+ const foo = generatedTypes.find(type => type.name === 'Foo')
100
+ expect(foo).toBe(undefined)
101
+ // Account and Wallet
102
+ expect(generatedTypes.size).toBe(2)
103
+ })
104
+
105
+ test('Account is an entity with the correct methods', () => {
106
+ testEntity(generatedTypes, {
107
+ name: 'Account',
108
+ members: [],
109
+ methods: [
110
+ {
111
+ name: 'constructor',
112
+ params: [new Param('id', new NamedType('string'))],
113
+ returnType: undefined,
114
+ body: `
115
+ super()
116
+ this.set('id', Value.fromString(id))
117
+
118
+ this.set('name', Value.fromString(''))
119
+ this.set('count', Value.fromI32(0))
120
+ `,
121
+ },
122
+ {
123
+ name: 'save',
124
+ params: [],
125
+ returnType: new NamedType('void'),
126
+ body: `
127
+ let id = this.get('id')
128
+ assert(id != null, 'Cannot save Account entity without an ID')
129
+ if (id) {
130
+ assert(
131
+ id.kind == ValueKind.STRING,
132
+ 'Cannot save Account entity with non-string ID. ' +
133
+ 'Considering using .toHex() to convert the "id" to a string.'
134
+ )
135
+ store.set('Account', id.toString(), this)
136
+ }
137
+ `,
138
+ },
139
+ {
140
+ name: 'load',
141
+ static: true,
142
+ params: [new Param('id', new NamedType('string'))],
143
+ returnType: new NullableType(new NamedType('Account')),
144
+ body: `
145
+ return changetype<Account | null>(store.get('Account', id))
146
+ `,
147
+ },
148
+ {
149
+ name: 'get id',
150
+ params: [],
151
+ returnType: new NamedType('string'),
152
+ body: `
153
+ let value = this.get('id')
154
+ return value!.toString()
155
+ `,
156
+ },
157
+ {
158
+ name: 'set id',
159
+ params: [new Param('value', new NamedType('string'))],
160
+ returnType: undefined,
161
+ body: `
162
+ this.set('id', Value.fromString(value))
163
+ `,
164
+ },
165
+ {
166
+ name: 'get description',
167
+ params: [],
168
+ returnType: new NullableType(new NamedType('string')),
169
+ body: `
170
+ let value = this.get('description')
171
+ if (!value || value.kind == ValueKind.NULL) {
172
+ return null
173
+ } else {
174
+ return value.toString()
175
+ }
176
+ `,
177
+ },
178
+ {
179
+ name: 'set description',
180
+ params: [new Param('value', new NullableType(new NamedType('string')))],
181
+ returnType: undefined,
182
+ body: `
183
+ if (!value) {
184
+ this.unset('description')
185
+ } else {
186
+ this.set('description', Value.fromString(<string>value))
187
+ }
188
+ `,
189
+ },
190
+ {
191
+ name: 'get name',
192
+ params: [],
193
+ returnType: new NamedType('string'),
194
+ body: `
195
+ let value = this.get('name')
196
+ return value!.toString()
197
+ `,
198
+ },
199
+ {
200
+ name: 'set name',
201
+ params: [new Param('value', new NamedType('string'))],
202
+ returnType: undefined,
203
+ body: `
204
+ this.set('name', Value.fromString(value))
205
+ `,
206
+ },
207
+ {
208
+ name: 'get age',
209
+ params: [],
210
+ returnType: new NamedType('i32'),
211
+ body: `
212
+ let value = this.get('age')
213
+ return value!.toI32()
214
+ `,
215
+ },
216
+ {
217
+ name: 'set age',
218
+ params: [new Param('value', new NamedType('i32'))],
219
+ returnType: undefined,
220
+ body: `
221
+ this.set('age', Value.fromI32(value))
222
+ `,
223
+ },
224
+ {
225
+ name: 'get count',
226
+ params: [],
227
+ returnType: new NamedType('i32'),
228
+ body: `
229
+ let value = this.get('count')
230
+ return value!.toI32()
231
+ `,
232
+ },
233
+ {
234
+ name: 'set count',
235
+ params: [new Param('value', new NamedType('i32'))],
236
+ returnType: undefined,
237
+ body: `
238
+ this.set('count', Value.fromI32(value))
239
+ `,
240
+ },
241
+ {
242
+ name: 'get wallets',
243
+ params: [],
244
+ returnType: new NullableType(new ArrayType(new NamedType('string'))),
245
+ body: `
246
+ let value = this.get('wallets')
247
+ if (!value || value.kind == ValueKind.NULL) {
248
+ return null
249
+ } else {
250
+ return value.toStringArray()
251
+ }
252
+ `,
253
+ },
254
+ {
255
+ name: 'set wallets',
256
+ params: [new Param('value', new NullableType(new ArrayType(new NamedType('string'))))],
257
+ returnType: undefined,
258
+ body: `
259
+ if (!value) {
260
+ this.unset('wallets')
261
+ } else {
262
+ this.set('wallets', Value.fromStringArray(<Array<string>>value))
263
+ }
264
+ `,
265
+ },
266
+ ],
267
+ })
268
+ })
269
+
270
+ test('Wallet is an entity with the correct methods', () => {
271
+ testEntity(generatedTypes, {
272
+ name: 'Wallet',
273
+ members: [],
274
+ methods: [
275
+ {
276
+ name: 'constructor',
277
+ params: [new Param('id', new NamedType('string'))],
278
+ returnType: undefined,
279
+ body: `
280
+ super()
281
+ this.set('id', Value.fromString(id))
282
+
283
+ this.set('amount', Value.fromBigInt(BigInt.zero()))
284
+ this.set('account', Value.fromString(''))
285
+ `,
286
+ },
287
+ {
288
+ name: 'save',
289
+ params: [],
290
+ returnType: new NamedType('void'),
291
+ body: `
292
+ let id = this.get('id')
293
+ assert(id != null, 'Cannot save Wallet entity without an ID')
294
+ if (id) {
295
+ assert(
296
+ id.kind == ValueKind.STRING,
297
+ 'Cannot save Wallet entity with non-string ID. ' +
298
+ 'Considering using .toHex() to convert the "id" to a string.'
299
+ )
300
+ store.set('Wallet', id.toString(), this)
301
+ }
302
+ `,
303
+ },
304
+ {
305
+ name: 'load',
306
+ static: true,
307
+ params: [new Param('id', new NamedType('string'))],
308
+ returnType: new NullableType(new NamedType('Wallet')),
309
+ body: `
310
+ return changetype<Wallet | null>(store.get('Wallet', id))
311
+ `,
312
+ },
313
+ {
314
+ name: 'get id',
315
+ params: [],
316
+ returnType: new NamedType('string'),
317
+ body: `
318
+ let value = this.get('id')
319
+ return value!.toString()
320
+ `,
321
+ },
322
+ {
323
+ name: 'set id',
324
+ params: [new Param('value', new NamedType('string'))],
325
+ returnType: undefined,
326
+ body: `
327
+ this.set('id', Value.fromString(value))
328
+ `,
329
+ },
330
+ {
331
+ name: 'get amount',
332
+ params: [],
333
+ returnType: new NamedType('BigInt'),
334
+ body: `
335
+ let value = this.get('amount')
336
+ return value!.toBigInt()
337
+ `,
338
+ },
339
+ {
340
+ name: 'set amount',
341
+ params: [new Param('value', new NamedType('BigInt'))],
342
+ returnType: undefined,
343
+ body: `
344
+ this.set('amount', Value.fromBigInt(value))
345
+ `,
346
+ },
347
+ {
348
+ name: 'get account',
349
+ params: [],
350
+ returnType: new NamedType('string'),
351
+ body: `
352
+ let value = this.get('account')
353
+ return value!.toString()
354
+ `,
355
+ },
356
+ {
357
+ name: 'set account',
358
+ params: [new Param('value', new NamedType('string'))],
359
+ returnType: undefined,
360
+ body: `
361
+ this.set('account', Value.fromString(value))
362
+ `,
363
+ },
364
+ ],
365
+ })
366
+ })
367
+ })
368
+ })
@@ -12,17 +12,6 @@ class Param {
12
12
  }
13
13
  }
14
14
 
15
- class ReturnType {
16
- constructor(name, type) {
17
- this.name = name
18
- this.type = type
19
- }
20
-
21
- toString() {
22
- return `${this.type.toString()}`
23
- }
24
- }
25
-
26
15
  class Method {
27
16
  constructor(name, params, returnType, body) {
28
17
  this.name = name
@@ -185,8 +174,15 @@ const GENERATED_FILE_NOTE = `
185
174
 
186
175
  module.exports = {
187
176
  // Types
177
+ Param,
178
+ Method,
179
+ StaticMethod,
180
+ Class,
181
+ ClassMember,
182
+ NamedType,
188
183
  NullableType,
189
184
  ArrayType,
185
+ ModuleImports,
190
186
 
191
187
  // Code generators
192
188
  namedType,
@@ -30,6 +30,7 @@ Options:
30
30
  -l --version-label <label> Version label used for the deployment
31
31
  -h, --help Show usage information
32
32
  -i, --ipfs <node> Upload build results to an IPFS node (default: ${DEFAULT_IPFS_URL})
33
+ --debug-fork ID of a remote subgraph whose store will be GraphQL queried
33
34
  -o, --output-dir <path> Output directory for build results (default: build/)
34
35
  --skip-migrations Skip subgraph migrations (default: false)
35
36
  -w, --watch Regenerate types when subgraph files change (default: false)
@@ -96,6 +97,7 @@ module.exports = {
96
97
  skipMigrations,
97
98
  w,
98
99
  watch,
100
+ debugFork,
99
101
  } = toolbox.parameters.options
100
102
 
101
103
  // Support both long and short option variants
@@ -264,7 +266,7 @@ module.exports = {
264
266
  // `Failed to deploy to Graph node ${requestUrl}`,
265
267
  client.request(
266
268
  'subgraph_deploy',
267
- { name: subgraphName, ipfs_hash: ipfsHash, version_label: versionLabel },
269
+ { name: subgraphName, ipfs_hash: ipfsHash, version_label: versionLabel, debug_fork: debugFork },
268
270
  async (requestError, jsonRpcError, res) => {
269
271
  if (jsonRpcError) {
270
272
  spinner.fail(
@@ -283,6 +283,8 @@ const getEtherscanLikeAPIUrl = (network) => {
283
283
  case "bsc": return `https://api.bscscan.com/api`;
284
284
  case "matic": return `https://api.polygonscan.com/api`;
285
285
  case "mumbai": return `https://api-testnet.polygonscan.com/api`;
286
+ case "aurora": return `https://api.aurorascan.dev/api`;
287
+ case "aurora-testnet": return `https://api-testnet.aurorascan.dev/api`;
286
288
  default: return `https://api-${network}.etherscan.io/api`;
287
289
  }
288
290
  }
@@ -2,8 +2,9 @@ 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')
5
+ const { filesystem, patching, print, system } = require('gluegun')
6
6
  const { fixParameters } = require('../command-helpers/gluegun')
7
+ const path = require('path')
7
8
  const semver = require('semver')
8
9
  const { spawn, exec } = require('child_process')
9
10
  const yaml = require('js-yaml')
@@ -102,7 +103,7 @@ async function runBinary(datasource, opts) {
102
103
  let latestVersion = opts.get("latestVersion")
103
104
  let recompileOpt = opts.get("recompile")
104
105
 
105
- const platform = getPlatform(logsOpt)
106
+ const platform = await getPlatform(logsOpt)
106
107
 
107
108
  const url = `https://github.com/LimeChain/matchstick/releases/download/${versionOpt || latestVersion}/${platform}`
108
109
 
@@ -120,19 +121,21 @@ async function runBinary(datasource, opts) {
120
121
  args.length > 0 ? binary.run(...args) : binary.run()
121
122
  }
122
123
 
123
- function getPlatform(logsOpt) {
124
+ async function getPlatform(logsOpt) {
124
125
  const type = os.type()
125
126
  const arch = os.arch()
126
- const release = os.release()
127
127
  const cpuCore = os.cpus()[0]
128
- const majorVersion = semver.major(release)
129
- const isM1 = cpuCore.model.includes("Apple M1")
128
+ const isM1 = (arch === 'arm64' && /Apple (M1|processor)/.test(cpuCore.model))
129
+ const linuxInfo = type === 'Linux' ? await getLinuxInfo() : new Map()
130
+ const linuxDistro = linuxInfo.get('name')
131
+ const release = linuxInfo.get('version') || os.release()
132
+ const majorVersion = parseInt(linuxInfo.get('version'), 10) || semver.major(release)
130
133
 
131
134
  if (logsOpt) {
132
- print.info(`OS type: ${type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
135
+ print.info(`OS type: ${linuxDistro || type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
133
136
  }
134
137
 
135
- if (arch === 'x64' || (arch === 'arm64' && isM1)) {
138
+ if (arch === 'x64' || isM1) {
136
139
  if (type === 'Darwin') {
137
140
  if (majorVersion === 19) {
138
141
  return 'binary-macos-10.15'
@@ -145,8 +148,9 @@ function getPlatform(logsOpt) {
145
148
  } else if (type === 'Linux') {
146
149
  if (majorVersion === 18) {
147
150
  return 'binary-linux-18'
151
+ } else {
152
+ return 'binary-linux-20'
148
153
  }
149
- return 'binary-linux-20'
150
154
  } else if (type === 'Windows_NT') {
151
155
  return 'binary-windows'
152
156
  }
@@ -155,6 +159,23 @@ function getPlatform(logsOpt) {
155
159
  throw new Error(`Unsupported platform: ${type} ${arch} ${majorVersion}`)
156
160
  }
157
161
 
162
+ async function getLinuxInfo() {
163
+ try {
164
+ let result = await system.run("cat /etc/*-release | grep -E '(^VERSION|^NAME)='", {trim: true})
165
+ let infoArray = result.replace(/['"]+/g, '').split('\n').map(p => p.split('='))
166
+ let infoMap = new Map();
167
+
168
+ infoArray.forEach((val) => {
169
+ infoMap.set(val[0].toLowerCase(), val[1])
170
+ });
171
+
172
+ return infoMap
173
+ } catch (error) {
174
+ print.error(`Error fetching the Linux version:\n ${error}`)
175
+ process.exit(1)
176
+ }
177
+ }
178
+
158
179
  async function runDocker(datasource, opts) {
159
180
  let coverageOpt = opts.get("coverage")
160
181
  let forceOpt = opts.get("force")
@@ -169,27 +190,34 @@ async function runDocker(datasource, opts) {
169
190
  // Get current working directory
170
191
  let current_folder = await filesystem.cwd()
171
192
 
172
- // Build the Dockerfile location. Defaults to ./tests/.docker if
173
- // a custom testsFolder is not declared in the subgraph.yaml
174
- let dockerDir = ""
193
+ // Declate dockerfilePath with default location
194
+ let dockerfilePath = "./tests/.docker/Dockerfile"
175
195
 
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
196
+ // Check if matchstick.yaml config exists
197
+ if(filesystem.exists('matchstick.yaml')) {
198
+ try {
199
+ // Load the config
200
+ let config = await yaml.load(filesystem.read('matchstick.yaml', 'utf8'))
201
+
202
+ // Check if matchstick.yaml is not empty
203
+ if(config != null) {
204
+ // If a custom tests folder is declared update dockerfilePath
205
+ dockerfilePath = path.join(config.testsFolder || 'tests', '.docker/Dockerfile')
206
+ }
207
+ } catch (error) {
208
+ print.info('A problem occurred while reading matchstick.yaml. Please attend to the errors below:')
209
+ print.error(error.message)
210
+ process.exit(1)
211
+ }
183
212
  }
184
213
 
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
214
+ // Check if the Dockerfil already exists
215
+ let dockerfileExists = filesystem.exists(dockerfilePath)
216
+
217
+ // Generate the Dockerfile only if it doesn't exists,
218
+ // version flag and/or force flag is passed.
219
+ if(!dockerfileExists || versionOpt || forceOpt) {
220
+ await dockerfile(dockerfilePath, versionOpt, latestVersion)
193
221
  }
194
222
 
195
223
  // Run a command to check if matchstick image already exists
@@ -212,10 +240,10 @@ async function runDocker(datasource, opts) {
212
240
 
213
241
  // If a matchstick image does not exists, the command returns an empty string,
214
242
  // 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.
243
+ // Delete current image(if any) and rebuild.
216
244
  // Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
217
- if(stdout === '' || versionOpt || forceOpt) {
218
- if ((stdout !== '' && versionOpt) || forceOpt) {
245
+ if(!dockerfileExists || stdout === '' || versionOpt || forceOpt) {
246
+ if (stdout !== '') {
219
247
  exec('docker image rm matchstick', (error, stdout, stderr) => {
220
248
  print.info(chalk.bold(`Removing matchstick image\n${stdout}`))
221
249
  })
@@ -224,7 +252,7 @@ async function runDocker(datasource, opts) {
224
252
  // run a container from that image.
225
253
  spawn(
226
254
  'docker',
227
- ['build', '--no-cache', '-f', `${dockerDir}/Dockerfile`, '-t', 'matchstick', '.'],
255
+ ['build', '-f', dockerfilePath, '-t', 'matchstick', '.'],
228
256
  { stdio: 'inherit' }
229
257
  ).on('close', code => {
230
258
  if (code === 0) {
@@ -239,37 +267,32 @@ async function runDocker(datasource, opts) {
239
267
  })
240
268
  }
241
269
 
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
270
+ // Downloads Dockerfile template from the demo-subgraph repo
271
+ // Replaces the placeholders with their respective values
272
+ async function dockerfile(dockerfilePath, versionOpt, latestVersion) {
273
+ let spinner = print.spin("Generating Dockerfile...")
257
274
 
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
275
+ try {
276
+ // Fetch the Dockerfile template content from the demo-subgraph repo
277
+ let content = await fetch('https://raw.githubusercontent.com/LimeChain/demo-subgraph/main/Dockerfile')
278
+ .then((response) => {
279
+ if (response.ok) {
280
+ return response.text()
281
+ } else {
282
+ throw new Error(`Status Code: ${response.status}, with error: ${response.statusText}`);
283
+ }
284
+ })
263
285
 
264
- # Create a matchstick dir where the host will be copied
265
- RUN mkdir matchstick
266
- WORKDIR matchstick
286
+ // Write the Dockerfile
287
+ await filesystem.write(dockerfilePath, content)
267
288
 
268
- # Copy host to /matchstick
269
- COPY ../ .
289
+ // Replaces the version placeholders
290
+ await patching.replace(dockerfilePath, '<MATCHSTICK_VERSION>', versionOpt || latestVersion)
270
291
 
271
- RUN graph codegen
272
- RUN graph build
292
+ } catch (error) {
293
+ spinner.fail(`A problem occurred while generating the Dockerfile. Please attend to the errors below:\n ${error.message}`)
294
+ process.exit(1)
295
+ }
273
296
 
274
- CMD ../binary-linux-20 \${ARGS}`
297
+ spinner.succeed('Successfully generated Dockerfile.')
275
298
  }