UNPKG

30.8 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10var __generator = (this && this.__generator) || function (thisArg, body) {
11 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
12 return { next: verb(0), "throw": verb(1), "return": verb(2) };
13 function verb(n) { return function (v) { return step([n, v]); }; }
14 function step(op) {
15 if (f) throw new TypeError("Generator is already executing.");
16 while (_) try {
17 if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
18 if (y = 0, t) op = [0, t.value];
19 switch (op[0]) {
20 case 0: case 1: t = op; break;
21 case 4: _.label++; return { value: op[1], done: false };
22 case 5: _.label++; y = op[1]; op = [0]; continue;
23 case 7: op = _.ops.pop(); _.trys.pop(); continue;
24 default:
25 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29 if (t[2]) _.ops.pop();
30 _.trys.pop(); continue;
31 }
32 op = body.call(thisArg, _);
33 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35 }
36};
37var Constants_1 = require("./Constants");
38var Types_1 = require("./Types");
39var Errors_1 = require("./Errors");
40var Log = require("./log");
41var Util_1 = require("./Util");
42var ModelMapper_1 = require("./ModelMapper");
43var MetadataManager_1 = require("./MetadataManager");
44var typeguard_1 = require("typeguard");
45// Logger
46var log = Log.create(__filename);
47/**
48 * The core Repo implementation
49 *
50 * When requested from the coordinator,
51 * it offers itself to all configured plugins for
52 * them to attach to the model pipeline
53 *
54 *
55 */
56var Repo = (function () {
57 /**
58 * Core repo is instantiated by providing the implementing/extending
59 * class and the model that will be supported
60 *
61 * @param repoClazz
62 * @param modelClazz
63 */
64 function Repo(repoClazz, modelClazz) {
65 var _this = this;
66 this.repoClazz = repoClazz;
67 this.modelClazz = modelClazz;
68 this.plugins = Array();
69 this.getPlugins = function (predicate) { return _this.plugins.filter(predicate); };
70 }
71 Repo.prototype.getRepoPlugins = function () {
72 return Util_1.PluginFilter(this.plugins, Types_1.PluginType.Repo);
73 // return this.plugins
74 // .filter((plugin) => isRepoPlugin(plugin)) as IRepoPlugin<M>[]
75 };
76 Repo.prototype.getFinderPlugins = function () {
77 return Util_1.PluginFilter(this.plugins, Types_1.PluginType.Finder);
78 };
79 Repo.prototype.attr = function (name) {
80 return this.modelType.options.attrs.find(function (attr) { return attr.name === name; });
81 };
82 Repo.prototype.init = function (coordinator) {
83 this.coordinator = coordinator;
84 this.modelType = coordinator.getModel(this.modelClazz);
85 this.modelOpts = this.modelType.options;
86 this.repoOpts = Reflect.getMetadata(Constants_1.TypeStoreRepoKey, this.repoClazz) || {};
87 };
88 Repo.prototype.start = function () {
89 // Grab a mapper
90 this.mapper = this.getMapper(this.modelClazz);
91 // Decorate all the finders
92 this.decorateFinders();
93 };
94 Repo.prototype.getMapper = function (clazz) {
95 return ModelMapper_1.getDefaultMapper(clazz);
96 };
97 /**
98 * Attach a plugin to the repo - could be a store,
99 * indexer, etc, etc
100 *
101 * @param plugin
102 * @returns {Repo}
103 */
104 Repo.prototype.attach = function (plugin) {
105 if (this.plugins.includes(plugin)) {
106 log.warn("Trying to register repo plugin a second time");
107 }
108 else {
109 this.plugins.push(plugin);
110 }
111 return this;
112 };
113 Repo.prototype.getFinderOptions = function (finderKey) {
114 return MetadataManager_1.getMetadata(Constants_1.TypeStoreFinderKey, this, finderKey);
115 };
116 /**
117 * Decorate finder by iterating all finder plugins
118 * and trying until resolved
119 *
120 * @param finderKey
121 */
122 Repo.prototype.decorateFinder = function (finderKey) {
123 var finder;
124 // Iterate all finder plugins
125 for (var _i = 0, _a = this.getPlugins(Util_1.isFinderPlugin); _i < _a.length; _i++) {
126 var plugin = _a[_i];
127 if (!typeguard_1.isFunction(plugin.decorateFinder))
128 continue;
129 var finderPlugin = plugin;
130 //let finderResult
131 if (finder = finderPlugin.decorateFinder(this, finderKey)) {
132 /**
133 * If we got a promise back then we need to wait
134 *
135 * IE. pouch db creating an index
136 */
137 // if (isFunction(finderResult.then)) {
138 // finder = (...args) => {
139 // return (finderResult as Promise<any>).then(finderFn => {
140 // if (!finderFn)
141 // NotImplemented(`Promised finder is not available ${finderKey}`)
142 //
143 // return finderFn(...args)
144 // })
145 // }
146 // } else {
147 //
148 // }
149 //finder = finderResult
150 break;
151 }
152 }
153 if (!finder && this.getFinderOptions(finderKey).optional !== true)
154 Errors_1.NotImplemented("No plugin supports this finder " + finderKey);
155 this.setFinder(finderKey, finder);
156 };
157 /**
158 * Decorate all finders on Repo
159 */
160 Repo.prototype.decorateFinders = function () {
161 var _this = this;
162 (Reflect.getMetadata(Constants_1.TypeStoreFindersKey, this) || [])
163 .forEach(function (finderKey) { return _this.decorateFinder(finderKey); });
164 };
165 /**
166 * Create a generic finder, in order
167 * to do this search options must have been
168 * annotated on the model
169 *
170 * @param finderKey
171 * @param searchProvider
172 * @param searchOpts
173 * @returns {any}
174 */
175 Repo.prototype.makeGenericFinder = function (finderKey, searchProvider, searchOpts) {
176 var _this = this;
177 /**
178 * Get the finder options
179 * @type {any}
180 */
181 var opts = this.getFinderOptions(finderKey);
182 return function () {
183 var args = [];
184 for (var _i = 0; _i < arguments.length; _i++) {
185 args[_i] = arguments[_i];
186 }
187 return __awaiter(_this, void 0, void 0, function () {
188 var _this = this;
189 var results, keys;
190 return __generator(this, function (_a) {
191 switch (_a.label) {
192 case 0: return [4 /*yield*/, searchProvider.search(this.modelType, searchOpts, args)];
193 case 1:
194 results = _a.sent();
195 keys = results.map(function (result) {
196 return searchOpts.resultKeyMapper(_this, searchOpts.resultType, result);
197 });
198 return [2 /*return*/, keys.map(function (key) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
199 switch (_a.label) {
200 case 0: return [4 /*yield*/, this.get(key)];
201 case 1: return [2 /*return*/, _a.sent()];
202 }
203 }); }); })];
204 }
205 });
206 });
207 };
208 };
209 /**
210 * Set a finder function on the repo
211 *
212 * @param finderKey
213 * @param finderFn
214 */
215 Repo.prototype.setFinder = function (finderKey, finderFn) {
216 this[finderKey] = finderFn;
217 };
218 /**
219 * Triggers manually attached persistence callbacks
220 * - works for internal indexing solutions, etc
221 *
222 * @param type
223 * @param models
224 */
225 Repo.prototype.triggerPersistenceEvent = function (type) {
226 var models = [];
227 for (var _i = 1; _i < arguments.length; _i++) {
228 models[_i - 1] = arguments[_i];
229 }
230 if (models.length < 1)
231 return;
232 var onPersistenceEvent = this.modelType.options.onPersistenceEvent;
233 onPersistenceEvent && onPersistenceEvent.apply(void 0, [type].concat(models));
234 };
235 Repo.prototype.supportPersistenceEvents = function () {
236 var onPersistenceEvent = this.modelType.options.onPersistenceEvent;
237 return typeof onPersistenceEvent !== 'undefined' && onPersistenceEvent !== null;
238 };
239 /**
240 * Call out to the indexers
241 *
242 * @param type
243 * @param models
244 * @returns {Bluebird<boolean>}
245 */
246 Repo.prototype.index = function (type) {
247 var models = [];
248 for (var _i = 1; _i < arguments.length; _i++) {
249 models[_i - 1] = arguments[_i];
250 }
251 return __awaiter(this, void 0, void 0, function () {
252 var _this = this;
253 var indexPlugins, doIndex;
254 return __generator(this, function (_a) {
255 switch (_a.label) {
256 case 0:
257 indexPlugins = Util_1.PluginFilter(this.plugins, Types_1.PluginType.Indexer);
258 doIndex = function (indexConfig) {
259 return indexPlugins.map(function (plugin) { return plugin.index.apply(plugin, [type,
260 indexConfig,
261 _this.modelType,
262 _this].concat(models)); });
263 };
264 if (!(this.repoOpts && this.repoOpts.indexes)) return [3 /*break*/, 2];
265 return [4 /*yield*/, Promise.all(this.repoOpts.indexes.reduce(function (promises, indexConfig) {
266 return promises.concat(doIndex(indexConfig));
267 }, []))];
268 case 1:
269 _a.sent();
270 _a.label = 2;
271 case 2: return [2 /*return*/, Promise.resolve(true)];
272 }
273 });
274 });
275 };
276 Repo.prototype.indexPromise = function (action) {
277 var _this = this;
278 return function (models) { return __awaiter(_this, void 0, void 0, function () {
279 var indexPromise;
280 return __generator(this, function (_a) {
281 switch (_a.label) {
282 case 0:
283 indexPromise = this.index.apply(this, [action].concat(models.filter(function (model) { return !!model; })));
284 return [4 /*yield*/, Promise.resolve(indexPromise)];
285 case 1:
286 _a.sent();
287 return [2 /*return*/, models];
288 }
289 });
290 }); };
291 };
292 /**
293 * Not implemented
294 *
295 * @param args
296 * @returns {null}
297 */
298 Repo.prototype.key = function () {
299 var args = [];
300 for (var _i = 0; _i < arguments.length; _i++) {
301 args[_i] = arguments[_i];
302 }
303 for (var _a = 0, _b = this.getRepoPlugins(); _a < _b.length; _a++) {
304 var plugin = _b[_a];
305 var key = plugin.key.apply(plugin, args);
306 if (key)
307 return key;
308 }
309 return Errors_1.NotImplemented('key');
310 };
311 /**
312 * Get one or more models with keys
313 *
314 * @param key
315 * @returns {null}
316 */
317 Repo.prototype.get = function (key) {
318 return __awaiter(this, void 0, void 0, function () {
319 var _this = this;
320 var results, _i, results_1, result;
321 return __generator(this, function (_a) {
322 results = this.getRepoPlugins().map(function (plugin) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
323 switch (_a.label) {
324 case 0: return [4 /*yield*/, plugin.get(key)];
325 case 1: return [2 /*return*/, _a.sent()];
326 }
327 }); }); });
328 for (_i = 0, results_1 = results; _i < results_1.length; _i++) {
329 result = results_1[_i];
330 if (result)
331 return [2 /*return*/, result];
332 }
333 return [2 /*return*/, null];
334 });
335 });
336 };
337 /**
338 * Save model
339 *
340 * @param o
341 * @returns {null}
342 */
343 Repo.prototype.save = function (o) {
344 return __awaiter(this, void 0, void 0, function () {
345 var results, _i, results_2, result;
346 return __generator(this, function (_a) {
347 switch (_a.label) {
348 case 0: return [4 /*yield*/, Util_1.PromiseMap(this.getRepoPlugins(), function (plugin) { return plugin.save(o); })];
349 case 1:
350 results = _a.sent();
351 return [4 /*yield*/, this.indexPromise(Types_1.IndexAction.Add)(results)];
352 case 2:
353 _a.sent();
354 for (_i = 0, results_2 = results; _i < results_2.length; _i++) {
355 result = results_2[_i];
356 if (result)
357 return [2 /*return*/, result];
358 }
359 return [2 /*return*/, null];
360 }
361 });
362 });
363 };
364 /**
365 * Remove a model
366 *
367 * @param key
368 * @returns {null}
369 */
370 Repo.prototype.remove = function (key) {
371 return __awaiter(this, void 0, void 0, function () {
372 var model;
373 return __generator(this, function (_a) {
374 switch (_a.label) {
375 case 0: return [4 /*yield*/, this.get(key)];
376 case 1:
377 model = _a.sent();
378 if (!model) {
379 log.warn("No model found to remove with key", key);
380 return [2 /*return*/, null];
381 }
382 return [4 /*yield*/, Util_1.PromiseMap(this.getRepoPlugins(), function (plugin) { return plugin.remove(key); })];
383 case 2:
384 _a.sent();
385 return [2 /*return*/, this.indexPromise(Types_1.IndexAction.Remove)([model])];
386 }
387 });
388 });
389 };
390 /**
391 * Count models
392 *
393 * @returns {null}
394 */
395 Repo.prototype.count = function () {
396 return __awaiter(this, void 0, void 0, function () {
397 var _this = this;
398 var results;
399 return __generator(this, function (_a) {
400 switch (_a.label) {
401 case 0: return [4 /*yield*/, Promise.all(this.getRepoPlugins().map(function (plugin) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
402 switch (_a.label) {
403 case 0: return [4 /*yield*/, plugin.count()];
404 case 1: return [2 /*return*/, _a.sent()];
405 }
406 }); }); }))];
407 case 1:
408 results = _a.sent();
409 return [2 /*return*/, results.reduce(function (prev, current) { return prev + current; })];
410 }
411 });
412 });
413 };
414 Repo.prototype.bulkGet = function () {
415 var keys = [];
416 for (var _i = 0; _i < arguments.length; _i++) {
417 keys[_i] = arguments[_i];
418 }
419 return __awaiter(this, void 0, void 0, function () {
420 var results;
421 return __generator(this, function (_a) {
422 switch (_a.label) {
423 case 0: return [4 /*yield*/, Util_1.PromiseMap(this.getRepoPlugins(), function (plugin) { return plugin.bulkGet.apply(plugin, keys); })];
424 case 1:
425 results = _a.sent();
426 return [2 /*return*/, results.reduce(function (allResults, result) {
427 return allResults.concat(result);
428 }, [])];
429 }
430 });
431 });
432 };
433 Repo.prototype.bulkSave = function () {
434 var models = [];
435 for (var _i = 0; _i < arguments.length; _i++) {
436 models[_i] = arguments[_i];
437 }
438 return __awaiter(this, void 0, void 0, function () {
439 var results;
440 return __generator(this, function (_a) {
441 switch (_a.label) {
442 case 0: return [4 /*yield*/, Util_1.PromiseMap(this.getRepoPlugins(), function (plugin) { return plugin.bulkSave.apply(plugin, models); })];
443 case 1:
444 results = _a.sent();
445 results = results.reduce(function (allResults, result) {
446 return allResults.concat(result);
447 }, []);
448 return [2 /*return*/, this.indexPromise(Types_1.IndexAction.Add)(results)];
449 }
450 });
451 });
452 };
453 Repo.prototype.bulkRemove = function () {
454 var keys = [];
455 for (var _i = 0; _i < arguments.length; _i++) {
456 keys[_i] = arguments[_i];
457 }
458 return __awaiter(this, void 0, void 0, function () {
459 var models;
460 return __generator(this, function (_a) {
461 switch (_a.label) {
462 case 0: return [4 /*yield*/, this.bulkGet.apply(this, keys)];
463 case 1:
464 models = _a.sent();
465 if (models.length != keys.length)
466 throw new Error('Not all keys exist');
467 return [4 /*yield*/, Util_1.PromiseMap(this.getRepoPlugins(), function (plugin) { return plugin.bulkRemove.apply(plugin, keys); })];
468 case 2:
469 _a.sent();
470 // results = results.reduce((allResults,result) => {
471 // return allResults.concat(result)
472 // },[])
473 return [2 /*return*/, this.indexPromise(Types_1.IndexAction.Remove)(models)];
474 }
475 });
476 });
477 };
478 return Repo;
479}());
480exports.Repo = Repo;
481//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVwby5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9SZXBvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHlDQUlvQjtBQUVwQixpQ0FnQmdCO0FBR2hCLG1DQUF1QztBQUN2QywyQkFBNEI7QUFFNUIsK0JBSWU7QUFFZiw2Q0FBMEQ7QUFHMUQscURBQThDO0FBQzlDLHVDQUFzQztBQUV0QyxTQUFTO0FBQ1QsSUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQTtBQUdsQzs7Ozs7Ozs7R0FRRztBQUNIO0lBU0M7Ozs7OztPQU1HO0lBQ0gsY0FBbUIsU0FBYSxFQUFRLFVBQXNCO1FBQTlELGlCQUNDO1FBRGtCLGNBQVMsR0FBVCxTQUFTLENBQUk7UUFBUSxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBVHBELFlBQU8sR0FBRyxLQUFLLEVBQVcsQ0FBQTtRQTBFcEMsZUFBVSxHQUFHLFVBQUMsU0FBb0IsSUFBSyxPQUFBLEtBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUE5QixDQUE4QixDQUFBO0lBaEVyRSxDQUFDO0lBRVMsNkJBQWMsR0FBeEI7UUFDQyxNQUFNLENBQUMsbUJBQVksQ0FBaUIsSUFBSSxDQUFDLE9BQU8sRUFBQyxrQkFBVSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ2pFLHNCQUFzQjtRQUN0QixpRUFBaUU7SUFDbEUsQ0FBQztJQUVTLCtCQUFnQixHQUExQjtRQUNDLE1BQU0sQ0FBQyxtQkFBWSxDQUFnQixJQUFJLENBQUMsT0FBTyxFQUFDLGtCQUFVLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDbkUsQ0FBQztJQUVELG1CQUFJLEdBQUosVUFBSyxJQUFXO1FBQ2YsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBQSxJQUFJLElB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
\No newline at end of file