@graphprotocol/graph-cli 0.45.0 → 0.45.1-alpha-20230405193954-4e288f4
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 +9 -0
- package/dist/codegen/schema.js +53 -54
- package/dist/codegen/schema.test.js +3 -4
- package/dist/schema.js +1 -2
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @graphprotocol/graph-cli
|
|
2
2
|
|
|
3
|
+
## 0.45.1-alpha-20230405193954-4e288f4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1259](https://github.com/graphprotocol/graph-tooling/pull/1259)
|
|
8
|
+
[`4e288f4`](https://github.com/graphprotocol/graph-tooling/commit/4e288f4148a397a02738e2b142bbedec566207ca)
|
|
9
|
+
Thanks [@saihaj](https://github.com/saihaj)! - refactor out immutable.js usage from schema
|
|
10
|
+
generation
|
|
11
|
+
|
|
3
12
|
## 0.45.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
package/dist/codegen/schema.js
CHANGED
|
@@ -22,17 +22,18 @@ 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
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
/* eslint-disable unicorn/no-array-for-each */
|
|
30
|
-
const immutable_1 = __importDefault(require("immutable"));
|
|
31
26
|
const typesCodegen = __importStar(require("./types"));
|
|
32
27
|
const tsCodegen = __importStar(require("./typescript"));
|
|
33
28
|
class IdField {
|
|
34
29
|
constructor(idField) {
|
|
35
|
-
|
|
30
|
+
if (idField?.type.kind !== 'NonNullType') {
|
|
31
|
+
throw Error('id field must be non-nullable');
|
|
32
|
+
}
|
|
33
|
+
if (idField.type.type.kind !== 'NamedType') {
|
|
34
|
+
throw Error('id field must be a named type');
|
|
35
|
+
}
|
|
36
|
+
const typeName = idField.type.type.name.value;
|
|
36
37
|
this.kind = typeName === 'Bytes' ? IdField.BYTES : IdField.STRING;
|
|
37
38
|
}
|
|
38
39
|
typeName() {
|
|
@@ -57,11 +58,11 @@ class IdField {
|
|
|
57
58
|
return this.kind == IdField.BYTES ? 'id.toHexString()' : 'id';
|
|
58
59
|
}
|
|
59
60
|
static fromFields(fields) {
|
|
60
|
-
const idField = fields
|
|
61
|
+
const idField = fields?.find(field => field.name.value === 'id');
|
|
61
62
|
return new IdField(idField);
|
|
62
63
|
}
|
|
63
64
|
static fromTypeDef(def) {
|
|
64
|
-
return IdField.fromFields(def.
|
|
65
|
+
return IdField.fromFields(def.fields);
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
IdField.BYTES = Symbol('Bytes');
|
|
@@ -89,33 +90,33 @@ class SchemaCodeGenerator {
|
|
|
89
90
|
];
|
|
90
91
|
}
|
|
91
92
|
generateTypes() {
|
|
92
|
-
return this.schema.ast
|
|
93
|
-
.
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
return this.schema.ast.definitions
|
|
94
|
+
.map(def => {
|
|
95
|
+
if (this._isEntityTypeDefinition(def)) {
|
|
96
|
+
return this._generateEntityType(def);
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
.filter(Boolean);
|
|
96
100
|
}
|
|
97
101
|
_isEntityTypeDefinition(def) {
|
|
98
|
-
return (def.
|
|
99
|
-
def
|
|
100
|
-
.get('directives')
|
|
101
|
-
.find((directive) => directive.getIn(['name', 'value']) === 'entity') !== undefined);
|
|
102
|
+
return (def.kind === 'ObjectTypeDefinition' &&
|
|
103
|
+
def.directives?.find(directive => directive.name.value === 'entity') !== undefined);
|
|
102
104
|
}
|
|
103
105
|
_isInterfaceDefinition(def) {
|
|
104
|
-
return def.
|
|
106
|
+
return def.kind === 'InterfaceTypeDefinition';
|
|
105
107
|
}
|
|
106
108
|
_generateEntityType(def) {
|
|
107
|
-
const name = def.
|
|
109
|
+
const name = def.name.value;
|
|
108
110
|
const klass = tsCodegen.klass(name, { export: true, extends: 'Entity' });
|
|
109
|
-
const fields = def.
|
|
111
|
+
const fields = def.fields;
|
|
110
112
|
const idField = IdField.fromFields(fields);
|
|
111
113
|
// Generate and add a constructor
|
|
112
114
|
klass.addMethod(this._generateConstructor(name, fields));
|
|
113
115
|
// Generate and add save() and getById() methods
|
|
114
116
|
this._generateStoreMethods(name, idField).forEach(method => klass.addMethod(method));
|
|
115
117
|
// Generate and add entity field getters and setters
|
|
116
|
-
def
|
|
117
|
-
.
|
|
118
|
-
.reduce((methods, field) => methods.concat(this._generateEntityFieldMethods(def, field)), immutable_1.default.List())
|
|
118
|
+
def.fields
|
|
119
|
+
?.reduce((methods, field) => methods.concat(this._generateEntityFieldMethods(def, field)), [])
|
|
119
120
|
.forEach((method) => klass.addMethod(method));
|
|
120
121
|
return klass;
|
|
121
122
|
}
|
|
@@ -127,7 +128,8 @@ class SchemaCodeGenerator {
|
|
|
127
128
|
`);
|
|
128
129
|
}
|
|
129
130
|
_generateStoreMethods(entityName, idField) {
|
|
130
|
-
return
|
|
131
|
+
return [
|
|
132
|
+
tsCodegen.method('save', [], tsCodegen.namedType('void'), `
|
|
131
133
|
let id = this.get('id')
|
|
132
134
|
assert(id != null,
|
|
133
135
|
'Cannot save ${entityName} entity without an ID')
|
|
@@ -135,23 +137,24 @@ class SchemaCodeGenerator {
|
|
|
135
137
|
assert(id.kind == ${idField.tsValueKind()},
|
|
136
138
|
\`Entities of type ${entityName} must have an ID of type ${idField.gqlTypeName()} but the id '\${id.displayData()}' is of type \${id.displayKind()}\`)
|
|
137
139
|
store.set('${entityName}', ${idField.tsValueToString()}, this)
|
|
138
|
-
}`),
|
|
140
|
+
}`),
|
|
141
|
+
tsCodegen.staticMethod('load', [tsCodegen.param('id', tsCodegen.namedType(idField.typeName()))], tsCodegen.nullableType(tsCodegen.namedType(entityName)), `
|
|
139
142
|
return changetype<${entityName} | null>(store.get('${entityName}', ${idField.tsToString()}))
|
|
140
|
-
`)
|
|
143
|
+
`),
|
|
144
|
+
];
|
|
141
145
|
}
|
|
142
146
|
_generateEntityFieldMethods(entityDef, fieldDef) {
|
|
143
|
-
return
|
|
144
|
-
.List([
|
|
147
|
+
return [
|
|
145
148
|
this._generateEntityFieldGetter(entityDef, fieldDef),
|
|
146
149
|
this._generateEntityFieldSetter(entityDef, fieldDef),
|
|
147
|
-
]
|
|
150
|
+
]
|
|
148
151
|
// generator can return null if the field is not supported
|
|
149
152
|
// so we filter all falsy values
|
|
150
|
-
.filter(Boolean)
|
|
153
|
+
.filter(Boolean);
|
|
151
154
|
}
|
|
152
155
|
_generateEntityFieldGetter(_entityDef, fieldDef) {
|
|
153
|
-
const name = fieldDef.
|
|
154
|
-
const gqlType = fieldDef.
|
|
156
|
+
const name = fieldDef.name.value;
|
|
157
|
+
const gqlType = fieldDef.type;
|
|
155
158
|
const fieldValueType = this._valueTypeFromGraphQl(gqlType);
|
|
156
159
|
const returnType = this._typeFromGraphQl(gqlType);
|
|
157
160
|
const isNullable = returnType instanceof tsCodegen.NullableType;
|
|
@@ -167,14 +170,12 @@ class SchemaCodeGenerator {
|
|
|
167
170
|
`);
|
|
168
171
|
}
|
|
169
172
|
_generateEntityFieldSetter(_entityDef, fieldDef) {
|
|
170
|
-
const name = fieldDef.
|
|
171
|
-
const isDerivedField = !!fieldDef
|
|
172
|
-
.get('directives')
|
|
173
|
-
.find((directive) => directive.getIn(['name', 'value']) === 'derivedFrom');
|
|
173
|
+
const name = fieldDef.name.value;
|
|
174
|
+
const isDerivedField = !!fieldDef.directives?.find(directive => directive.name.value === 'derivedFrom');
|
|
174
175
|
// We cannot have setters for derived fields
|
|
175
176
|
if (isDerivedField)
|
|
176
177
|
return null;
|
|
177
|
-
const gqlType = fieldDef.
|
|
178
|
+
const gqlType = fieldDef.type;
|
|
178
179
|
const fieldValueType = this._valueTypeFromGraphQl(gqlType);
|
|
179
180
|
const paramType = this._typeFromGraphQl(gqlType);
|
|
180
181
|
const isNullable = paramType instanceof tsCodegen.NullableType;
|
|
@@ -200,13 +201,11 @@ Suggestion: add an '!' to the member type of the List, change from '[${baseType}
|
|
|
200
201
|
return tsCodegen.method(`set ${name}`, [tsCodegen.param('value', paramType)], undefined, isNullable ? setNullable : setNonNullable);
|
|
201
202
|
}
|
|
202
203
|
_resolveFieldType(gqlType) {
|
|
203
|
-
const typeName = gqlType.
|
|
204
|
+
const typeName = gqlType.name.value;
|
|
204
205
|
// If this is a reference to another type, the field has the type of
|
|
205
206
|
// the referred type's id field
|
|
206
|
-
const typeDef = this.schema.ast
|
|
207
|
-
.
|
|
208
|
-
.find((def) => (this._isEntityTypeDefinition(def) || this._isInterfaceDefinition(def)) &&
|
|
209
|
-
def.getIn(['name', 'value']) === typeName);
|
|
207
|
+
const typeDef = this.schema.ast.definitions?.find(def => (this._isEntityTypeDefinition(def) || this._isInterfaceDefinition(def)) &&
|
|
208
|
+
def.name.value === typeName);
|
|
210
209
|
if (typeDef) {
|
|
211
210
|
return IdField.fromTypeDef(typeDef).typeName();
|
|
212
211
|
}
|
|
@@ -217,31 +216,31 @@ Suggestion: add an '!' to the member type of the List, change from '[${baseType}
|
|
|
217
216
|
* other entity types, this is the same as the type of the id of the
|
|
218
217
|
* referred type, i.e., `string` or `Bytes`*/
|
|
219
218
|
_valueTypeFromGraphQl(gqlType) {
|
|
220
|
-
if (gqlType.
|
|
221
|
-
return this._valueTypeFromGraphQl(gqlType.
|
|
219
|
+
if (gqlType.kind === 'NonNullType') {
|
|
220
|
+
return this._valueTypeFromGraphQl(gqlType.type);
|
|
222
221
|
}
|
|
223
|
-
if (gqlType.
|
|
224
|
-
return '[' + this._valueTypeFromGraphQl(gqlType.
|
|
222
|
+
if (gqlType.kind === 'ListType') {
|
|
223
|
+
return '[' + this._valueTypeFromGraphQl(gqlType.type) + ']';
|
|
225
224
|
}
|
|
226
225
|
return this._resolveFieldType(gqlType);
|
|
227
226
|
}
|
|
228
227
|
/** Determine the base type of `gqlType` by removing any non-null
|
|
229
228
|
* constraints and using the type of elements of lists */
|
|
230
229
|
_baseType(gqlType) {
|
|
231
|
-
if (gqlType.
|
|
232
|
-
return this._baseType(gqlType.
|
|
230
|
+
if (gqlType.kind === 'NonNullType') {
|
|
231
|
+
return this._baseType(gqlType.type);
|
|
233
232
|
}
|
|
234
|
-
if (gqlType.
|
|
235
|
-
return this._baseType(gqlType.
|
|
233
|
+
if (gqlType.kind === 'ListType') {
|
|
234
|
+
return this._baseType(gqlType.type);
|
|
236
235
|
}
|
|
237
|
-
return gqlType.
|
|
236
|
+
return gqlType.name.value;
|
|
238
237
|
}
|
|
239
238
|
_typeFromGraphQl(gqlType, nullable = true) {
|
|
240
|
-
if (gqlType.
|
|
241
|
-
return this._typeFromGraphQl(gqlType.
|
|
239
|
+
if (gqlType.kind === 'NonNullType') {
|
|
240
|
+
return this._typeFromGraphQl(gqlType.type, false);
|
|
242
241
|
}
|
|
243
|
-
if (gqlType.
|
|
244
|
-
const type = tsCodegen.arrayType(this._typeFromGraphQl(gqlType.
|
|
242
|
+
if (gqlType.kind === 'ListType') {
|
|
243
|
+
const type = tsCodegen.arrayType(this._typeFromGraphQl(gqlType.type));
|
|
245
244
|
return nullable ? tsCodegen.nullableType(type) : type;
|
|
246
245
|
}
|
|
247
246
|
// NamedType
|
|
@@ -27,13 +27,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
const graphql = __importStar(require("graphql/language"));
|
|
30
|
-
const immutable_1 = __importDefault(require("immutable"));
|
|
31
30
|
const prettier_1 = __importDefault(require("prettier"));
|
|
32
31
|
const schema_1 = __importDefault(require("../schema"));
|
|
33
32
|
const schema_2 = __importDefault(require("./schema"));
|
|
34
33
|
const typescript_1 = require("./typescript");
|
|
35
34
|
const formatTS = (code) => prettier_1.default.format(code, { parser: 'typescript', semi: false });
|
|
36
|
-
const createSchemaCodeGen = (schema) => new schema_2.default(new schema_1.default('', schema,
|
|
35
|
+
const createSchemaCodeGen = (schema) => new schema_2.default(new schema_1.default('', schema, graphql.parse(schema)));
|
|
37
36
|
const testEntity = (generatedTypes, expectedEntity) => {
|
|
38
37
|
const entity = generatedTypes.find(type => type.name === expectedEntity.name);
|
|
39
38
|
expect(entity instanceof typescript_1.Class).toBe(true);
|
|
@@ -64,7 +63,7 @@ describe('Schema code generator', () => {
|
|
|
64
63
|
barfoo: Int
|
|
65
64
|
}
|
|
66
65
|
`);
|
|
67
|
-
expect(codegen.generateTypes().
|
|
66
|
+
expect(codegen.generateTypes().length).toBe(0);
|
|
68
67
|
});
|
|
69
68
|
describe('Should generate correct classes for each entity', () => {
|
|
70
69
|
const codegen = createSchemaCodeGen(`
|
|
@@ -99,7 +98,7 @@ describe('Schema code generator', () => {
|
|
|
99
98
|
const foo = generatedTypes.find((type) => type.name === 'Foo');
|
|
100
99
|
expect(foo).toBe(undefined);
|
|
101
100
|
// Account and Wallet
|
|
102
|
-
expect(generatedTypes.
|
|
101
|
+
expect(generatedTypes.length).toBe(2);
|
|
103
102
|
});
|
|
104
103
|
test('Account is an entity with the correct methods', () => {
|
|
105
104
|
testEntity(generatedTypes, {
|
package/dist/schema.js
CHANGED
|
@@ -28,7 +28,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
30
30
|
const graphql = __importStar(require("graphql/language"));
|
|
31
|
-
const immutable_1 = __importDefault(require("immutable"));
|
|
32
31
|
const schema_1 = __importDefault(require("./codegen/schema"));
|
|
33
32
|
class Schema {
|
|
34
33
|
constructor(filename, document, ast) {
|
|
@@ -45,7 +44,7 @@ class Schema {
|
|
|
45
44
|
static async load(filename) {
|
|
46
45
|
const document = await fs_extra_1.default.readFile(filename, 'utf-8');
|
|
47
46
|
const ast = graphql.parse(document);
|
|
48
|
-
return new Schema(filename, document,
|
|
47
|
+
return new Schema(filename, document, ast);
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
50
|
exports.default = Schema;
|
package/oclif.manifest.json
CHANGED