@graphprotocol/graph-cli 0.37.4 → 0.37.5

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 (100) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/bin.js +6 -0
  3. package/dist/cli.js +26 -0
  4. package/dist/codegen/schema.js +244 -0
  5. package/dist/codegen/schema.test.js +455 -0
  6. package/dist/codegen/template.js +66 -0
  7. package/dist/codegen/types/conversions.js +335 -0
  8. package/dist/codegen/types/index.js +71 -0
  9. package/dist/codegen/types/index.test.js +563 -0
  10. package/dist/codegen/typescript.js +200 -0
  11. package/dist/codegen/util.js +40 -0
  12. package/dist/codegen/util.test.js +93 -0
  13. package/dist/command-helpers/abi.js +76 -0
  14. package/dist/command-helpers/auth.js +76 -0
  15. package/dist/command-helpers/compiler.js +66 -0
  16. package/dist/command-helpers/data-sources.js +29 -0
  17. package/dist/command-helpers/fs.js +9 -0
  18. package/dist/command-helpers/gluegun.js +48 -0
  19. package/dist/command-helpers/ipfs.js +5 -0
  20. package/dist/command-helpers/jsonrpc.js +27 -0
  21. package/dist/command-helpers/network.js +90 -0
  22. package/dist/command-helpers/network.test.js +86 -0
  23. package/dist/command-helpers/node.js +40 -0
  24. package/dist/command-helpers/scaffold.js +110 -0
  25. package/dist/command-helpers/spinner.js +80 -0
  26. package/dist/command-helpers/studio.js +14 -0
  27. package/dist/command-helpers/studio.test.js +41 -0
  28. package/dist/command-helpers/subgraph.js +22 -0
  29. package/dist/command-helpers/version.js +66 -0
  30. package/dist/command-helpers/version.test.js +186 -0
  31. package/dist/commands/add.js +187 -0
  32. package/dist/commands/auth.js +122 -0
  33. package/dist/commands/build.js +136 -0
  34. package/dist/commands/codegen.js +128 -0
  35. package/dist/commands/create.js +94 -0
  36. package/dist/commands/deploy.js +335 -0
  37. package/dist/commands/init.js +800 -0
  38. package/dist/commands/local.js +380 -0
  39. package/dist/commands/remove.js +95 -0
  40. package/dist/commands/test.js +293 -0
  41. package/dist/compiler/asc.js +83 -0
  42. package/dist/compiler/index.js +466 -0
  43. package/dist/debug.js +16 -0
  44. package/dist/migrations/mapping_api_version_0_0_1.js +83 -0
  45. package/dist/migrations/mapping_api_version_0_0_2.js +83 -0
  46. package/dist/migrations/mapping_api_version_0_0_3.js +83 -0
  47. package/dist/migrations/mapping_api_version_0_0_4.js +85 -0
  48. package/dist/migrations/mapping_api_version_0_0_5.js +85 -0
  49. package/dist/migrations/spec_version_0_0_2.js +45 -0
  50. package/dist/migrations/spec_version_0_0_3.js +50 -0
  51. package/dist/migrations/util/load-manifest.js +16 -0
  52. package/dist/migrations/util/versions.js +28 -0
  53. package/dist/migrations.js +54 -0
  54. package/dist/protocols/arweave/manifest.graphql +57 -0
  55. package/dist/protocols/arweave/scaffold/manifest.js +18 -0
  56. package/dist/protocols/arweave/scaffold/mapping.js +52 -0
  57. package/dist/protocols/arweave/subgraph.js +23 -0
  58. package/dist/protocols/contract.js +2 -0
  59. package/dist/protocols/cosmos/manifest.graphql +76 -0
  60. package/dist/protocols/cosmos/scaffold/manifest.js +15 -0
  61. package/dist/protocols/cosmos/scaffold/mapping.js +38 -0
  62. package/dist/protocols/cosmos/subgraph.js +28 -0
  63. package/dist/protocols/ethereum/abi.js +138 -0
  64. package/dist/protocols/ethereum/codegen/abi.js +474 -0
  65. package/dist/protocols/ethereum/codegen/abi.test.js +325 -0
  66. package/dist/protocols/ethereum/codegen/template.js +52 -0
  67. package/dist/protocols/ethereum/contract.js +22 -0
  68. package/dist/protocols/ethereum/manifest.graphql +94 -0
  69. package/dist/protocols/ethereum/scaffold/manifest.js +32 -0
  70. package/dist/protocols/ethereum/scaffold/mapping.js +65 -0
  71. package/dist/protocols/ethereum/subgraph.js +172 -0
  72. package/dist/protocols/ethereum/type-generator.js +123 -0
  73. package/dist/protocols/index.js +266 -0
  74. package/dist/protocols/ipfs/codegen/file_template.js +53 -0
  75. package/dist/protocols/near/contract.js +41 -0
  76. package/dist/protocols/near/manifest.graphql +64 -0
  77. package/dist/protocols/near/scaffold/manifest.js +16 -0
  78. package/dist/protocols/near/scaffold/mapping.js +38 -0
  79. package/dist/protocols/near/subgraph.js +23 -0
  80. package/dist/protocols/subgraph.js +2 -0
  81. package/dist/protocols/substreams/manifest.graphql +45 -0
  82. package/dist/protocols/substreams/scaffold/manifest.js +12 -0
  83. package/dist/protocols/substreams/subgraph.js +23 -0
  84. package/dist/scaffold/cosmos.test.js +82 -0
  85. package/dist/scaffold/ethereum.test.js +496 -0
  86. package/dist/scaffold/index.js +133 -0
  87. package/dist/scaffold/mapping.js +57 -0
  88. package/dist/scaffold/near.test.js +85 -0
  89. package/dist/scaffold/schema.js +86 -0
  90. package/dist/scaffold/tests.js +179 -0
  91. package/dist/schema.js +54 -0
  92. package/dist/subgraph.js +243 -0
  93. package/dist/type-generator.js +225 -0
  94. package/dist/validation/contract.js +44 -0
  95. package/dist/validation/index.js +10 -0
  96. package/dist/validation/manifest.js +266 -0
  97. package/dist/validation/schema.js +768 -0
  98. package/dist/validation/schema.test.js +35 -0
  99. package/dist/watcher.js +79 -0
  100. package/package.json +1 -1
@@ -0,0 +1,466 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const crypto_1 = __importDefault(require("crypto"));
30
+ const path_1 = __importDefault(require("path"));
31
+ const chalk_1 = __importDefault(require("chalk"));
32
+ const fs_extra_1 = __importDefault(require("fs-extra"));
33
+ const toolbox = __importStar(require("gluegun"));
34
+ const immutable_1 = __importDefault(require("immutable"));
35
+ const js_yaml_1 = __importDefault(require("js-yaml"));
36
+ const spinner_1 = require("../command-helpers/spinner");
37
+ const debug_1 = __importDefault(require("../debug"));
38
+ const migrations_1 = require("../migrations");
39
+ const subgraph_1 = __importDefault(require("../subgraph"));
40
+ const watcher_1 = __importDefault(require("../watcher"));
41
+ const asc = __importStar(require("./asc"));
42
+ const compilerDebug = (0, debug_1.default)('graph-cli:compiler');
43
+ class Compiler {
44
+ options;
45
+ ipfs;
46
+ sourceDir;
47
+ blockIpfsMethods;
48
+ libsDirs;
49
+ globalsFile;
50
+ protocol;
51
+ ABI;
52
+ constructor(options) {
53
+ this.options = options;
54
+ this.options = options;
55
+ this.ipfs = options.ipfs;
56
+ this.sourceDir = path_1.default.dirname(options.subgraphManifest);
57
+ this.blockIpfsMethods = options.blockIpfsMethods;
58
+ this.libsDirs = [];
59
+ if (options.protocol.name !== 'substreams') {
60
+ for (let dir = path_1.default.resolve(this.sourceDir);
61
+ // Terminate after the root dir or when we have found node_modules
62
+ dir !== undefined;
63
+ // Continue with the parent directory, terminate after the root dir
64
+ dir = path_1.default.dirname(dir) === dir ? undefined : path_1.default.dirname(dir)) {
65
+ if (fs_extra_1.default.existsSync(path_1.default.join(dir, 'node_modules'))) {
66
+ this.libsDirs.push(path_1.default.join(dir, 'node_modules'));
67
+ }
68
+ }
69
+ if (this.libsDirs.length === 0) {
70
+ throw Error(`could not locate \`node_modules\` in parent directories of subgraph manifest`);
71
+ }
72
+ const globalsFile = path_1.default.join('@graphprotocol', 'graph-ts', 'global', 'global.ts');
73
+ const globalsLib = this.libsDirs.find(item => {
74
+ return fs_extra_1.default.existsSync(path_1.default.join(item, globalsFile));
75
+ });
76
+ if (!globalsLib) {
77
+ throw Error('Could not locate `@graphprotocol/graph-ts` package in parent directories of subgraph manifest.');
78
+ }
79
+ this.globalsFile = path_1.default.join(globalsLib, globalsFile);
80
+ }
81
+ // @ts-expect-error assigned or not, we dont care
82
+ if (!this.globalsFile) {
83
+ throw new Error('Globals file is missing.');
84
+ }
85
+ this.protocol = this.options.protocol;
86
+ this.ABI = this.protocol.getABI();
87
+ process.on('uncaughtException', e => {
88
+ toolbox.print.error(`UNCAUGHT EXCEPTION: ${e}`);
89
+ });
90
+ }
91
+ subgraphDir(parent, subgraph) {
92
+ return path_1.default.join(parent, subgraph.get('name'));
93
+ }
94
+ displayPath(p) {
95
+ return path_1.default.relative(process.cwd(), p);
96
+ }
97
+ cacheKeyForFile(filename) {
98
+ const hash = crypto_1.default.createHash('sha1');
99
+ hash.update(fs_extra_1.default.readFileSync(filename));
100
+ return hash.digest('hex');
101
+ }
102
+ async compile() {
103
+ try {
104
+ if (!this.options.skipMigrations) {
105
+ await (0, migrations_1.applyMigrations)({
106
+ sourceDir: this.sourceDir,
107
+ manifestFile: this.options.subgraphManifest,
108
+ });
109
+ }
110
+ const subgraph = await this.loadSubgraph();
111
+ const compiledSubgraph = await this.compileSubgraph(subgraph);
112
+ const localSubgraph = await this.writeSubgraphToOutputDirectory(this.options.protocol, compiledSubgraph);
113
+ if (this.ipfs !== undefined) {
114
+ const ipfsHash = await this.uploadSubgraphToIPFS(localSubgraph);
115
+ this.completed(ipfsHash);
116
+ return ipfsHash;
117
+ }
118
+ this.completed(path_1.default.join(this.options.outputDir, 'subgraph.yaml'));
119
+ return true;
120
+ }
121
+ catch (e) {
122
+ toolbox.print.error(e);
123
+ return false;
124
+ }
125
+ }
126
+ completed(ipfsHashOrPath) {
127
+ toolbox.print.info('');
128
+ toolbox.print.success(`Build completed: ${chalk_1.default.blue(ipfsHashOrPath)}`);
129
+ toolbox.print.info('');
130
+ }
131
+ async loadSubgraph({ quiet } = { quiet: false }) {
132
+ const subgraphLoadOptions = { protocol: this.protocol, skipValidation: false };
133
+ if (quiet) {
134
+ return (await subgraph_1.default.load(this.options.subgraphManifest, subgraphLoadOptions)).result;
135
+ }
136
+ const manifestPath = this.displayPath(this.options.subgraphManifest);
137
+ return await (0, spinner_1.withSpinner)(`Load subgraph from ${manifestPath}`, `Failed to load subgraph from ${manifestPath}`, `Warnings loading subgraph from ${manifestPath}`, async () => {
138
+ return subgraph_1.default.load(this.options.subgraphManifest, subgraphLoadOptions);
139
+ });
140
+ }
141
+ async getFilesToWatch() {
142
+ try {
143
+ const files = [];
144
+ const subgraph = await this.loadSubgraph({ quiet: true });
145
+ // Add the subgraph manifest file
146
+ files.push(this.options.subgraphManifest);
147
+ // Add all file paths specified in manifest
148
+ files.push(path_1.default.resolve(subgraph.getIn(['schema', 'file'])));
149
+ subgraph.get('dataSources').map((dataSource) => {
150
+ files.push(dataSource.getIn(['mapping', 'file']));
151
+ // Only watch ABI related files if the target protocol has support/need for them.
152
+ if (this.protocol.hasABIs()) {
153
+ dataSource.getIn(['mapping', 'abis']).map((abi) => {
154
+ files.push(abi.get('file'));
155
+ });
156
+ }
157
+ });
158
+ // Make paths absolute
159
+ return files.map(file => path_1.default.resolve(file));
160
+ }
161
+ catch (e) {
162
+ throw Error(`Failed to load subgraph: ${e.message}`);
163
+ }
164
+ }
165
+ async watchAndCompile(onCompiled) {
166
+ const compiler = this;
167
+ let spinner;
168
+ // Create watcher and recompile once and then on every change to a watched file
169
+ const watcher = new watcher_1.default({
170
+ onReady: () => (spinner = toolbox.print.spin('Watching subgraph files')),
171
+ onTrigger: async (changedFile) => {
172
+ if (changedFile !== undefined) {
173
+ spinner.info(`File change detected: ${this.displayPath(changedFile)}\n`);
174
+ }
175
+ const ipfsHash = await compiler.compile();
176
+ onCompiled?.(ipfsHash);
177
+ spinner.start();
178
+ },
179
+ onCollectFiles: async () => await compiler.getFilesToWatch(),
180
+ onError: error => {
181
+ spinner.stop();
182
+ toolbox.print.error(`${error.message}\n`);
183
+ spinner.start();
184
+ },
185
+ });
186
+ // Catch keyboard interrupt: close watcher and exit process
187
+ process.on('SIGINT', () => {
188
+ watcher.close();
189
+ process.exit();
190
+ });
191
+ try {
192
+ await watcher.watch();
193
+ }
194
+ catch (e) {
195
+ toolbox.print.error(String(e.message));
196
+ }
197
+ }
198
+ _writeSubgraphFile(maybeRelativeFile, data, sourceDir, targetDir, spinner) {
199
+ const absoluteSourceFile = path_1.default.resolve(sourceDir, maybeRelativeFile);
200
+ const relativeSourceFile = path_1.default.relative(sourceDir, absoluteSourceFile);
201
+ const targetFile = path_1.default.join(targetDir, relativeSourceFile);
202
+ (0, spinner_1.step)(spinner, 'Write subgraph file', this.displayPath(targetFile));
203
+ fs_extra_1.default.mkdirsSync(path_1.default.dirname(targetFile));
204
+ fs_extra_1.default.writeFileSync(targetFile, data);
205
+ return targetFile;
206
+ }
207
+ async compileSubgraph(subgraph) {
208
+ return await (0, spinner_1.withSpinner)(`Compile subgraph`, `Failed to compile subgraph`, `Warnings while compiling subgraph`, async (spinner) => {
209
+ // Cache compiled files so identical input files are only compiled once
210
+ const compiledFiles = new Map();
211
+ await asc.ready();
212
+ subgraph = subgraph.update('dataSources', (dataSources) => dataSources.map((dataSource) => dataSource.updateIn(['mapping', 'file'], (mappingPath) => this._compileDataSourceMapping(this.protocol, dataSource, mappingPath, compiledFiles, spinner))));
213
+ subgraph = subgraph.update('templates', (templates) => templates === undefined
214
+ ? templates
215
+ : templates.map((template) => template.updateIn(['mapping', 'file'], (mappingPath) => this._compileTemplateMapping(template, mappingPath, compiledFiles, spinner))));
216
+ return subgraph;
217
+ });
218
+ }
219
+ _compileDataSourceMapping(protocol, dataSource, mappingPath, compiledFiles, spinner) {
220
+ if (protocol.name == 'substreams') {
221
+ return;
222
+ }
223
+ try {
224
+ const dataSourceName = dataSource.getIn(['name']);
225
+ const baseDir = this.sourceDir;
226
+ const absoluteMappingPath = path_1.default.resolve(baseDir, mappingPath);
227
+ const inputFile = path_1.default.relative(baseDir, absoluteMappingPath);
228
+ this._validateMappingContent(absoluteMappingPath);
229
+ // If the file has already been compiled elsewhere, just use that output
230
+ // file and return early
231
+ const inputCacheKey = this.cacheKeyForFile(absoluteMappingPath);
232
+ const alreadyCompiled = compiledFiles.has(inputCacheKey);
233
+ if (alreadyCompiled) {
234
+ const outFile = compiledFiles.get(inputCacheKey);
235
+ (0, spinner_1.step)(spinner, 'Compile data source:', `${dataSourceName} => ${this.displayPath(outFile)} (already compiled)`);
236
+ return outFile;
237
+ }
238
+ const outFile = path_1.default.resolve(this.subgraphDir(this.options.outputDir, dataSource), this.options.outputFormat == 'wasm' ? `${dataSourceName}.wasm` : `${dataSourceName}.wast`);
239
+ (0, spinner_1.step)(spinner, 'Compile data source:', `${dataSourceName} => ${this.displayPath(outFile)}`);
240
+ const outputFile = path_1.default.relative(baseDir, outFile);
241
+ // Create output directory
242
+ fs_extra_1.default.mkdirsSync(path_1.default.dirname(outFile));
243
+ const libs = this.libsDirs.join(',');
244
+ const global = path_1.default.relative(baseDir, this.globalsFile);
245
+ asc.compile({
246
+ inputFile,
247
+ global,
248
+ baseDir,
249
+ libs,
250
+ outputFile,
251
+ });
252
+ // Remember the output file to avoid compiling the same file again
253
+ compiledFiles.set(inputCacheKey, outFile);
254
+ return outFile;
255
+ }
256
+ catch (e) {
257
+ throw Error(`Failed to compile data source mapping: ${e.message}`);
258
+ }
259
+ }
260
+ _compileTemplateMapping(template, mappingPath, compiledFiles, spinner) {
261
+ try {
262
+ const templateName = template.get('name');
263
+ const baseDir = this.sourceDir;
264
+ const absoluteMappingPath = path_1.default.resolve(baseDir, mappingPath);
265
+ const inputFile = path_1.default.relative(baseDir, absoluteMappingPath);
266
+ this._validateMappingContent(absoluteMappingPath);
267
+ // If the file has already been compiled elsewhere, just use that output
268
+ // file and return early
269
+ const inputCacheKey = this.cacheKeyForFile(absoluteMappingPath);
270
+ const alreadyCompiled = compiledFiles.has(inputCacheKey);
271
+ if (alreadyCompiled) {
272
+ const outFile = compiledFiles.get(inputCacheKey);
273
+ (0, spinner_1.step)(spinner, 'Compile data source template:', `${templateName} => ${this.displayPath(outFile)} (already compiled)`);
274
+ return outFile;
275
+ }
276
+ const outFile = path_1.default.resolve(this.options.outputDir, 'templates', templateName, this.options.outputFormat == 'wasm' ? `${templateName}.wasm` : `${templateName}.wast`);
277
+ (0, spinner_1.step)(spinner, 'Compile data source template:', `${templateName} => ${this.displayPath(outFile)}`);
278
+ const outputFile = path_1.default.relative(baseDir, outFile);
279
+ // Create output directory
280
+ fs_extra_1.default.mkdirsSync(path_1.default.dirname(outFile));
281
+ const libs = this.libsDirs.join(',');
282
+ const global = path_1.default.relative(baseDir, this.globalsFile);
283
+ asc.compile({
284
+ inputFile,
285
+ global,
286
+ baseDir,
287
+ libs,
288
+ outputFile,
289
+ });
290
+ // Remember the output file to avoid compiling the same file again
291
+ compiledFiles.set(inputCacheKey, outFile);
292
+ return outFile;
293
+ }
294
+ catch (e) {
295
+ throw Error(`Failed to compile data source template: ${e.message}`);
296
+ }
297
+ }
298
+ _validateMappingContent(filePath) {
299
+ const data = fs_extra_1.default.readFileSync(filePath);
300
+ if (this.blockIpfsMethods && (data.includes('ipfs.cat') || data.includes('ipfs.map'))) {
301
+ throw Error(`
302
+ Subgraph Studio does not support mappings with ipfs methods.
303
+ Please remove all instances of ipfs.cat and ipfs.map from
304
+ ${filePath}
305
+ `);
306
+ }
307
+ }
308
+ async writeSubgraphToOutputDirectory(protocol, subgraph) {
309
+ const displayDir = `${this.displayPath(this.options.outputDir)}${toolbox.filesystem.separator}`;
310
+ return await (0, spinner_1.withSpinner)(`Write compiled subgraph to ${displayDir}`, `Failed to write compiled subgraph to ${displayDir}`, `Warnings while writing compiled subgraph to ${displayDir}`, async (spinner) => {
311
+ // Copy schema and update its path
312
+ subgraph = subgraph.updateIn(['schema', 'file'], schemaFile => {
313
+ const schemaFilePath = path_1.default.resolve(this.sourceDir, schemaFile);
314
+ const schemaFileName = path_1.default.basename(schemaFile);
315
+ const targetFile = path_1.default.resolve(this.options.outputDir, schemaFileName);
316
+ (0, spinner_1.step)(spinner, 'Copy schema file', this.displayPath(targetFile));
317
+ fs_extra_1.default.copyFileSync(schemaFilePath, targetFile);
318
+ return path_1.default.relative(this.options.outputDir, targetFile);
319
+ });
320
+ // Copy data source files and update their paths
321
+ subgraph = subgraph.update('dataSources', (dataSources) => dataSources.map(dataSource => {
322
+ let updatedDataSource = dataSource;
323
+ if (this.protocol.hasABIs()) {
324
+ updatedDataSource = updatedDataSource
325
+ // Write data source ABIs to the output directory
326
+ .updateIn(['mapping', 'abis'], (abis) => abis.map((abi) => abi.update('file', (abiFile) => {
327
+ abiFile = path_1.default.resolve(this.sourceDir, abiFile);
328
+ const abiData = this.ABI.load(abi.get('name'), abiFile);
329
+ return path_1.default.relative(this.options.outputDir, this._writeSubgraphFile(abiFile, JSON.stringify(abiData.data.toJS(), null, 2), this.sourceDir, this.subgraphDir(this.options.outputDir, dataSource), spinner));
330
+ })));
331
+ }
332
+ if (protocol.name == 'substreams') {
333
+ updatedDataSource = updatedDataSource
334
+ // Write data source ABIs to the output directory
335
+ .updateIn(['source', 'package'], (substreamsPackage) => substreamsPackage.update('file', (packageFile) => {
336
+ packageFile = path_1.default.resolve(this.sourceDir, packageFile);
337
+ const packageContent = fs_extra_1.default.readFileSync(packageFile);
338
+ return path_1.default.relative(this.options.outputDir, this._writeSubgraphFile(packageFile, packageContent, this.sourceDir, this.subgraphDir(this.options.outputDir, dataSource), spinner));
339
+ }));
340
+ return updatedDataSource;
341
+ }
342
+ // The mapping file is already being written to the output
343
+ // directory by the AssemblyScript compiler
344
+ return updatedDataSource.updateIn(['mapping', 'file'], (mappingFile) => path_1.default.relative(this.options.outputDir, path_1.default.resolve(this.sourceDir, mappingFile)));
345
+ }));
346
+ // Copy template files and update their paths
347
+ subgraph = subgraph.update('templates', templates => templates === undefined
348
+ ? templates
349
+ : templates.map((template) => {
350
+ let updatedTemplate = template;
351
+ if (this.protocol.hasABIs()) {
352
+ updatedTemplate = updatedTemplate
353
+ // Write template ABIs to the output directory
354
+ .updateIn(['mapping', 'abis'], (abis) => abis.map(abi => abi.update('file', (abiFile) => {
355
+ abiFile = path_1.default.resolve(this.sourceDir, abiFile);
356
+ const abiData = this.ABI.load(abi.get('name'), abiFile);
357
+ return path_1.default.relative(this.options.outputDir, this._writeSubgraphFile(abiFile, JSON.stringify(abiData.data.toJS(), null, 2), this.sourceDir, this.subgraphDir(this.options.outputDir, template), spinner));
358
+ })));
359
+ }
360
+ // The mapping file is already being written to the output
361
+ // directory by the AssemblyScript compiler
362
+ return updatedTemplate.updateIn(['mapping', 'file'], (mappingFile) => path_1.default.relative(this.options.outputDir, path_1.default.resolve(this.sourceDir, mappingFile)));
363
+ }));
364
+ // Write the subgraph manifest itself
365
+ const outputFilename = path_1.default.join(this.options.outputDir, 'subgraph.yaml');
366
+ (0, spinner_1.step)(spinner, 'Write subgraph manifest', this.displayPath(outputFilename));
367
+ await subgraph_1.default.write(subgraph, outputFilename);
368
+ return subgraph;
369
+ });
370
+ }
371
+ async uploadSubgraphToIPFS(subgraph) {
372
+ return (0, spinner_1.withSpinner)(`Upload subgraph to IPFS`, `Failed to upload subgraph to IPFS`, `Warnings while uploading subgraph to IPFS`, async (spinner) => {
373
+ // Cache uploaded IPFS files so identical files are only uploaded once
374
+ const uploadedFiles = new Map();
375
+ // Collect all source (path -> hash) updates to apply them later
376
+ const updates = [];
377
+ // Upload the schema to IPFS
378
+ updates.push({
379
+ keyPath: ['schema', 'file'],
380
+ value: await this._uploadFileToIPFS(subgraph.getIn(['schema', 'file']), uploadedFiles, spinner),
381
+ });
382
+ if (this.protocol.hasABIs()) {
383
+ for (const [i, dataSource] of subgraph.get('dataSources').entries()) {
384
+ for (const [j, abi] of dataSource.getIn(['mapping', 'abis']).entries()) {
385
+ updates.push({
386
+ keyPath: ['dataSources', i, 'mapping', 'abis', j, 'file'],
387
+ value: await this._uploadFileToIPFS(abi.get('file'), uploadedFiles, spinner),
388
+ });
389
+ }
390
+ }
391
+ }
392
+ // Upload all mappings
393
+ if (this.protocol.name !== 'substreams') {
394
+ for (const [i, dataSource] of subgraph.get('dataSources').entries()) {
395
+ updates.push({
396
+ keyPath: ['dataSources', i, 'mapping', 'file'],
397
+ value: await this._uploadFileToIPFS(dataSource.getIn(['mapping', 'file']), uploadedFiles, spinner),
398
+ });
399
+ }
400
+ }
401
+ else {
402
+ for (const [i, dataSource] of subgraph.get('dataSources').entries()) {
403
+ updates.push({
404
+ keyPath: ['dataSources', i, 'source', 'package', 'file'],
405
+ value: await this._uploadFileToIPFS(dataSource.getIn(['source', 'package', 'file']), uploadedFiles, spinner),
406
+ });
407
+ }
408
+ }
409
+ for (const [i, template] of subgraph.get('templates', immutable_1.default.List()).entries()) {
410
+ if (this.protocol.hasABIs()) {
411
+ for (const [j, abi] of template.getIn(['mapping', 'abis']).entries()) {
412
+ updates.push({
413
+ keyPath: ['templates', i, 'mapping', 'abis', j, 'file'],
414
+ value: await this._uploadFileToIPFS(abi.get('file'), uploadedFiles, spinner),
415
+ });
416
+ }
417
+ }
418
+ updates.push({
419
+ keyPath: ['templates', i, 'mapping', 'file'],
420
+ value: await this._uploadFileToIPFS(template.getIn(['mapping', 'file']), uploadedFiles, spinner),
421
+ });
422
+ }
423
+ // Apply all updates to the subgraph
424
+ for (const update of updates) {
425
+ subgraph = subgraph.setIn(update.keyPath, update.value);
426
+ }
427
+ // Upload the subgraph itself
428
+ return await this._uploadSubgraphDefinitionToIPFS(subgraph);
429
+ });
430
+ }
431
+ async _uploadFileToIPFS(maybeRelativeFile, uploadedFiles, spinner) {
432
+ compilerDebug('Resolving IPFS file "%s" from output dir "%s"', maybeRelativeFile, this.options.outputDir);
433
+ const absoluteFile = path_1.default.resolve(this.options.outputDir, maybeRelativeFile);
434
+ (0, spinner_1.step)(spinner, 'Add file to IPFS', this.displayPath(absoluteFile));
435
+ const uploadCacheKey = this.cacheKeyForFile(absoluteFile);
436
+ const alreadyUploaded = uploadedFiles.has(uploadCacheKey);
437
+ if (!alreadyUploaded) {
438
+ // @ts-expect-error Buffer.from with Buffer data can indeed accept utf-8
439
+ const content = Buffer.from(await fs_extra_1.default.readFile(absoluteFile), 'utf-8');
440
+ const hash = await this._uploadToIPFS({
441
+ path: path_1.default.relative(this.options.outputDir, absoluteFile),
442
+ content,
443
+ });
444
+ uploadedFiles.set(uploadCacheKey, hash);
445
+ }
446
+ const hash = uploadedFiles.get(uploadCacheKey);
447
+ (0, spinner_1.step)(spinner, ' ..', `${hash}${alreadyUploaded ? ' (already uploaded)' : ''}`);
448
+ return immutable_1.default.fromJS({ '/': `/ipfs/${hash}` });
449
+ }
450
+ async _uploadSubgraphDefinitionToIPFS(subgraph) {
451
+ const str = js_yaml_1.default.safeDump(subgraph.toJS(), { noRefs: true, sortKeys: true });
452
+ const file = { path: 'subgraph.yaml', content: Buffer.from(str, 'utf-8') };
453
+ return await this._uploadToIPFS(file);
454
+ }
455
+ async _uploadToIPFS(file) {
456
+ try {
457
+ const hash = (await this.ipfs.add([file]))[0].hash;
458
+ await this.ipfs.pin.add(hash);
459
+ return hash;
460
+ }
461
+ catch (e) {
462
+ throw Error(`Failed to upload file to IPFS: ${e.message}`);
463
+ }
464
+ }
465
+ }
466
+ exports.default = Compiler;
package/dist/debug.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const debug_1 = __importDefault(require("debug"));
7
+ debug_1.default.formatters.L = immutableList => {
8
+ return JSON.stringify(immutableList);
9
+ };
10
+ debug_1.default.formatters.M = immutableMap => {
11
+ if (immutableMap.toMap != null) {
12
+ return JSON.stringify(immutableMap.toMap());
13
+ }
14
+ return immutableMap;
15
+ };
16
+ exports.default = debug_1.default;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ /* eslint-disable */
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ const toolbox = __importStar(require("gluegun"));
31
+ const semver_1 = __importDefault(require("semver"));
32
+ const load_manifest_1 = require("./util/load-manifest");
33
+ const versions_1 = require("./util/versions");
34
+ // If any of the manifest apiVersions are 0.0.1, replace them with 0.0.2
35
+ exports.default = {
36
+ name: 'Bump mapping apiVersion from 0.0.1 to 0.0.2',
37
+ predicate: async ({ sourceDir, manifestFile }) => {
38
+ // Obtain the graph-ts version, if possible
39
+ let graphTsVersion;
40
+ try {
41
+ graphTsVersion = await (0, versions_1.getGraphTsVersion)(sourceDir);
42
+ }
43
+ catch (_) {
44
+ // If we cannot obtain the version, return a hint that the graph-ts
45
+ // hasn't been installed yet
46
+ return 'graph-ts dependency not installed yet';
47
+ }
48
+ const manifest = await (0, load_manifest_1.loadManifest)(manifestFile);
49
+ return (
50
+ // Only migrate if the graph-ts version is > 0.5.1...
51
+ semver_1.default.gt(graphTsVersion, '0.5.1') &&
52
+ // ...and we have a manifest with mapping > apiVersion = 0.0.1
53
+ manifest &&
54
+ typeof manifest === 'object' &&
55
+ Array.isArray(manifest.dataSources) &&
56
+ (manifest.dataSources.reduce((hasOldMappings, dataSource) => hasOldMappings ||
57
+ (typeof dataSource === 'object' &&
58
+ dataSource.mapping &&
59
+ typeof dataSource.mapping === 'object' &&
60
+ dataSource.mapping.apiVersion === '0.0.1'), false) ||
61
+ (Array.isArray(manifest.templates) &&
62
+ manifest.templates.reduce((hasOldMappings, template) => hasOldMappings ||
63
+ (typeof template === 'object' &&
64
+ template.mapping &&
65
+ typeof template.mapping === 'object' &&
66
+ template.mapping.apiVersion === '0.0.1'), false))));
67
+ },
68
+ apply: async ({ manifestFile }) => {
69
+ // Make sure we catch all variants; we could load the manifest
70
+ // and replace the values in the data structures here; unfortunately
71
+ // writing that back to the file messes with the formatting more than
72
+ // we'd like; that's why for now, we use a simple patching approach
73
+ await toolbox.patching.replace(manifestFile,
74
+ // @ts-expect-error toolbox patching seems to accept RegExp
75
+ new RegExp('apiVersion: 0.0.1', 'g'), 'apiVersion: 0.0.2');
76
+ await toolbox.patching.replace(manifestFile,
77
+ // @ts-expect-error toolbox patching seems to accept RegExp
78
+ new RegExp("apiVersion: '0.0.1'", 'g'), "apiVersion: '0.0.2'");
79
+ await toolbox.patching.replace(manifestFile,
80
+ // @ts-expect-error toolbox patching seems to accept RegExp
81
+ new RegExp('apiVersion: "0.0.1"', 'g'), 'apiVersion: "0.0.2"');
82
+ },
83
+ };
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ /* eslint-disable */
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ const toolbox = __importStar(require("gluegun"));
31
+ const semver_1 = __importDefault(require("semver"));
32
+ const load_manifest_1 = require("./util/load-manifest");
33
+ const versions_1 = require("./util/versions");
34
+ // If any of the manifest apiVersions are 0.0.2, replace them with 0.0.3
35
+ exports.default = {
36
+ name: 'Bump mapping apiVersion from 0.0.2 to 0.0.3',
37
+ predicate: async ({ sourceDir, manifestFile }) => {
38
+ // Obtain the graph-ts version, if possible
39
+ let graphTsVersion;
40
+ try {
41
+ graphTsVersion = await (0, versions_1.getGraphTsVersion)(sourceDir);
42
+ }
43
+ catch (_) {
44
+ // If we cannot obtain the version, return a hint that the graph-ts
45
+ // hasn't been installed yet
46
+ return 'graph-ts dependency not installed yet';
47
+ }
48
+ const manifest = await (0, load_manifest_1.loadManifest)(manifestFile);
49
+ return (
50
+ // Only migrate if the graph-ts version is > 0.12.0...
51
+ semver_1.default.gt(graphTsVersion, '0.12.0') &&
52
+ // ...and we have a manifest with mapping > apiVersion = 0.0.2
53
+ manifest &&
54
+ typeof manifest === 'object' &&
55
+ Array.isArray(manifest.dataSources) &&
56
+ (manifest.dataSources.reduce((hasOldMappings, dataSource) => hasOldMappings ||
57
+ (typeof dataSource === 'object' &&
58
+ dataSource.mapping &&
59
+ typeof dataSource.mapping === 'object' &&
60
+ dataSource.mapping.apiVersion === '0.0.2'), false) ||
61
+ (Array.isArray(manifest.templates) &&
62
+ manifest.templates.reduce((hasOldMappings, template) => hasOldMappings ||
63
+ (typeof template === 'object' &&
64
+ template.mapping &&
65
+ typeof template.mapping === 'object' &&
66
+ template.mapping.apiVersion === '0.0.2'), false))));
67
+ },
68
+ apply: async ({ manifestFile }) => {
69
+ // Make sure we catch all variants; we could load the manifest
70
+ // and replace the values in the data structures here; unfortunately
71
+ // writing that back to the file messes with the formatting more than
72
+ // we'd like; that's why for now, we use a simple patching approach
73
+ await toolbox.patching.replace(manifestFile,
74
+ // @ts-expect-error toolbox patching seems to accept RegExp
75
+ new RegExp('apiVersion: 0.0.2', 'g'), 'apiVersion: 0.0.3');
76
+ await toolbox.patching.replace(manifestFile,
77
+ // @ts-expect-error toolbox patching seems to accept RegExp
78
+ new RegExp("apiVersion: '0.0.2'", 'g'), "apiVersion: '0.0.3'");
79
+ await toolbox.patching.replace(manifestFile,
80
+ // @ts-expect-error toolbox patching seems to accept RegExp
81
+ new RegExp('apiVersion: "0.0.2"', 'g'), 'apiVersion: "0.0.3"');
82
+ },
83
+ };