@graphql-tools/mock 8.6.13 → 8.7.0-alpha-b76ec274.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/cjs/MockList.js +75 -0
- package/cjs/MockStore.js +489 -0
- package/cjs/addMocksToSchema.js +204 -0
- package/cjs/index.js +9 -0
- package/cjs/mockServer.js +39 -0
- package/cjs/package.json +1 -0
- package/cjs/pagination.js +74 -0
- package/cjs/types.js +17 -0
- package/cjs/utils.js +54 -0
- package/esm/MockList.js +69 -0
- package/{index.mjs → esm/MockStore.js} +7 -432
- package/esm/addMocksToSchema.js +200 -0
- package/esm/index.js +6 -0
- package/esm/mockServer.js +35 -0
- package/esm/pagination.js +70 -0
- package/esm/types.js +11 -0
- package/esm/utils.js +43 -0
- package/package.json +33 -12
- package/{MockList.d.ts → typings/MockList.d.ts} +0 -0
- package/{MockStore.d.ts → typings/MockStore.d.ts} +1 -1
- package/{addMocksToSchema.d.ts → typings/addMocksToSchema.d.ts} +1 -1
- package/typings/index.d.ts +6 -0
- package/{mockServer.d.ts → typings/mockServer.d.ts} +1 -1
- package/{pagination.d.ts → typings/pagination.d.ts} +1 -1
- package/{types.d.ts → typings/types.d.ts} +0 -0
- package/{utils.d.ts → typings/utils.d.ts} +1 -1
- package/README.md +0 -5
- package/index.d.ts +0 -6
- package/index.js +0 -925
package/cjs/MockList.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deepResolveMockList = exports.MockList = exports.isMockList = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
function isMockList(obj) {
|
|
8
|
+
if (typeof (obj === null || obj === void 0 ? void 0 : obj.len) === 'number' || (Array.isArray(obj === null || obj === void 0 ? void 0 : obj.len) && typeof (obj === null || obj === void 0 ? void 0 : obj.len[0]) === 'number')) {
|
|
9
|
+
if (typeof obj.wrappedFunction === 'undefined' || typeof obj.wrappedFunction === 'function') {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
exports.isMockList = isMockList;
|
|
16
|
+
/**
|
|
17
|
+
* This is an object you can return from your mock resolvers which calls the
|
|
18
|
+
* provided `mockFunction` once for each list item.
|
|
19
|
+
*/
|
|
20
|
+
class MockList {
|
|
21
|
+
/**
|
|
22
|
+
* @param length Either the exact length of items to return or an inclusive
|
|
23
|
+
* range of possible lengths.
|
|
24
|
+
* @param mockFunction The function to call for each item in the list to
|
|
25
|
+
* resolve it. It can return another MockList or a value.
|
|
26
|
+
*/
|
|
27
|
+
constructor(length, mockFunction) {
|
|
28
|
+
this.len = length;
|
|
29
|
+
if (typeof mockFunction !== 'undefined') {
|
|
30
|
+
if (typeof mockFunction !== 'function') {
|
|
31
|
+
throw new Error('Second argument to MockList must be a function or undefined');
|
|
32
|
+
}
|
|
33
|
+
this.wrappedFunction = mockFunction;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
mock() {
|
|
40
|
+
let arr;
|
|
41
|
+
if (Array.isArray(this.len)) {
|
|
42
|
+
arr = new Array(this.randint(this.len[0], this.len[1]));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
arr = new Array(this.len);
|
|
46
|
+
}
|
|
47
|
+
for (let i = 0; i < arr.length; i++) {
|
|
48
|
+
if (typeof this.wrappedFunction === 'function') {
|
|
49
|
+
const res = this.wrappedFunction();
|
|
50
|
+
if (isMockList(res)) {
|
|
51
|
+
arr[i] = res.mock();
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
arr[i] = res;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
arr[i] = undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return arr;
|
|
62
|
+
}
|
|
63
|
+
randint(low, high) {
|
|
64
|
+
return Math.floor(Math.random() * (high - low + 1) + low);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.MockList = MockList;
|
|
68
|
+
function deepResolveMockList(mockList) {
|
|
69
|
+
return mockList.mock().map(v => {
|
|
70
|
+
if (isMockList(v))
|
|
71
|
+
return deepResolveMockList(v);
|
|
72
|
+
return v;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
exports.deepResolveMockList = deepResolveMockList;
|
package/cjs/MockStore.js
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMockStore = exports.MockStore = exports.defaultMocks = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
const fast_json_stable_stringify_1 = tslib_1.__importDefault(require("fast-json-stable-stringify"));
|
|
7
|
+
const types_js_1 = require("./types.js");
|
|
8
|
+
const utils_js_1 = require("./utils.js");
|
|
9
|
+
const MockList_js_1 = require("./MockList.js");
|
|
10
|
+
exports.defaultMocks = {
|
|
11
|
+
Int: () => Math.round(Math.random() * 200) - 100,
|
|
12
|
+
Float: () => Math.random() * 200 - 100,
|
|
13
|
+
String: () => 'Hello World',
|
|
14
|
+
Boolean: () => Math.random() > 0.5,
|
|
15
|
+
ID: () => (0, utils_js_1.uuidv4)(),
|
|
16
|
+
};
|
|
17
|
+
const defaultKeyFieldNames = ['id', '_id'];
|
|
18
|
+
class MockStore {
|
|
19
|
+
constructor({ schema, mocks, typePolicies, }) {
|
|
20
|
+
this.store = {};
|
|
21
|
+
this.schema = schema;
|
|
22
|
+
this.mocks = { ...exports.defaultMocks, ...mocks };
|
|
23
|
+
this.typePolicies = typePolicies || {};
|
|
24
|
+
}
|
|
25
|
+
has(typeName, key) {
|
|
26
|
+
return !!this.store[typeName] && !!this.store[typeName][key];
|
|
27
|
+
}
|
|
28
|
+
get(_typeName, _key, _fieldName, _fieldArgs) {
|
|
29
|
+
if (typeof _typeName !== 'string') {
|
|
30
|
+
if (_key === undefined) {
|
|
31
|
+
if ((0, types_js_1.isRef)(_typeName)) {
|
|
32
|
+
throw new Error("Can't provide a ref as first argument and no other argument");
|
|
33
|
+
}
|
|
34
|
+
// get({...})
|
|
35
|
+
return this.getImpl(_typeName);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
(0, types_js_1.assertIsRef)(_typeName);
|
|
39
|
+
const { $ref } = _typeName;
|
|
40
|
+
// arguments shift
|
|
41
|
+
_fieldArgs = _fieldName;
|
|
42
|
+
_fieldName = _key;
|
|
43
|
+
_key = $ref.key;
|
|
44
|
+
_typeName = $ref.typeName;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const args = {
|
|
48
|
+
typeName: _typeName,
|
|
49
|
+
};
|
|
50
|
+
if ((0, types_js_1.isRecord)(_key) || _key === undefined) {
|
|
51
|
+
// get('User', { name: 'Alex'})
|
|
52
|
+
args.defaultValue = _key;
|
|
53
|
+
return this.getImpl(args);
|
|
54
|
+
}
|
|
55
|
+
args.key = _key;
|
|
56
|
+
if (Array.isArray(_fieldName) && _fieldName.length === 1) {
|
|
57
|
+
_fieldName = _fieldName[0];
|
|
58
|
+
}
|
|
59
|
+
if (typeof _fieldName !== 'string' && !Array.isArray(_fieldName)) {
|
|
60
|
+
// get('User', 'me', { name: 'Alex'})
|
|
61
|
+
args.defaultValue = _fieldName;
|
|
62
|
+
return this.getImpl(args);
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(_fieldName)) {
|
|
65
|
+
// get('User', 'me', ['father', 'name'])
|
|
66
|
+
const ref = this.get(_typeName, _key, _fieldName[0], _fieldArgs);
|
|
67
|
+
(0, types_js_1.assertIsRef)(ref);
|
|
68
|
+
return this.get(ref.$ref.typeName, ref.$ref.key, _fieldName.slice(1, _fieldName.length));
|
|
69
|
+
}
|
|
70
|
+
// get('User', 'me', 'name'...);
|
|
71
|
+
args.fieldName = _fieldName;
|
|
72
|
+
args.fieldArgs = _fieldArgs;
|
|
73
|
+
return this.getImpl(args);
|
|
74
|
+
}
|
|
75
|
+
set(_typeName, _key, _fieldName, _value) {
|
|
76
|
+
if (typeof _typeName !== 'string') {
|
|
77
|
+
if (_key === undefined) {
|
|
78
|
+
if ((0, types_js_1.isRef)(_typeName)) {
|
|
79
|
+
throw new Error("Can't provide a ref as first argument and no other argument");
|
|
80
|
+
}
|
|
81
|
+
// set({...})
|
|
82
|
+
return this.setImpl(_typeName);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
(0, types_js_1.assertIsRef)(_typeName);
|
|
86
|
+
const { $ref } = _typeName;
|
|
87
|
+
// arguments shift
|
|
88
|
+
_value = _fieldName;
|
|
89
|
+
_fieldName = _key;
|
|
90
|
+
_key = $ref.key;
|
|
91
|
+
_typeName = $ref.typeName;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
assertIsDefined(_key, 'key was not provided');
|
|
95
|
+
const args = {
|
|
96
|
+
typeName: _typeName,
|
|
97
|
+
key: _key,
|
|
98
|
+
};
|
|
99
|
+
if (typeof _fieldName !== 'string') {
|
|
100
|
+
// set('User', 1, { name: 'Foo' })
|
|
101
|
+
if (!(0, types_js_1.isRecord)(_fieldName))
|
|
102
|
+
throw new Error('Expected value to be a record');
|
|
103
|
+
args.value = _fieldName;
|
|
104
|
+
return this.setImpl(args);
|
|
105
|
+
}
|
|
106
|
+
args.fieldName = _fieldName;
|
|
107
|
+
args.value = _value;
|
|
108
|
+
return this.setImpl(args);
|
|
109
|
+
}
|
|
110
|
+
reset() {
|
|
111
|
+
this.store = {};
|
|
112
|
+
}
|
|
113
|
+
filter(key, predicate) {
|
|
114
|
+
const entity = this.store[key];
|
|
115
|
+
return Object.values(entity).filter(predicate);
|
|
116
|
+
}
|
|
117
|
+
find(key, predicate) {
|
|
118
|
+
const entity = this.store[key];
|
|
119
|
+
return Object.values(entity).find(predicate);
|
|
120
|
+
}
|
|
121
|
+
getImpl(args) {
|
|
122
|
+
const { typeName, key, fieldName, fieldArgs, defaultValue } = args;
|
|
123
|
+
if (!fieldName) {
|
|
124
|
+
if (defaultValue !== undefined && !(0, types_js_1.isRecord)(defaultValue)) {
|
|
125
|
+
throw new Error('`defaultValue` should be an object');
|
|
126
|
+
}
|
|
127
|
+
let valuesToInsert = defaultValue || {};
|
|
128
|
+
if (key) {
|
|
129
|
+
valuesToInsert = { ...valuesToInsert, ...(0, utils_js_1.makeRef)(typeName, key) };
|
|
130
|
+
}
|
|
131
|
+
return this.insert(typeName, valuesToInsert, true);
|
|
132
|
+
}
|
|
133
|
+
assertIsDefined(key, 'key argument should be given when fieldName is given');
|
|
134
|
+
const fieldNameInStore = getFieldNameInStore(fieldName, fieldArgs);
|
|
135
|
+
if (this.store[typeName] === undefined ||
|
|
136
|
+
this.store[typeName][key] === undefined ||
|
|
137
|
+
this.store[typeName][key][fieldNameInStore] === undefined) {
|
|
138
|
+
let value;
|
|
139
|
+
if (defaultValue !== undefined) {
|
|
140
|
+
value = defaultValue;
|
|
141
|
+
}
|
|
142
|
+
else if (this.isKeyField(typeName, fieldName)) {
|
|
143
|
+
value = key;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
value = this.generateFieldValue(typeName, fieldName, (otherFieldName, otherValue) => {
|
|
147
|
+
// if we get a key field in the mix we don't care
|
|
148
|
+
if (this.isKeyField(typeName, otherFieldName))
|
|
149
|
+
return;
|
|
150
|
+
this.set({ typeName, key, fieldName: otherFieldName, value: otherValue, noOverride: true });
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
this.set({ typeName, key, fieldName, fieldArgs, value, noOverride: true });
|
|
154
|
+
}
|
|
155
|
+
return this.store[typeName][key][fieldNameInStore];
|
|
156
|
+
}
|
|
157
|
+
setImpl(args) {
|
|
158
|
+
const { typeName, key, fieldName, fieldArgs, noOverride } = args;
|
|
159
|
+
let { value } = args;
|
|
160
|
+
if ((0, MockList_js_1.isMockList)(value)) {
|
|
161
|
+
value = (0, MockList_js_1.deepResolveMockList)(value);
|
|
162
|
+
}
|
|
163
|
+
if (this.store[typeName] === undefined) {
|
|
164
|
+
this.store[typeName] = {};
|
|
165
|
+
}
|
|
166
|
+
if (this.store[typeName][key] === undefined) {
|
|
167
|
+
this.store[typeName][key] = {};
|
|
168
|
+
}
|
|
169
|
+
if (!fieldName) {
|
|
170
|
+
if (!(0, types_js_1.isRecord)(value)) {
|
|
171
|
+
throw new Error('When no `fieldName` is provided, `value` should be a record.');
|
|
172
|
+
}
|
|
173
|
+
for (const fieldName in value) {
|
|
174
|
+
this.setImpl({
|
|
175
|
+
typeName,
|
|
176
|
+
key,
|
|
177
|
+
fieldName,
|
|
178
|
+
value: value[fieldName],
|
|
179
|
+
noOverride,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const fieldNameInStore = getFieldNameInStore(fieldName, fieldArgs);
|
|
185
|
+
if (this.isKeyField(typeName, fieldName) && value !== key) {
|
|
186
|
+
throw new Error(`Field ${fieldName} is a key field of ${typeName} and you are trying to set it to ${value} while the key is ${key}`);
|
|
187
|
+
}
|
|
188
|
+
// if already set and we don't override
|
|
189
|
+
if (this.store[typeName][key][fieldNameInStore] !== undefined && noOverride) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const fieldType = this.getFieldType(typeName, fieldName);
|
|
193
|
+
const currentValue = this.store[typeName][key][fieldNameInStore];
|
|
194
|
+
let valueToStore;
|
|
195
|
+
try {
|
|
196
|
+
valueToStore = this.normalizeValueToStore(fieldType, value, currentValue, (typeName, values) => this.insert(typeName, values, noOverride));
|
|
197
|
+
}
|
|
198
|
+
catch (e) {
|
|
199
|
+
throw new Error(`Value to set in ${typeName}.${fieldName} in not normalizable: ${e.message}`);
|
|
200
|
+
}
|
|
201
|
+
this.store[typeName][key] = {
|
|
202
|
+
...this.store[typeName][key],
|
|
203
|
+
[fieldNameInStore]: valueToStore,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
normalizeValueToStore(fieldType, value, currentValue, onInsertType) {
|
|
207
|
+
const fieldTypeName = fieldType.toString();
|
|
208
|
+
if (value === null) {
|
|
209
|
+
if (!(0, graphql_1.isNullableType)(fieldType)) {
|
|
210
|
+
throw new Error(`should not be null because ${fieldTypeName} is not nullable. Received null.`);
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const nullableFieldType = (0, graphql_1.getNullableType)(fieldType);
|
|
215
|
+
if (value === undefined)
|
|
216
|
+
return this.generateValueFromType(nullableFieldType);
|
|
217
|
+
// deal with nesting insert
|
|
218
|
+
if ((0, graphql_1.isCompositeType)(nullableFieldType)) {
|
|
219
|
+
if (!(0, types_js_1.isRecord)(value))
|
|
220
|
+
throw new Error(`should be an object or null or undefined. Received ${value}`);
|
|
221
|
+
let joinedTypeName;
|
|
222
|
+
if ((0, graphql_1.isAbstractType)(nullableFieldType)) {
|
|
223
|
+
if ((0, types_js_1.isRef)(value)) {
|
|
224
|
+
joinedTypeName = value.$ref.typeName;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
if (typeof value['__typename'] !== 'string') {
|
|
228
|
+
throw new Error(`should contain a '__typename' because ${nullableFieldType.name} an abstract type`);
|
|
229
|
+
}
|
|
230
|
+
joinedTypeName = value['__typename'];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
joinedTypeName = nullableFieldType.name;
|
|
235
|
+
}
|
|
236
|
+
return onInsertType(joinedTypeName, (0, types_js_1.isRef)(currentValue) ? { ...currentValue, ...value } : value);
|
|
237
|
+
}
|
|
238
|
+
if ((0, graphql_1.isListType)(nullableFieldType)) {
|
|
239
|
+
if (!Array.isArray(value))
|
|
240
|
+
throw new Error(`should be an array or null or undefined. Received ${value}`);
|
|
241
|
+
return value.map((v, index) => {
|
|
242
|
+
return this.normalizeValueToStore(nullableFieldType.ofType, v, typeof currentValue === 'object' && currentValue != null && currentValue[index] ? currentValue : undefined, onInsertType);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
insert(typeName, values, noOverride) {
|
|
248
|
+
const keyFieldName = this.getKeyFieldName(typeName);
|
|
249
|
+
let key;
|
|
250
|
+
// when we generate a key for the type, we might produce
|
|
251
|
+
// other associated values with it
|
|
252
|
+
// We keep track of them and we'll insert them, with propririty
|
|
253
|
+
// for the ones that we areasked to insert
|
|
254
|
+
const otherValues = {};
|
|
255
|
+
if ((0, types_js_1.isRef)(values)) {
|
|
256
|
+
key = values.$ref.key;
|
|
257
|
+
}
|
|
258
|
+
else if (keyFieldName && keyFieldName in values) {
|
|
259
|
+
key = values[keyFieldName];
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
key = this.generateKeyForType(typeName, (otherFieldName, otherFieldValue) => {
|
|
263
|
+
otherValues[otherFieldName] = otherFieldValue;
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
const toInsert = { ...otherValues, ...values };
|
|
267
|
+
for (const fieldName in toInsert) {
|
|
268
|
+
if (fieldName === '$ref')
|
|
269
|
+
continue;
|
|
270
|
+
if (fieldName === '__typename')
|
|
271
|
+
continue;
|
|
272
|
+
this.set({
|
|
273
|
+
typeName,
|
|
274
|
+
key,
|
|
275
|
+
fieldName,
|
|
276
|
+
value: toInsert[fieldName],
|
|
277
|
+
noOverride,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
if (this.store[typeName] === undefined) {
|
|
281
|
+
this.store[typeName] = {};
|
|
282
|
+
}
|
|
283
|
+
if (this.store[typeName][key] === undefined) {
|
|
284
|
+
this.store[typeName][key] = {};
|
|
285
|
+
}
|
|
286
|
+
return (0, utils_js_1.makeRef)(typeName, key);
|
|
287
|
+
}
|
|
288
|
+
generateFieldValue(typeName, fieldName, onOtherFieldsGenerated) {
|
|
289
|
+
const mockedValue = this.generateFieldValueFromMocks(typeName, fieldName, onOtherFieldsGenerated);
|
|
290
|
+
if (mockedValue !== undefined)
|
|
291
|
+
return mockedValue;
|
|
292
|
+
const fieldType = this.getFieldType(typeName, fieldName);
|
|
293
|
+
return this.generateValueFromType(fieldType);
|
|
294
|
+
}
|
|
295
|
+
generateFieldValueFromMocks(typeName, fieldName, onOtherFieldsGenerated) {
|
|
296
|
+
let value;
|
|
297
|
+
const mock = this.mocks ? this.mocks[typeName] : undefined;
|
|
298
|
+
if (mock) {
|
|
299
|
+
if (typeof mock === 'function') {
|
|
300
|
+
const values = mock();
|
|
301
|
+
if (typeof values !== 'object' || values == null) {
|
|
302
|
+
throw new Error(`Value returned by the mock for ${typeName} is not an object`);
|
|
303
|
+
}
|
|
304
|
+
for (const otherFieldName in values) {
|
|
305
|
+
if (otherFieldName === fieldName)
|
|
306
|
+
continue;
|
|
307
|
+
if (typeof values[otherFieldName] === 'function')
|
|
308
|
+
continue;
|
|
309
|
+
onOtherFieldsGenerated && onOtherFieldsGenerated(otherFieldName, values[otherFieldName]);
|
|
310
|
+
}
|
|
311
|
+
value = values[fieldName];
|
|
312
|
+
if (typeof value === 'function')
|
|
313
|
+
value = value();
|
|
314
|
+
}
|
|
315
|
+
else if (typeof mock === 'object' && mock != null && typeof mock[fieldName] === 'function') {
|
|
316
|
+
value = mock[fieldName]();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (value !== undefined)
|
|
320
|
+
return value;
|
|
321
|
+
const type = this.getType(typeName);
|
|
322
|
+
// GraphQL 14 Compatibility
|
|
323
|
+
const interfaces = 'getInterfaces' in type ? type.getInterfaces() : [];
|
|
324
|
+
if (interfaces.length > 0) {
|
|
325
|
+
for (const interface_ of interfaces) {
|
|
326
|
+
if (value)
|
|
327
|
+
break;
|
|
328
|
+
value = this.generateFieldValueFromMocks(interface_.name, fieldName, onOtherFieldsGenerated);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return value;
|
|
332
|
+
}
|
|
333
|
+
generateKeyForType(typeName, onOtherFieldsGenerated) {
|
|
334
|
+
const keyFieldName = this.getKeyFieldName(typeName);
|
|
335
|
+
if (!keyFieldName)
|
|
336
|
+
return (0, utils_js_1.uuidv4)();
|
|
337
|
+
return this.generateFieldValue(typeName, keyFieldName, onOtherFieldsGenerated);
|
|
338
|
+
}
|
|
339
|
+
generateValueFromType(fieldType) {
|
|
340
|
+
const nullableType = (0, graphql_1.getNullableType)(fieldType);
|
|
341
|
+
if ((0, graphql_1.isScalarType)(nullableType)) {
|
|
342
|
+
const mockFn = this.mocks[nullableType.name];
|
|
343
|
+
if (typeof mockFn !== 'function')
|
|
344
|
+
throw new Error(`No mock defined for type "${nullableType.name}"`);
|
|
345
|
+
return mockFn();
|
|
346
|
+
}
|
|
347
|
+
else if ((0, graphql_1.isEnumType)(nullableType)) {
|
|
348
|
+
const mockFn = this.mocks[nullableType.name];
|
|
349
|
+
if (typeof mockFn === 'function')
|
|
350
|
+
return mockFn();
|
|
351
|
+
const values = nullableType.getValues().map(v => v.value);
|
|
352
|
+
return (0, utils_js_1.takeRandom)(values);
|
|
353
|
+
}
|
|
354
|
+
else if ((0, graphql_1.isObjectType)(nullableType)) {
|
|
355
|
+
// this will create a new random ref
|
|
356
|
+
return this.insert(nullableType.name, {});
|
|
357
|
+
}
|
|
358
|
+
else if ((0, graphql_1.isListType)(nullableType)) {
|
|
359
|
+
return [...new Array((0, utils_js_1.randomListLength)())].map(() => this.generateValueFromType(nullableType.ofType));
|
|
360
|
+
}
|
|
361
|
+
else if ((0, graphql_1.isAbstractType)(nullableType)) {
|
|
362
|
+
const mock = this.mocks[nullableType.name];
|
|
363
|
+
let typeName;
|
|
364
|
+
let values = {};
|
|
365
|
+
if (!mock) {
|
|
366
|
+
typeName = (0, utils_js_1.takeRandom)(this.schema.getPossibleTypes(nullableType).map(t => t.name));
|
|
367
|
+
}
|
|
368
|
+
else if (typeof mock === 'function') {
|
|
369
|
+
const mockRes = mock();
|
|
370
|
+
if (mockRes === null)
|
|
371
|
+
return null;
|
|
372
|
+
if (!(0, types_js_1.isRecord)(mockRes)) {
|
|
373
|
+
throw new Error(`Value returned by the mock for ${nullableType.name} is not an object or null`);
|
|
374
|
+
}
|
|
375
|
+
values = mockRes;
|
|
376
|
+
if (typeof values['__typename'] !== 'string') {
|
|
377
|
+
throw new Error(`Please return a __typename in "${nullableType.name}"`);
|
|
378
|
+
}
|
|
379
|
+
typeName = values['__typename'];
|
|
380
|
+
}
|
|
381
|
+
else if (typeof mock === 'object' && mock != null && typeof mock['__typename'] === 'function') {
|
|
382
|
+
const mockRes = mock['__typename']();
|
|
383
|
+
if (typeof mockRes !== 'string')
|
|
384
|
+
throw new Error(`'__typename' returned by the mock for abstract type ${nullableType.name} is not a string`);
|
|
385
|
+
typeName = mockRes;
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
throw new Error(`Please return a __typename in "${nullableType.name}"`);
|
|
389
|
+
}
|
|
390
|
+
const toInsert = {};
|
|
391
|
+
for (const fieldName in values) {
|
|
392
|
+
if (fieldName === '__typename')
|
|
393
|
+
continue;
|
|
394
|
+
const fieldValue = values[fieldName];
|
|
395
|
+
toInsert[fieldName] = typeof fieldValue === 'function' ? fieldValue() : fieldValue;
|
|
396
|
+
}
|
|
397
|
+
return this.insert(typeName, toInsert);
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
throw new Error(`${nullableType} not implemented`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
getFieldType(typeName, fieldName) {
|
|
404
|
+
if (fieldName === '__typename') {
|
|
405
|
+
return graphql_1.GraphQLString;
|
|
406
|
+
}
|
|
407
|
+
const type = this.getType(typeName);
|
|
408
|
+
const field = type.getFields()[fieldName];
|
|
409
|
+
if (!field) {
|
|
410
|
+
throw new Error(`${fieldName} does not exist on type ${typeName}`);
|
|
411
|
+
}
|
|
412
|
+
return field.type;
|
|
413
|
+
}
|
|
414
|
+
getType(typeName) {
|
|
415
|
+
const type = this.schema.getType(typeName);
|
|
416
|
+
if (!type || !((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type))) {
|
|
417
|
+
throw new Error(`${typeName} does not exist on schema or is not an object or interface`);
|
|
418
|
+
}
|
|
419
|
+
return type;
|
|
420
|
+
}
|
|
421
|
+
isKeyField(typeName, fieldName) {
|
|
422
|
+
return this.getKeyFieldName(typeName) === fieldName;
|
|
423
|
+
}
|
|
424
|
+
getKeyFieldName(typeName) {
|
|
425
|
+
var _a;
|
|
426
|
+
const typePolicyKeyField = (_a = this.typePolicies[typeName]) === null || _a === void 0 ? void 0 : _a.keyFieldName;
|
|
427
|
+
if (typePolicyKeyField !== undefined) {
|
|
428
|
+
if (typePolicyKeyField === false)
|
|
429
|
+
return null;
|
|
430
|
+
return typePolicyKeyField;
|
|
431
|
+
}
|
|
432
|
+
// How about common key field names?
|
|
433
|
+
const gqlType = this.getType(typeName);
|
|
434
|
+
for (const fieldName in gqlType.getFields()) {
|
|
435
|
+
if (defaultKeyFieldNames.includes(fieldName)) {
|
|
436
|
+
return fieldName;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
exports.MockStore = MockStore;
|
|
443
|
+
const getFieldNameInStore = (fieldName, fieldArgs) => {
|
|
444
|
+
if (!fieldArgs)
|
|
445
|
+
return fieldName;
|
|
446
|
+
if (typeof fieldArgs === 'string') {
|
|
447
|
+
return `${fieldName}:${fieldArgs}`;
|
|
448
|
+
}
|
|
449
|
+
// empty args
|
|
450
|
+
if (Object.keys(fieldArgs).length === 0) {
|
|
451
|
+
return fieldName;
|
|
452
|
+
}
|
|
453
|
+
return `${fieldName}:${(0, fast_json_stable_stringify_1.default)(fieldArgs)}`;
|
|
454
|
+
};
|
|
455
|
+
function assertIsDefined(value, message) {
|
|
456
|
+
if (value !== undefined && value !== null) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
throw new Error(process.env['NODE_ENV'] === 'production' ? 'Invariant failed:' : `Invariant failed: ${message || ''}`);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Will create `MockStore` for the given `schema`.
|
|
463
|
+
*
|
|
464
|
+
* A `MockStore` will generate mock values for the given schem when queried.
|
|
465
|
+
*
|
|
466
|
+
* It will stores generated mocks, so that, provided with same arguments
|
|
467
|
+
* the returned values will be the same.
|
|
468
|
+
*
|
|
469
|
+
* Its API also allows to modify the stored values.
|
|
470
|
+
*
|
|
471
|
+
* Basic example:
|
|
472
|
+
* ```ts
|
|
473
|
+
* store.get('User', 1, 'name');
|
|
474
|
+
* // > "Hello World"
|
|
475
|
+
* store.set('User', 1, 'name', 'Alexandre');
|
|
476
|
+
* store.get('User', 1, 'name');
|
|
477
|
+
* // > "Alexandre"
|
|
478
|
+
* ```
|
|
479
|
+
*
|
|
480
|
+
* The storage key will correspond to the "key field"
|
|
481
|
+
* of the type. Field with name `id` or `_id` will be
|
|
482
|
+
* by default considered as the key field for the type.
|
|
483
|
+
* However, use `typePolicies` to precise the field to use
|
|
484
|
+
* as key.
|
|
485
|
+
*/
|
|
486
|
+
function createMockStore(options) {
|
|
487
|
+
return new MockStore(options);
|
|
488
|
+
}
|
|
489
|
+
exports.createMockStore = createMockStore;
|