@vsaas/loopback-datasource-juggler 10.0.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/LICENSE +25 -0
- package/NOTICE +23 -0
- package/README.md +74 -0
- package/dist/_virtual/_rolldown/runtime.js +4 -0
- package/dist/index.js +26 -0
- package/dist/lib/browser.depd.js +13 -0
- package/dist/lib/case-utils.js +21 -0
- package/dist/lib/connectors/kv-memory.js +158 -0
- package/dist/lib/connectors/memory.js +810 -0
- package/dist/lib/connectors/transient.js +126 -0
- package/dist/lib/dao.js +2445 -0
- package/dist/lib/datasource.js +2215 -0
- package/dist/lib/date-string.js +87 -0
- package/dist/lib/geo.js +244 -0
- package/dist/lib/globalize.js +33 -0
- package/dist/lib/hooks.js +79 -0
- package/dist/lib/id-utils.js +66 -0
- package/dist/lib/include.js +795 -0
- package/dist/lib/include_utils.js +104 -0
- package/dist/lib/introspection.js +37 -0
- package/dist/lib/jutil.js +65 -0
- package/dist/lib/kvao/delete-all.js +57 -0
- package/dist/lib/kvao/delete.js +43 -0
- package/dist/lib/kvao/expire.js +35 -0
- package/dist/lib/kvao/get.js +34 -0
- package/dist/lib/kvao/index.js +28 -0
- package/dist/lib/kvao/iterate-keys.js +38 -0
- package/dist/lib/kvao/keys.js +55 -0
- package/dist/lib/kvao/set.js +39 -0
- package/dist/lib/kvao/ttl.js +35 -0
- package/dist/lib/list.js +101 -0
- package/dist/lib/mixins.js +58 -0
- package/dist/lib/model-builder.js +608 -0
- package/dist/lib/model-definition.js +231 -0
- package/dist/lib/model-utils.js +368 -0
- package/dist/lib/model.js +586 -0
- package/dist/lib/observer.js +235 -0
- package/dist/lib/relation-definition.js +2604 -0
- package/dist/lib/relations.js +587 -0
- package/dist/lib/scope.js +392 -0
- package/dist/lib/transaction.js +183 -0
- package/dist/lib/types.js +58 -0
- package/dist/lib/utils.js +625 -0
- package/dist/lib/validations.js +742 -0
- package/dist/package.js +93 -0
- package/package.json +85 -0
- package/types/common.d.ts +28 -0
- package/types/connector.d.ts +52 -0
- package/types/datasource.d.ts +324 -0
- package/types/date-string.d.ts +21 -0
- package/types/inclusion-mixin.d.ts +44 -0
- package/types/index.d.ts +36 -0
- package/types/kv-model.d.ts +201 -0
- package/types/model.d.ts +368 -0
- package/types/observer-mixin.d.ts +174 -0
- package/types/persisted-model.d.ts +505 -0
- package/types/query.d.ts +108 -0
- package/types/relation-mixin.d.ts +577 -0
- package/types/relation.d.ts +301 -0
- package/types/scope.d.ts +92 -0
- package/types/transaction-mixin.d.ts +47 -0
- package/types/types.d.ts +65 -0
- package/types/validation-mixin.d.ts +287 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
3
|
+
const require_lib_globalize = require("./globalize.js");
|
|
4
|
+
const require_lib_utils = require("./utils.js");
|
|
5
|
+
const require_lib_model = require("./model.js");
|
|
6
|
+
//#region src/lib/scope.ts
|
|
7
|
+
var require_scope = /* @__PURE__ */ require_runtime.__commonJSMin(((exports) => {
|
|
8
|
+
const i8n = require("inflection");
|
|
9
|
+
const g = require_lib_globalize();
|
|
10
|
+
const { isDeepStrictEqual } = require("util");
|
|
11
|
+
const utils = require_lib_utils;
|
|
12
|
+
const defineCachedRelations = utils.defineCachedRelations;
|
|
13
|
+
const setScopeValuesFromWhere = utils.setScopeValuesFromWhere;
|
|
14
|
+
const mergeQuery = utils.mergeQuery;
|
|
15
|
+
const DefaultModelBaseClass = require_lib_model;
|
|
16
|
+
const collectTargetIds = utils.collectTargetIds;
|
|
17
|
+
const idName = utils.idName;
|
|
18
|
+
const deprecated = require("depd")("loopback-datasource-juggler");
|
|
19
|
+
function isObject(value) {
|
|
20
|
+
return value !== null && typeof value === "object";
|
|
21
|
+
}
|
|
22
|
+
function isEmptyObject(value) {
|
|
23
|
+
return Object.keys(value).length === 0;
|
|
24
|
+
}
|
|
25
|
+
function omit(object, keyToOmit) {
|
|
26
|
+
const result = {};
|
|
27
|
+
const keys = Object.keys(object);
|
|
28
|
+
for (let i = 0; i < keys.length; i++) {
|
|
29
|
+
const key = keys[i];
|
|
30
|
+
if (key !== keyToOmit) result[key] = object[key];
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
function intersectionWith(left, right, comparator) {
|
|
35
|
+
const result = [];
|
|
36
|
+
for (let i = 0; i < left.length; i++) {
|
|
37
|
+
const leftValue = left[i];
|
|
38
|
+
for (let j = 0; j < right.length; j++) if (comparator(leftValue, right[j])) {
|
|
39
|
+
result.push(leftValue);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
function isEqual(left, right) {
|
|
46
|
+
return isDeepStrictEqual(left, right);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Module exports
|
|
50
|
+
*/
|
|
51
|
+
exports.defineScope = defineScope;
|
|
52
|
+
function ScopeDefinition(definition) {
|
|
53
|
+
this.isStatic = definition.isStatic;
|
|
54
|
+
this.modelFrom = definition.modelFrom;
|
|
55
|
+
this.modelTo = definition.modelTo || definition.modelFrom;
|
|
56
|
+
this.name = definition.name;
|
|
57
|
+
this.params = definition.params;
|
|
58
|
+
this.methods = definition.methods || {};
|
|
59
|
+
this.options = definition.options || {};
|
|
60
|
+
}
|
|
61
|
+
ScopeDefinition.prototype.targetModel = function(receiver) {
|
|
62
|
+
let modelTo;
|
|
63
|
+
if (typeof this.options.modelTo === "function") modelTo = this.options.modelTo.call(this, receiver) || this.modelTo;
|
|
64
|
+
else modelTo = this.modelTo;
|
|
65
|
+
if (!(modelTo.prototype instanceof DefaultModelBaseClass)) {
|
|
66
|
+
let msg = "Invalid target model for scope `";
|
|
67
|
+
msg += (this.isStatic ? this.modelFrom : this.modelFrom.constructor).modelName;
|
|
68
|
+
msg += this.isStatic ? "." : ".prototype.";
|
|
69
|
+
msg += this.name + "`.";
|
|
70
|
+
throw new Error(msg);
|
|
71
|
+
}
|
|
72
|
+
return modelTo;
|
|
73
|
+
};
|
|
74
|
+
/*!
|
|
75
|
+
* Find related model instances
|
|
76
|
+
* @param {*} receiver The target model class/prototype
|
|
77
|
+
* @param {Object|Function} scopeParams
|
|
78
|
+
* @param {Boolean|Object} [condOrRefresh] true for refresh or object as a filter
|
|
79
|
+
* @param {Object} [options]
|
|
80
|
+
* @param {Function} cb
|
|
81
|
+
* @returns {*}
|
|
82
|
+
*/
|
|
83
|
+
ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefresh, options, cb) {
|
|
84
|
+
const name = this.name;
|
|
85
|
+
const self = receiver;
|
|
86
|
+
let actualCond = {};
|
|
87
|
+
let actualRefresh = false;
|
|
88
|
+
let saveOnCache = receiver instanceof DefaultModelBaseClass;
|
|
89
|
+
if (typeof condOrRefresh === "function" && options === void 0 && cb === void 0) {
|
|
90
|
+
cb = condOrRefresh;
|
|
91
|
+
options = {};
|
|
92
|
+
condOrRefresh = void 0;
|
|
93
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
94
|
+
cb = options;
|
|
95
|
+
options = {};
|
|
96
|
+
}
|
|
97
|
+
options = options || {};
|
|
98
|
+
if (condOrRefresh !== void 0) if (typeof condOrRefresh === "boolean") actualRefresh = condOrRefresh;
|
|
99
|
+
else {
|
|
100
|
+
actualCond = condOrRefresh;
|
|
101
|
+
actualRefresh = true;
|
|
102
|
+
saveOnCache = false;
|
|
103
|
+
}
|
|
104
|
+
cb = cb || utils.createPromiseCallback();
|
|
105
|
+
if (!self.__cachedRelations || self.__cachedRelations[name] === void 0 || actualRefresh) {
|
|
106
|
+
const params = mergeQuery(actualCond, scopeParams, { nestedInclude: true });
|
|
107
|
+
const targetModel = this.targetModel(receiver);
|
|
108
|
+
const scopeOnRelatedModel = params.collect && params.include.scope !== null && typeof params.include.scope === "object";
|
|
109
|
+
let filter, queryRelated;
|
|
110
|
+
if (scopeOnRelatedModel) {
|
|
111
|
+
filter = params.include;
|
|
112
|
+
queryRelated = filter.scope;
|
|
113
|
+
delete params.include.scope;
|
|
114
|
+
}
|
|
115
|
+
targetModel.find(params, options, function(err, data) {
|
|
116
|
+
if (!err && saveOnCache) {
|
|
117
|
+
defineCachedRelations(self);
|
|
118
|
+
self.__cachedRelations[name] = data;
|
|
119
|
+
}
|
|
120
|
+
if (scopeOnRelatedModel === true) {
|
|
121
|
+
const relatedModel = targetModel.relations[filter.relation].modelTo;
|
|
122
|
+
const IdKey = idName(relatedModel);
|
|
123
|
+
const smartMerge = function(idCollection, qWhere) {
|
|
124
|
+
if (!qWhere[IdKey]) return idCollection;
|
|
125
|
+
let merged = {};
|
|
126
|
+
const idsA = idCollection.inq;
|
|
127
|
+
const intersect = intersectionWith(idsA, qWhere[IdKey].inq ? qWhere[IdKey].inq : [qWhere[IdKey]], isEqual);
|
|
128
|
+
if (intersect.length === 1) merged = intersect[0];
|
|
129
|
+
if (intersect.length > 1) merged = { inq: intersect };
|
|
130
|
+
return merged;
|
|
131
|
+
};
|
|
132
|
+
if (queryRelated.where !== void 0) {
|
|
133
|
+
const IdKeyCondition = {};
|
|
134
|
+
IdKeyCondition[IdKey] = smartMerge(collectTargetIds(data, IdKey), queryRelated.where);
|
|
135
|
+
if (isObject(IdKeyCondition[IdKey]) && isEmptyObject(IdKeyCondition[IdKey])) return cb(null, []);
|
|
136
|
+
const mergedWhere = { and: [IdKeyCondition, omit(queryRelated.where, IdKey)] };
|
|
137
|
+
queryRelated.where = mergedWhere;
|
|
138
|
+
} else {
|
|
139
|
+
queryRelated.where = {};
|
|
140
|
+
queryRelated.where[IdKey] = collectTargetIds(data, IdKey);
|
|
141
|
+
}
|
|
142
|
+
relatedModel.find(queryRelated, options, cb);
|
|
143
|
+
} else cb(err, data);
|
|
144
|
+
});
|
|
145
|
+
} else cb(null, self.__cachedRelations[name]);
|
|
146
|
+
return cb.promise;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Define a scope method
|
|
150
|
+
* @param {String} name of the method
|
|
151
|
+
* @param {Function} function to define
|
|
152
|
+
*/
|
|
153
|
+
ScopeDefinition.prototype.defineMethod = function(name, fn) {
|
|
154
|
+
return this.methods[name] = fn;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Define a scope to the class
|
|
158
|
+
* @param {Model} cls The class where the scope method is added
|
|
159
|
+
* @param {Model} targetClass The class that a query to run against
|
|
160
|
+
* @param {String} name The name of the scope
|
|
161
|
+
* @param {Object|Function} params The parameters object for the query or a function
|
|
162
|
+
* to return the query object
|
|
163
|
+
* @param methods An object of methods keyed by the method name to be bound to the class
|
|
164
|
+
*/
|
|
165
|
+
function defineScope(cls, targetClass, name, params, methods, options) {
|
|
166
|
+
if (!cls._scopeMeta) cls._scopeMeta = {};
|
|
167
|
+
if (cls === targetClass) cls._scopeMeta[name] = params;
|
|
168
|
+
else if (targetClass) {
|
|
169
|
+
if (!targetClass._scopeMeta) targetClass._scopeMeta = {};
|
|
170
|
+
}
|
|
171
|
+
options = options || {};
|
|
172
|
+
const isStatic = typeof cls === "function" || options.isStatic || false;
|
|
173
|
+
const definition = new ScopeDefinition({
|
|
174
|
+
isStatic,
|
|
175
|
+
modelFrom: cls,
|
|
176
|
+
modelTo: targetClass,
|
|
177
|
+
name,
|
|
178
|
+
params,
|
|
179
|
+
methods,
|
|
180
|
+
options
|
|
181
|
+
});
|
|
182
|
+
if (isStatic) {
|
|
183
|
+
cls.scopes = cls.scopes || {};
|
|
184
|
+
cls.scopes[name] = definition;
|
|
185
|
+
} else {
|
|
186
|
+
cls.constructor.scopes = cls.constructor.scopes || {};
|
|
187
|
+
cls.constructor.scopes[name] = definition;
|
|
188
|
+
}
|
|
189
|
+
Object.defineProperty(cls, name, {
|
|
190
|
+
enumerable: false,
|
|
191
|
+
configurable: true,
|
|
192
|
+
get: function() {
|
|
193
|
+
const targetModel = definition.targetModel(this);
|
|
194
|
+
const self = this;
|
|
195
|
+
const f = function(condOrRefresh, options, cb) {
|
|
196
|
+
if (arguments.length === 0) {
|
|
197
|
+
if (typeof f.value === "function") return f.value(self);
|
|
198
|
+
else if (self.__cachedRelations) return self.__cachedRelations[name];
|
|
199
|
+
} else {
|
|
200
|
+
if (typeof condOrRefresh === "function" && options === void 0 && cb === void 0) {
|
|
201
|
+
cb = condOrRefresh;
|
|
202
|
+
options = {};
|
|
203
|
+
condOrRefresh = void 0;
|
|
204
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
205
|
+
cb = options;
|
|
206
|
+
options = {};
|
|
207
|
+
}
|
|
208
|
+
options = options || {};
|
|
209
|
+
if (f._scope.collect && condOrRefresh !== null && typeof condOrRefresh === "object") {
|
|
210
|
+
f._scope.include = {
|
|
211
|
+
relation: f._scope.collect,
|
|
212
|
+
scope: condOrRefresh
|
|
213
|
+
};
|
|
214
|
+
condOrRefresh = {};
|
|
215
|
+
}
|
|
216
|
+
return definition.related(self, f._scope, condOrRefresh, options, cb);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
f._receiver = this;
|
|
220
|
+
f._scope = typeof definition.params === "function" ? definition.params.call(self) : definition.params;
|
|
221
|
+
f._targetClass = targetModel.modelName;
|
|
222
|
+
if (f._scope.collect) {
|
|
223
|
+
const rel = targetModel.relations[f._scope.collect];
|
|
224
|
+
f._targetClass = rel && rel.modelTo && rel.modelTo.modelName || i8n.camelize(f._scope.collect);
|
|
225
|
+
}
|
|
226
|
+
f.find = function(condOrRefresh, options, cb) {
|
|
227
|
+
if (typeof condOrRefresh === "function" && options === void 0 && cb === void 0) {
|
|
228
|
+
cb = condOrRefresh;
|
|
229
|
+
options = {};
|
|
230
|
+
condOrRefresh = {};
|
|
231
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
232
|
+
cb = options;
|
|
233
|
+
options = {};
|
|
234
|
+
}
|
|
235
|
+
options = options || {};
|
|
236
|
+
return definition.related(self, f._scope, condOrRefresh, options, cb);
|
|
237
|
+
};
|
|
238
|
+
f.getAsync = function() {
|
|
239
|
+
deprecated(g.f("Scope method \"getAsync()\" is deprecated, use \"find()\" instead."));
|
|
240
|
+
return this.find.apply(this, arguments);
|
|
241
|
+
};
|
|
242
|
+
f.build = build;
|
|
243
|
+
f.create = create;
|
|
244
|
+
f.updateAll = updateAll;
|
|
245
|
+
f.destroyAll = destroyAll;
|
|
246
|
+
f.findById = findById;
|
|
247
|
+
f.findOne = findOne;
|
|
248
|
+
f.count = count;
|
|
249
|
+
for (const i in definition.methods) f[i] = definition.methods[i].bind(self);
|
|
250
|
+
if (!targetClass) return f;
|
|
251
|
+
Object.keys(targetClass._scopeMeta).forEach(function(name) {
|
|
252
|
+
Object.defineProperty(f, name, {
|
|
253
|
+
enumerable: false,
|
|
254
|
+
get: function() {
|
|
255
|
+
mergeQuery(f._scope, targetModel._scopeMeta[name]);
|
|
256
|
+
return f;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}.bind(self));
|
|
260
|
+
return f;
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
const fn = function() {
|
|
264
|
+
this[name].apply(this[name], arguments);
|
|
265
|
+
};
|
|
266
|
+
cls["__get__" + name] = fn;
|
|
267
|
+
const fnCreate = function() {
|
|
268
|
+
this[name].create.apply(this[name], arguments);
|
|
269
|
+
};
|
|
270
|
+
cls["__create__" + name] = fnCreate;
|
|
271
|
+
const fnDelete = function() {
|
|
272
|
+
this[name].destroyAll.apply(this[name], arguments);
|
|
273
|
+
};
|
|
274
|
+
cls["__delete__" + name] = fnDelete;
|
|
275
|
+
const fnUpdate = function() {
|
|
276
|
+
this[name].updateAll.apply(this[name], arguments);
|
|
277
|
+
};
|
|
278
|
+
cls["__update__" + name] = fnUpdate;
|
|
279
|
+
const fnFindById = function(_cb) {
|
|
280
|
+
this[name].findById.apply(this[name], arguments);
|
|
281
|
+
};
|
|
282
|
+
cls["__findById__" + name] = fnFindById;
|
|
283
|
+
const fnFindOne = function(_cb) {
|
|
284
|
+
this[name].findOne.apply(this[name], arguments);
|
|
285
|
+
};
|
|
286
|
+
cls["__findOne__" + name] = fnFindOne;
|
|
287
|
+
const fnCount = function(_cb) {
|
|
288
|
+
this[name].count.apply(this[name], arguments);
|
|
289
|
+
};
|
|
290
|
+
cls["__count__" + name] = fnCount;
|
|
291
|
+
function build(data) {
|
|
292
|
+
data = data || {};
|
|
293
|
+
const targetModel = definition.targetModel(this._receiver);
|
|
294
|
+
const where = this._scope && this._scope.where || {};
|
|
295
|
+
setScopeValuesFromWhere(data, where, targetModel);
|
|
296
|
+
return new targetModel(data);
|
|
297
|
+
}
|
|
298
|
+
function create(data, options, cb) {
|
|
299
|
+
if (typeof data === "function" && options === void 0 && cb === void 0) {
|
|
300
|
+
cb = data;
|
|
301
|
+
data = {};
|
|
302
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
303
|
+
cb = options;
|
|
304
|
+
options = {};
|
|
305
|
+
}
|
|
306
|
+
options = options || {};
|
|
307
|
+
return this.build(data).save(options, cb);
|
|
308
|
+
}
|
|
309
|
+
function destroyAll(where, options, cb) {
|
|
310
|
+
if (typeof where === "function") {
|
|
311
|
+
cb = where;
|
|
312
|
+
where = {};
|
|
313
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
314
|
+
cb = options;
|
|
315
|
+
options = {};
|
|
316
|
+
}
|
|
317
|
+
options = options || {};
|
|
318
|
+
const targetModel = definition.targetModel(this._receiver);
|
|
319
|
+
const filter = mergeQuery({ where: this._scope && this._scope.where || {} }, { where: where || {} });
|
|
320
|
+
return targetModel.destroyAll(filter.where, options, cb);
|
|
321
|
+
}
|
|
322
|
+
function updateAll(where, data, options, cb) {
|
|
323
|
+
if (typeof data === "function" && options === void 0 && cb === void 0) {
|
|
324
|
+
cb = data;
|
|
325
|
+
data = where;
|
|
326
|
+
where = {};
|
|
327
|
+
options = {};
|
|
328
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
329
|
+
cb = options;
|
|
330
|
+
options = {};
|
|
331
|
+
}
|
|
332
|
+
options = options || {};
|
|
333
|
+
const targetModel = definition.targetModel(this._receiver);
|
|
334
|
+
const filter = mergeQuery({ where: this._scope && this._scope.where || {} }, { where: where || {} });
|
|
335
|
+
return targetModel.updateAll(filter.where, data, options, cb);
|
|
336
|
+
}
|
|
337
|
+
function findById(id, filter, options, cb) {
|
|
338
|
+
if (options === void 0 && cb === void 0) {
|
|
339
|
+
if (typeof filter === "function") {
|
|
340
|
+
cb = filter;
|
|
341
|
+
filter = {};
|
|
342
|
+
}
|
|
343
|
+
} else if (cb === void 0) {
|
|
344
|
+
if (typeof options === "function") {
|
|
345
|
+
cb = options;
|
|
346
|
+
options = {};
|
|
347
|
+
if (typeof filter === "object" && !(filter.include || filter.fields)) {
|
|
348
|
+
options = filter;
|
|
349
|
+
filter = {};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
options = options || {};
|
|
354
|
+
filter = filter || {};
|
|
355
|
+
const idName = definition.targetModel(this._receiver).definition.idName();
|
|
356
|
+
let query = { where: {} };
|
|
357
|
+
query.where[idName] = id;
|
|
358
|
+
query = mergeQuery(query, filter);
|
|
359
|
+
return this.findOne(query, options, cb);
|
|
360
|
+
}
|
|
361
|
+
function findOne(filter, options, cb) {
|
|
362
|
+
if (typeof filter === "function") {
|
|
363
|
+
cb = filter;
|
|
364
|
+
filter = {};
|
|
365
|
+
options = {};
|
|
366
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
367
|
+
cb = options;
|
|
368
|
+
options = {};
|
|
369
|
+
}
|
|
370
|
+
options = options || {};
|
|
371
|
+
const targetModel = definition.targetModel(this._receiver);
|
|
372
|
+
filter = mergeQuery({ where: this._scope && this._scope.where || {} }, filter || {});
|
|
373
|
+
return targetModel.findOne(filter, options, cb);
|
|
374
|
+
}
|
|
375
|
+
function count(where, options, cb) {
|
|
376
|
+
if (typeof where === "function") {
|
|
377
|
+
cb = where;
|
|
378
|
+
where = {};
|
|
379
|
+
} else if (typeof options === "function" && cb === void 0) {
|
|
380
|
+
cb = options;
|
|
381
|
+
options = {};
|
|
382
|
+
}
|
|
383
|
+
options = options || {};
|
|
384
|
+
const targetModel = definition.targetModel(this._receiver);
|
|
385
|
+
const filter = mergeQuery({ where: this._scope && this._scope.where || {} }, { where: where || {} });
|
|
386
|
+
return targetModel.count(filter.where, options, cb);
|
|
387
|
+
}
|
|
388
|
+
return definition;
|
|
389
|
+
}
|
|
390
|
+
}));
|
|
391
|
+
//#endregion
|
|
392
|
+
module.exports = require_scope();
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
3
|
+
const require_lib_globalize = require("./globalize.js");
|
|
4
|
+
const require_lib_jutil = require("./jutil.js");
|
|
5
|
+
const require_lib_utils = require("./utils.js");
|
|
6
|
+
const require_lib_observer = require("./observer.js");
|
|
7
|
+
const require_lib_id_utils = require("./id-utils.js");
|
|
8
|
+
//#region src/lib/transaction.ts
|
|
9
|
+
var require_transaction = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
|
|
10
|
+
const g = require_lib_globalize();
|
|
11
|
+
const debug = require("debug")("loopback:connector:transaction");
|
|
12
|
+
const { uuidV1 } = require_lib_id_utils;
|
|
13
|
+
const utils = require_lib_utils;
|
|
14
|
+
const jutil = require_lib_jutil;
|
|
15
|
+
const ObserverMixin = require_lib_observer;
|
|
16
|
+
const Transaction = require("@vsaas/loopback-connector").Transaction;
|
|
17
|
+
module.exports = TransactionMixin;
|
|
18
|
+
/**
|
|
19
|
+
* TransactionMixin class. Use to add transaction APIs to a model class.
|
|
20
|
+
*
|
|
21
|
+
* @class TransactionMixin
|
|
22
|
+
*/
|
|
23
|
+
function TransactionMixin() {}
|
|
24
|
+
/**
|
|
25
|
+
* Begin a new transaction.
|
|
26
|
+
*
|
|
27
|
+
* A transaction can be committed or rolled back. If timeout happens, the
|
|
28
|
+
* transaction will be rolled back. Please note a transaction is typically
|
|
29
|
+
* associated with a pooled connection. Committing or rolling back a transaction
|
|
30
|
+
* will release the connection back to the pool.
|
|
31
|
+
*
|
|
32
|
+
* Once the transaction is committed or rolled back, the connection property
|
|
33
|
+
* will be set to null to mark the transaction to be inactive. Trying to commit
|
|
34
|
+
* or rollback an inactive transaction will receive an error from the callback.
|
|
35
|
+
*
|
|
36
|
+
* Please also note that the transaction is only honored with the same data
|
|
37
|
+
* source/connector instance. CRUD methods will not join the current transaction
|
|
38
|
+
* if its model is not attached the same data source.
|
|
39
|
+
*
|
|
40
|
+
* Example:
|
|
41
|
+
*
|
|
42
|
+
* To pass the transaction context to one of the CRUD methods, use the `options`
|
|
43
|
+
* argument with `transaction` property, for example,
|
|
44
|
+
*
|
|
45
|
+
* ```js
|
|
46
|
+
* MyModel.beginTransaction('READ COMMITTED', function(err, tx) {
|
|
47
|
+
* MyModel.create({x: 1, y: 'a'}, {transaction: tx}, function(err, inst) {
|
|
48
|
+
* MyModel.find({x: 1}, {transaction: tx}, function(err, results) {
|
|
49
|
+
* // ...
|
|
50
|
+
* tx.commit(function(err) {...});
|
|
51
|
+
* });
|
|
52
|
+
* });
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @param {Object|String} options Options to be passed upon transaction.
|
|
57
|
+
*
|
|
58
|
+
* Can be one of the forms:
|
|
59
|
+
* - Object: {isolationLevel: '...', timeout: 1000}
|
|
60
|
+
* - String: isolationLevel
|
|
61
|
+
*
|
|
62
|
+
* Valid values of `isolationLevel` are:
|
|
63
|
+
*
|
|
64
|
+
* - Transaction.READ_COMMITTED = 'READ COMMITTED'; // default
|
|
65
|
+
* - Transaction.READ_UNCOMMITTED = 'READ UNCOMMITTED';
|
|
66
|
+
* - Transaction.SERIALIZABLE = 'SERIALIZABLE';
|
|
67
|
+
* - Transaction.REPEATABLE_READ = 'REPEATABLE READ';
|
|
68
|
+
* @callback {Function} cb Callback function.
|
|
69
|
+
* @returns {Promise|undefined} Returns a callback promise.
|
|
70
|
+
*/
|
|
71
|
+
TransactionMixin.beginTransaction = function(options, cb) {
|
|
72
|
+
cb = cb || utils.createPromiseCallback();
|
|
73
|
+
if (Transaction) {
|
|
74
|
+
const connector = this.getConnector();
|
|
75
|
+
Transaction.begin(connector, options, function(err, transaction) {
|
|
76
|
+
if (err) return cb(err);
|
|
77
|
+
if (!transaction.id) transaction.id = uuidV1();
|
|
78
|
+
if (options.timeout && !transaction.timeout) transaction.timeout = setTimeout(function() {
|
|
79
|
+
const context = {
|
|
80
|
+
transaction,
|
|
81
|
+
operation: "timeout"
|
|
82
|
+
};
|
|
83
|
+
transaction.notifyObserversOf("timeout", context, function(err) {
|
|
84
|
+
if (!err) transaction.rollback(function() {
|
|
85
|
+
debug("Transaction %s is rolled back due to timeout", transaction.id);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}, options.timeout);
|
|
89
|
+
cb(err, transaction);
|
|
90
|
+
});
|
|
91
|
+
} else process.nextTick(function() {
|
|
92
|
+
const err = new Error(g.f("{{Transaction}} is not supported"));
|
|
93
|
+
cb(err);
|
|
94
|
+
});
|
|
95
|
+
return cb.promise;
|
|
96
|
+
};
|
|
97
|
+
if (Transaction) {
|
|
98
|
+
jutil.mixin(Transaction.prototype, ObserverMixin);
|
|
99
|
+
/**
|
|
100
|
+
* Commit a transaction and release it back to the pool.
|
|
101
|
+
*
|
|
102
|
+
* Example:
|
|
103
|
+
*
|
|
104
|
+
* ```js
|
|
105
|
+
* MyModel.beginTransaction('READ COMMITTED', function(err, tx) {
|
|
106
|
+
* // some crud operation of your choice
|
|
107
|
+
* tx.commit(function(err) {
|
|
108
|
+
* // release the connection pool upon committing
|
|
109
|
+
* tx.close(err);
|
|
110
|
+
* });
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @callback {Function} cb Callback function.
|
|
115
|
+
* @returns {Promise|undefined} Returns a callback promise.
|
|
116
|
+
*/
|
|
117
|
+
Transaction.prototype.commit = function(cb) {
|
|
118
|
+
cb = cb || utils.createPromiseCallback();
|
|
119
|
+
if (this.ensureActive(cb)) {
|
|
120
|
+
const context = {
|
|
121
|
+
transaction: this,
|
|
122
|
+
operation: "commit"
|
|
123
|
+
};
|
|
124
|
+
this.notifyObserversAround("commit", context, (done) => {
|
|
125
|
+
this.connector.commit(this.connection, done);
|
|
126
|
+
}, (err) => {
|
|
127
|
+
this.connection = null;
|
|
128
|
+
cb(err);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return cb.promise;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Rollback a transaction and release it back to the pool.
|
|
135
|
+
*
|
|
136
|
+
* Example:
|
|
137
|
+
*
|
|
138
|
+
* ```js
|
|
139
|
+
* MyModel.beginTransaction('READ COMMITTED', function(err, tx) {
|
|
140
|
+
* // some crud operation of your choice
|
|
141
|
+
* tx.rollback(function(err) {
|
|
142
|
+
* // release the connection pool upon committing
|
|
143
|
+
* tx.close(err);
|
|
144
|
+
* });
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @callback {Function} cb Callback function.
|
|
149
|
+
* @returns {Promise|undefined} Returns a callback promise.
|
|
150
|
+
*/
|
|
151
|
+
Transaction.prototype.rollback = function(cb) {
|
|
152
|
+
cb = cb || utils.createPromiseCallback();
|
|
153
|
+
if (this.ensureActive(cb)) {
|
|
154
|
+
const context = {
|
|
155
|
+
transaction: this,
|
|
156
|
+
operation: "rollback"
|
|
157
|
+
};
|
|
158
|
+
this.notifyObserversAround("rollback", context, (done) => {
|
|
159
|
+
this.connector.rollback(this.connection, done);
|
|
160
|
+
}, (err) => {
|
|
161
|
+
this.connection = null;
|
|
162
|
+
cb(err);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return cb.promise;
|
|
166
|
+
};
|
|
167
|
+
Transaction.prototype.ensureActive = function(cb) {
|
|
168
|
+
if (!this.connection) process.nextTick(() => {
|
|
169
|
+
cb(new Error(g.f("The {{transaction}} is not active: %s", this.id)));
|
|
170
|
+
});
|
|
171
|
+
return !!this.connection;
|
|
172
|
+
};
|
|
173
|
+
Transaction.prototype.toJSON = function() {
|
|
174
|
+
return this.id;
|
|
175
|
+
};
|
|
176
|
+
Transaction.prototype.toString = function() {
|
|
177
|
+
return this.id;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
TransactionMixin.Transaction = Transaction;
|
|
181
|
+
}));
|
|
182
|
+
//#endregion
|
|
183
|
+
module.exports = require_transaction();
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
3
|
+
const require_lib_date_string = require("./date-string.js");
|
|
4
|
+
const require_lib_geo = require("./geo.js");
|
|
5
|
+
//#region src/lib/types.ts
|
|
6
|
+
var require_types = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
|
|
7
|
+
const Types = {};
|
|
8
|
+
/**
|
|
9
|
+
* Schema types
|
|
10
|
+
*/
|
|
11
|
+
Types.Text = function Text(value) {
|
|
12
|
+
if (!(this instanceof Text)) return value;
|
|
13
|
+
this.value = value;
|
|
14
|
+
};
|
|
15
|
+
Types.Text.prototype.toObject = Types.Text.prototype.toJSON = function() {
|
|
16
|
+
return this.value;
|
|
17
|
+
};
|
|
18
|
+
Types.JSON = function JSON(value) {
|
|
19
|
+
if (!(this instanceof JSON)) return value;
|
|
20
|
+
this.value = value;
|
|
21
|
+
};
|
|
22
|
+
Types.JSON.prototype.toObject = Types.JSON.prototype.toJSON = function() {
|
|
23
|
+
return this.value;
|
|
24
|
+
};
|
|
25
|
+
Types.Any = function Any(value) {
|
|
26
|
+
if (!(this instanceof Any)) return value;
|
|
27
|
+
this.value = value;
|
|
28
|
+
};
|
|
29
|
+
Types.Any.prototype.toObject = Types.Any.prototype.toJSON = function() {
|
|
30
|
+
return this.value;
|
|
31
|
+
};
|
|
32
|
+
module.exports = function(modelTypes) {
|
|
33
|
+
const DateString = require_lib_date_string;
|
|
34
|
+
const GeoPoint = require_lib_geo.GeoPoint;
|
|
35
|
+
for (const t in Types) modelTypes[t] = Types[t];
|
|
36
|
+
modelTypes.schemaTypes = {};
|
|
37
|
+
modelTypes.registerType = function(type, names) {
|
|
38
|
+
names = names || [];
|
|
39
|
+
names = names.concat([type.name]);
|
|
40
|
+
for (let n = 0; n < names.length; n++) this.schemaTypes[names[n].toLowerCase()] = type;
|
|
41
|
+
};
|
|
42
|
+
modelTypes.registerType(Types.Text);
|
|
43
|
+
modelTypes.registerType(Types.JSON);
|
|
44
|
+
modelTypes.registerType(Types.Any);
|
|
45
|
+
modelTypes.registerType(String);
|
|
46
|
+
modelTypes.registerType(Number);
|
|
47
|
+
modelTypes.registerType(Boolean);
|
|
48
|
+
modelTypes.registerType(Date);
|
|
49
|
+
modelTypes.registerType(DateString);
|
|
50
|
+
modelTypes.registerType(Buffer, ["Binary"]);
|
|
51
|
+
modelTypes.registerType(Array);
|
|
52
|
+
modelTypes.registerType(GeoPoint);
|
|
53
|
+
modelTypes.registerType(Object);
|
|
54
|
+
};
|
|
55
|
+
module.exports.Types = Types;
|
|
56
|
+
}));
|
|
57
|
+
//#endregion
|
|
58
|
+
module.exports = require_types();
|