meadow 2.0.23 → 2.0.27

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.
Files changed (62) hide show
  1. package/README.md +110 -141
  2. package/docs/README.md +34 -230
  3. package/docs/_cover.md +14 -0
  4. package/docs/_sidebar.md +44 -12
  5. package/docs/_topbar.md +5 -0
  6. package/docs/api/doCount.md +109 -0
  7. package/docs/api/doCreate.md +132 -0
  8. package/docs/api/doDelete.md +101 -0
  9. package/docs/api/doRead.md +122 -0
  10. package/docs/api/doReads.md +136 -0
  11. package/docs/api/doUndelete.md +98 -0
  12. package/docs/api/doUpdate.md +129 -0
  13. package/docs/api/getRoleName.md +84 -0
  14. package/docs/api/loadFromPackage.md +153 -0
  15. package/docs/api/marshalRecordFromSourceToObject.md +92 -0
  16. package/docs/api/query.md +133 -0
  17. package/docs/api/rawQueries.md +197 -0
  18. package/docs/api/reference.md +117 -0
  19. package/docs/api/setAuthorizer.md +103 -0
  20. package/docs/api/setDefault.md +90 -0
  21. package/docs/api/setDefaultIdentifier.md +84 -0
  22. package/docs/api/setDomain.md +56 -0
  23. package/docs/api/setIDUser.md +91 -0
  24. package/docs/api/setJsonSchema.md +92 -0
  25. package/docs/api/setProvider.md +87 -0
  26. package/docs/api/setSchema.md +107 -0
  27. package/docs/api/setScope.md +68 -0
  28. package/docs/api/validateObject.md +119 -0
  29. package/docs/architecture.md +316 -0
  30. package/docs/audit-tracking.md +226 -0
  31. package/docs/configuration.md +317 -0
  32. package/docs/providers/meadow-endpoints.md +306 -0
  33. package/docs/providers/mongodb.md +319 -0
  34. package/docs/providers/postgresql.md +312 -0
  35. package/docs/providers/rocksdb.md +297 -0
  36. package/docs/query-dsl.md +269 -0
  37. package/docs/quick-start.md +384 -0
  38. package/docs/raw-queries.md +193 -0
  39. package/docs/retold-catalog.json +61 -1
  40. package/docs/retold-keyword-index.json +15860 -4839
  41. package/docs/soft-deletes.md +224 -0
  42. package/package.json +44 -13
  43. package/scripts/bookstore-seed-postgresql.sql +135 -0
  44. package/scripts/dgraph-test-db.sh +144 -0
  45. package/scripts/meadow-test-cleanup.sh +5 -1
  46. package/scripts/mongodb-test-db.sh +98 -0
  47. package/scripts/postgresql-test-db.sh +124 -0
  48. package/scripts/solr-test-db.sh +135 -0
  49. package/source/Meadow.js +5 -0
  50. package/source/providers/Meadow-Provider-DGraph.js +679 -0
  51. package/source/providers/Meadow-Provider-MeadowEndpoints.js +1 -1
  52. package/source/providers/Meadow-Provider-MongoDB.js +527 -0
  53. package/source/providers/Meadow-Provider-PostgreSQL.js +361 -0
  54. package/source/providers/Meadow-Provider-RocksDB.js +1300 -0
  55. package/source/providers/Meadow-Provider-Solr.js +726 -0
  56. package/test/Meadow-Provider-DGraph_tests.js +741 -0
  57. package/test/Meadow-Provider-MongoDB_tests.js +661 -0
  58. package/test/Meadow-Provider-PostgreSQL_tests.js +787 -0
  59. package/test/Meadow-Provider-RocksDB_tests.js +887 -0
  60. package/test/Meadow-Provider-SQLiteBrowser-Headless_tests.js +657 -0
  61. package/test/Meadow-Provider-SQLiteBrowser_tests.js +895 -0
  62. package/test/Meadow-Provider-Solr_tests.js +679 -0
@@ -0,0 +1,361 @@
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.PostgreSQL)
18
+ {
19
+ _GlobalLogLevel = _Fable.settings.PostgreSQL.GlobalLogLevel || 0;
20
+ }
21
+
22
+ /**
23
+ * Convert named parameters (:paramName) to positional ($N) parameters
24
+ * for the pg library.
25
+ *
26
+ * @param {String} pQueryBody - SQL query body with :paramName placeholders
27
+ * @param {Object} pNamedParams - Object of parameter name -> value mappings
28
+ * @return {Object} { text: String, values: Array }
29
+ */
30
+ var convertNamedToPositional = function (pQueryBody, pNamedParams)
31
+ {
32
+ var tmpValues = [];
33
+ var tmpParamIndex = 0;
34
+ // Track which named params we've already mapped to a positional index
35
+ var tmpParamMap = {};
36
+
37
+ // Match :paramName patterns (word characters after a colon)
38
+ // but not inside quoted strings and not ::type casts
39
+ var tmpText = pQueryBody.replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, function (pMatch, pParamName)
40
+ {
41
+ if (!pNamedParams.hasOwnProperty(pParamName))
42
+ {
43
+ // Not a known parameter; leave it as-is (could be a ::typecast)
44
+ return pMatch;
45
+ }
46
+
47
+ if (tmpParamMap.hasOwnProperty(pParamName))
48
+ {
49
+ // Reuse the same positional index for duplicate references
50
+ return '$' + tmpParamMap[pParamName];
51
+ }
52
+
53
+ tmpParamIndex++;
54
+ tmpParamMap[pParamName] = tmpParamIndex;
55
+
56
+ var tmpValue = pNamedParams[pParamName];
57
+ if (Array.isArray(tmpValue))
58
+ {
59
+ // IN clause: expand array into $N, $N+1, ...
60
+ var tmpPlaceholders = [];
61
+ for (var i = 0; i < tmpValue.length; i++)
62
+ {
63
+ if (i > 0)
64
+ {
65
+ tmpParamIndex++;
66
+ }
67
+ tmpValues.push(tmpValue[i]);
68
+ tmpPlaceholders.push('$' + tmpParamIndex);
69
+ }
70
+ return tmpPlaceholders.join(', ');
71
+ }
72
+ else
73
+ {
74
+ tmpValues.push(tmpValue);
75
+ return '$' + tmpParamIndex;
76
+ }
77
+ });
78
+
79
+ return { text: tmpText, values: tmpValues };
80
+ };
81
+
82
+ /**
83
+ * Build a connection pool, shared within this provider.
84
+ */
85
+ var getSQLPool = function ()
86
+ {
87
+ // New-style default connection pool provider
88
+ if (typeof (_Fable.MeadowPostgreSQLProvider) == 'object' && _Fable.MeadowPostgreSQLProvider.connected)
89
+ {
90
+ return _Fable.MeadowPostgreSQLProvider.pool;
91
+ }
92
+
93
+ return false;
94
+ };
95
+
96
+ var getProvider = function ()
97
+ {
98
+ // New-style default connection pool provider
99
+ if (typeof (_Fable.MeadowPostgreSQLProvider) == 'object')
100
+ {
101
+ return _Fable.MeadowPostgreSQLProvider;
102
+ }
103
+
104
+ return false;
105
+ };
106
+
107
+ // The Meadow marshaller also passes in the Schema as the third parameter, but this is a blunt function ATM.
108
+ var marshalRecordFromSourceToObject = function (pObject, pRecord)
109
+ {
110
+ // For now, crudely assign everything in pRecord to pObject
111
+ for (var tmpColumn in pRecord)
112
+ {
113
+ pObject[tmpColumn] = pRecord[tmpColumn];
114
+ }
115
+ };
116
+
117
+ var Create = function (pQuery, fCallback)
118
+ {
119
+ var tmpResult = pQuery.parameters.result;
120
+
121
+ pQuery.setDialect('PostgreSQL').buildCreateQuery();
122
+
123
+ if (pQuery.logLevel > 0 ||
124
+ _GlobalLogLevel > 0)
125
+ {
126
+ _Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
127
+ }
128
+
129
+ var tmpConverted = convertNamedToPositional(pQuery.query.body, pQuery.query.parameters);
130
+
131
+ getSQLPool().query(
132
+ tmpConverted.text,
133
+ tmpConverted.values,
134
+ function (pError, pDBResult)
135
+ {
136
+ tmpResult.error = pError;
137
+ tmpResult.value = false;
138
+ try
139
+ {
140
+ // RETURNING * gives us the full row; find the AutoIdentity column
141
+ if (pDBResult && pDBResult.rows && pDBResult.rows.length > 0)
142
+ {
143
+ var tmpSchema = Array.isArray(pQuery.query.schema) ? pQuery.query.schema : [];
144
+ var tmpIDColumn = false;
145
+ for (var i = 0; i < tmpSchema.length; i++)
146
+ {
147
+ if (tmpSchema[i].Type === 'AutoIdentity')
148
+ {
149
+ tmpIDColumn = tmpSchema[i].Column;
150
+ break;
151
+ }
152
+ }
153
+ if (tmpIDColumn && pDBResult.rows[0].hasOwnProperty(tmpIDColumn))
154
+ {
155
+ tmpResult.value = pDBResult.rows[0][tmpIDColumn];
156
+ }
157
+ else
158
+ {
159
+ // Fall back to the first column of the first row
160
+ var tmpFirstKey = Object.keys(pDBResult.rows[0])[0];
161
+ tmpResult.value = pDBResult.rows[0][tmpFirstKey];
162
+ }
163
+ }
164
+ }
165
+ catch (pErrorGettingID)
166
+ {
167
+ _Fable.log.warn('Error getting insert ID during create query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
168
+ }
169
+
170
+ tmpResult.executed = true;
171
+ return fCallback();
172
+ }
173
+ );
174
+ };
175
+
176
+ // This is a synchronous read, good for a few records.
177
+ var Read = function (pQuery, fCallback)
178
+ {
179
+ var tmpResult = pQuery.parameters.result;
180
+
181
+ pQuery.setDialect('PostgreSQL').buildReadQuery();
182
+
183
+ if (pQuery.logLevel > 0 ||
184
+ _GlobalLogLevel > 0)
185
+ {
186
+ _Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
187
+ }
188
+
189
+ var tmpConverted = convertNamedToPositional(pQuery.query.body, pQuery.query.parameters);
190
+
191
+ getSQLPool().query(
192
+ tmpConverted.text,
193
+ tmpConverted.values,
194
+ function (pError, pDBResult)
195
+ {
196
+ tmpResult.error = pError;
197
+ tmpResult.value = pDBResult ? pDBResult.rows : [];
198
+ tmpResult.executed = true;
199
+ return fCallback();
200
+ }
201
+ );
202
+ };
203
+
204
+ var Update = function (pQuery, fCallback)
205
+ {
206
+ var tmpResult = pQuery.parameters.result;
207
+
208
+ pQuery.setDialect('PostgreSQL').buildUpdateQuery();
209
+
210
+ if (pQuery.logLevel > 0 ||
211
+ _GlobalLogLevel > 0)
212
+ {
213
+ _Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
214
+ }
215
+
216
+ var tmpConverted = convertNamedToPositional(pQuery.query.body, pQuery.query.parameters);
217
+
218
+ getSQLPool().query(
219
+ tmpConverted.text,
220
+ tmpConverted.values,
221
+ function (pError, pDBResult)
222
+ {
223
+ tmpResult.error = pError;
224
+ tmpResult.value = pDBResult ? pDBResult.rows : [];
225
+ tmpResult.executed = true;
226
+ return fCallback();
227
+ }
228
+ );
229
+ };
230
+
231
+ var Delete = function (pQuery, fCallback)
232
+ {
233
+ var tmpResult = pQuery.parameters.result;
234
+
235
+ pQuery.setDialect('PostgreSQL').buildDeleteQuery();
236
+
237
+ if (pQuery.logLevel > 0 ||
238
+ _GlobalLogLevel > 0)
239
+ {
240
+ _Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
241
+ }
242
+
243
+ var tmpConverted = convertNamedToPositional(pQuery.query.body, pQuery.query.parameters);
244
+
245
+ getSQLPool().query(
246
+ tmpConverted.text,
247
+ tmpConverted.values,
248
+ function (pError, pDBResult)
249
+ {
250
+ tmpResult.error = pError;
251
+ tmpResult.value = false;
252
+ try
253
+ {
254
+ tmpResult.value = pDBResult ? pDBResult.rowCount : 0;
255
+ }
256
+ catch (pErrorGettingRowcount)
257
+ {
258
+ _Fable.log.warn('Error getting affected rowcount during delete query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
259
+ }
260
+ tmpResult.executed = true;
261
+ return fCallback();
262
+ }
263
+ );
264
+ };
265
+
266
+ var Undelete = function (pQuery, fCallback)
267
+ {
268
+ var tmpResult = pQuery.parameters.result;
269
+
270
+ pQuery.setDialect('PostgreSQL').buildUndeleteQuery();
271
+
272
+ if (pQuery.logLevel > 0 ||
273
+ _GlobalLogLevel > 0)
274
+ {
275
+ _Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
276
+ }
277
+
278
+ var tmpConverted = convertNamedToPositional(pQuery.query.body, pQuery.query.parameters);
279
+
280
+ getSQLPool().query(
281
+ tmpConverted.text,
282
+ tmpConverted.values,
283
+ function (pError, pDBResult)
284
+ {
285
+ tmpResult.error = pError;
286
+ tmpResult.value = false;
287
+ try
288
+ {
289
+ tmpResult.value = pDBResult ? pDBResult.rowCount : 0;
290
+ }
291
+ catch (pErrorGettingRowcount)
292
+ {
293
+ _Fable.log.warn('Error getting affected rowcount during undelete query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
294
+ }
295
+ tmpResult.executed = true;
296
+ return fCallback();
297
+ }
298
+ );
299
+ };
300
+
301
+ var Count = function (pQuery, fCallback)
302
+ {
303
+ var tmpResult = pQuery.parameters.result;
304
+
305
+ pQuery.setDialect('PostgreSQL').buildCountQuery();
306
+
307
+ if (pQuery.logLevel > 0 ||
308
+ _GlobalLogLevel > 0)
309
+ {
310
+ _Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
311
+ }
312
+
313
+ var tmpConverted = convertNamedToPositional(pQuery.query.body, pQuery.query.parameters);
314
+
315
+ getSQLPool().query(
316
+ tmpConverted.text,
317
+ tmpConverted.values,
318
+ function (pError, pDBResult)
319
+ {
320
+ tmpResult.executed = true;
321
+ tmpResult.error = pError;
322
+ tmpResult.value = false;
323
+ try
324
+ {
325
+ // PostgreSQL COUNT(*) returns bigint, which the pg library delivers as a string
326
+ tmpResult.value = parseInt(pDBResult.rows[0].rowcount, 10);
327
+ }
328
+ catch (pErrorGettingRowcount)
329
+ {
330
+ _Fable.log.warn('Error getting rowcount during count query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
331
+ }
332
+ return fCallback();
333
+ }
334
+ );
335
+ };
336
+
337
+ var tmpNewProvider = (
338
+ {
339
+ marshalRecordFromSourceToObject: marshalRecordFromSourceToObject,
340
+
341
+ Create: Create,
342
+ Read: Read,
343
+ Update: Update,
344
+ Delete: Delete,
345
+ Undelete: Undelete,
346
+ Count: Count,
347
+
348
+ getProvider: getProvider,
349
+ providerCreatesSupported: false,
350
+
351
+ new: createNew
352
+ });
353
+
354
+
355
+ return tmpNewProvider;
356
+ }
357
+
358
+ return createNew();
359
+ };
360
+
361
+ module.exports = new MeadowProvider();