@graphprotocol/graph-cli 0.53.0 → 0.54.0-alpha-20230724180700-d5ce4e2

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,5 +1,21 @@
1
1
  # @graphprotocol/graph-cli
2
2
 
3
+ ## 0.54.0-alpha-20230724180700-d5ce4e2
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1407](https://github.com/graphprotocol/graph-tooling/pull/1407)
8
+ [`d388127`](https://github.com/graphprotocol/graph-tooling/commit/d388127aa46a47feaab5024d0a2f2da49c9cabac)
9
+ Thanks [@saihaj](https://github.com/saihaj)! - add skipInstall flag for init
10
+
11
+ ### Patch Changes
12
+
13
+ - [#1394](https://github.com/graphprotocol/graph-tooling/pull/1394)
14
+ [`a2a6ae6`](https://github.com/graphprotocol/graph-tooling/commit/a2a6ae697ae93631e020c8583d7c04a338d3c298)
15
+ Thanks [@saihaj](https://github.com/saihaj)! - dependencies updates:
16
+ - Added dependency [`zod@^3.21.4` ↗︎](https://www.npmjs.com/package/zod/v/3.21.4) (to
17
+ `dependencies`)
18
+
3
19
  ## 0.53.0
4
20
 
5
21
  ### Minor Changes
@@ -29,7 +29,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const core_1 = require("@oclif/core");
30
30
  const errors_1 = require("@oclif/core/lib/errors");
31
31
  const gluegun_1 = require("gluegun");
32
- const immutable_1 = __importDefault(require("immutable"));
33
32
  const abi_1 = require("../command-helpers/abi");
34
33
  const DataSourcesExtractor = __importStar(require("../command-helpers/data-sources"));
35
34
  const network_1 = require("../command-helpers/network");
@@ -44,8 +43,8 @@ class AddCommand extends core_1.Command {
44
43
  const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifestPath);
45
44
  const protocol = protocols_1.default.fromDataSources(dataSourcesAndTemplates);
46
45
  const manifest = await subgraph_1.default.load(manifestPath, { protocol });
47
- const network = manifest.result.getIn(['dataSources', 0, 'network']);
48
- const result = manifest.result.asMutable();
46
+ const network = manifest.result.dataSources?.[0].network;
47
+ const result = manifest.result;
49
48
  let startBlock = startBlockFlag;
50
49
  const entities = getEntities(manifest);
51
50
  const contractNames = getContractNames(manifest);
@@ -87,23 +86,22 @@ class AddCommand extends core_1.Command {
87
86
  await (0, scaffold_1.writeABI)(ethabi, contractName);
88
87
  const { collisionEntities, onlyCollisions, abiData } = updateEventNamesOnCollision(ethabi, entities, contractName, mergeEntities);
89
88
  ethabi.data = abiData;
90
- await (0, scaffold_1.writeSchema)(ethabi, protocol, result.getIn(['schema', 'file']), collisionEntities, contractName);
89
+ await (0, scaffold_1.writeSchema)(ethabi, protocol, result.schema.file, collisionEntities, contractName);
91
90
  await (0, scaffold_1.writeMapping)(ethabi, protocol, contractName, collisionEntities);
92
91
  await (0, scaffold_1.writeTestsFiles)(ethabi, protocol, contractName);
93
- const dataSources = result.get('dataSources');
92
+ const dataSources = result.dataSources;
94
93
  const dataSource = await (0, scaffold_1.generateDataSource)(protocol, contractName, network, address, ethabi, startBlock);
95
94
  // Handle the collisions edge case by copying another data source yaml data
96
95
  if (mergeEntities && onlyCollisions) {
97
- const firstDataSource = dataSources.get(0);
96
+ const firstDataSource = dataSources?.[0];
98
97
  const source = dataSource.get('source');
99
- const mapping = firstDataSource.get('mapping').asMutable();
98
+ const mapping = firstDataSource.mapping;
100
99
  // Save the address of the new data source
101
- source.abi = firstDataSource.get('source').get('abi');
100
+ source.abi = firstDataSource.source.abi;
102
101
  dataSource.set('mapping', mapping);
103
102
  dataSource.set('source', source);
104
103
  }
105
- result.set('dataSources', dataSources.push(dataSource));
106
- await subgraph_1.default.write(result, manifestPath);
104
+ await subgraph_1.default.write({ ...result, dataSources: [...dataSources, dataSource] }, manifestPath);
107
105
  // Update networks.json
108
106
  if (gluegun_1.filesystem.exists(networksFile)) {
109
107
  await (0, network_1.updateNetworksFile)(network, contractName, address, networksFile);
@@ -155,17 +153,17 @@ AddCommand.flags = {
155
153
  };
156
154
  exports.default = AddCommand;
157
155
  const getEntities = (manifest) => {
158
- const dataSources = manifest.result.get('dataSources', immutable_1.default.List());
159
- const templates = manifest.result.get('templates', immutable_1.default.List());
160
- return dataSources
161
- .concat(templates)
162
- .map((dataSource) => dataSource.getIn(['mapping', 'entities']))
163
- .flatten();
156
+ const dataSources = manifest.result?.dataSources || [];
157
+ const templates = manifest.result?.templates || [];
158
+ return [
159
+ ...dataSources.map(source => source.mapping.entities),
160
+ ...templates.map(template => template.mapping.entities),
161
+ ].flat();
164
162
  };
165
163
  const getContractNames = (manifest) => {
166
- const dataSources = manifest.result.get('dataSources', immutable_1.default.List());
167
- const templates = manifest.result.get('templates', immutable_1.default.List());
168
- return dataSources.concat(templates).map((dataSource) => dataSource.get('name'));
164
+ const dataSources = manifest.result?.dataSources || [];
165
+ const templates = manifest.result?.templates || [];
166
+ return [...dataSources.map(source => source.name), templates.map(template => template.name)];
169
167
  };
170
168
  const updateEventNamesOnCollision = (ethabi, entities, contractName, mergeEntities) => {
171
169
  let abiData = ethabi.data;
@@ -16,6 +16,7 @@ export default class InitCommand extends Command {
16
16
  'from-example': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
17
17
  'contract-name': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
18
18
  'index-events': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
+ 'skip-install': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
20
  'start-block': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
20
21
  abi: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
21
22
  spkg: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
@@ -24,7 +24,7 @@ const availableNetworks = protocols_1.default.availableNetworks();
24
24
  const DEFAULT_EXAMPLE_SUBGRAPH = 'ethereum-gravatar';
25
25
  class InitCommand extends core_1.Command {
26
26
  async run() {
27
- const { args: { subgraphName, directory }, flags: { protocol, product, studio, node: nodeFlag, 'allow-simple-name': allowSimpleNameFlag, 'from-contract': fromContract, 'contract-name': contractName, 'from-example': fromExample, 'index-events': indexEvents, network, abi: abiPath, 'start-block': startBlock, spkg: spkgPath, }, } = await this.parse(InitCommand);
27
+ const { args: { subgraphName, directory }, flags: { protocol, product, studio, node: nodeFlag, 'allow-simple-name': allowSimpleNameFlag, 'from-contract': fromContract, 'contract-name': contractName, 'from-example': fromExample, 'index-events': indexEvents, 'skip-install': skipInstall, network, abi: abiPath, 'start-block': startBlock, spkg: spkgPath, }, } = await this.parse(InitCommand);
28
28
  let { node, allowSimpleName } = (0, node_1.chooseNodeUrl)({
29
29
  product,
30
30
  // if we are loading example, we want to ensure we are using studio
@@ -66,6 +66,7 @@ class InitCommand extends core_1.Command {
66
66
  allowSimpleName,
67
67
  directory,
68
68
  subgraphName,
69
+ skipInstall,
69
70
  }, { commands });
70
71
  // Exit with success
71
72
  return this.exit(0);
@@ -119,6 +120,7 @@ class InitCommand extends core_1.Command {
119
120
  product,
120
121
  startBlock,
121
122
  spkgPath,
123
+ skipInstall,
122
124
  }, { commands, addContract: false });
123
125
  // Exit with success
124
126
  return this.exit(0);
@@ -138,6 +140,7 @@ class InitCommand extends core_1.Command {
138
140
  fromExample,
139
141
  subgraphName: answers.subgraphName,
140
142
  directory: answers.directory,
143
+ skipInstall,
141
144
  }, { commands });
142
145
  }
143
146
  else {
@@ -185,6 +188,7 @@ class InitCommand extends core_1.Command {
185
188
  product: answers.product,
186
189
  startBlock: answers.startBlock,
187
190
  spkgPath: answers.spkgPath,
191
+ skipInstall,
188
192
  }, { commands, addContract: true });
189
193
  }
190
194
  // Exit with success
@@ -239,6 +243,10 @@ InitCommand.flags = {
239
243
  description: 'Index contract events as entities.',
240
244
  dependsOn: ['from-contract'],
241
245
  }),
246
+ 'skip-install': core_1.Flags.boolean({
247
+ summary: 'Skip installing dependencies.',
248
+ default: false,
249
+ }),
242
250
  'start-block': core_1.Flags.string({
243
251
  helpGroup: 'Scaffold from contract',
244
252
  description: 'Block number to start indexing from.',
@@ -652,7 +660,7 @@ Subgraph ${subgraphName} created in ${relativeDir}
652
660
 
653
661
  Make sure to visit the documentation on https://thegraph.com/docs/ for further information.`);
654
662
  }
655
- async function initSubgraphFromExample({ fromExample, allowSimpleName, subgraphName, directory, }, { commands, }) {
663
+ async function initSubgraphFromExample({ fromExample, allowSimpleName, subgraphName, directory, skipInstall, }, { commands, }) {
656
664
  // Fail if the subgraph name is invalid
657
665
  if (!revalidateSubgraphName.bind(this)(subgraphName, { allowSimpleName })) {
658
666
  process.exitCode = 1;
@@ -733,10 +741,12 @@ async function initSubgraphFromExample({ fromExample, allowSimpleName, subgraphN
733
741
  return;
734
742
  }
735
743
  // Install dependencies
736
- const installed = await installDependencies(directory, commands);
737
- if (installed !== true) {
738
- this.exit(1);
739
- return;
744
+ if (!skipInstall) {
745
+ const installed = await installDependencies(directory, commands);
746
+ if (installed !== true) {
747
+ this.exit(1);
748
+ return;
749
+ }
740
750
  }
741
751
  // Run code-generation
742
752
  const codegen = await runCodegen(directory, commands.codegen);
@@ -746,7 +756,7 @@ async function initSubgraphFromExample({ fromExample, allowSimpleName, subgraphN
746
756
  }
747
757
  printNextSteps.bind(this)({ subgraphName, directory }, { commands });
748
758
  }
749
- async function initSubgraphFromContract({ protocolInstance, allowSimpleName, subgraphName, directory, abi, network, contract, indexEvents, contractName, node, studio, product, startBlock, spkgPath, }, { commands, addContract, }) {
759
+ async function initSubgraphFromContract({ protocolInstance, allowSimpleName, subgraphName, directory, abi, network, contract, indexEvents, contractName, node, studio, product, startBlock, spkgPath, skipInstall, }, { commands, addContract, }) {
750
760
  const isSubstreams = protocolInstance.name === 'substreams';
751
761
  // Fail if the subgraph name is invalid
752
762
  if (!revalidateSubgraphName.bind(this)(subgraphName, { allowSimpleName })) {
@@ -808,11 +818,13 @@ async function initSubgraphFromContract({ protocolInstance, allowSimpleName, sub
808
818
  this.exit(1);
809
819
  return;
810
820
  }
811
- // Install dependencies
812
- const installed = await installDependencies(directory, commands);
813
- if (installed !== true) {
814
- this.exit(1);
815
- return;
821
+ if (!skipInstall) {
822
+ // Install dependencies
823
+ const installed = await installDependencies(directory, commands);
824
+ if (installed !== true) {
825
+ this.exit(1);
826
+ return;
827
+ }
816
828
  }
817
829
  // Substreams we have nothing to install or generate
818
830
  if (!isSubstreams) {
@@ -0,0 +1,511 @@
1
+ import { z } from 'zod';
2
+ export declare const Manifest: z.ZodObject<{
3
+ specVersion: z.ZodString;
4
+ schema: z.ZodObject<{
5
+ file: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ file: string;
8
+ }, {
9
+ file: string;
10
+ }>;
11
+ description: z.ZodOptional<z.ZodString>;
12
+ repository: z.ZodOptional<z.ZodString>;
13
+ graft: z.ZodOptional<z.ZodObject<{
14
+ base: z.ZodString;
15
+ block: z.ZodBigInt;
16
+ }, "strip", z.ZodTypeAny, {
17
+ base: string;
18
+ block: bigint;
19
+ }, {
20
+ base: string;
21
+ block: bigint;
22
+ }>>;
23
+ dataSources: z.ZodArray<z.ZodObject<{
24
+ kind: z.ZodString;
25
+ name: z.ZodString;
26
+ network: z.ZodString;
27
+ source: z.ZodObject<{
28
+ address: z.ZodString;
29
+ abi: z.ZodString;
30
+ startBlock: z.ZodOptional<z.ZodUnion<[z.ZodBigInt, z.ZodNumber]>>;
31
+ }, "strip", z.ZodTypeAny, {
32
+ address: string;
33
+ abi: string;
34
+ startBlock?: number | bigint | undefined;
35
+ }, {
36
+ address: string;
37
+ abi: string;
38
+ startBlock?: number | bigint | undefined;
39
+ }>;
40
+ mapping: z.ZodObject<{
41
+ kind: z.ZodLiteral<"ethereum/events">;
42
+ apiVersion: z.ZodString;
43
+ language: z.ZodLiteral<"wasm/assemblyscript">;
44
+ entities: z.ZodArray<z.ZodString, "many">;
45
+ eventHandlers: z.ZodOptional<z.ZodArray<z.ZodObject<{
46
+ event: z.ZodString;
47
+ handler: z.ZodString;
48
+ topic0: z.ZodOptional<z.ZodString>;
49
+ }, "strip", z.ZodTypeAny, {
50
+ event: string;
51
+ handler: string;
52
+ topic0?: string | undefined;
53
+ }, {
54
+ event: string;
55
+ handler: string;
56
+ topic0?: string | undefined;
57
+ }>, "many">>;
58
+ callHandlers: z.ZodOptional<z.ZodArray<z.ZodObject<{
59
+ function: z.ZodString;
60
+ handler: z.ZodString;
61
+ }, "strip", z.ZodTypeAny, {
62
+ function: string;
63
+ handler: string;
64
+ }, {
65
+ function: string;
66
+ handler: string;
67
+ }>, "many">>;
68
+ blockHandlers: z.ZodOptional<z.ZodArray<z.ZodObject<{
69
+ handler: z.ZodString;
70
+ filter: z.ZodOptional<z.ZodObject<{
71
+ kind: z.ZodLiteral<"call">;
72
+ }, "strip", z.ZodTypeAny, {
73
+ kind: "call";
74
+ }, {
75
+ kind: "call";
76
+ }>>;
77
+ }, "strip", z.ZodTypeAny, {
78
+ handler: string;
79
+ filter?: {
80
+ kind: "call";
81
+ } | undefined;
82
+ }, {
83
+ handler: string;
84
+ filter?: {
85
+ kind: "call";
86
+ } | undefined;
87
+ }>, "many">>;
88
+ file: z.ZodString;
89
+ }, "strip", z.ZodTypeAny, {
90
+ file: string;
91
+ kind: "ethereum/events";
92
+ apiVersion: string;
93
+ language: "wasm/assemblyscript";
94
+ entities: string[];
95
+ eventHandlers?: {
96
+ event: string;
97
+ handler: string;
98
+ topic0?: string | undefined;
99
+ }[] | undefined;
100
+ callHandlers?: {
101
+ function: string;
102
+ handler: string;
103
+ }[] | undefined;
104
+ blockHandlers?: {
105
+ handler: string;
106
+ filter?: {
107
+ kind: "call";
108
+ } | undefined;
109
+ }[] | undefined;
110
+ }, {
111
+ file: string;
112
+ kind: "ethereum/events";
113
+ apiVersion: string;
114
+ language: "wasm/assemblyscript";
115
+ entities: string[];
116
+ eventHandlers?: {
117
+ event: string;
118
+ handler: string;
119
+ topic0?: string | undefined;
120
+ }[] | undefined;
121
+ callHandlers?: {
122
+ function: string;
123
+ handler: string;
124
+ }[] | undefined;
125
+ blockHandlers?: {
126
+ handler: string;
127
+ filter?: {
128
+ kind: "call";
129
+ } | undefined;
130
+ }[] | undefined;
131
+ }>;
132
+ }, "strip", z.ZodTypeAny, {
133
+ kind: string;
134
+ name: string;
135
+ network: string;
136
+ source: {
137
+ address: string;
138
+ abi: string;
139
+ startBlock?: number | bigint | undefined;
140
+ };
141
+ mapping: {
142
+ file: string;
143
+ kind: "ethereum/events";
144
+ apiVersion: string;
145
+ language: "wasm/assemblyscript";
146
+ entities: string[];
147
+ eventHandlers?: {
148
+ event: string;
149
+ handler: string;
150
+ topic0?: string | undefined;
151
+ }[] | undefined;
152
+ callHandlers?: {
153
+ function: string;
154
+ handler: string;
155
+ }[] | undefined;
156
+ blockHandlers?: {
157
+ handler: string;
158
+ filter?: {
159
+ kind: "call";
160
+ } | undefined;
161
+ }[] | undefined;
162
+ };
163
+ }, {
164
+ kind: string;
165
+ name: string;
166
+ network: string;
167
+ source: {
168
+ address: string;
169
+ abi: string;
170
+ startBlock?: number | bigint | undefined;
171
+ };
172
+ mapping: {
173
+ file: string;
174
+ kind: "ethereum/events";
175
+ apiVersion: string;
176
+ language: "wasm/assemblyscript";
177
+ entities: string[];
178
+ eventHandlers?: {
179
+ event: string;
180
+ handler: string;
181
+ topic0?: string | undefined;
182
+ }[] | undefined;
183
+ callHandlers?: {
184
+ function: string;
185
+ handler: string;
186
+ }[] | undefined;
187
+ blockHandlers?: {
188
+ handler: string;
189
+ filter?: {
190
+ kind: "call";
191
+ } | undefined;
192
+ }[] | undefined;
193
+ };
194
+ }>, "many">;
195
+ templates: z.ZodOptional<z.ZodArray<z.ZodObject<{
196
+ kind: z.ZodString;
197
+ name: z.ZodString;
198
+ network: z.ZodString;
199
+ source: z.ZodObject<{
200
+ abi: z.ZodString;
201
+ startBlock: z.ZodOptional<z.ZodUnion<[z.ZodBigInt, z.ZodNumber]>>;
202
+ }, "strip", z.ZodTypeAny, {
203
+ abi: string;
204
+ startBlock?: number | bigint | undefined;
205
+ }, {
206
+ abi: string;
207
+ startBlock?: number | bigint | undefined;
208
+ }>;
209
+ mapping: z.ZodObject<{
210
+ kind: z.ZodLiteral<"ethereum/events">;
211
+ apiVersion: z.ZodString;
212
+ language: z.ZodLiteral<"wasm/assemblyscript">;
213
+ entities: z.ZodArray<z.ZodString, "many">;
214
+ eventHandlers: z.ZodOptional<z.ZodArray<z.ZodObject<{
215
+ event: z.ZodString;
216
+ handler: z.ZodString;
217
+ topic0: z.ZodOptional<z.ZodString>;
218
+ }, "strip", z.ZodTypeAny, {
219
+ event: string;
220
+ handler: string;
221
+ topic0?: string | undefined;
222
+ }, {
223
+ event: string;
224
+ handler: string;
225
+ topic0?: string | undefined;
226
+ }>, "many">>;
227
+ callHandlers: z.ZodOptional<z.ZodArray<z.ZodObject<{
228
+ function: z.ZodString;
229
+ handler: z.ZodString;
230
+ }, "strip", z.ZodTypeAny, {
231
+ function: string;
232
+ handler: string;
233
+ }, {
234
+ function: string;
235
+ handler: string;
236
+ }>, "many">>;
237
+ blockHandlers: z.ZodOptional<z.ZodArray<z.ZodObject<{
238
+ handler: z.ZodString;
239
+ filter: z.ZodOptional<z.ZodObject<{
240
+ kind: z.ZodLiteral<"call">;
241
+ }, "strip", z.ZodTypeAny, {
242
+ kind: "call";
243
+ }, {
244
+ kind: "call";
245
+ }>>;
246
+ }, "strip", z.ZodTypeAny, {
247
+ handler: string;
248
+ filter?: {
249
+ kind: "call";
250
+ } | undefined;
251
+ }, {
252
+ handler: string;
253
+ filter?: {
254
+ kind: "call";
255
+ } | undefined;
256
+ }>, "many">>;
257
+ file: z.ZodString;
258
+ }, "strip", z.ZodTypeAny, {
259
+ file: string;
260
+ kind: "ethereum/events";
261
+ apiVersion: string;
262
+ language: "wasm/assemblyscript";
263
+ entities: string[];
264
+ eventHandlers?: {
265
+ event: string;
266
+ handler: string;
267
+ topic0?: string | undefined;
268
+ }[] | undefined;
269
+ callHandlers?: {
270
+ function: string;
271
+ handler: string;
272
+ }[] | undefined;
273
+ blockHandlers?: {
274
+ handler: string;
275
+ filter?: {
276
+ kind: "call";
277
+ } | undefined;
278
+ }[] | undefined;
279
+ }, {
280
+ file: string;
281
+ kind: "ethereum/events";
282
+ apiVersion: string;
283
+ language: "wasm/assemblyscript";
284
+ entities: string[];
285
+ eventHandlers?: {
286
+ event: string;
287
+ handler: string;
288
+ topic0?: string | undefined;
289
+ }[] | undefined;
290
+ callHandlers?: {
291
+ function: string;
292
+ handler: string;
293
+ }[] | undefined;
294
+ blockHandlers?: {
295
+ handler: string;
296
+ filter?: {
297
+ kind: "call";
298
+ } | undefined;
299
+ }[] | undefined;
300
+ }>;
301
+ }, "strip", z.ZodTypeAny, {
302
+ kind: string;
303
+ name: string;
304
+ network: string;
305
+ source: {
306
+ abi: string;
307
+ startBlock?: number | bigint | undefined;
308
+ };
309
+ mapping: {
310
+ file: string;
311
+ kind: "ethereum/events";
312
+ apiVersion: string;
313
+ language: "wasm/assemblyscript";
314
+ entities: string[];
315
+ eventHandlers?: {
316
+ event: string;
317
+ handler: string;
318
+ topic0?: string | undefined;
319
+ }[] | undefined;
320
+ callHandlers?: {
321
+ function: string;
322
+ handler: string;
323
+ }[] | undefined;
324
+ blockHandlers?: {
325
+ handler: string;
326
+ filter?: {
327
+ kind: "call";
328
+ } | undefined;
329
+ }[] | undefined;
330
+ };
331
+ }, {
332
+ kind: string;
333
+ name: string;
334
+ network: string;
335
+ source: {
336
+ abi: string;
337
+ startBlock?: number | bigint | undefined;
338
+ };
339
+ mapping: {
340
+ file: string;
341
+ kind: "ethereum/events";
342
+ apiVersion: string;
343
+ language: "wasm/assemblyscript";
344
+ entities: string[];
345
+ eventHandlers?: {
346
+ event: string;
347
+ handler: string;
348
+ topic0?: string | undefined;
349
+ }[] | undefined;
350
+ callHandlers?: {
351
+ function: string;
352
+ handler: string;
353
+ }[] | undefined;
354
+ blockHandlers?: {
355
+ handler: string;
356
+ filter?: {
357
+ kind: "call";
358
+ } | undefined;
359
+ }[] | undefined;
360
+ };
361
+ }>, "many">>;
362
+ }, "strip", z.ZodTypeAny, {
363
+ specVersion: string;
364
+ schema: {
365
+ file: string;
366
+ };
367
+ dataSources: {
368
+ kind: string;
369
+ name: string;
370
+ network: string;
371
+ source: {
372
+ address: string;
373
+ abi: string;
374
+ startBlock?: number | bigint | undefined;
375
+ };
376
+ mapping: {
377
+ file: string;
378
+ kind: "ethereum/events";
379
+ apiVersion: string;
380
+ language: "wasm/assemblyscript";
381
+ entities: string[];
382
+ eventHandlers?: {
383
+ event: string;
384
+ handler: string;
385
+ topic0?: string | undefined;
386
+ }[] | undefined;
387
+ callHandlers?: {
388
+ function: string;
389
+ handler: string;
390
+ }[] | undefined;
391
+ blockHandlers?: {
392
+ handler: string;
393
+ filter?: {
394
+ kind: "call";
395
+ } | undefined;
396
+ }[] | undefined;
397
+ };
398
+ }[];
399
+ description?: string | undefined;
400
+ repository?: string | undefined;
401
+ graft?: {
402
+ base: string;
403
+ block: bigint;
404
+ } | undefined;
405
+ templates?: {
406
+ kind: string;
407
+ name: string;
408
+ network: string;
409
+ source: {
410
+ abi: string;
411
+ startBlock?: number | bigint | undefined;
412
+ };
413
+ mapping: {
414
+ file: string;
415
+ kind: "ethereum/events";
416
+ apiVersion: string;
417
+ language: "wasm/assemblyscript";
418
+ entities: string[];
419
+ eventHandlers?: {
420
+ event: string;
421
+ handler: string;
422
+ topic0?: string | undefined;
423
+ }[] | undefined;
424
+ callHandlers?: {
425
+ function: string;
426
+ handler: string;
427
+ }[] | undefined;
428
+ blockHandlers?: {
429
+ handler: string;
430
+ filter?: {
431
+ kind: "call";
432
+ } | undefined;
433
+ }[] | undefined;
434
+ };
435
+ }[] | undefined;
436
+ }, {
437
+ specVersion: string;
438
+ schema: {
439
+ file: string;
440
+ };
441
+ dataSources: {
442
+ kind: string;
443
+ name: string;
444
+ network: string;
445
+ source: {
446
+ address: string;
447
+ abi: string;
448
+ startBlock?: number | bigint | undefined;
449
+ };
450
+ mapping: {
451
+ file: string;
452
+ kind: "ethereum/events";
453
+ apiVersion: string;
454
+ language: "wasm/assemblyscript";
455
+ entities: string[];
456
+ eventHandlers?: {
457
+ event: string;
458
+ handler: string;
459
+ topic0?: string | undefined;
460
+ }[] | undefined;
461
+ callHandlers?: {
462
+ function: string;
463
+ handler: string;
464
+ }[] | undefined;
465
+ blockHandlers?: {
466
+ handler: string;
467
+ filter?: {
468
+ kind: "call";
469
+ } | undefined;
470
+ }[] | undefined;
471
+ };
472
+ }[];
473
+ description?: string | undefined;
474
+ repository?: string | undefined;
475
+ graft?: {
476
+ base: string;
477
+ block: bigint;
478
+ } | undefined;
479
+ templates?: {
480
+ kind: string;
481
+ name: string;
482
+ network: string;
483
+ source: {
484
+ abi: string;
485
+ startBlock?: number | bigint | undefined;
486
+ };
487
+ mapping: {
488
+ file: string;
489
+ kind: "ethereum/events";
490
+ apiVersion: string;
491
+ language: "wasm/assemblyscript";
492
+ entities: string[];
493
+ eventHandlers?: {
494
+ event: string;
495
+ handler: string;
496
+ topic0?: string | undefined;
497
+ }[] | undefined;
498
+ callHandlers?: {
499
+ function: string;
500
+ handler: string;
501
+ }[] | undefined;
502
+ blockHandlers?: {
503
+ handler: string;
504
+ filter?: {
505
+ kind: "call";
506
+ } | undefined;
507
+ }[] | undefined;
508
+ };
509
+ }[] | undefined;
510
+ }>;
511
+ export type ManifestZodSchema = z.infer<typeof Manifest>;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Manifest = void 0;
4
+ const zod_1 = require("zod");
5
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#14-schema
6
+ const Schema = zod_1.z.object({
7
+ file: zod_1.z.string().describe('The path of the GraphQL IDL file, either local or on IPFS.'),
8
+ });
9
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#151-ethereumcontractsource
10
+ const EthereumContractSource = zod_1.z.object({
11
+ address: zod_1.z.string(),
12
+ abi: zod_1.z.string(),
13
+ startBlock: zod_1.z.union([zod_1.z.bigint(), zod_1.z.number()]).optional(),
14
+ });
15
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#151-ethereumcontractsource
16
+ const EthereumTemplateContractSource = zod_1.z.object({
17
+ abi: zod_1.z.string(),
18
+ startBlock: zod_1.z.union([zod_1.z.bigint(), zod_1.z.number()]).optional(),
19
+ });
20
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#1522-eventhandler
21
+ const EventHandler = zod_1.z.object({
22
+ event: zod_1.z
23
+ .string()
24
+ .describe('An identifier for an event that will be handled in the mapping script. For Ethereum contracts, this must be the full event signature to distinguish from events that may share the same name. No alias types can be used.'),
25
+ handler: zod_1.z
26
+ .string()
27
+ .describe('The name of an exported function in the mapping script that should handle the specified event.'),
28
+ topic0: zod_1.z
29
+ .string()
30
+ .optional()
31
+ .describe('A 0x prefixed hex string. If provided, events whose topic0 is equal to this value will be processed by the given handler. When topic0 is provided, only the topic0 value will be matched, and not the hash of the event signature. This is useful for processing anonymous events in Solidity, which can have their topic0 set to anything. By default, topic0 is equal to the hash of the event signature.'),
32
+ });
33
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#1523-callhandler
34
+ const CallHandler = zod_1.z.object({
35
+ function: zod_1.z
36
+ .string()
37
+ .describe('An identifier for a function that will be handled in the mapping script. For Ethereum contracts, this is the normalized function signature to filter calls by.'),
38
+ handler: zod_1.z
39
+ .string()
40
+ .describe('The name of an exported function in the mapping script that should handle the specified event.'),
41
+ });
42
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#15241-blockhandlerfilter
43
+ const BlockHandlerFilter = zod_1.z.object({
44
+ kind: zod_1.z.literal('call').describe('The selected block handler filter.'),
45
+ });
46
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#1524-blockhandler
47
+ const BlockHandler = zod_1.z.object({
48
+ handler: zod_1.z
49
+ .string()
50
+ .describe('The name of an exported function in the mapping script that should handle the specified event.'),
51
+ filter: BlockHandlerFilter.optional().describe('Definition of the filter to apply. If none is supplied, the handler will be called on every block.'),
52
+ });
53
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#1521-ethereum-mapping
54
+ const EthereumMapping = zod_1.z.object({
55
+ kind: zod_1.z
56
+ .literal('ethereum/events')
57
+ .describe('Must be "ethereum/events" for Ethereum Events Mapping.'),
58
+ apiVersion: zod_1.z
59
+ .string()
60
+ .describe('Semver string of the version of the Mappings API that will be used by the mapping script.'),
61
+ language: zod_1.z
62
+ .literal('wasm/assemblyscript')
63
+ .describe('The language of the runtime for the Mapping API.'),
64
+ entities: zod_1.z
65
+ .array(zod_1.z.string())
66
+ .describe('A list of entities that will be ingested as part of this mapping. Must correspond to names of entities in the GraphQL IDL.'),
67
+ eventHandlers: zod_1.z
68
+ .array(EventHandler)
69
+ .optional()
70
+ .describe('Handlers for specific events, which will be defined in the mapping script.'),
71
+ callHandlers: zod_1.z
72
+ .array(CallHandler)
73
+ .optional()
74
+ .describe('A list of functions that will trigger a handler and the name of the corresponding handlers in the mapping.'),
75
+ blockHandlers: zod_1.z
76
+ .array(BlockHandler)
77
+ .optional()
78
+ .describe('Defines block filters and handlers to process matching blocks.'),
79
+ file: zod_1.z.string().describe('The path of the mapping script.'),
80
+ });
81
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#152-mapping
82
+ const Mapping = EthereumMapping;
83
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#15-data-source
84
+ const DataSource = zod_1.z.object({
85
+ kind: zod_1.z.string().describe('The type of data source. Possible values: ethereum/contract.'),
86
+ name: zod_1.z
87
+ .string()
88
+ .describe('The name of the source data. Will be used to generate APIs in the mapping and also for self-documentation purposes.'),
89
+ network: zod_1.z
90
+ .string()
91
+ .describe('For blockchains, this describes which network the subgraph targets'),
92
+ source: EthereumContractSource.describe('The source data on a blockchain such as Ethereum.'),
93
+ mapping: Mapping.describe('The mapping that defines how to ingest the data.'),
94
+ });
95
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#17-data-source-templates
96
+ const TemplateSource = zod_1.z.object({
97
+ kind: zod_1.z.string().describe('The type of data source. Possible values: ethereum/contract.'),
98
+ name: zod_1.z
99
+ .string()
100
+ .describe('The name of the source data. Will be used to generate APIs in the mapping and also for self-documentation purposes.'),
101
+ network: zod_1.z
102
+ .string()
103
+ .describe('For blockchains, this describes which network the subgraph targets'),
104
+ source: EthereumTemplateContractSource.describe('The source data on a blockchain such as Ethereum.'),
105
+ mapping: Mapping.describe('The mapping that defines how to ingest the data.'),
106
+ });
107
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#18-graft-base
108
+ const GraftBase = zod_1.z.object({
109
+ base: zod_1.z.string().describe('The subgraph ID of the base subgraph'),
110
+ block: zod_1.z.bigint().describe('The block number up to which to use data from the base subgraph'),
111
+ });
112
+ // https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#13-top-level-api
113
+ exports.Manifest = zod_1.z.object({
114
+ specVersion: zod_1.z
115
+ .string()
116
+ .describe('A Semver version indicating which version of this API is being used.'),
117
+ schema: Schema.describe('The GraphQL schema of this subgraph.'),
118
+ description: zod_1.z.string().describe("An optional description of the subgraph's purpose.").optional(),
119
+ repository: zod_1.z.string().describe('An optional link to where the subgraph lives.').optional(),
120
+ graft: GraftBase.describe('An optional base to graft onto.').optional(),
121
+ dataSources: zod_1.z
122
+ .array(DataSource)
123
+ .describe("Each data source spec defines the data that will be ingested as well as the transformation logic to derive the state of the subgraph's entities based on the source data."),
124
+ templates: zod_1.z
125
+ .array(TemplateSource)
126
+ .optional()
127
+ .describe('Each data source template defines a data source that can be created dynamically from the mappings.'),
128
+ });
@@ -1,25 +1,105 @@
1
- import immutable from 'immutable';
2
1
  import { Subgraph as ISubgraph } from './protocols/subgraph';
2
+ import { ManifestZodSchema } from './manifest';
3
3
  type ResolveFile = (path: string) => string;
4
4
  export default class Subgraph {
5
5
  static validate(data: any, protocol: any, { resolveFile }: {
6
6
  resolveFile: ResolveFile;
7
7
  }): Promise<any>;
8
- static validateSchema(manifest: any, { resolveFile }: {
8
+ static validateSchema(manifest: ManifestZodSchema, { resolveFile }: {
9
9
  resolveFile: ResolveFile;
10
10
  }): void;
11
- static validateRepository(manifest: immutable.Collection<any, any>): immutable.List<unknown>;
12
- static validateDescription(manifest: immutable.Collection<any, any>): immutable.List<unknown>;
13
- static validateHandlers(manifest: immutable.Collection<any, any>, protocol: any, protocolSubgraph: ISubgraph): any;
14
- static validateContractValues(manifest: any, protocol: any): any;
15
- static validateUniqueDataSourceNames(manifest: any): any;
16
- static validateUniqueTemplateNames(manifest: any): any;
17
- static dump(manifest: any): string;
11
+ static validateRepository(manifest: ManifestZodSchema): {
12
+ path: string[];
13
+ message: string;
14
+ }[];
15
+ static validateDescription(manifest: ManifestZodSchema): {
16
+ path: string[];
17
+ message: string;
18
+ }[];
19
+ static validateHandlers(manifest: ManifestZodSchema, protocol: any, protocolSubgraph: ISubgraph): any;
20
+ static validateContractValues(manifest: ManifestZodSchema, protocol: any): any;
21
+ static validateUniqueDataSourceNames(manifest: ManifestZodSchema): any;
22
+ static validateUniqueTemplateNames(manifest: ManifestZodSchema): any;
23
+ static dump(manifest: ManifestZodSchema): string;
18
24
  static load(filename: string, { protocol, skipValidation }?: {
19
25
  protocol?: any;
20
26
  skipValidation?: boolean;
21
27
  }): Promise<{
22
- result: immutable.Map<any, any>;
28
+ result: {
29
+ specVersion: string;
30
+ schema: {
31
+ file: string;
32
+ };
33
+ dataSources: {
34
+ kind: string;
35
+ name: string;
36
+ network: string;
37
+ source: {
38
+ address: string;
39
+ abi: string;
40
+ startBlock?: number | bigint | undefined;
41
+ };
42
+ mapping: {
43
+ file: string;
44
+ kind: "ethereum/events";
45
+ apiVersion: string;
46
+ language: "wasm/assemblyscript";
47
+ entities: string[];
48
+ eventHandlers?: {
49
+ event: string;
50
+ handler: string;
51
+ topic0?: string | undefined;
52
+ }[] | undefined;
53
+ callHandlers?: {
54
+ function: string;
55
+ handler: string;
56
+ }[] | undefined;
57
+ blockHandlers?: {
58
+ handler: string;
59
+ filter?: {
60
+ kind: "call";
61
+ } | undefined;
62
+ }[] | undefined;
63
+ };
64
+ }[];
65
+ description?: string | undefined;
66
+ repository?: string | undefined;
67
+ graft?: {
68
+ base: string;
69
+ block: bigint;
70
+ } | undefined;
71
+ templates?: {
72
+ kind: string;
73
+ name: string;
74
+ network: string;
75
+ source: {
76
+ abi: string;
77
+ startBlock?: number | bigint | undefined;
78
+ };
79
+ mapping: {
80
+ file: string;
81
+ kind: "ethereum/events";
82
+ apiVersion: string;
83
+ language: "wasm/assemblyscript";
84
+ entities: string[];
85
+ eventHandlers?: {
86
+ event: string;
87
+ handler: string;
88
+ topic0?: string | undefined;
89
+ }[] | undefined;
90
+ callHandlers?: {
91
+ function: string;
92
+ handler: string;
93
+ }[] | undefined;
94
+ blockHandlers?: {
95
+ handler: string;
96
+ filter?: {
97
+ kind: "call";
98
+ } | undefined;
99
+ }[] | undefined;
100
+ };
101
+ }[] | undefined;
102
+ };
23
103
  warning: string | null;
24
104
  }>;
25
105
  static write(manifest: any, filename: string): Promise<void>;
package/dist/subgraph.js CHANGED
@@ -34,18 +34,19 @@ const yaml_1 = __importDefault(require("yaml"));
34
34
  const types_1 = require("yaml/types");
35
35
  const debug_1 = __importDefault(require("./debug"));
36
36
  const validation = __importStar(require("./validation"));
37
+ const manifest_1 = require("./manifest");
37
38
  const subgraphDebug = (0, debug_1.default)('graph-cli:subgraph');
38
39
  const throwCombinedError = (filename, errors) => {
39
40
  throw new Error(errors.reduce((msg, e) => `${msg}
40
41
 
41
- Path: ${e.get('path').size === 0 ? '/' : e.get('path').join(' > ')}
42
- ${e.get('message').split('\n').join('\n ')}`, `Error in ${path_1.default.relative(process.cwd(), filename)}:`));
42
+ Path: ${e.path.length === 0 ? '/' : e.path.join(' > ')}
43
+ ${e.message.split('\n').join('\n ')}`, `Error in ${path_1.default.relative(process.cwd(), filename)}:`));
43
44
  };
44
- const buildCombinedWarning = (filename, warnings) => warnings.size > 0
45
+ const buildCombinedWarning = (filename, warnings) => warnings.length > 0
45
46
  ? warnings.reduce((msg, w) => `${msg}
46
47
 
47
- Path: ${w.get('path').size === 0 ? '/' : w.get('path').join(' > ')}
48
- ${w.get('message').split('\n').join('\n ')}`, `Warnings in ${path_1.default.relative(process.cwd(), filename)}:`) + '\n'
48
+ Path: ${w.path.length === 0 ? '/' : w.path.join(' > ')}
49
+ ${w.message.split('\n').join('\n ')}`, `Warnings in ${path_1.default.relative(process.cwd(), filename)}:`) + '\n'
49
50
  : null;
50
51
  class Subgraph {
51
52
  static async validate(data, protocol, { resolveFile }) {
@@ -66,10 +67,12 @@ class Subgraph {
66
67
  return definition.name.value === 'SubgraphManifest';
67
68
  });
68
69
  // Validate the subgraph manifest using this schema
69
- return validation.validateManifest(data, rootType, schema, protocol, { resolveFile });
70
+ return validation.validateManifest(data, rootType, schema, protocol, {
71
+ resolveFile,
72
+ });
70
73
  }
71
74
  static validateSchema(manifest, { resolveFile }) {
72
- const filename = resolveFile(manifest.getIn(['schema', 'file']));
75
+ const filename = resolveFile(manifest.schema.file);
73
76
  const validationErrors = validation.validateSchema(filename);
74
77
  let errors;
75
78
  if (validationErrors.size > 0) {
@@ -94,103 +97,106 @@ class Subgraph {
94
97
  }
95
98
  }
96
99
  static validateRepository(manifest) {
97
- const repository = manifest.get('repository');
100
+ const repository = manifest.repository;
101
+ // repository is optional, so no need to throw error if it's not set
102
+ if (!repository)
103
+ return [];
98
104
  return /^https:\/\/github\.com\/graphprotocol\/graph-tooling?$/.test(repository) ||
99
105
  // For legacy reasons, we should error on example subgraphs
100
106
  /^https:\/\/github\.com\/graphprotocol\/example-subgraphs?$/.test(repository)
101
- ? immutable_1.default.List().push(immutable_1.default.fromJS({
102
- path: ['repository'],
103
- message: `\
107
+ ? [
108
+ {
109
+ path: ['repository'],
110
+ message: `\
104
111
  The repository is still set to ${repository}.
105
112
  Please replace it with a link to your subgraph source code.`,
106
- }))
107
- : immutable_1.default.List();
113
+ },
114
+ ]
115
+ : [];
108
116
  }
109
117
  static validateDescription(manifest) {
110
118
  // TODO: Maybe implement this in the future for each protocol example description
111
- return manifest.get('description', '').startsWith('Gravatar for ')
112
- ? immutable_1.default.List().push(immutable_1.default.fromJS({
113
- path: ['description'],
114
- message: `\
119
+ return (manifest?.description || '').startsWith('Gravatar for ')
120
+ ? [
121
+ {
122
+ path: ['description'],
123
+ message: `\
115
124
  The description is still the one from the example subgraph.
116
125
  Please update it to tell users more about your subgraph.`,
117
- }))
118
- : immutable_1.default.List();
126
+ },
127
+ ]
128
+ : [];
119
129
  }
120
130
  static validateHandlers(manifest, protocol, protocolSubgraph) {
121
- return manifest
122
- .get('dataSources')
123
- .filter((dataSource) => protocol.isValidKindName(dataSource.get('kind')))
131
+ return manifest.dataSources
132
+ .filter(dataSource => protocol.isValidKindName(dataSource.kind))
124
133
  .reduce((errors, dataSource, dataSourceIndex) => {
125
134
  const path = ['dataSources', dataSourceIndex, 'mapping'];
126
- const mapping = dataSource.get('mapping');
135
+ const mapping = dataSource.mapping;
127
136
  const handlerTypes = protocolSubgraph.handlerTypes();
128
- subgraphDebug('Validating dataSource "%s" handlers with %d handlers types defined for protocol', dataSource.get('name'), handlerTypes.size);
137
+ subgraphDebug('Validating dataSource "%s" handlers with %d handlers types defined for protocol', dataSource.name, handlerTypes.size);
129
138
  if (handlerTypes.size == 0) {
130
139
  return errors;
131
140
  }
132
141
  const areAllHandlersEmpty = handlerTypes
133
- .map((handlerType) => mapping.get(handlerType, immutable_1.default.List()))
134
- .every((handlers) => handlers.isEmpty());
142
+ // @ts-expect-error TODO: handlerTypes needs to be improved
143
+ .map(handlerType => mapping?.[handlerType] || [])
144
+ .every(handlers => handlers.length === 0);
135
145
  const handlerNamesWithoutLast = handlerTypes.pop().join(', ');
136
146
  return areAllHandlersEmpty
137
- ? errors.push(immutable_1.default.fromJS({
147
+ ? errors.push({
138
148
  path,
139
149
  message: `\
140
150
  Mapping has no ${handlerNamesWithoutLast} or ${handlerTypes.get(-1)}.
141
151
  At least one such handler must be defined.`,
142
- }))
152
+ })
143
153
  : errors;
144
- }, immutable_1.default.List());
154
+ }, []);
145
155
  }
146
156
  static validateContractValues(manifest, protocol) {
147
157
  if (!protocol.hasContract()) {
148
- return immutable_1.default.List();
158
+ return [];
149
159
  }
150
160
  return validation.validateContractValues(manifest, protocol);
151
161
  }
152
162
  // Validate that data source names are unique, so they don't overwrite each other.
153
163
  static validateUniqueDataSourceNames(manifest) {
154
164
  const names = [];
155
- return manifest
156
- .get('dataSources')
157
- .reduce((errors, dataSource, dataSourceIndex) => {
165
+ return manifest.dataSources.reduce((errors, dataSource, dataSourceIndex) => {
158
166
  const path = ['dataSources', dataSourceIndex, 'name'];
159
- const name = dataSource.get('name');
167
+ const name = dataSource.name;
160
168
  if (names.includes(name)) {
161
- errors = errors.push(immutable_1.default.fromJS({
169
+ errors = errors.push({
162
170
  path,
163
171
  message: `\
164
172
  More than one data source named '${name}', data source names must be unique.`,
165
- }));
173
+ });
166
174
  }
167
175
  names.push(name);
168
176
  return errors;
169
- }, immutable_1.default.List());
177
+ }, []);
170
178
  }
171
179
  static validateUniqueTemplateNames(manifest) {
172
180
  const names = [];
173
- return manifest
174
- .get('templates', immutable_1.default.List())
175
- .reduce((errors, template, templateIndex) => {
181
+ return (manifest?.templates || []).reduce((errors, template, templateIndex) => {
176
182
  const path = ['templates', templateIndex, 'name'];
177
- const name = template.get('name');
183
+ const name = template.name;
178
184
  if (names.includes(name)) {
179
- errors = errors.push(immutable_1.default.fromJS({
185
+ errors = errors.push({
180
186
  path,
181
187
  message: `\
182
188
  More than one template named '${name}', template names must be unique.`,
183
- }));
189
+ });
184
190
  }
185
191
  names.push(name);
186
192
  return errors;
187
- }, immutable_1.default.List());
193
+ }, []);
188
194
  }
189
195
  static dump(manifest) {
190
196
  types_1.strOptions.fold.lineWidth = 90;
191
197
  // @ts-expect-error TODO: plain is the value behind the TS constant
192
198
  types_1.strOptions.defaultType = 'PLAIN';
193
- return yaml_1.default.stringify(manifest.toJS());
199
+ return yaml_1.default.stringify(manifest);
194
200
  }
195
201
  static async load(filename, { protocol, skipValidation } = {
196
202
  skipValidation: false,
@@ -210,12 +216,18 @@ More than one template named '${name}', template names must be unique.`,
210
216
  const resolveFile = maybeRelativeFile => path_1.default.resolve(path_1.default.dirname(filename), maybeRelativeFile);
211
217
  // TODO: Validation for file data sources
212
218
  if (!has_file_data_sources) {
213
- const manifestErrors = await Subgraph.validate(data, protocol, { resolveFile });
219
+ const manifestErrors = await Subgraph.validate(data, protocol, {
220
+ resolveFile,
221
+ });
214
222
  if (manifestErrors.size > 0) {
215
223
  throwCombinedError(filename, manifestErrors);
216
224
  }
217
225
  }
218
- const manifest = immutable_1.default.fromJS(data);
226
+ const manifestSchema = manifest_1.Manifest.safeParse(data);
227
+ if (!manifestSchema.success) {
228
+ throw new Error(manifestSchema.error.message);
229
+ }
230
+ const manifest = manifestSchema.data;
219
231
  // Validate the schema
220
232
  Subgraph.validateSchema(manifest, { resolveFile });
221
233
  // Perform other validations
@@ -224,18 +236,24 @@ More than one template named '${name}', template names must be unique.`,
224
236
  resolveFile,
225
237
  });
226
238
  const errors = skipValidation
227
- ? immutable_1.default.List()
228
- : immutable_1.default.List.of(...protocolSubgraph.validateManifest(), ...Subgraph.validateContractValues(manifest, protocol), ...Subgraph.validateUniqueDataSourceNames(manifest), ...Subgraph.validateUniqueTemplateNames(manifest), ...Subgraph.validateHandlers(manifest, protocol, protocolSubgraph));
229
- if (errors.size > 0) {
239
+ ? []
240
+ : [
241
+ ...protocolSubgraph.validateManifest(),
242
+ ...Subgraph.validateContractValues(manifest, protocol),
243
+ ...Subgraph.validateUniqueDataSourceNames(manifest),
244
+ ...Subgraph.validateUniqueTemplateNames(manifest),
245
+ ...Subgraph.validateHandlers(manifest, protocol, protocolSubgraph),
246
+ ];
247
+ if (errors.length > 0) {
230
248
  throwCombinedError(filename, errors);
231
249
  }
232
250
  // Perform warning validations
233
251
  const warnings = skipValidation
234
- ? immutable_1.default.List()
235
- : immutable_1.default.List.of(...Subgraph.validateRepository(manifest), ...Subgraph.validateDescription(manifest));
252
+ ? []
253
+ : [...Subgraph.validateRepository(manifest), ...Subgraph.validateDescription(manifest)];
236
254
  return {
237
255
  result: manifest,
238
- warning: warnings.size > 0 ? buildCombinedWarning(filename, warnings) : null,
256
+ warning: warnings.length > 0 ? buildCombinedWarning(filename, warnings) : null,
239
257
  };
240
258
  }
241
259
  static async write(manifest, filename) {
@@ -1,6 +1,6 @@
1
- import immutable from 'immutable';
2
1
  import Protocol from '../protocols';
3
2
  import { ContractCtor } from '../protocols/contract';
3
+ import { ManifestZodSchema } from '../manifest';
4
4
  export declare const validateContract: (value: string, ProtocolContract: ContractCtor) => {
5
5
  valid: false;
6
6
  error: string;
@@ -8,4 +8,4 @@ export declare const validateContract: (value: string, ProtocolContract: Contrac
8
8
  valid: true;
9
9
  error: string | null;
10
10
  };
11
- export declare const validateContractValues: (manifest: immutable.Map<any, any>, protocol: Protocol) => any;
11
+ export declare const validateContractValues: (manifest: ManifestZodSchema, protocol: Protocol) => any;
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.validateContractValues = exports.validateContract = void 0;
7
- const immutable_1 = __importDefault(require("immutable"));
8
4
  const validateContract = (value, ProtocolContract) => {
9
5
  const contract = new ProtocolContract(value);
10
6
  const { valid, error } = contract.validate();
@@ -20,25 +16,26 @@ exports.validateContract = validateContract;
20
16
  const validateContractValues = (manifest, protocol) => {
21
17
  const ProtocolContract = protocol.getContract();
22
18
  const fieldName = ProtocolContract.identifierName();
23
- return manifest
24
- .get('dataSources')
25
- .filter((dataSource) => protocol.isValidKindName(dataSource.get('kind')))
19
+ return manifest.dataSources
20
+ .filter(datasource => protocol.isValidKindName(datasource.kind))
26
21
  .reduce((errors, dataSource, dataSourceIndex) => {
27
22
  const path = ['dataSources', dataSourceIndex, 'source', fieldName];
28
23
  // No need to validate if the source has no contract field
29
- if (!dataSource.get('source').has(fieldName)) {
24
+ // @ts-expect-error TODO: we need to rework the classes to make this `fieldName` not be a string
25
+ if (!dataSource.source[fieldName]) {
30
26
  return errors;
31
27
  }
32
- const contractValue = dataSource.getIn(['source', fieldName]);
28
+ // @ts-expect-error TODO: we need to rework the classes to make this `fieldName` not be a string
29
+ const contractValue = dataSource.source[fieldName];
33
30
  const { valid, error } = (0, exports.validateContract)(contractValue, ProtocolContract);
34
31
  // Validate whether the contract is valid for the protocol
35
32
  if (valid) {
36
33
  return errors;
37
34
  }
38
- return errors.push(immutable_1.default.fromJS({
35
+ return errors.push({
39
36
  path,
40
37
  message: error,
41
- }));
42
- }, immutable_1.default.List());
38
+ });
39
+ }, []);
43
40
  };
44
41
  exports.validateContractValues = validateContractValues;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.53.0",
2
+ "version": "0.54.0-alpha-20230724180700-d5ce4e2",
3
3
  "commands": {
4
4
  "add": {
5
5
  "id": "add",
@@ -561,6 +561,12 @@
561
561
  "from-contract"
562
562
  ]
563
563
  },
564
+ "skip-install": {
565
+ "name": "skip-install",
566
+ "type": "boolean",
567
+ "summary": "Skip installing dependencies.",
568
+ "allowNo": false
569
+ },
564
570
  "start-block": {
565
571
  "name": "start-block",
566
572
  "type": "option",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.53.0",
3
+ "version": "0.54.0-alpha-20230724180700-d5ce4e2",
4
4
  "description": "CLI for building for and deploying to The Graph",
5
5
  "license": "(Apache-2.0 OR MIT)",
6
6
  "engines": {
@@ -44,13 +44,15 @@
44
44
  "tmp-promise": "3.0.3",
45
45
  "web3-eth-abi": "1.7.0",
46
46
  "which": "2.0.2",
47
- "yaml": "1.10.2"
47
+ "yaml": "1.10.2",
48
+ "zod": "^3.21.4"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@types/debug": "^4.1.7",
51
52
  "@types/fs-extra": "^9.0.13",
52
53
  "@types/jest": "^29.0.0",
53
54
  "@types/js-yaml": "^3.12.7",
55
+ "@types/node": "^20.3.2",
54
56
  "@types/semver": "^7.3.13",
55
57
  "@types/which": "^2.0.1",
56
58
  "copyfiles": "^2.4.1",
@@ -59,7 +61,8 @@
59
61
  "spawn-command": "0.0.2-1",
60
62
  "strip-ansi": "6.0.1",
61
63
  "tern": "0.24.3",
62
- "typescript": "^5.0.0"
64
+ "typescript": "^5.0.0",
65
+ "zod-to-json-schema": "^3.21.3"
63
66
  },
64
67
  "publishConfig": {
65
68
  "access": "public"
@@ -75,7 +78,7 @@
75
78
  ]
76
79
  },
77
80
  "scripts": {
78
- "build": "tsc -b tsconfig.build.json && oclif manifest && oclif readme && copyfiles -u 1 src/**/*.graphql dist/",
81
+ "build": "tsc -b tsconfig.build.json && oclif manifest && oclif readme && copyfiles -u 1 src/**/*.graphql dist/ && node scripts/generate-json-schema.mjs",
79
82
  "oclif:pack": "npm pack && pnpm oclif pack tarballs --no-xz && node scripts/rename-tarballs.mjs",
80
83
  "test": "jest --verbose",
81
84
  "test:add": "jest tests/cli/add.test.ts --verbose",