meadow 2.0.23 → 2.0.26
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/README.md +110 -141
- package/docs/README.md +34 -230
- package/docs/_cover.md +14 -0
- package/docs/_sidebar.md +44 -12
- package/docs/_topbar.md +5 -0
- package/docs/api/doCount.md +109 -0
- package/docs/api/doCreate.md +132 -0
- package/docs/api/doDelete.md +101 -0
- package/docs/api/doRead.md +122 -0
- package/docs/api/doReads.md +136 -0
- package/docs/api/doUndelete.md +98 -0
- package/docs/api/doUpdate.md +129 -0
- package/docs/api/getRoleName.md +84 -0
- package/docs/api/loadFromPackage.md +153 -0
- package/docs/api/marshalRecordFromSourceToObject.md +92 -0
- package/docs/api/query.md +133 -0
- package/docs/api/rawQueries.md +197 -0
- package/docs/api/reference.md +117 -0
- package/docs/api/setAuthorizer.md +103 -0
- package/docs/api/setDefault.md +90 -0
- package/docs/api/setDefaultIdentifier.md +84 -0
- package/docs/api/setDomain.md +56 -0
- package/docs/api/setIDUser.md +91 -0
- package/docs/api/setJsonSchema.md +92 -0
- package/docs/api/setProvider.md +87 -0
- package/docs/api/setSchema.md +107 -0
- package/docs/api/setScope.md +68 -0
- package/docs/api/validateObject.md +119 -0
- package/docs/architecture.md +316 -0
- package/docs/audit-tracking.md +226 -0
- package/docs/configuration.md +317 -0
- package/docs/providers/meadow-endpoints.md +306 -0
- package/docs/providers/mongodb.md +319 -0
- package/docs/providers/postgresql.md +312 -0
- package/docs/providers/rocksdb.md +297 -0
- package/docs/query-dsl.md +269 -0
- package/docs/quick-start.md +384 -0
- package/docs/raw-queries.md +193 -0
- package/docs/retold-catalog.json +61 -1
- package/docs/retold-keyword-index.json +15860 -4839
- package/docs/soft-deletes.md +224 -0
- package/package.json +36 -9
- package/scripts/bookstore-seed-postgresql.sql +135 -0
- package/scripts/dgraph-test-db.sh +144 -0
- package/scripts/meadow-test-cleanup.sh +5 -1
- package/scripts/mongodb-test-db.sh +98 -0
- package/scripts/postgresql-test-db.sh +124 -0
- package/scripts/solr-test-db.sh +135 -0
- package/source/Meadow.js +5 -0
- package/source/providers/Meadow-Provider-DGraph.js +679 -0
- package/source/providers/Meadow-Provider-MongoDB.js +527 -0
- package/source/providers/Meadow-Provider-PostgreSQL.js +361 -0
- package/source/providers/Meadow-Provider-RocksDB.js +1300 -0
- package/source/providers/Meadow-Provider-Solr.js +726 -0
- package/test/Meadow-Provider-DGraph_tests.js +741 -0
- package/test/Meadow-Provider-MongoDB_tests.js +661 -0
- package/test/Meadow-Provider-PostgreSQL_tests.js +787 -0
- package/test/Meadow-Provider-RocksDB_tests.js +887 -0
- package/test/Meadow-Provider-Solr_tests.js +679 -0
|
@@ -0,0 +1,679 @@
|
|
|
1
|
+
// ##### Part of the **[retold](https://stevenvelozo.github.io/retold/)** system
|
|
2
|
+
/**
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @author <steven@velozo.com>
|
|
5
|
+
*/
|
|
6
|
+
var MeadowProvider = function ()
|
|
7
|
+
{
|
|
8
|
+
function createNew(pFable)
|
|
9
|
+
{
|
|
10
|
+
// If a valid Fable object isn't passed in, return a constructor
|
|
11
|
+
if (typeof (pFable) !== 'object')
|
|
12
|
+
{
|
|
13
|
+
return { new: createNew };
|
|
14
|
+
}
|
|
15
|
+
var _Fable = pFable;
|
|
16
|
+
var _GlobalLogLevel = 0;
|
|
17
|
+
if (_Fable.settings.DGraph)
|
|
18
|
+
{
|
|
19
|
+
_GlobalLogLevel = _Fable.settings.DGraph.GlobalLogLevel || 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get the DGraph client from the connection service.
|
|
24
|
+
*/
|
|
25
|
+
var getClient = function ()
|
|
26
|
+
{
|
|
27
|
+
if (typeof (_Fable.MeadowDGraphProvider) == 'object' && _Fable.MeadowDGraphProvider.connected)
|
|
28
|
+
{
|
|
29
|
+
return _Fable.MeadowDGraphProvider.pool;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
var getProvider = function ()
|
|
35
|
+
{
|
|
36
|
+
if (typeof (_Fable.MeadowDGraphProvider) == 'object')
|
|
37
|
+
{
|
|
38
|
+
return _Fable.MeadowDGraphProvider;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Deep-walk an object and replace $$NOW sentinels with ISO datetime strings.
|
|
45
|
+
* DGraph expects RFC3339/ISO8601 formatted datetime strings.
|
|
46
|
+
*
|
|
47
|
+
* @param {Object} pObj Object to process (mutated in place)
|
|
48
|
+
* @return {Object} The same object with sentinels replaced
|
|
49
|
+
*/
|
|
50
|
+
var replaceSentinels = function (pObj)
|
|
51
|
+
{
|
|
52
|
+
if (typeof pObj !== 'object' || pObj === null)
|
|
53
|
+
{
|
|
54
|
+
return pObj;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (var tmpKey in pObj)
|
|
58
|
+
{
|
|
59
|
+
if (!pObj.hasOwnProperty(tmpKey))
|
|
60
|
+
{
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (pObj[tmpKey] === '$$NOW')
|
|
65
|
+
{
|
|
66
|
+
pObj[tmpKey] = new Date().toISOString();
|
|
67
|
+
}
|
|
68
|
+
else if (typeof pObj[tmpKey] === 'object' && pObj[tmpKey] !== null)
|
|
69
|
+
{
|
|
70
|
+
replaceSentinels(pObj[tmpKey]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return pObj;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get the next auto-increment sequence value for a type/column pair.
|
|
78
|
+
* Uses MeadowCounter nodes in DGraph with query-then-mutate.
|
|
79
|
+
*
|
|
80
|
+
* @param {Object} pClient DGraph client instance
|
|
81
|
+
* @param {String} pScope Type name
|
|
82
|
+
* @param {String} pIDColumn Identity column name
|
|
83
|
+
* @param {Function} fCallback (error, nextSequenceValue)
|
|
84
|
+
*/
|
|
85
|
+
var getNextSequence = function (pClient, pScope, pIDColumn, fCallback)
|
|
86
|
+
{
|
|
87
|
+
var tmpCounterKey = pScope + '.' + pIDColumn;
|
|
88
|
+
|
|
89
|
+
// Query for existing counter
|
|
90
|
+
var tmpQuery = '{ counter(func: eq(MeadowCounter.scope, "' + tmpCounterKey + '")) { uid MeadowCounter.sequence } }';
|
|
91
|
+
var tmpTxn = pClient.newTxn();
|
|
92
|
+
|
|
93
|
+
tmpTxn.query(tmpQuery)
|
|
94
|
+
.then(function (pResponse)
|
|
95
|
+
{
|
|
96
|
+
var tmpData = pResponse.data || {};
|
|
97
|
+
var tmpCounters = tmpData.counter || [];
|
|
98
|
+
|
|
99
|
+
if (tmpCounters.length > 0)
|
|
100
|
+
{
|
|
101
|
+
// Counter exists, increment it
|
|
102
|
+
var tmpCurrentSeq = tmpCounters[0]['MeadowCounter.sequence'] || 0;
|
|
103
|
+
var tmpNextSeq = tmpCurrentSeq + 1;
|
|
104
|
+
var tmpUid = tmpCounters[0].uid;
|
|
105
|
+
|
|
106
|
+
var tmpMutation = {
|
|
107
|
+
setJson: {
|
|
108
|
+
uid: tmpUid,
|
|
109
|
+
'MeadowCounter.sequence': tmpNextSeq
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return tmpTxn.mutate(tmpMutation)
|
|
114
|
+
.then(function ()
|
|
115
|
+
{
|
|
116
|
+
return tmpTxn.commit();
|
|
117
|
+
})
|
|
118
|
+
.then(function ()
|
|
119
|
+
{
|
|
120
|
+
return fCallback(null, tmpNextSeq);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
else
|
|
124
|
+
{
|
|
125
|
+
// Create new counter with sequence=1
|
|
126
|
+
var tmpMutation = {
|
|
127
|
+
setJson: {
|
|
128
|
+
'dgraph.type': 'MeadowCounter',
|
|
129
|
+
'MeadowCounter.scope': tmpCounterKey,
|
|
130
|
+
'MeadowCounter.sequence': 1
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
return tmpTxn.mutate(tmpMutation)
|
|
135
|
+
.then(function ()
|
|
136
|
+
{
|
|
137
|
+
return tmpTxn.commit();
|
|
138
|
+
})
|
|
139
|
+
.then(function ()
|
|
140
|
+
{
|
|
141
|
+
return fCallback(null, 1);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
.catch(function (pError)
|
|
146
|
+
{
|
|
147
|
+
try { tmpTxn.discard(); } catch(e) {}
|
|
148
|
+
return fCallback(pError);
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// The Meadow marshaller also passes in the Schema as the third parameter
|
|
153
|
+
var marshalRecordFromSourceToObject = function (pObject, pRecord)
|
|
154
|
+
{
|
|
155
|
+
for (var tmpColumn in pRecord)
|
|
156
|
+
{
|
|
157
|
+
// Skip DGraph internal fields
|
|
158
|
+
if (tmpColumn === 'uid' || tmpColumn === 'dgraph.type')
|
|
159
|
+
{
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
// Strip scope prefix from DGraph predicate names (e.g. "FableTest.IDAnimal" → "IDAnimal")
|
|
163
|
+
var tmpFieldName = tmpColumn;
|
|
164
|
+
var tmpDotIndex = tmpFieldName.indexOf('.');
|
|
165
|
+
if (tmpDotIndex >= 0)
|
|
166
|
+
{
|
|
167
|
+
tmpFieldName = tmpFieldName.substring(tmpDotIndex + 1);
|
|
168
|
+
}
|
|
169
|
+
pObject[tmpFieldName] = pRecord[tmpColumn];
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
var Create = function (pQuery, fCallback)
|
|
174
|
+
{
|
|
175
|
+
var tmpResult = pQuery.parameters.result;
|
|
176
|
+
|
|
177
|
+
pQuery.setDialect('DGraph').buildCreateQuery();
|
|
178
|
+
|
|
179
|
+
if (pQuery.logLevel > 0 ||
|
|
180
|
+
_GlobalLogLevel > 0)
|
|
181
|
+
{
|
|
182
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
var tmpClient = getClient();
|
|
186
|
+
if (!tmpClient)
|
|
187
|
+
{
|
|
188
|
+
tmpResult.error = new Error('No DGraph connection available.');
|
|
189
|
+
tmpResult.executed = true;
|
|
190
|
+
return fCallback();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
var tmpOp = pQuery.query.parameters.dgraphOperation;
|
|
194
|
+
if (!tmpOp)
|
|
195
|
+
{
|
|
196
|
+
tmpResult.error = new Error('No DGraph operation generated.');
|
|
197
|
+
tmpResult.executed = true;
|
|
198
|
+
return fCallback();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
var tmpDocument = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.document)));
|
|
202
|
+
|
|
203
|
+
// Check for $$AUTOINCREMENT sentinel
|
|
204
|
+
var tmpAutoIncrementColumn = false;
|
|
205
|
+
for (var tmpKey in tmpDocument)
|
|
206
|
+
{
|
|
207
|
+
if (tmpDocument[tmpKey] === '$$AUTOINCREMENT')
|
|
208
|
+
{
|
|
209
|
+
tmpAutoIncrementColumn = tmpKey;
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (tmpAutoIncrementColumn)
|
|
215
|
+
{
|
|
216
|
+
// Get next sequence, then insert
|
|
217
|
+
getNextSequence(tmpClient, tmpOp.type, tmpAutoIncrementColumn, function (pSeqError, pSeqValue)
|
|
218
|
+
{
|
|
219
|
+
if (pSeqError)
|
|
220
|
+
{
|
|
221
|
+
tmpResult.error = pSeqError;
|
|
222
|
+
tmpResult.value = false;
|
|
223
|
+
tmpResult.executed = true;
|
|
224
|
+
return fCallback();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
tmpDocument[tmpAutoIncrementColumn] = pSeqValue;
|
|
228
|
+
|
|
229
|
+
var tmpTxn = tmpClient.newTxn();
|
|
230
|
+
tmpTxn.mutate({ setJson: tmpDocument })
|
|
231
|
+
.then(function ()
|
|
232
|
+
{
|
|
233
|
+
return tmpTxn.commit();
|
|
234
|
+
})
|
|
235
|
+
.then(function ()
|
|
236
|
+
{
|
|
237
|
+
tmpResult.error = null;
|
|
238
|
+
tmpResult.value = pSeqValue;
|
|
239
|
+
tmpResult.executed = true;
|
|
240
|
+
return fCallback();
|
|
241
|
+
})
|
|
242
|
+
.catch(function (pError)
|
|
243
|
+
{
|
|
244
|
+
try { tmpTxn.discard(); } catch(e) {}
|
|
245
|
+
tmpResult.error = pError;
|
|
246
|
+
tmpResult.value = false;
|
|
247
|
+
tmpResult.executed = true;
|
|
248
|
+
return fCallback();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
else
|
|
253
|
+
{
|
|
254
|
+
var tmpTxn = tmpClient.newTxn();
|
|
255
|
+
tmpTxn.mutate({ setJson: tmpDocument })
|
|
256
|
+
.then(function (pMutateResult)
|
|
257
|
+
{
|
|
258
|
+
return tmpTxn.commit()
|
|
259
|
+
.then(function ()
|
|
260
|
+
{
|
|
261
|
+
tmpResult.error = null;
|
|
262
|
+
// Return the assigned UID(s)
|
|
263
|
+
var tmpUids = pMutateResult.data && pMutateResult.data.uids;
|
|
264
|
+
tmpResult.value = tmpUids ? tmpUids[Object.keys(tmpUids)[0]] : true;
|
|
265
|
+
tmpResult.executed = true;
|
|
266
|
+
return fCallback();
|
|
267
|
+
});
|
|
268
|
+
})
|
|
269
|
+
.catch(function (pError)
|
|
270
|
+
{
|
|
271
|
+
try { tmpTxn.discard(); } catch(e) {}
|
|
272
|
+
tmpResult.error = pError;
|
|
273
|
+
tmpResult.value = false;
|
|
274
|
+
tmpResult.executed = true;
|
|
275
|
+
return fCallback();
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
var Read = function (pQuery, fCallback)
|
|
281
|
+
{
|
|
282
|
+
var tmpResult = pQuery.parameters.result;
|
|
283
|
+
|
|
284
|
+
pQuery.setDialect('DGraph').buildReadQuery();
|
|
285
|
+
|
|
286
|
+
if (pQuery.logLevel > 0 ||
|
|
287
|
+
_GlobalLogLevel > 0)
|
|
288
|
+
{
|
|
289
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
var tmpClient = getClient();
|
|
293
|
+
if (!tmpClient)
|
|
294
|
+
{
|
|
295
|
+
tmpResult.error = new Error('No DGraph connection available.');
|
|
296
|
+
tmpResult.executed = true;
|
|
297
|
+
return fCallback();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
var tmpOp = pQuery.query.parameters.dgraphOperation;
|
|
301
|
+
var tmpTxn = tmpClient.newTxn({ readOnly: true });
|
|
302
|
+
|
|
303
|
+
tmpTxn.query(tmpOp.query)
|
|
304
|
+
.then(function (pResponse)
|
|
305
|
+
{
|
|
306
|
+
var tmpData = pResponse.data || {};
|
|
307
|
+
tmpResult.error = null;
|
|
308
|
+
tmpResult.value = tmpData[tmpOp.queryName] || [];
|
|
309
|
+
tmpResult.executed = true;
|
|
310
|
+
return fCallback();
|
|
311
|
+
})
|
|
312
|
+
.catch(function (pError)
|
|
313
|
+
{
|
|
314
|
+
tmpResult.error = pError;
|
|
315
|
+
tmpResult.value = false;
|
|
316
|
+
tmpResult.executed = true;
|
|
317
|
+
return fCallback();
|
|
318
|
+
});
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
var Update = function (pQuery, fCallback)
|
|
322
|
+
{
|
|
323
|
+
var tmpResult = pQuery.parameters.result;
|
|
324
|
+
|
|
325
|
+
pQuery.setDialect('DGraph').buildUpdateQuery();
|
|
326
|
+
|
|
327
|
+
if (pQuery.logLevel > 0 ||
|
|
328
|
+
_GlobalLogLevel > 0)
|
|
329
|
+
{
|
|
330
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
var tmpClient = getClient();
|
|
334
|
+
if (!tmpClient)
|
|
335
|
+
{
|
|
336
|
+
tmpResult.error = new Error('No DGraph connection available.');
|
|
337
|
+
tmpResult.executed = true;
|
|
338
|
+
return fCallback();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
var tmpOp = pQuery.query.parameters.dgraphOperation;
|
|
342
|
+
if (!tmpOp)
|
|
343
|
+
{
|
|
344
|
+
tmpResult.error = new Error('No DGraph operation generated.');
|
|
345
|
+
tmpResult.executed = true;
|
|
346
|
+
return fCallback();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// First query for matching UIDs
|
|
350
|
+
var tmpReadTxn = tmpClient.newTxn({ readOnly: true });
|
|
351
|
+
tmpReadTxn.query(tmpOp.queryForUIDs)
|
|
352
|
+
.then(function (pResponse)
|
|
353
|
+
{
|
|
354
|
+
var tmpData = pResponse.data || {};
|
|
355
|
+
var tmpNodes = tmpData[tmpOp.queryName] || [];
|
|
356
|
+
|
|
357
|
+
if (tmpNodes.length === 0)
|
|
358
|
+
{
|
|
359
|
+
tmpResult.error = null;
|
|
360
|
+
tmpResult.value = 0;
|
|
361
|
+
tmpResult.executed = true;
|
|
362
|
+
return fCallback();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Build mutation: set updated fields on each matching UID
|
|
366
|
+
var tmpUpdateDoc = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.update)));
|
|
367
|
+
var tmpMutations = [];
|
|
368
|
+
for (var i = 0; i < tmpNodes.length; i++)
|
|
369
|
+
{
|
|
370
|
+
var tmpSetDoc = JSON.parse(JSON.stringify(tmpUpdateDoc));
|
|
371
|
+
tmpSetDoc.uid = tmpNodes[i].uid;
|
|
372
|
+
tmpMutations.push(tmpSetDoc);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
var tmpWriteTxn = tmpClient.newTxn();
|
|
376
|
+
tmpWriteTxn.mutate({ setJson: tmpMutations })
|
|
377
|
+
.then(function ()
|
|
378
|
+
{
|
|
379
|
+
return tmpWriteTxn.commit();
|
|
380
|
+
})
|
|
381
|
+
.then(function ()
|
|
382
|
+
{
|
|
383
|
+
tmpResult.error = null;
|
|
384
|
+
tmpResult.value = tmpMutations;
|
|
385
|
+
tmpResult.executed = true;
|
|
386
|
+
return fCallback();
|
|
387
|
+
})
|
|
388
|
+
.catch(function (pError)
|
|
389
|
+
{
|
|
390
|
+
try { tmpWriteTxn.discard(); } catch(e) {}
|
|
391
|
+
tmpResult.error = pError;
|
|
392
|
+
tmpResult.value = false;
|
|
393
|
+
tmpResult.executed = true;
|
|
394
|
+
return fCallback();
|
|
395
|
+
});
|
|
396
|
+
})
|
|
397
|
+
.catch(function (pError)
|
|
398
|
+
{
|
|
399
|
+
tmpResult.error = pError;
|
|
400
|
+
tmpResult.value = false;
|
|
401
|
+
tmpResult.executed = true;
|
|
402
|
+
return fCallback();
|
|
403
|
+
});
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
var Delete = function (pQuery, fCallback)
|
|
407
|
+
{
|
|
408
|
+
var tmpResult = pQuery.parameters.result;
|
|
409
|
+
|
|
410
|
+
pQuery.setDialect('DGraph').buildDeleteQuery();
|
|
411
|
+
|
|
412
|
+
if (pQuery.logLevel > 0 ||
|
|
413
|
+
_GlobalLogLevel > 0)
|
|
414
|
+
{
|
|
415
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
var tmpClient = getClient();
|
|
419
|
+
if (!tmpClient)
|
|
420
|
+
{
|
|
421
|
+
tmpResult.error = new Error('No DGraph connection available.');
|
|
422
|
+
tmpResult.executed = true;
|
|
423
|
+
return fCallback();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
var tmpOp = pQuery.query.parameters.dgraphOperation;
|
|
427
|
+
|
|
428
|
+
// First query for matching UIDs
|
|
429
|
+
var tmpReadTxn = tmpClient.newTxn({ readOnly: true });
|
|
430
|
+
tmpReadTxn.query(tmpOp.queryForUIDs)
|
|
431
|
+
.then(function (pResponse)
|
|
432
|
+
{
|
|
433
|
+
var tmpData = pResponse.data || {};
|
|
434
|
+
var tmpNodes = tmpData[tmpOp.queryName] || [];
|
|
435
|
+
|
|
436
|
+
if (tmpNodes.length === 0)
|
|
437
|
+
{
|
|
438
|
+
tmpResult.error = null;
|
|
439
|
+
tmpResult.value = 0;
|
|
440
|
+
tmpResult.executed = true;
|
|
441
|
+
return fCallback();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (tmpOp.operation === 'upsert')
|
|
445
|
+
{
|
|
446
|
+
// Soft delete: update matching nodes with delete setters
|
|
447
|
+
var tmpUpdateDoc = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.update)));
|
|
448
|
+
var tmpMutations = [];
|
|
449
|
+
for (var i = 0; i < tmpNodes.length; i++)
|
|
450
|
+
{
|
|
451
|
+
var tmpSetDoc = JSON.parse(JSON.stringify(tmpUpdateDoc));
|
|
452
|
+
tmpSetDoc.uid = tmpNodes[i].uid;
|
|
453
|
+
tmpMutations.push(tmpSetDoc);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
var tmpWriteTxn = tmpClient.newTxn();
|
|
457
|
+
tmpWriteTxn.mutate({ setJson: tmpMutations })
|
|
458
|
+
.then(function ()
|
|
459
|
+
{
|
|
460
|
+
return tmpWriteTxn.commit();
|
|
461
|
+
})
|
|
462
|
+
.then(function ()
|
|
463
|
+
{
|
|
464
|
+
tmpResult.error = null;
|
|
465
|
+
tmpResult.value = tmpNodes.length;
|
|
466
|
+
tmpResult.executed = true;
|
|
467
|
+
return fCallback();
|
|
468
|
+
})
|
|
469
|
+
.catch(function (pError)
|
|
470
|
+
{
|
|
471
|
+
try { tmpWriteTxn.discard(); } catch(e) {}
|
|
472
|
+
tmpResult.error = pError;
|
|
473
|
+
tmpResult.value = false;
|
|
474
|
+
tmpResult.executed = true;
|
|
475
|
+
return fCallback();
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
else
|
|
479
|
+
{
|
|
480
|
+
// Hard delete: delete the nodes
|
|
481
|
+
var tmpDeleteDocs = [];
|
|
482
|
+
for (var j = 0; j < tmpNodes.length; j++)
|
|
483
|
+
{
|
|
484
|
+
tmpDeleteDocs.push({ uid: tmpNodes[j].uid });
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
var tmpWriteTxn = tmpClient.newTxn();
|
|
488
|
+
tmpWriteTxn.mutate({ deleteJson: tmpDeleteDocs })
|
|
489
|
+
.then(function ()
|
|
490
|
+
{
|
|
491
|
+
return tmpWriteTxn.commit();
|
|
492
|
+
})
|
|
493
|
+
.then(function ()
|
|
494
|
+
{
|
|
495
|
+
tmpResult.error = null;
|
|
496
|
+
tmpResult.value = tmpNodes.length;
|
|
497
|
+
tmpResult.executed = true;
|
|
498
|
+
return fCallback();
|
|
499
|
+
})
|
|
500
|
+
.catch(function (pError)
|
|
501
|
+
{
|
|
502
|
+
try { tmpWriteTxn.discard(); } catch(e) {}
|
|
503
|
+
tmpResult.error = pError;
|
|
504
|
+
tmpResult.value = false;
|
|
505
|
+
tmpResult.executed = true;
|
|
506
|
+
return fCallback();
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
})
|
|
510
|
+
.catch(function (pError)
|
|
511
|
+
{
|
|
512
|
+
tmpResult.error = pError;
|
|
513
|
+
tmpResult.value = false;
|
|
514
|
+
tmpResult.executed = true;
|
|
515
|
+
return fCallback();
|
|
516
|
+
});
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
var Undelete = function (pQuery, fCallback)
|
|
520
|
+
{
|
|
521
|
+
var tmpResult = pQuery.parameters.result;
|
|
522
|
+
|
|
523
|
+
pQuery.setDialect('DGraph').buildUndeleteQuery();
|
|
524
|
+
|
|
525
|
+
if (pQuery.logLevel > 0 ||
|
|
526
|
+
_GlobalLogLevel > 0)
|
|
527
|
+
{
|
|
528
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
var tmpClient = getClient();
|
|
532
|
+
if (!tmpClient)
|
|
533
|
+
{
|
|
534
|
+
tmpResult.error = new Error('No DGraph connection available.');
|
|
535
|
+
tmpResult.executed = true;
|
|
536
|
+
return fCallback();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
var tmpOp = pQuery.query.parameters.dgraphOperation;
|
|
540
|
+
if (!tmpOp || tmpOp.operation === 'noop')
|
|
541
|
+
{
|
|
542
|
+
tmpResult.error = null;
|
|
543
|
+
tmpResult.value = 0;
|
|
544
|
+
tmpResult.executed = true;
|
|
545
|
+
return fCallback();
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Query for matching UIDs
|
|
549
|
+
var tmpReadTxn = tmpClient.newTxn({ readOnly: true });
|
|
550
|
+
tmpReadTxn.query(tmpOp.queryForUIDs)
|
|
551
|
+
.then(function (pResponse)
|
|
552
|
+
{
|
|
553
|
+
var tmpData = pResponse.data || {};
|
|
554
|
+
var tmpNodes = tmpData[tmpOp.queryName] || [];
|
|
555
|
+
|
|
556
|
+
if (tmpNodes.length === 0)
|
|
557
|
+
{
|
|
558
|
+
tmpResult.error = null;
|
|
559
|
+
tmpResult.value = 0;
|
|
560
|
+
tmpResult.executed = true;
|
|
561
|
+
return fCallback();
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
var tmpUpdateDoc = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.update)));
|
|
565
|
+
var tmpMutations = [];
|
|
566
|
+
for (var i = 0; i < tmpNodes.length; i++)
|
|
567
|
+
{
|
|
568
|
+
var tmpSetDoc = JSON.parse(JSON.stringify(tmpUpdateDoc));
|
|
569
|
+
tmpSetDoc.uid = tmpNodes[i].uid;
|
|
570
|
+
tmpMutations.push(tmpSetDoc);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
var tmpWriteTxn = tmpClient.newTxn();
|
|
574
|
+
tmpWriteTxn.mutate({ setJson: tmpMutations })
|
|
575
|
+
.then(function ()
|
|
576
|
+
{
|
|
577
|
+
return tmpWriteTxn.commit();
|
|
578
|
+
})
|
|
579
|
+
.then(function ()
|
|
580
|
+
{
|
|
581
|
+
tmpResult.error = null;
|
|
582
|
+
tmpResult.value = tmpNodes.length;
|
|
583
|
+
tmpResult.executed = true;
|
|
584
|
+
return fCallback();
|
|
585
|
+
})
|
|
586
|
+
.catch(function (pError)
|
|
587
|
+
{
|
|
588
|
+
try { tmpWriteTxn.discard(); } catch(e) {}
|
|
589
|
+
tmpResult.error = pError;
|
|
590
|
+
tmpResult.value = false;
|
|
591
|
+
tmpResult.executed = true;
|
|
592
|
+
return fCallback();
|
|
593
|
+
});
|
|
594
|
+
})
|
|
595
|
+
.catch(function (pError)
|
|
596
|
+
{
|
|
597
|
+
tmpResult.error = pError;
|
|
598
|
+
tmpResult.value = false;
|
|
599
|
+
tmpResult.executed = true;
|
|
600
|
+
return fCallback();
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
var Count = function (pQuery, fCallback)
|
|
605
|
+
{
|
|
606
|
+
var tmpResult = pQuery.parameters.result;
|
|
607
|
+
|
|
608
|
+
pQuery.setDialect('DGraph').buildCountQuery();
|
|
609
|
+
|
|
610
|
+
if (pQuery.logLevel > 0 ||
|
|
611
|
+
_GlobalLogLevel > 0)
|
|
612
|
+
{
|
|
613
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
var tmpClient = getClient();
|
|
617
|
+
if (!tmpClient)
|
|
618
|
+
{
|
|
619
|
+
tmpResult.error = new Error('No DGraph connection available.');
|
|
620
|
+
tmpResult.executed = true;
|
|
621
|
+
return fCallback();
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
var tmpOp = pQuery.query.parameters.dgraphOperation;
|
|
625
|
+
var tmpTxn = tmpClient.newTxn({ readOnly: true });
|
|
626
|
+
|
|
627
|
+
tmpTxn.query(tmpOp.query)
|
|
628
|
+
.then(function (pResponse)
|
|
629
|
+
{
|
|
630
|
+
var tmpData = pResponse.data || {};
|
|
631
|
+
var tmpResults = tmpData[tmpOp.queryName] || [];
|
|
632
|
+
tmpResult.error = null;
|
|
633
|
+
|
|
634
|
+
if (tmpResults.length > 0 && typeof tmpResults[0].total !== 'undefined')
|
|
635
|
+
{
|
|
636
|
+
tmpResult.value = tmpResults[0].total;
|
|
637
|
+
}
|
|
638
|
+
else
|
|
639
|
+
{
|
|
640
|
+
tmpResult.value = 0;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
tmpResult.executed = true;
|
|
644
|
+
return fCallback();
|
|
645
|
+
})
|
|
646
|
+
.catch(function (pError)
|
|
647
|
+
{
|
|
648
|
+
tmpResult.error = pError;
|
|
649
|
+
tmpResult.value = false;
|
|
650
|
+
tmpResult.executed = true;
|
|
651
|
+
return fCallback();
|
|
652
|
+
});
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
var tmpNewProvider = (
|
|
656
|
+
{
|
|
657
|
+
marshalRecordFromSourceToObject: marshalRecordFromSourceToObject,
|
|
658
|
+
|
|
659
|
+
Create: Create,
|
|
660
|
+
Read: Read,
|
|
661
|
+
Update: Update,
|
|
662
|
+
Delete: Delete,
|
|
663
|
+
Undelete: Undelete,
|
|
664
|
+
Count: Count,
|
|
665
|
+
|
|
666
|
+
getProvider: getProvider,
|
|
667
|
+
providerCreatesSupported: true,
|
|
668
|
+
|
|
669
|
+
new: createNew
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
return tmpNewProvider;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return createNew();
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
module.exports = new MeadowProvider();
|