@graphprotocol/graph-cli 0.49.0-alpha-20230504181204-a99dddd → 0.49.0-alpha-20230505103249-d3fbf0b
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 +1 -39
- package/dist/codegen/schema.d.ts +7 -0
- package/dist/codegen/schema.js +97 -0
- package/dist/codegen/schema.test.js +2 -7
- package/dist/command-helpers/scaffold.d.ts +0 -8
- package/dist/commands/init.js +214 -231
- package/dist/protocols/index.js +8 -1
- package/dist/scaffold/index.d.ts +0 -9
- package/dist/scaffold/index.js +0 -27
- package/dist/type-generator.js +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @graphprotocol/graph-cli
|
|
2
2
|
|
|
3
|
-
## 0.49.0-alpha-
|
|
3
|
+
## 0.49.0-alpha-20230505103249-d3fbf0b
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
@@ -9,49 +9,11 @@
|
|
|
9
9
|
Thanks [@saihaj](https://github.com/saihaj)! - do not generate types, instead show a message to
|
|
10
10
|
user to use substreams CLI for codegen.
|
|
11
11
|
|
|
12
|
-
- [#1335](https://github.com/graphprotocol/graph-tooling/pull/1335)
|
|
13
|
-
[`6bd042b`](https://github.com/graphprotocol/graph-tooling/commit/6bd042bb5dd8facff02450c874e8811aebc83fcc)
|
|
14
|
-
Thanks [@saihaj](https://github.com/saihaj)! - For substreams generate the directory tree as
|
|
15
|
-
follows
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
.
|
|
19
|
-
├── package.json
|
|
20
|
-
├── schema.graphql
|
|
21
|
-
└── subgraph.yaml
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
In the `package.json` we only depend on the CLI since that is what developer will use to deploy
|
|
25
|
-
the subgraph. The `schema.graphql` is the schema of the subgraph and the `subgraph.yaml` is the
|
|
26
|
-
manifest file for the subgraph.
|
|
27
|
-
|
|
28
|
-
- [#1335](https://github.com/graphprotocol/graph-tooling/pull/1335)
|
|
29
|
-
[`f90dd75`](https://github.com/graphprotocol/graph-tooling/commit/f90dd757a558f4e66cc46780f13612309f45646a)
|
|
30
|
-
Thanks [@saihaj](https://github.com/saihaj)! - remove index events as entities for substreams
|
|
31
|
-
|
|
32
12
|
- [#1306](https://github.com/graphprotocol/graph-tooling/pull/1306)
|
|
33
13
|
[`f5e4b58`](https://github.com/graphprotocol/graph-tooling/commit/f5e4b58989edc5f3bb8211f1b912449e77832de8)
|
|
34
14
|
Thanks [@saihaj](https://github.com/saihaj)! - Add loadInBlock function for entities as part of
|
|
35
15
|
codegen
|
|
36
16
|
|
|
37
|
-
- [#1335](https://github.com/graphprotocol/graph-tooling/pull/1335)
|
|
38
|
-
[`f90dd75`](https://github.com/graphprotocol/graph-tooling/commit/f90dd757a558f4e66cc46780f13612309f45646a)
|
|
39
|
-
Thanks [@saihaj](https://github.com/saihaj)! - remove start block selection for substreams
|
|
40
|
-
|
|
41
|
-
### Patch Changes
|
|
42
|
-
|
|
43
|
-
- [#1335](https://github.com/graphprotocol/graph-tooling/pull/1335)
|
|
44
|
-
[`aac26c9`](https://github.com/graphprotocol/graph-tooling/commit/aac26c97b5427156f8d61311924bac215155b4cb)
|
|
45
|
-
Thanks [@saihaj](https://github.com/saihaj)! - dependencies updates:
|
|
46
|
-
|
|
47
|
-
- Updated dependency [`gluegun@5.1.2` ↗︎](https://www.npmjs.com/package/gluegun/v/5.1.2) (from
|
|
48
|
-
`https://github.com/edgeandnode/gluegun#v4.3.1-pin-colors-dep`, in `dependencies`)
|
|
49
|
-
|
|
50
|
-
- [#1331](https://github.com/graphprotocol/graph-tooling/pull/1331)
|
|
51
|
-
[`b2c8dec`](https://github.com/graphprotocol/graph-tooling/commit/b2c8decb7806d25df6ca4e07f6dfdf7941516435)
|
|
52
|
-
Thanks [@saihaj](https://github.com/saihaj)! - only allow mainnet for substreams in network
|
|
53
|
-
selection for init
|
|
54
|
-
|
|
55
17
|
## 0.48.0
|
|
56
18
|
|
|
57
19
|
### Minor Changes
|
package/dist/codegen/schema.d.ts
CHANGED
|
@@ -21,13 +21,20 @@ export default class SchemaCodeGenerator {
|
|
|
21
21
|
constructor(schema: Schema);
|
|
22
22
|
generateModuleImports(): tsCodegen.ModuleImports[];
|
|
23
23
|
generateTypes(): Array<tsCodegen.Class>;
|
|
24
|
+
generateDerivedLoaders(): any[];
|
|
24
25
|
_isEntityTypeDefinition(def: DefinitionNode): def is ObjectTypeDefinitionNode;
|
|
26
|
+
_isDerivedField(field: any): boolean;
|
|
25
27
|
_isInterfaceDefinition(def: DefinitionNode): def is InterfaceTypeDefinitionNode;
|
|
26
28
|
_generateEntityType(def: ObjectTypeDefinitionNode): tsCodegen.Class;
|
|
29
|
+
_generateDerivedLoader(typeName: string): any;
|
|
30
|
+
_getTypeNameForField(gqlType: TypeNode): string;
|
|
27
31
|
_generateConstructor(_entityName: string, fields: readonly FieldDefinitionNode[] | undefined): tsCodegen.Method;
|
|
28
32
|
_generateStoreMethods(entityName: string, idField: IdField): Array<tsCodegen.Method | tsCodegen.StaticMethod>;
|
|
29
33
|
_generateEntityFieldMethods(entityDef: ObjectTypeDefinitionNode, fieldDef: FieldDefinitionNode): Array<tsCodegen.Method>;
|
|
30
34
|
_generateEntityFieldGetter(_entityDef: ObjectTypeDefinitionNode, fieldDef: FieldDefinitionNode): tsCodegen.Method;
|
|
35
|
+
_generateDerivedFieldGetter(entityDef: any, fieldDef: FieldDefinitionNode): tsCodegen.Method;
|
|
36
|
+
_returnTypeForDervied(gqlType: any): any;
|
|
37
|
+
_generatedEntityDerivedFieldGetter(_entityDef: any, fieldDef: FieldDefinitionNode): tsCodegen.Method;
|
|
31
38
|
_generateEntityFieldSetter(_entityDef: ObjectTypeDefinitionNode, fieldDef: FieldDefinitionNode): tsCodegen.Method | null;
|
|
32
39
|
_resolveFieldType(gqlType: NamedTypeNode): string;
|
|
33
40
|
/** Return the type that values for this field must have. For scalar
|
package/dist/codegen/schema.js
CHANGED
|
@@ -22,7 +22,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
/* eslint-disable unicorn/no-array-for-each */
|
|
30
|
+
const debug_1 = __importDefault(require("debug"));
|
|
26
31
|
const typesCodegen = __importStar(require("./types"));
|
|
27
32
|
const tsCodegen = __importStar(require("./typescript"));
|
|
28
33
|
class IdField {
|
|
@@ -98,10 +103,24 @@ class SchemaCodeGenerator {
|
|
|
98
103
|
})
|
|
99
104
|
.filter(Boolean);
|
|
100
105
|
}
|
|
106
|
+
generateDerivedLoaders() {
|
|
107
|
+
const fields = this.schema.ast.definitions
|
|
108
|
+
.filter(def => this._isEntityTypeDefinition(def))
|
|
109
|
+
.flatMap((def) => def.fields)
|
|
110
|
+
.filter((def) => this._isDerivedField(def))
|
|
111
|
+
.map((def) => this._getTypeNameForField(def.type));
|
|
112
|
+
return [...new Set(fields)].map((typeName) => {
|
|
113
|
+
return this._generateDerivedLoader(typeName);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
101
116
|
_isEntityTypeDefinition(def) {
|
|
102
117
|
return (def.kind === 'ObjectTypeDefinition' &&
|
|
103
118
|
def.directives?.find(directive => directive.name.value === 'entity') !== undefined);
|
|
104
119
|
}
|
|
120
|
+
_isDerivedField(field) {
|
|
121
|
+
return (field.directives?.find((directive) => directive.name.value === 'derivedFrom') !==
|
|
122
|
+
undefined);
|
|
123
|
+
}
|
|
105
124
|
_isInterfaceDefinition(def) {
|
|
106
125
|
return def.kind === 'InterfaceTypeDefinition';
|
|
107
126
|
}
|
|
@@ -120,6 +139,42 @@ class SchemaCodeGenerator {
|
|
|
120
139
|
.forEach((method) => klass.addMethod(method));
|
|
121
140
|
return klass;
|
|
122
141
|
}
|
|
142
|
+
_generateDerivedLoader(typeName) {
|
|
143
|
+
// <field>Loader
|
|
144
|
+
const klass = tsCodegen.klass(`${typeName}Loader`, { export: true, extends: 'Entity' });
|
|
145
|
+
klass.addMember(tsCodegen.klassMember('_entity', 'string'));
|
|
146
|
+
klass.addMember(tsCodegen.klassMember('_field', 'string'));
|
|
147
|
+
klass.addMember(tsCodegen.klassMember('_id', 'string'));
|
|
148
|
+
// Generate and add a constructor
|
|
149
|
+
klass.addMethod(tsCodegen.method('constructor', [
|
|
150
|
+
tsCodegen.param('entity', 'string'),
|
|
151
|
+
tsCodegen.param('id', 'string'),
|
|
152
|
+
tsCodegen.param('field', 'string'),
|
|
153
|
+
], undefined, `
|
|
154
|
+
super();
|
|
155
|
+
this._entity = entity;
|
|
156
|
+
this._id = id;
|
|
157
|
+
this._field = field;
|
|
158
|
+
`));
|
|
159
|
+
// Generate load() method for the Loader
|
|
160
|
+
klass.addMethod(tsCodegen.method('load', [], `${typeName}[]`, `
|
|
161
|
+
let value = store.loadRelated(this._entity, this._id, this._field);
|
|
162
|
+
return changetype<${typeName}[]>(value);
|
|
163
|
+
`));
|
|
164
|
+
return klass;
|
|
165
|
+
}
|
|
166
|
+
_getTypeNameForField(gqlType) {
|
|
167
|
+
if (gqlType.kind === 'NonNullType') {
|
|
168
|
+
return this._getTypeNameForField(gqlType.type);
|
|
169
|
+
}
|
|
170
|
+
if (gqlType.kind === 'ListType') {
|
|
171
|
+
return this._getTypeNameForField(gqlType.type);
|
|
172
|
+
}
|
|
173
|
+
if (gqlType.kind === 'NamedType') {
|
|
174
|
+
return gqlType.name.value;
|
|
175
|
+
}
|
|
176
|
+
throw new Error(`Unknown type kind: ${gqlType}`);
|
|
177
|
+
}
|
|
123
178
|
_generateConstructor(_entityName, fields) {
|
|
124
179
|
const idField = IdField.fromFields(fields);
|
|
125
180
|
return tsCodegen.method('constructor', [tsCodegen.param('id', idField.tsNamedType())], undefined, `
|
|
@@ -156,6 +211,12 @@ class SchemaCodeGenerator {
|
|
|
156
211
|
.filter(Boolean);
|
|
157
212
|
}
|
|
158
213
|
_generateEntityFieldGetter(_entityDef, fieldDef) {
|
|
214
|
+
const isDerivedField = this._isDerivedField(fieldDef);
|
|
215
|
+
const codegenDebug = (0, debug_1.default)('codegen');
|
|
216
|
+
if (isDerivedField) {
|
|
217
|
+
codegenDebug(`Generating derived field getter for ${fieldDef.name.value}`);
|
|
218
|
+
return this._generateDerivedFieldGetter(_entityDef, fieldDef);
|
|
219
|
+
}
|
|
159
220
|
const name = fieldDef.name.value;
|
|
160
221
|
const gqlType = fieldDef.type;
|
|
161
222
|
const fieldValueType = this._valueTypeFromGraphQl(gqlType);
|
|
@@ -179,6 +240,42 @@ class SchemaCodeGenerator {
|
|
|
179
240
|
${isNullable ? getNullable : getNonNullable}
|
|
180
241
|
`);
|
|
181
242
|
}
|
|
243
|
+
_generateDerivedFieldGetter(entityDef, fieldDef) {
|
|
244
|
+
const entityName = entityDef.name.value;
|
|
245
|
+
const name = fieldDef.name.value;
|
|
246
|
+
const gqlType = fieldDef.type;
|
|
247
|
+
const returnType = this._returnTypeForDervied(gqlType);
|
|
248
|
+
return tsCodegen.method(`get ${name}`, [], returnType, `
|
|
249
|
+
return new ${returnType}('${entityName}', this.get('id')!.toString(), '${name}')
|
|
250
|
+
`);
|
|
251
|
+
}
|
|
252
|
+
_returnTypeForDervied(gqlType) {
|
|
253
|
+
if (gqlType.kind === 'NonNullType') {
|
|
254
|
+
return this._returnTypeForDervied(gqlType.type);
|
|
255
|
+
}
|
|
256
|
+
if (gqlType.kind === 'ListType') {
|
|
257
|
+
return this._returnTypeForDervied(gqlType.type);
|
|
258
|
+
}
|
|
259
|
+
const type = tsCodegen.namedType(gqlType.name.value + 'Loader');
|
|
260
|
+
return type;
|
|
261
|
+
}
|
|
262
|
+
_generatedEntityDerivedFieldGetter(_entityDef, fieldDef) {
|
|
263
|
+
const name = fieldDef.name.value;
|
|
264
|
+
const gqlType = fieldDef.type;
|
|
265
|
+
const fieldValueType = this._valueTypeFromGraphQl(gqlType);
|
|
266
|
+
const returnType = this._typeFromGraphQl(gqlType);
|
|
267
|
+
const isNullable = returnType instanceof tsCodegen.NullableType;
|
|
268
|
+
const getNonNullable = `return ${typesCodegen.valueToAsc('value!', fieldValueType)}`;
|
|
269
|
+
const getNullable = `if (!value || value.kind == ValueKind.NULL) {
|
|
270
|
+
return null
|
|
271
|
+
} else {
|
|
272
|
+
return ${typesCodegen.valueToAsc('value', fieldValueType)}
|
|
273
|
+
}`;
|
|
274
|
+
return tsCodegen.method(`get ${name}`, [], returnType, `
|
|
275
|
+
let value = this.get('${name}')
|
|
276
|
+
${isNullable ? getNullable : getNonNullable}
|
|
277
|
+
`);
|
|
278
|
+
}
|
|
182
279
|
_generateEntityFieldSetter(_entityDef, fieldDef) {
|
|
183
280
|
const name = fieldDef.name.value;
|
|
184
281
|
const isDerivedField = !!fieldDef.directives?.find(directive => directive.name.value === 'derivedFrom');
|
|
@@ -276,14 +276,9 @@ describe('Schema code generator', () => {
|
|
|
276
276
|
{
|
|
277
277
|
name: 'get wallets',
|
|
278
278
|
params: [],
|
|
279
|
-
returnType: new typescript_1.
|
|
279
|
+
returnType: new typescript_1.NamedType('WalletLoader'),
|
|
280
280
|
body: `
|
|
281
|
-
|
|
282
|
-
if (!value || value.kind == ValueKind.NULL) {
|
|
283
|
-
return null
|
|
284
|
-
} else {
|
|
285
|
-
return value.toStringArray()
|
|
286
|
-
}
|
|
281
|
+
return new WalletLoader("Account", this.get('id')!.toString(), "wallets")
|
|
287
282
|
`,
|
|
288
283
|
},
|
|
289
284
|
],
|
|
@@ -14,14 +14,6 @@ export declare const generateScaffold: ({ protocolInstance, abi, contract, netwo
|
|
|
14
14
|
startBlock?: string | undefined;
|
|
15
15
|
node?: string | undefined;
|
|
16
16
|
}, spinner: Spinner) => Promise<{
|
|
17
|
-
'subgraph.yaml': string;
|
|
18
|
-
'schema.graphql': string;
|
|
19
|
-
'package.json': string;
|
|
20
|
-
'tsconfig.json'?: undefined;
|
|
21
|
-
src?: undefined;
|
|
22
|
-
abis?: undefined;
|
|
23
|
-
tests?: undefined;
|
|
24
|
-
} | {
|
|
25
17
|
'package.json': string;
|
|
26
18
|
'subgraph.yaml': string;
|
|
27
19
|
'schema.graphql': string;
|
package/dist/commands/init.js
CHANGED
|
@@ -39,10 +39,12 @@ const scaffold_1 = require("../command-helpers/scaffold");
|
|
|
39
39
|
const spinner_1 = require("../command-helpers/spinner");
|
|
40
40
|
const studio_1 = require("../command-helpers/studio");
|
|
41
41
|
const subgraph_1 = require("../command-helpers/subgraph");
|
|
42
|
+
const debug_1 = __importDefault(require("../debug"));
|
|
42
43
|
const protocols_1 = __importDefault(require("../protocols"));
|
|
43
44
|
const schema_1 = require("../scaffold/schema");
|
|
44
45
|
const validation_1 = require("../validation");
|
|
45
46
|
const add_1 = __importDefault(require("./add"));
|
|
47
|
+
const initDebug = (0, debug_1.default)('graph-cli:init');
|
|
46
48
|
const protocolChoices = Array.from(protocols_1.default.availableProtocols().keys());
|
|
47
49
|
const availableNetworks = protocols_1.default.availableNetworks();
|
|
48
50
|
const DEFAULT_EXAMPLE_SUBGRAPH = 'ethereum/gravatar';
|
|
@@ -83,18 +85,8 @@ class InitCommand extends core_1.Command {
|
|
|
83
85
|
};
|
|
84
86
|
// If all parameters are provided from the command-line,
|
|
85
87
|
// go straight to creating the subgraph from the example
|
|
86
|
-
if (fromExample && subgraphName && directory
|
|
87
|
-
await initSubgraphFromExample.bind(this)({
|
|
88
|
-
fromExample,
|
|
89
|
-
allowSimpleName,
|
|
90
|
-
directory,
|
|
91
|
-
subgraphName,
|
|
92
|
-
studio,
|
|
93
|
-
product,
|
|
94
|
-
protocolInstance: new protocols_1.default(protocol),
|
|
95
|
-
}, { commands });
|
|
96
|
-
// Exit with success
|
|
97
|
-
return this.exit(0);
|
|
88
|
+
if (fromExample && subgraphName && directory) {
|
|
89
|
+
return await initSubgraphFromExample.bind(this)({ fromExample, allowSimpleName, directory, subgraphName, studio, product }, { commands });
|
|
98
90
|
}
|
|
99
91
|
// Will be assigned below if ethereum
|
|
100
92
|
let abi;
|
|
@@ -130,7 +122,7 @@ class InitCommand extends core_1.Command {
|
|
|
130
122
|
}
|
|
131
123
|
}
|
|
132
124
|
}
|
|
133
|
-
await initSubgraphFromContract.bind(this)({
|
|
125
|
+
return await initSubgraphFromContract.bind(this)({
|
|
134
126
|
protocolInstance,
|
|
135
127
|
abi,
|
|
136
128
|
allowSimpleName,
|
|
@@ -145,8 +137,6 @@ class InitCommand extends core_1.Command {
|
|
|
145
137
|
product,
|
|
146
138
|
startBlock,
|
|
147
139
|
}, { commands, addContract: false });
|
|
148
|
-
// Exit with success
|
|
149
|
-
return this.exit(0);
|
|
150
140
|
}
|
|
151
141
|
// Otherwise, take the user through the interactive form
|
|
152
142
|
const answers = await processInitForm.bind(this)({
|
|
@@ -176,7 +166,6 @@ class InitCommand extends core_1.Command {
|
|
|
176
166
|
directory: answers.directory,
|
|
177
167
|
studio: answers.studio,
|
|
178
168
|
product: answers.product,
|
|
179
|
-
protocolInstance: answers.protocolInstance,
|
|
180
169
|
}, { commands });
|
|
181
170
|
}
|
|
182
171
|
else {
|
|
@@ -202,8 +191,6 @@ class InitCommand extends core_1.Command {
|
|
|
202
191
|
startBlock: answers.startBlock,
|
|
203
192
|
}, { commands, addContract: true });
|
|
204
193
|
}
|
|
205
|
-
// Exit with success
|
|
206
|
-
this.exit(0);
|
|
207
194
|
}
|
|
208
195
|
}
|
|
209
196
|
InitCommand.description = 'Creates a new subgraph with basic scaffolding.';
|
|
@@ -278,224 +265,227 @@ InitCommand.flags = {
|
|
|
278
265
|
}),
|
|
279
266
|
};
|
|
280
267
|
exports.default = InitCommand;
|
|
281
|
-
async function processInitForm({ protocol
|
|
268
|
+
async function processInitForm({ protocol, product, studio, node, abi, allowSimpleName, directory, contract, indexEvents, fromExample, network, subgraphName, contractName, startBlock, }) {
|
|
282
269
|
let abiFromEtherscan = undefined;
|
|
283
|
-
|
|
284
|
-
|
|
270
|
+
let abiFromFile = undefined;
|
|
271
|
+
let protocolInstance;
|
|
272
|
+
let ProtocolContract;
|
|
273
|
+
let ABI;
|
|
274
|
+
const questions = [
|
|
275
|
+
{
|
|
285
276
|
type: 'select',
|
|
286
277
|
name: 'protocol',
|
|
287
278
|
message: 'Protocol',
|
|
288
279
|
choices: protocolChoices,
|
|
289
|
-
skip: protocolChoices.includes(String(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
type: 'select',
|
|
296
|
-
name: 'product',
|
|
297
|
-
message: 'Product for which to initialize',
|
|
298
|
-
choices: ['subgraph-studio', 'hosted-service'],
|
|
299
|
-
skip: protocol === 'arweave' ||
|
|
300
|
-
protocol === 'cosmos' ||
|
|
301
|
-
protocol === 'near' ||
|
|
302
|
-
initProduct === 'subgraph-studio' ||
|
|
303
|
-
initProduct === 'hosted-service' ||
|
|
304
|
-
initStudio !== undefined ||
|
|
305
|
-
initNode !== undefined,
|
|
306
|
-
result: value => {
|
|
307
|
-
if (initProduct)
|
|
308
|
-
return initProduct;
|
|
309
|
-
if (initStudio)
|
|
310
|
-
return 'subgraph-studio';
|
|
311
|
-
// For now we only support NEAR subgraphs in the Hosted Service
|
|
312
|
-
if (protocol === 'near') {
|
|
313
|
-
return 'hosted-service';
|
|
314
|
-
}
|
|
315
|
-
if (value == 'subgraph-studio') {
|
|
316
|
-
initAllowSimpleName = true;
|
|
317
|
-
}
|
|
318
|
-
return value;
|
|
319
|
-
},
|
|
280
|
+
skip: protocolChoices.includes(String(protocol)),
|
|
281
|
+
result: (value) => {
|
|
282
|
+
// eslint-disable-next-line -- prettier has problems with ||=
|
|
283
|
+
protocol = protocol || value;
|
|
284
|
+
protocolInstance = new protocols_1.default(protocol);
|
|
285
|
+
return protocol;
|
|
320
286
|
},
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
type: 'select',
|
|
290
|
+
name: 'product',
|
|
291
|
+
message: 'Product for which to initialize',
|
|
292
|
+
choices: ['subgraph-studio', 'hosted-service'],
|
|
293
|
+
skip: () => protocol === 'arweave' ||
|
|
294
|
+
protocol === 'cosmos' ||
|
|
295
|
+
protocol === 'near' ||
|
|
296
|
+
product === 'subgraph-studio' ||
|
|
297
|
+
product === 'hosted-service' ||
|
|
298
|
+
studio !== undefined ||
|
|
299
|
+
node !== undefined,
|
|
300
|
+
result: (value) => {
|
|
301
|
+
// For now we only support NEAR subgraphs in the Hosted Service
|
|
302
|
+
if (protocol === 'near') {
|
|
303
|
+
// Can be overwritten because the question will be skipped (product === undefined)
|
|
304
|
+
product = 'hosted-service';
|
|
305
|
+
return product;
|
|
306
|
+
}
|
|
307
|
+
if (value == 'subgraph-studio') {
|
|
308
|
+
allowSimpleName = true;
|
|
309
|
+
}
|
|
310
|
+
product = value;
|
|
311
|
+
return value;
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
type: 'input',
|
|
316
|
+
name: 'subgraphName',
|
|
317
|
+
message: () => (product == 'subgraph-studio' || studio ? 'Subgraph slug' : 'Subgraph name'),
|
|
318
|
+
initial: subgraphName,
|
|
319
|
+
validate: (name) => {
|
|
320
|
+
try {
|
|
321
|
+
(0, subgraph_1.validateSubgraphName)(name, { allowSimpleName });
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
catch (e) {
|
|
325
|
+
return `${e.message}
|
|
335
326
|
|
|
336
|
-
|
|
327
|
+
Examples:
|
|
337
328
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
},
|
|
329
|
+
$ graph init ${os_1.default.userInfo().username}/${name}
|
|
330
|
+
$ graph init ${name} --allow-simple-name`;
|
|
331
|
+
}
|
|
342
332
|
},
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
type: 'input',
|
|
347
|
-
name: 'directory',
|
|
348
|
-
message: 'Directory to create the subgraph in',
|
|
349
|
-
initial: () => initDirectory || (0, subgraph_1.getSubgraphBasename)(subgraphName),
|
|
350
|
-
validate: value => gluegun_1.filesystem.exists(value || initDirectory || (0, subgraph_1.getSubgraphBasename)(subgraphName))
|
|
351
|
-
? 'Directory already exists'
|
|
352
|
-
: true,
|
|
333
|
+
result: (value) => {
|
|
334
|
+
subgraphName = value;
|
|
335
|
+
return value;
|
|
353
336
|
},
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
type: 'input',
|
|
340
|
+
name: 'directory',
|
|
341
|
+
message: 'Directory to create the subgraph in',
|
|
342
|
+
initial: () => directory ||
|
|
343
|
+
(0, subgraph_1.getSubgraphBasename)(
|
|
344
|
+
// @ts-expect-error will be set by previous question
|
|
345
|
+
subgraphName),
|
|
346
|
+
validate: (value) => gluegun_1.filesystem.exists(value ||
|
|
347
|
+
directory ||
|
|
348
|
+
(0, subgraph_1.getSubgraphBasename)(
|
|
349
|
+
// @ts-expect-error will be set by previous question
|
|
350
|
+
subgraphName))
|
|
351
|
+
? 'Directory already exists'
|
|
352
|
+
: true,
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
type: 'select',
|
|
356
|
+
name: 'network',
|
|
357
|
+
message: () => `${protocolInstance.displayName()} network`,
|
|
358
|
+
choices: () => {
|
|
359
|
+
initDebug('Generating list of available networks for protocol "%s" (%M)', protocol, availableNetworks.get(protocol));
|
|
360
|
+
return (
|
|
361
|
+
// @ts-expect-error TODO: wait what?
|
|
362
|
+
availableNetworks
|
|
361
363
|
.get(protocol) // Get networks related to the chosen protocol.
|
|
362
|
-
|
|
363
|
-
skip: initFromExample !== undefined,
|
|
364
|
-
result: value => {
|
|
365
|
-
if (initNetwork)
|
|
366
|
-
return initNetwork;
|
|
367
|
-
return value;
|
|
368
|
-
},
|
|
364
|
+
.toArray()); // Needed because of gluegun. It can't even receive a JS iterable.
|
|
369
365
|
},
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
catch (e) {
|
|
411
|
-
// noop
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
// If startBlock is not set, try to load it.
|
|
415
|
-
if (!initStartBlock) {
|
|
416
|
-
try {
|
|
417
|
-
// Load startBlock for this contract
|
|
418
|
-
initStartBlock = Number(await (0, abi_1.loadStartBlockForContract)(network, value)).toString();
|
|
366
|
+
skip: fromExample !== undefined,
|
|
367
|
+
initial: network || 'mainnet',
|
|
368
|
+
result: (value) => {
|
|
369
|
+
network = value;
|
|
370
|
+
return value;
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
// TODO:
|
|
374
|
+
//
|
|
375
|
+
// protocols that don't support contract
|
|
376
|
+
// - arweave
|
|
377
|
+
// - cosmos
|
|
378
|
+
{
|
|
379
|
+
type: 'input',
|
|
380
|
+
name: 'contract',
|
|
381
|
+
message: () => {
|
|
382
|
+
ProtocolContract = protocolInstance.getContract();
|
|
383
|
+
return `Contract ${ProtocolContract.identifierName()}`;
|
|
384
|
+
},
|
|
385
|
+
skip: () => fromExample !== undefined || !protocolInstance.hasContract(),
|
|
386
|
+
initial: contract,
|
|
387
|
+
validate: async (value) => {
|
|
388
|
+
if (fromExample !== undefined || !protocolInstance.hasContract()) {
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
// Validate whether the contract is valid
|
|
392
|
+
const { valid, error } = (0, validation_1.validateContract)(value, ProtocolContract);
|
|
393
|
+
return valid ? true : error;
|
|
394
|
+
},
|
|
395
|
+
result: async (value) => {
|
|
396
|
+
if (fromExample !== undefined) {
|
|
397
|
+
return value;
|
|
398
|
+
}
|
|
399
|
+
ABI = protocolInstance.getABI();
|
|
400
|
+
// Try loading the ABI from Etherscan, if none was provided
|
|
401
|
+
if (protocolInstance.hasABIs() && !abi) {
|
|
402
|
+
try {
|
|
403
|
+
if (network === 'poa-core') {
|
|
404
|
+
// TODO: this variable is never used anywhere, what happens?
|
|
405
|
+
// abiFromBlockScout = await loadAbiFromBlockScout(ABI, network, value)
|
|
419
406
|
}
|
|
420
|
-
|
|
421
|
-
|
|
407
|
+
else {
|
|
408
|
+
abiFromEtherscan = await (0, abi_1.loadAbiFromEtherscan)(ABI, network, value);
|
|
422
409
|
}
|
|
423
410
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
},
|
|
427
|
-
]);
|
|
428
|
-
const { abi: abiFromFile } = await gluegun_1.prompt.ask([
|
|
429
|
-
{
|
|
430
|
-
type: 'input',
|
|
431
|
-
name: 'abi',
|
|
432
|
-
message: 'ABI file (path)',
|
|
433
|
-
initial: initAbi,
|
|
434
|
-
skip: () => !protocolInstance.hasABIs() ||
|
|
435
|
-
initFromExample !== undefined ||
|
|
436
|
-
abiFromEtherscan !== undefined ||
|
|
437
|
-
isSubstreams,
|
|
438
|
-
validate: async (value) => {
|
|
439
|
-
if (initFromExample || abiFromEtherscan || !protocolInstance.hasABIs()) {
|
|
440
|
-
return true;
|
|
411
|
+
catch (e) {
|
|
412
|
+
// noop
|
|
441
413
|
}
|
|
442
|
-
|
|
414
|
+
}
|
|
415
|
+
// If startBlock is not set, try to load it.
|
|
416
|
+
if (!startBlock) {
|
|
443
417
|
try {
|
|
444
|
-
|
|
418
|
+
// Load startBlock for this contract
|
|
419
|
+
startBlock = Number(await (0, abi_1.loadStartBlockForContract)(network, value)).toString();
|
|
445
420
|
}
|
|
446
|
-
catch (
|
|
447
|
-
|
|
421
|
+
catch (error) {
|
|
422
|
+
// noop
|
|
448
423
|
}
|
|
449
|
-
}
|
|
424
|
+
}
|
|
425
|
+
return value;
|
|
450
426
|
},
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
type: 'input',
|
|
430
|
+
name: 'abi',
|
|
431
|
+
message: 'ABI file (path)',
|
|
432
|
+
initial: abi,
|
|
433
|
+
skip: () => !protocolInstance.hasABIs() || fromExample !== undefined || abiFromEtherscan !== undefined,
|
|
434
|
+
validate: async (value) => {
|
|
435
|
+
if (fromExample || abiFromEtherscan || !protocolInstance.hasABIs()) {
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
try {
|
|
439
|
+
abiFromFile = loadAbiFromFile(ABI, value);
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
catch (e) {
|
|
443
|
+
return e.message;
|
|
444
|
+
}
|
|
465
445
|
},
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
type: 'input',
|
|
449
|
+
name: 'startBlock',
|
|
450
|
+
message: 'Start Block',
|
|
451
|
+
initial: () => startBlock || '0',
|
|
452
|
+
skip: () => fromExample !== undefined,
|
|
453
|
+
validate: (value) => parseInt(value) >= 0,
|
|
454
|
+
result: (value) => {
|
|
455
|
+
startBlock = value;
|
|
456
|
+
return value;
|
|
475
457
|
},
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
type: 'input',
|
|
461
|
+
name: 'contractName',
|
|
462
|
+
message: 'Contract Name',
|
|
463
|
+
initial: contractName || 'Contract',
|
|
464
|
+
skip: () => fromExample !== undefined || !protocolInstance.hasContract(),
|
|
465
|
+
validate: (value) => value && value.length > 0,
|
|
466
|
+
result: (value) => {
|
|
467
|
+
contractName = value;
|
|
468
|
+
return value;
|
|
484
469
|
},
|
|
485
|
-
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
type: 'confirm',
|
|
473
|
+
name: 'indexEvents',
|
|
474
|
+
message: 'Index contract events as entities',
|
|
475
|
+
initial: true,
|
|
476
|
+
skip: () => !!indexEvents,
|
|
477
|
+
result: (value) => {
|
|
478
|
+
indexEvents = value;
|
|
479
|
+
return value;
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
];
|
|
483
|
+
try {
|
|
484
|
+
const answers = await gluegun_1.prompt.ask(questions);
|
|
486
485
|
return {
|
|
486
|
+
...answers,
|
|
487
487
|
abi: abiFromEtherscan || abiFromFile,
|
|
488
488
|
protocolInstance,
|
|
489
|
-
subgraphName,
|
|
490
|
-
directory,
|
|
491
|
-
studio: product === 'subgraph-studio',
|
|
492
|
-
startBlock,
|
|
493
|
-
fromExample: !!initFromExample,
|
|
494
|
-
product,
|
|
495
|
-
network,
|
|
496
|
-
contractName,
|
|
497
|
-
contract,
|
|
498
|
-
indexEvents,
|
|
499
489
|
};
|
|
500
490
|
}
|
|
501
491
|
catch (e) {
|
|
@@ -573,8 +563,7 @@ Subgraph ${subgraphName} created in ${relativeDir}
|
|
|
573
563
|
|
|
574
564
|
Make sure to visit the documentation on https://thegraph.com/docs/ for further information.`);
|
|
575
565
|
}
|
|
576
|
-
async function initSubgraphFromExample({
|
|
577
|
-
const isSubstreams = protocolInstance.name === 'substreams';
|
|
566
|
+
async function initSubgraphFromExample({ fromExample, allowSimpleName, subgraphName, directory, studio, product, }, { commands, }) {
|
|
578
567
|
// Fail if the subgraph name is invalid
|
|
579
568
|
if (!revalidateSubgraphName.bind(this)(subgraphName, { allowSimpleName })) {
|
|
580
569
|
process.exitCode = 1;
|
|
@@ -667,18 +656,15 @@ async function initSubgraphFromExample({ protocolInstance, fromExample, allowSim
|
|
|
667
656
|
this.exit(1);
|
|
668
657
|
return;
|
|
669
658
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
return;
|
|
676
|
-
}
|
|
659
|
+
// Run code-generation
|
|
660
|
+
const codegen = await runCodegen(directory, commands.codegen);
|
|
661
|
+
if (codegen !== true) {
|
|
662
|
+
this.exit(1);
|
|
663
|
+
return;
|
|
677
664
|
}
|
|
678
665
|
printNextSteps.bind(this)({ subgraphName, directory }, { commands });
|
|
679
666
|
}
|
|
680
667
|
async function initSubgraphFromContract({ protocolInstance, allowSimpleName, subgraphName, directory, abi, network, contract, indexEvents, contractName, node, studio, product, startBlock, }, { commands, addContract, }) {
|
|
681
|
-
const isSubstreams = protocolInstance.name === 'substreams';
|
|
682
668
|
// Fail if the subgraph name is invalid
|
|
683
669
|
if (!revalidateSubgraphName.bind(this)(subgraphName, { allowSimpleName })) {
|
|
684
670
|
this.exit(1);
|
|
@@ -744,17 +730,14 @@ async function initSubgraphFromContract({ protocolInstance, allowSimpleName, sub
|
|
|
744
730
|
this.exit(1);
|
|
745
731
|
return;
|
|
746
732
|
}
|
|
747
|
-
//
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
}
|
|
755
|
-
while (addContract) {
|
|
756
|
-
addContract = await addAnotherContract.bind(this)({ protocolInstance, directory });
|
|
757
|
-
}
|
|
733
|
+
// Run code-generation
|
|
734
|
+
const codegen = await runCodegen(directory, commands.codegen);
|
|
735
|
+
if (codegen !== true) {
|
|
736
|
+
this.exit(1);
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
while (addContract) {
|
|
740
|
+
addContract = await addAnotherContract.bind(this)({ protocolInstance, directory });
|
|
758
741
|
}
|
|
759
742
|
printNextSteps.bind(this)({ subgraphName, directory }, { commands });
|
|
760
743
|
}
|
package/dist/protocols/index.js
CHANGED
|
@@ -88,7 +88,7 @@ class Protocol {
|
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
static availableNetworks() {
|
|
91
|
-
|
|
91
|
+
let networks = immutable_1.default.fromJS({
|
|
92
92
|
arweave: ['arweave-mainnet'],
|
|
93
93
|
ethereum: [
|
|
94
94
|
'mainnet',
|
|
@@ -135,6 +135,13 @@ class Protocol {
|
|
|
135
135
|
],
|
|
136
136
|
substreams: ['mainnet'],
|
|
137
137
|
});
|
|
138
|
+
const allNetworks = [];
|
|
139
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
140
|
+
networks.forEach(value => {
|
|
141
|
+
allNetworks.push(...value);
|
|
142
|
+
});
|
|
143
|
+
networks = networks.set('substreams', immutable_1.default.List(allNetworks));
|
|
144
|
+
return networks;
|
|
138
145
|
}
|
|
139
146
|
static normalizeName(name) {
|
|
140
147
|
return Protocol.availableProtocols().findKey(possibleNames => {
|
package/dist/scaffold/index.d.ts
CHANGED
|
@@ -23,7 +23,6 @@ export default class Scaffold {
|
|
|
23
23
|
startBlock?: string;
|
|
24
24
|
constructor(options: ScaffoldOptions);
|
|
25
25
|
generatePackageJson(): string;
|
|
26
|
-
generatePackageJsonForSubstreams(): string;
|
|
27
26
|
generateManifest(): string;
|
|
28
27
|
generateSchema(): string;
|
|
29
28
|
generateTsConfig(): string;
|
|
@@ -38,14 +37,6 @@ export default class Scaffold {
|
|
|
38
37
|
[x: string]: string;
|
|
39
38
|
} | undefined;
|
|
40
39
|
generate(): {
|
|
41
|
-
'subgraph.yaml': string;
|
|
42
|
-
'schema.graphql': string;
|
|
43
|
-
'package.json': string;
|
|
44
|
-
'tsconfig.json'?: undefined;
|
|
45
|
-
src?: undefined;
|
|
46
|
-
abis?: undefined;
|
|
47
|
-
tests?: undefined;
|
|
48
|
-
} | {
|
|
49
40
|
'package.json': string;
|
|
50
41
|
'subgraph.yaml': string;
|
|
51
42
|
'schema.graphql': string;
|
package/dist/scaffold/index.js
CHANGED
|
@@ -51,26 +51,6 @@ class Scaffold {
|
|
|
51
51
|
devDependencies: this.protocol.hasEvents() ? { 'matchstick-as': `0.5.0` } : undefined,
|
|
52
52
|
}), { parser: 'json' });
|
|
53
53
|
}
|
|
54
|
-
generatePackageJsonForSubstreams() {
|
|
55
|
-
return prettier_1.default.format(JSON.stringify({
|
|
56
|
-
name: (0, subgraph_1.getSubgraphBasename)(String(this.subgraphName)),
|
|
57
|
-
license: 'UNLICENSED',
|
|
58
|
-
scripts: {
|
|
59
|
-
build: 'graph build',
|
|
60
|
-
deploy: `graph deploy ` + `--node ${this.node} ` + this.subgraphName,
|
|
61
|
-
'create-local': `graph create --node http://localhost:8020/ ${this.subgraphName}`,
|
|
62
|
-
'remove-local': `graph remove --node http://localhost:8020/ ${this.subgraphName}`,
|
|
63
|
-
'deploy-local': `graph deploy ` +
|
|
64
|
-
`--node http://localhost:8020/ ` +
|
|
65
|
-
`--ipfs http://localhost:5001 ` +
|
|
66
|
-
this.subgraphName,
|
|
67
|
-
test: 'graph test',
|
|
68
|
-
},
|
|
69
|
-
dependencies: {
|
|
70
|
-
'@graphprotocol/graph-cli': GRAPH_CLI_VERSION,
|
|
71
|
-
},
|
|
72
|
-
}), { parser: 'json' });
|
|
73
|
-
}
|
|
74
54
|
generateManifest() {
|
|
75
55
|
const protocolManifest = this.protocol.getManifestScaffold();
|
|
76
56
|
return prettier_1.default.format(`
|
|
@@ -135,13 +115,6 @@ dataSources:
|
|
|
135
115
|
: undefined;
|
|
136
116
|
}
|
|
137
117
|
generate() {
|
|
138
|
-
if (this.protocol.name === 'substreams') {
|
|
139
|
-
return {
|
|
140
|
-
'subgraph.yaml': this.generateManifest(),
|
|
141
|
-
'schema.graphql': this.generateSchema(),
|
|
142
|
-
'package.json': this.generatePackageJsonForSubstreams(),
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
118
|
return {
|
|
146
119
|
'package.json': this.generatePackageJson(),
|
|
147
120
|
'subgraph.yaml': this.generateManifest(),
|
package/dist/type-generator.js
CHANGED
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphprotocol/graph-cli",
|
|
3
|
-
"version": "0.49.0-alpha-
|
|
3
|
+
"version": "0.49.0-alpha-20230505103249-d3fbf0b",
|
|
4
4
|
"description": "CLI for building for and deploying to The Graph",
|
|
5
5
|
"license": "(Apache-2.0 OR MIT)",
|
|
6
6
|
"engines": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dockerode": "2.5.8",
|
|
32
32
|
"fs-extra": "9.1.0",
|
|
33
33
|
"glob": "9.3.5",
|
|
34
|
-
"gluegun": "
|
|
34
|
+
"gluegun": "https://github.com/edgeandnode/gluegun#v4.3.1-pin-colors-dep",
|
|
35
35
|
"graphql": "15.5.0",
|
|
36
36
|
"immutable": "4.2.1",
|
|
37
37
|
"ipfs-http-client": "55.0.0",
|