@graphprotocol/graph-cli 0.50.0-alpha-20230523132328-eb6bf7e → 0.50.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.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,14 @@
1
1
  # @graphprotocol/graph-cli
2
2
 
3
- ## 0.50.0-alpha-20230523132328-eb6bf7e
3
+ ## 0.50.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
+ - [#1353](https://github.com/graphprotocol/graph-tooling/pull/1353)
8
+ [`125c687`](https://github.com/graphprotocol/graph-tooling/commit/125c6874e9d2fb67bf9f0211e9f9f306bc6fe55c)
9
+ Thanks [@saihaj](https://github.com/saihaj)! - Add a new `--ipfs-hash` flag to `graph deploy`
10
+ allowing to deploy a subgraph that is already compiled and uploaded to IPFS.
11
+
7
12
  - [#1335](https://github.com/graphprotocol/graph-tooling/pull/1335)
8
13
  [`7343f50`](https://github.com/graphprotocol/graph-tooling/commit/7343f50c0e2b767de04909e6020b88fea97ae3cd)
9
14
  Thanks [@saihaj](https://github.com/saihaj)! - For substreams generate the directory tree as
@@ -48,6 +53,10 @@
48
53
  - Updated dependency [`gluegun@5.1.2` ↗︎](https://www.npmjs.com/package/gluegun/v/5.1.2) (from
49
54
  `https://github.com/edgeandnode/gluegun#v4.3.1-pin-colors-dep`, in `dependencies`)
50
55
 
56
+ - [#1351](https://github.com/graphprotocol/graph-tooling/pull/1351)
57
+ [`c7cf89c`](https://github.com/graphprotocol/graph-tooling/commit/c7cf89c2b7b60b39bd89473d8440ece2acdcb9a3)
58
+ Thanks [@saihaj](https://github.com/saihaj)! - return tuple arrays as a Bytes array in GraphQL
59
+
51
60
  - [#1329](https://github.com/graphprotocol/graph-tooling/pull/1329)
52
61
  [`308cb8a`](https://github.com/graphprotocol/graph-tooling/commit/308cb8af3fb2cabbad08f409d77481994a95865c)
53
62
  Thanks [@saihaj](https://github.com/saihaj)! - Point to new examples repo instead of old
@@ -295,6 +295,7 @@ const ASSEMBLYSCRIPT_TO_VALUE = [
295
295
  ],
296
296
  ['Array<Array<string>>', /\[\[.*\]\]/, (code) => `Value.fromStringMatrix(${code})`],
297
297
  ['Array<Array<string | null>>', null, (code) => `Value.fromStringMatrix(${code})`],
298
+ ['Array<ethereum.Tuple>', '[Bytes]', (code) => `Value.fromArray(${code})`],
298
299
  // Arrays
299
300
  ['Array<Address>', '[Bytes]', (code) => `Value.fromBytesArray(${code})`],
300
301
  ['Array<Bytes>', '[Bytes]', (code) => `Value.fromBytesArray(${code})`],
@@ -1,4 +1,5 @@
1
1
  import immutable from 'immutable';
2
2
  import Protocol from '../protocols';
3
3
  export declare const fromFilePath: (manifestPath: string) => Promise<any>;
4
+ export declare function fromManifestString(manifest: string): any;
4
5
  export declare const fromManifest: (manifest: immutable.Map<any, any>, protocol: Protocol) => any;
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.fromManifest = exports.fromFilePath = void 0;
6
+ exports.fromManifest = exports.fromManifestString = exports.fromFilePath = void 0;
7
+ const js_yaml_1 = __importDefault(require("js-yaml"));
7
8
  const immutable_1 = __importDefault(require("immutable"));
8
9
  const load_manifest_1 = require("../migrations/util/load-manifest");
9
10
  // Loads manifest from file path and returns all:
@@ -15,6 +16,16 @@ const fromFilePath = async (manifestPath) => {
15
16
  return dataSources.concat(templates);
16
17
  };
17
18
  exports.fromFilePath = fromFilePath;
19
+ // Loads manifest from file path and returns all:
20
+ // - data sources
21
+ // - templates
22
+ // In a single list.
23
+ function fromManifestString(manifest) {
24
+ // TODO: can we make it typesafe?
25
+ const { dataSources = [], templates = [] } = (js_yaml_1.default.safeLoad(manifest) || {});
26
+ return dataSources.concat(templates);
27
+ }
28
+ exports.fromManifestString = fromManifestString;
18
29
  const extractDataSourceByType = (manifest, dataSourceType, protocol) => manifest
19
30
  .get(dataSourceType, immutable_1.default.List())
20
31
  .reduce((dataSources, dataSource, dataSourceIndex) => protocol.isValidKindName(dataSource.get('kind'))
@@ -14,6 +14,7 @@ export default class DeployCommand extends Command {
14
14
  'access-token': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
15
15
  'version-label': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
16
16
  ipfs: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
17
+ 'ipfs-hash': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
17
18
  headers: import("@oclif/core/lib/interfaces").OptionFlag<Record<string, string> | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
18
19
  'debug-fork': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
19
20
  'output-dir': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
@@ -40,6 +40,7 @@ const node_1 = require("../command-helpers/node");
40
40
  const studio_1 = require("../command-helpers/studio");
41
41
  const version_1 = require("../command-helpers/version");
42
42
  const protocols_1 = __importDefault(require("../protocols"));
43
+ const ipfs_http_client_1 = require("ipfs-http-client");
43
44
  const headersFlag = core_1.Flags.custom({
44
45
  summary: 'Add custom headers that will be used by the IPFS HTTP client.',
45
46
  aliases: ['hdr'],
@@ -49,7 +50,7 @@ const headersFlag = core_1.Flags.custom({
49
50
  const productOptions = ['subgraph-studio', 'hosted-service'];
50
51
  class DeployCommand extends core_1.Command {
51
52
  async run() {
52
- const { args: { 'subgraph-name': subgraphNameArg, 'subgraph-manifest': manifest }, flags: { product: productFlag, studio, 'deploy-key': deployKeyFlag, 'access-token': accessToken, 'version-label': versionLabelFlag, ipfs, headers, node: nodeFlag, 'output-dir': outputDir, 'skip-migrations': skipMigrations, watch, 'debug-fork': debugFork, network, 'network-file': networkFile, }, } = await this.parse(DeployCommand);
53
+ const { args: { 'subgraph-name': subgraphNameArg, 'subgraph-manifest': manifest }, flags: { product: productFlag, studio, 'deploy-key': deployKeyFlag, 'access-token': accessToken, 'version-label': versionLabelFlag, ipfs, headers, node: nodeFlag, 'output-dir': outputDir, 'skip-migrations': skipMigrations, watch, 'debug-fork': debugFork, network, 'network-file': networkFile, 'ipfs-hash': ipfsHash, }, } = await this.parse(DeployCommand);
53
54
  const subgraphName = subgraphNameArg ||
54
55
  (await core_1.ux.prompt('What is the subgraph name?', {
55
56
  required: true,
@@ -71,15 +72,6 @@ class DeployCommand extends core_1.Command {
71
72
  },
72
73
  ])
73
74
  .then(({ product }) => product));
74
- try {
75
- const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifest);
76
- for (const { network } of dataSourcesAndTemplates) {
77
- (0, studio_1.validateStudioNetwork)({ studio, product, network });
78
- }
79
- }
80
- catch (e) {
81
- this.error(e, { exit: 1 });
82
- }
83
75
  const { node } = (0, node_1.chooseNodeUrl)({
84
76
  product,
85
77
  studio,
@@ -89,49 +81,8 @@ class DeployCommand extends core_1.Command {
89
81
  // shouldn't happen, but we do the check to satisfy TS
90
82
  this.error('No Graph node provided');
91
83
  }
92
- let protocol;
93
- try {
94
- // Checks to make sure deploy doesn't run against
95
- // older subgraphs (both apiVersion and graph-ts version).
96
- //
97
- // We don't want the deploy to run without these conditions
98
- // because that would mean the CLI would try to compile code
99
- // using the wrong AssemblyScript compiler.
100
- await (0, version_1.assertManifestApiVersion)(manifest, '0.0.5');
101
- await (0, version_1.assertGraphTsVersion)(path_1.default.dirname(manifest), '0.25.0');
102
- const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifest);
103
- protocol = protocols_1.default.fromDataSources(dataSourcesAndTemplates);
104
- }
105
- catch (e) {
106
- this.error(e, { exit: 1 });
107
- }
108
- if (network) {
109
- const identifierName = protocol.getContract().identifierName();
110
- await (0, network_1.updateSubgraphNetwork)(manifest, network, networkFile, identifierName);
111
- }
112
84
  const isStudio = node.match(/studio/);
113
85
  const isHostedService = node.match(/thegraph.com/) && !isStudio;
114
- const compiler = (0, compiler_1.createCompiler)(manifest, {
115
- ipfs,
116
- headers,
117
- outputDir,
118
- outputFormat: 'wasm',
119
- skipMigrations,
120
- blockIpfsMethods: isStudio || undefined,
121
- protocol,
122
- });
123
- // Exit with an error code if the compiler couldn't be created
124
- if (!compiler) {
125
- this.exit(1);
126
- return;
127
- }
128
- // Ask for label if not on hosted service
129
- let versionLabel = versionLabelFlag;
130
- if (!versionLabel && !isHostedService) {
131
- versionLabel = await core_1.ux.prompt('Which version label to use? (e.g. "v0.0.1")', {
132
- required: true,
133
- });
134
- }
135
86
  const requestUrl = new url_1.URL(node);
136
87
  const client = (0, jsonrpc_1.createJsonRpcClient)(requestUrl);
137
88
  // Exit with an error code if the client couldn't be created
@@ -149,6 +100,13 @@ class DeployCommand extends core_1.Command {
149
100
  // @ts-expect-error options property seems to exist
150
101
  client.options.headers = { Authorization: 'Bearer ' + deployKey };
151
102
  }
103
+ // Ask for label if not on hosted service
104
+ let versionLabel = versionLabelFlag;
105
+ if (!versionLabel && !isHostedService) {
106
+ versionLabel = await core_1.ux.prompt('Which version label to use? (e.g. "v0.0.1")', {
107
+ required: true,
108
+ });
109
+ }
152
110
  // eslint-disable-next-line @typescript-eslint/no-this-alias -- request needs it
153
111
  const self = this;
154
112
  const deploySubgraph = async (ipfsHash) => {
@@ -175,8 +133,8 @@ class DeployCommand extends core_1.Command {
175
133
  }
176
134
  else {
177
135
  errorMessage += `
178
- Make sure to create the subgraph first by running the following command:
179
- $ graph create --node ${node} ${subgraphName}`;
136
+ Make sure to create the subgraph first by running the following command:
137
+ $ graph create --node ${node} ${subgraphName}`;
180
138
  }
181
139
  }
182
140
  self.error(errorMessage, { exit: 1 });
@@ -206,9 +164,79 @@ $ graph create --node ${node} ${subgraphName}`;
206
164
  gluegun_1.print.info('\nSubgraph endpoints:');
207
165
  gluegun_1.print.info(`Queries (HTTP): ${queries}`);
208
166
  gluegun_1.print.info(``);
167
+ process.exit(0);
209
168
  }
210
169
  });
211
170
  };
171
+ // we are provided the IPFS hash, so we deploy directly
172
+ if (ipfsHash) {
173
+ // Connect to the IPFS node (if a node address was provided)
174
+ const ipfsClient = (0, ipfs_http_client_1.create)({ url: (0, compiler_1.appendApiVersionForGraph)(ipfs.toString()), headers });
175
+ // Fetch the manifest from IPFS
176
+ const manifestBuffer = ipfsClient.cat(ipfsHash);
177
+ let manifestFile = '';
178
+ for await (const chunk of manifestBuffer) {
179
+ manifestFile += chunk.toString();
180
+ }
181
+ if (!manifestFile) {
182
+ this.error(`Could not find subgraph manifest at IPFS hash ${ipfsHash}`, { exit: 1 });
183
+ }
184
+ await ipfsClient.pin.add(ipfsHash);
185
+ try {
186
+ const dataSourcesAndTemplates = DataSourcesExtractor.fromManifestString(manifestFile);
187
+ for (const { network } of dataSourcesAndTemplates) {
188
+ (0, studio_1.validateStudioNetwork)({ studio, product, network });
189
+ }
190
+ }
191
+ catch (e) {
192
+ this.error(e, { exit: 1 });
193
+ }
194
+ await deploySubgraph(ipfsHash);
195
+ return;
196
+ }
197
+ try {
198
+ const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifest);
199
+ for (const { network } of dataSourcesAndTemplates) {
200
+ (0, studio_1.validateStudioNetwork)({ studio, product, network });
201
+ }
202
+ }
203
+ catch (e) {
204
+ this.error(e, { exit: 1 });
205
+ }
206
+ let protocol;
207
+ try {
208
+ // Checks to make sure deploy doesn't run against
209
+ // older subgraphs (both apiVersion and graph-ts version).
210
+ //
211
+ // We don't want the deploy to run without these conditions
212
+ // because that would mean the CLI would try to compile code
213
+ // using the wrong AssemblyScript compiler.
214
+ await (0, version_1.assertManifestApiVersion)(manifest, '0.0.5');
215
+ await (0, version_1.assertGraphTsVersion)(path_1.default.dirname(manifest), '0.25.0');
216
+ const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifest);
217
+ protocol = protocols_1.default.fromDataSources(dataSourcesAndTemplates);
218
+ }
219
+ catch (e) {
220
+ this.error(e, { exit: 1 });
221
+ }
222
+ if (network) {
223
+ const identifierName = protocol.getContract().identifierName();
224
+ await (0, network_1.updateSubgraphNetwork)(manifest, network, networkFile, identifierName);
225
+ }
226
+ const compiler = (0, compiler_1.createCompiler)(manifest, {
227
+ ipfs,
228
+ headers,
229
+ outputDir,
230
+ outputFormat: 'wasm',
231
+ skipMigrations,
232
+ blockIpfsMethods: isStudio || undefined,
233
+ protocol,
234
+ });
235
+ // Exit with an error code if the compiler couldn't be created
236
+ if (!compiler) {
237
+ this.exit(1);
238
+ return;
239
+ }
212
240
  if (watch) {
213
241
  await compiler.watchAndCompile(async (ipfsHash) => {
214
242
  if (ipfsHash !== undefined) {
@@ -268,6 +296,10 @@ DeployCommand.flags = {
268
296
  char: 'i',
269
297
  default: ipfs_1.DEFAULT_IPFS_URL,
270
298
  }),
299
+ 'ipfs-hash': core_1.Flags.string({
300
+ summary: 'IPFS hash of the subgraph manifest to deploy.',
301
+ required: false,
302
+ }),
271
303
  headers: headersFlag(),
272
304
  'debug-fork': core_1.Flags.string({
273
305
  summary: 'ID of a remote subgraph whose store will be GraphQL queried.',
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.50.0-alpha-20230523132328-eb6bf7e",
2
+ "version": "0.50.0",
3
3
  "commands": {
4
4
  "add": {
5
5
  "id": "add",
@@ -362,6 +362,13 @@
362
362
  "multiple": false,
363
363
  "default": "https://api.thegraph.com/ipfs/api/v0"
364
364
  },
365
+ "ipfs-hash": {
366
+ "name": "ipfs-hash",
367
+ "type": "option",
368
+ "summary": "IPFS hash of the subgraph manifest to deploy.",
369
+ "required": false,
370
+ "multiple": false
371
+ },
365
372
  "headers": {
366
373
  "name": "headers",
367
374
  "type": "option",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.50.0-alpha-20230523132328-eb6bf7e",
3
+ "version": "0.50.0",
4
4
  "description": "CLI for building for and deploying to The Graph",
5
5
  "license": "(Apache-2.0 OR MIT)",
6
6
  "engines": {