@stemy/backend 2.6.1 → 2.7.3

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 (117) hide show
  1. package/README.md +2 -2
  2. package/bundles/stemy-backend.umd.js +5553 -5465
  3. package/bundles/stemy-backend.umd.js.map +1 -1
  4. package/bundles/stemy-backend.umd.min.js +1 -1
  5. package/bundles/stemy-backend.umd.min.js.map +1 -1
  6. package/common-types.d.ts +226 -214
  7. package/esm2015/common-types.js +18 -18
  8. package/esm2015/public_api.js +338 -338
  9. package/esm2015/rest-controllers/assets.controller.js +116 -116
  10. package/esm2015/rest-controllers/auth.controller.js +75 -75
  11. package/esm2015/rest-controllers/gallery.controller.js +37 -37
  12. package/esm2015/rest-controllers/progresses.controller.js +57 -57
  13. package/esm2015/rest-middlewares/container.middleware.js +32 -32
  14. package/esm2015/rest-middlewares/error-handler.middleware.js +83 -83
  15. package/esm2015/rest-middlewares/language.middleware.js +28 -28
  16. package/esm2015/rest-middlewares/request-ended.middleware.js +25 -25
  17. package/esm2015/rest-middlewares/request-started.middleware.js +24 -24
  18. package/esm2015/rest-openapi.js +44 -44
  19. package/esm2015/services/asset-processor.js +101 -101
  20. package/esm2015/services/asset-resolver.js +53 -53
  21. package/esm2015/services/assets.js +110 -110
  22. package/esm2015/services/backend-provider.js +32 -32
  23. package/esm2015/services/cache-processor.js +34 -34
  24. package/esm2015/services/cache.js +94 -94
  25. package/esm2015/services/configuration.js +55 -55
  26. package/esm2015/services/endpoint-provider.js +29 -29
  27. package/esm2015/services/entities/asset.js +166 -112
  28. package/esm2015/services/entities/lazy-asset.js +93 -93
  29. package/esm2015/services/entities/progress.js +181 -181
  30. package/esm2015/services/fixtures.js +45 -45
  31. package/esm2015/services/gallery-cache.js +36 -36
  32. package/esm2015/services/gallery-image.js +48 -48
  33. package/esm2015/services/gallery.js +138 -138
  34. package/esm2015/services/id-generator.js +63 -63
  35. package/esm2015/services/job-manager.js +203 -203
  36. package/esm2015/services/lazy-assets.js +74 -74
  37. package/esm2015/services/mail-sender.js +59 -59
  38. package/esm2015/services/memory-cache.js +84 -84
  39. package/esm2015/services/mongo-connector.js +61 -61
  40. package/esm2015/services/progresses.js +91 -91
  41. package/esm2015/services/template-renderer.js +89 -89
  42. package/esm2015/services/translation-provider.js +31 -31
  43. package/esm2015/services/translator.js +85 -85
  44. package/esm2015/services/user-manager.js +47 -47
  45. package/esm2015/socket-controllers/progress.controller.js +82 -82
  46. package/esm2015/socket-middlewares/compression.middleware.js +19 -19
  47. package/esm2015/static.js +33 -33
  48. package/esm2015/stemy-backend.js +4 -4
  49. package/esm2015/utilities/di-container.js +84 -84
  50. package/esm2015/utilities/lazy-asset-generator.js +40 -40
  51. package/esm2015/utilities/tree.js +111 -111
  52. package/esm2015/utils.js +618 -601
  53. package/esm2015/validators.js +51 -51
  54. package/fesm2015/stemy-backend.js +3656 -3585
  55. package/fesm2015/stemy-backend.js.map +1 -1
  56. package/package.json +1 -1
  57. package/public_api.d.ts +33 -33
  58. package/rest-controllers/assets.controller.d.ts +16 -16
  59. package/rest-controllers/auth.controller.d.ts +14 -14
  60. package/rest-controllers/gallery.controller.d.ts +7 -7
  61. package/rest-controllers/progresses.controller.d.ts +9 -9
  62. package/rest-middlewares/container.middleware.d.ts +8 -8
  63. package/rest-middlewares/error-handler.middleware.d.ts +13 -13
  64. package/rest-middlewares/language.middleware.d.ts +8 -8
  65. package/rest-middlewares/request-ended.middleware.d.ts +5 -5
  66. package/rest-middlewares/request-started.middleware.d.ts +5 -5
  67. package/rest-openapi.d.ts +3 -3
  68. package/services/asset-processor.d.ts +12 -12
  69. package/services/asset-resolver.d.ts +9 -9
  70. package/services/assets.d.ts +19 -19
  71. package/services/backend-provider.d.ts +11 -11
  72. package/services/cache-processor.d.ts +4 -4
  73. package/services/cache.d.ts +23 -23
  74. package/services/configuration.d.ts +10 -10
  75. package/services/endpoint-provider.d.ts +4 -4
  76. package/services/entities/asset.d.ts +25 -23
  77. package/services/entities/lazy-asset.d.ts +29 -29
  78. package/services/entities/progress.d.ts +49 -49
  79. package/services/fixtures.d.ts +6 -6
  80. package/services/gallery-cache.d.ts +9 -9
  81. package/services/gallery-image.d.ts +11 -11
  82. package/services/gallery.d.ts +13 -13
  83. package/services/id-generator.d.ts +11 -11
  84. package/services/job-manager.d.ts +27 -27
  85. package/services/lazy-assets.d.ts +19 -19
  86. package/services/mail-sender.d.ts +20 -20
  87. package/services/memory-cache.d.ts +10 -10
  88. package/services/mongo-connector.d.ts +14 -14
  89. package/services/progresses.d.ts +18 -18
  90. package/services/template-renderer.d.ts +14 -14
  91. package/services/translation-provider.d.ts +10 -10
  92. package/services/translator.d.ts +15 -15
  93. package/services/user-manager.d.ts +6 -6
  94. package/socket-controllers/progress.controller.d.ts +10 -10
  95. package/socket-middlewares/compression.middleware.d.ts +4 -4
  96. package/static.d.ts +2 -2
  97. package/stemy-backend.d.ts +4 -4
  98. package/stemy-backend.metadata.json +1 -1
  99. package/utilities/di-container.d.ts +43 -43
  100. package/utilities/lazy-asset-generator.d.ts +15 -15
  101. package/utilities/tree.d.ts +14 -14
  102. package/utils.d.ts +76 -73
  103. package/validators.d.ts +7 -7
  104. package/di-container.d.ts +0 -40
  105. package/esm2015/di-container.js +0 -75
  106. package/esm2015/models/lazy-asset.js +0 -12
  107. package/esm2015/models/progress.js +0 -23
  108. package/esm2015/rest-middlewares/injector.middleware.js +0 -26
  109. package/esm2015/services/lazy-asset-helper.js +0 -74
  110. package/esm2015/services/logger.js +0 -14
  111. package/esm2015/services/progress-helper.js +0 -168
  112. package/models/lazy-asset.d.ts +0 -45
  113. package/models/progress.d.ts +0 -56
  114. package/rest-middlewares/injector.middleware.d.ts +0 -8
  115. package/services/lazy-asset-helper.d.ts +0 -15
  116. package/services/logger.d.ts +0 -2
  117. package/services/progress-helper.d.ts +0 -37
@@ -1,203 +1,203 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- var __param = (this && this.__param) || function (paramIndex, decorator) {
11
- return function (target, key) { decorator(target, key, paramIndex); }
12
- };
13
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
- return new (P || (P = Promise))(function (resolve, reject) {
16
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
- step((generator = generator.apply(thisArg, _arguments || [])).next());
20
- });
21
- };
22
- import { inject, injectable, injectAll, Lifecycle, scoped } from "tsyringe";
23
- import { Queue, Scheduler, Worker } from "node-resque";
24
- import { schedule, validate } from "node-cron";
25
- import ioredis from "ioredis";
26
- import { DI_CONTAINER, JOB } from "../common-types";
27
- import { getConstructorName, isArray, isObject } from "../utils";
28
- import { Configuration } from "./configuration";
29
- const IORedis = ioredis;
30
- let JobManager = class JobManager {
31
- constructor(config, container, jobTypes) {
32
- this.config = config;
33
- this.container = container;
34
- this.jobTypes = jobTypes || [];
35
- this.jobs = this.jobTypes.reduce((res, jobType) => {
36
- res[getConstructorName(jobType)] = {
37
- perform: this.toPerformFunction(jobType)
38
- };
39
- return res;
40
- }, {});
41
- }
42
- process(jobType, params = {}) {
43
- return __awaiter(this, void 0, void 0, function* () {
44
- let instance = null;
45
- try {
46
- instance = this.resolveJobInstance(jobType, params);
47
- }
48
- catch (e) {
49
- const jobName = getConstructorName(jobType);
50
- throw `Can't resolve params for job: ${jobName}, with params: ${JSON.stringify(params)}. Reason: ${e}`;
51
- }
52
- return instance.process();
53
- });
54
- }
55
- enqueueWithName(name, params = {}, que = "main") {
56
- return __awaiter(this, void 0, void 0, function* () {
57
- const jobName = yield this.tryResolveFromName(name, params);
58
- yield this.queue.enqueue(que, jobName, [params]);
59
- });
60
- }
61
- enqueue(jobType, params = {}, que = "main") {
62
- return __awaiter(this, void 0, void 0, function* () {
63
- const jobName = yield this.tryResolveAndConnect(jobType, params);
64
- yield this.queue.enqueue(que, jobName, [params]);
65
- });
66
- }
67
- enqueueAt(timestamp, jobType, params = {}, que = "main") {
68
- return __awaiter(this, void 0, void 0, function* () {
69
- const jobName = yield this.tryResolveAndConnect(jobType, params);
70
- yield this.queue.enqueueAt(timestamp, que, jobName, [params]);
71
- });
72
- }
73
- enqueueIn(time, jobType, params = {}, que = "main") {
74
- return __awaiter(this, void 0, void 0, function* () {
75
- const jobName = yield this.tryResolveAndConnect(jobType, params);
76
- yield this.queue.enqueueIn(time, que, jobName, [params]);
77
- });
78
- }
79
- schedule(minute, hour, dayOfMonth, month, dayOfWeek, jobType, params = {}, que = "main") {
80
- const expression = [minute, hour, dayOfMonth, month, dayOfWeek].map(t => {
81
- if (isObject(t)) {
82
- const range = t;
83
- return `${range.min || 0}-${range.max || 0}`;
84
- }
85
- if (isArray(t)) {
86
- return t.join(",");
87
- }
88
- return `${t}`;
89
- }).join(" ");
90
- const jobName = getConstructorName(jobType);
91
- if (!validate(expression)) {
92
- console.log(`Can't schedule the task: '${jobName}' because time expression is invalid.`);
93
- return null;
94
- }
95
- return schedule(expression, () => {
96
- this.enqueue(jobType, params, que).catch(e => {
97
- console.log(`Can't enqueue job: '${jobName}' because: ${e}`);
98
- });
99
- });
100
- }
101
- startProcessing() {
102
- return __awaiter(this, void 0, void 0, function* () {
103
- this.initialize();
104
- yield this.worker.connect();
105
- yield this.worker.start();
106
- yield this.scheduler.connect();
107
- yield this.scheduler.start();
108
- });
109
- }
110
- tryResolve(jobType, params) {
111
- const jobName = getConstructorName(jobType);
112
- if (!this.jobs[jobName]) {
113
- throw `Can't find job with name: ${jobName} so it can't be enqueued!`;
114
- }
115
- try {
116
- this.resolveJobInstance(jobType, params);
117
- }
118
- catch (e) {
119
- throw `Can't resolve params for job: ${jobName}, with params: ${JSON.stringify(params)}. Reason: ${e}`;
120
- }
121
- return jobName;
122
- }
123
- initialize() {
124
- if (this.queue)
125
- return;
126
- const config = this.config;
127
- const options = { password: config.resolve("redisPassword") };
128
- const sentinels = config.resolve("redisSentinels");
129
- const redis = !sentinels
130
- ? null
131
- : new IORedis({
132
- sentinels,
133
- name: config.resolve("redisCluster"),
134
- });
135
- const connection = {
136
- pkg: "ioredis",
137
- host: config.resolve("redisHost"),
138
- password: options.password,
139
- port: config.resolve("redisPort"),
140
- namespace: config.resolve("redisNamespace"),
141
- redis,
142
- options
143
- };
144
- const queues = config.resolve("workQueues");
145
- this.queue = new Queue({ connection }, this.jobs);
146
- this.worker = new Worker({ connection, queues }, this.jobs);
147
- this.worker.on("job", (queue, job) => {
148
- console.log(`working job ${queue} ${JSON.stringify(job)}`);
149
- });
150
- this.worker.on("reEnqueue", (queue, job, plugin) => {
151
- console.log(`reEnqueue job (${plugin}) ${queue} ${JSON.stringify(job)}`);
152
- });
153
- this.worker.on("success", (queue, job, result, duration) => {
154
- console.log(`job success ${queue} ${JSON.stringify(job)} >> ${result} (${duration}ms)`);
155
- });
156
- this.worker.on("failure", (queue, job, failure, duration) => {
157
- console.log(`job failure ${queue} ${JSON.stringify(job)} >> ${failure} (${duration}ms)`);
158
- });
159
- this.worker.on("error", (error, queue, job) => {
160
- console.log(`error ${queue} ${JSON.stringify(job)} >> ${error}`);
161
- });
162
- this.scheduler = new Scheduler({ connection }, this.jobs);
163
- }
164
- tryResolveFromName(jobName, params) {
165
- const jobType = this.jobTypes.find(type => {
166
- return getConstructorName(type) == jobName;
167
- });
168
- if (!jobType) {
169
- throw `Can't find job type with name: ${jobName} so it can't be enqueued!`;
170
- }
171
- return this.tryResolveAndConnect(jobType, params);
172
- }
173
- tryResolveAndConnect(jobType, params) {
174
- return __awaiter(this, void 0, void 0, function* () {
175
- this.initialize();
176
- const jobName = this.tryResolve(jobType, params);
177
- yield this.queue.connect();
178
- return jobName;
179
- });
180
- }
181
- resolveJobInstance(jobType, params) {
182
- const container = this.container.createChildContainer();
183
- Object.keys(params).map((name) => {
184
- container.register(name, { useValue: params[name] });
185
- });
186
- container.register(jobType, jobType);
187
- return container.resolve(jobType);
188
- }
189
- toPerformFunction(jobType) {
190
- return (jobParams) => {
191
- const job = this.resolveJobInstance(jobType, jobParams);
192
- return job.process();
193
- };
194
- }
195
- };
196
- JobManager = __decorate([
197
- injectable(),
198
- scoped(Lifecycle.ContainerScoped),
199
- __param(1, inject(DI_CONTAINER)), __param(2, injectAll(JOB)),
200
- __metadata("design:paramtypes", [Configuration, Object, Array])
201
- ], JobManager);
202
- export { JobManager };
203
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvam9iLW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFzQixNQUFNLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQy9GLE9BQU8sRUFBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUNyRCxPQUFPLEVBQUMsUUFBUSxFQUFFLFFBQVEsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUM3QyxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxFQUFDLFlBQVksRUFBa0IsR0FBRyxFQUFxRCxNQUFNLGlCQUFpQixDQUFDO0FBQ3RILE9BQU8sRUFBQyxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQy9ELE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUU5QyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFJWCxVQUFVLFNBQVYsVUFBVTtJQVFuQixZQUFxQixNQUFxQixFQUFpQyxTQUE4QixFQUFrQixRQUFzQjtRQUE1SCxXQUFNLEdBQU4sTUFBTSxDQUFlO1FBQWlDLGNBQVMsR0FBVCxTQUFTLENBQXFCO1FBQ3JHLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQzlDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHO2dCQUMvQixPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9B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RUFBRSxDQUFDO1lBQzNCLE9BQU8sT0FBTyxDQUFDO1FBQ25CLENBQUM7S0FBQTtJQUVTLGtCQUFrQixDQUFDLE9BQW1CLEVBQUUsTUFBaUI7UUFDL0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQ3hELE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDN0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUN2RCxDQUFDLENBQUMsQ0FBQztRQUNILFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXJDLE9BQU8sU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQVMsQ0FBQztJQUM5QyxDQUFDO0lBRVMsaUJBQWlCLENBQUMsT0FBbUI7UUFDM0MsT0FBTyxDQUFDLFNBQW9CLEVBQUUsRUFBRTtZQUM1QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3hELE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3pCLENBQUMsQ0FBQTtJQUNMLENBQUM7Q0FDSixDQUFBO0FBN0tZLFVBQVU7SUFGdEIsVUFBVSxFQUFFO0lBQ1osTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUM7SUFTZSxXQUFBLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQSxFQUEyQyxXQUFBLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtxQ0FBN0YsYUFBYTtHQVJqQyxVQUFVLENBNkt0QjtTQTdLWSxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtEZXBlbmRlbmN5Q29udGFpbmVyLCBpbmplY3QsIGluamVjdGFibGUsIGluamVjdEFsbCwgTGlmZWN5Y2xlLCBzY29wZWR9IGZyb20gXCJ0c3lyaW5nZVwiO1xuaW1wb3J0IHtRdWV1ZSwgU2NoZWR1bGVyLCBXb3JrZXJ9IGZyb20gXCJub2RlLXJlc3F1ZVwiO1xuaW1wb3J0IHtzY2hlZHVsZSwgdmFsaWRhdGV9IGZyb20gXCJub2RlLWNyb25cIjtcbmltcG9ydCBpb3JlZGlzIGZyb20gXCJpb3JlZGlzXCI7XG5pbXBvcnQge0RJX0NPTlRBSU5FUiwgSUpvYiwgSUpvYlRhc2ssIEpPQiwgSm9iUGFyYW1zLCBKb2JTY2hlZHVsZVJhbmdlLCBKb2JTY2hlZHVsZVRpbWUsIFR5cGV9IGZyb20gXCIuLi9jb21tb24tdHlwZXNcIjtcbmltcG9ydCB7Z2V0Q29uc3RydWN0b3JOYW1lLCBpc0FycmF5LCBpc09iamVjdH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQge0NvbmZpZ3VyYXRpb259IGZyb20gXCIuL2NvbmZpZ3VyYXRpb25cIjtcblxuY29uc3QgSU9SZWRpcyA9IGlvcmVkaXM7XG5cbkBpbmplY3RhYmxlKClcbkBzY29wZWQoTGlmZWN5Y2xlLkNvbnRhaW5lclNjb3BlZClcbmV4cG9ydCBjbGFzcyBKb2JNYW5hZ2VyIHtcblxuICAgIHByb3RlY3RlZCBqb2JzOiBhbnk7XG4gICAgcHJvdGVjdGVkIHF1ZXVlOiBRdWV1ZTtcbiAgICBwcm90ZWN0ZWQgd29ya2VyOiBXb3JrZXI7XG4gICAgcHJvdGVjdGVkIHNjaGVkdWxlcjogU2NoZWR1bGVyO1xuICAgIHByb3RlY3RlZCBqb2JUeXBlczogVHlwZTxJSm9iPltdO1xuXG4gICAgY29uc3RydWN0b3IocmVhZG9ubHkgY29uZmlnOiBDb25maWd1cmF0aW9uLCBAaW5qZWN0KERJX0NPTlRBSU5FUikgcmVhZG9ubHkgY29udGFpbmVyOiBEZXBlbmRlbmN5Q29udGFpbmVyLCBAaW5qZWN0QWxsKEpPQikgam9iVHlwZXM6IFR5cGU8SUpvYj5bXSkge1xuICAgICAgICB0aGlzLmpvYlR5cGVzID0gam9iVHlwZXMgfHwgW107XG4gICAgICAgIHRoaXMuam9icyA9IHRoaXMuam9iVHlwZXMucmVkdWNlKChyZXMsIGpvYlR5cGUpID0+IHtcbiAgICAgICAgICAgIHJlc1tnZXRDb25zdHJ1Y3Rvck5hbWUoam9iVHlwZSldID0ge1xuICAgICAgICAgICAgICAgIHBlcmZvcm06IHRoaXMudG9QZXJmb3JtRnVuY3Rpb24oam9iVHlwZSlcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9LCB7fSk7XG4gICAgfVxuXG4gICAgYXN5bmMgcHJvY2Vzcyhqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyA9IHt9KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgbGV0IGluc3RhbmNlOiBJSm9iID0gbnVsbDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGluc3RhbmNlID0gdGhpcy5yZXNvbHZlSm9iSW5zdGFuY2Uoam9iVHlwZSwgcGFyYW1zKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc3Qgam9iTmFtZSA9IGdldENvbnN0cnVjdG9yTmFtZShqb2JUeXBlKTtcbiAgICAgICAgICAgIHRocm93IGBDYW4ndCByZXNvbHZlIHBhcmFtcyBmb3Igam9iOiAke2pvYk5hbWV9LCB3aXRoIHBhcmFtczogJHtKU09OLnN0cmluZ2lmeShwYXJhbXMpfS4gUmVhc29uOiAke2V9YDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW5zdGFuY2UucHJvY2VzcygpO1xuICAgIH1cblxuICAgIGFzeW5jIGVucXVldWVXaXRoTmFtZShuYW1lOiBzdHJpbmcsIHBhcmFtczogSm9iUGFyYW1zID0ge30sIHF1ZTogc3RyaW5nID0gXCJtYWluXCIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICBjb25zdCBqb2JOYW1lID0gYXdhaXQgdGhpcy50cnlSZXNvbHZlRnJvbU5hbWUobmFtZSwgcGFyYW1zKTtcbiAgICAgICAgYXdhaXQgdGhpcy5xdWV1ZS5lbnF1ZXVlKHF1ZSwgam9iTmFtZSwgW3BhcmFtc10pO1xuICAgIH1cblxuICAgIGFzeW5jIGVucXVldWUoam9iVHlwZTogVHlwZTxJSm9iPiwgcGFyYW1zOiBKb2JQYXJhbXMgPSB7fSwgcXVlOiBzdHJpbmcgPSBcIm1haW5cIik6IFByb21pc2U8YW55PiB7XG4gICAgICAgIGNvbnN0IGpvYk5hbWUgPSBhd2FpdCB0aGlzLnRyeVJlc29sdmVBbmRDb25uZWN0KGpvYlR5cGUsIHBhcmFtcyk7XG4gICAgICAgIGF3YWl0IHRoaXMucXVldWUuZW5xdWV1ZShxdWUsIGpvYk5hbWUsIFtwYXJhbXNdKTtcbiAgICB9XG5cbiAgICBhc3luYyBlbnF1ZXVlQXQodGltZXN0YW1wOiBudW1iZXIsIGpvYlR5cGU6IFR5cGU8SUpvYj4sIHBhcmFtczogSm9iUGFyYW1zID0ge30sIHF1ZTogc3RyaW5nID0gXCJtYWluXCIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICBjb25zdCBqb2JOYW1lID0gYXdhaXQgdGhpcy50cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlLCBwYXJhbXMpO1xuICAgICAgICBhd2FpdCB0aGlzLnF1ZXVlLmVucXVldWVBdCh0aW1lc3RhbXAsIHF1ZSwgam9iTmFtZSwgW3BhcmFtc10pO1xuICAgIH1cblxuICAgIGFzeW5jIGVucXVldWVJbih0aW1lOiBudW1iZXIsIGpvYlR5cGU6IFR5cGU8SUpvYj4sIHBhcmFtczogSm9iUGFyYW1zID0ge30sIHF1ZTogc3RyaW5nID0gXCJtYWluXCIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICBjb25zdCBqb2JOYW1lID0gYXdhaXQgdGhpcy50cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlLCBwYXJhbXMpO1xuICAgICAgICBhd2FpdCB0aGlzLnF1ZXVlLmVucXVldWVJbih0aW1lLCBxdWUsIGpvYk5hbWUsIFtwYXJhbXNdKTtcbiAgICB9XG5cbiAgICBzY2hlZHVsZShtaW51dGU6IEpvYlNjaGVkdWxlVGltZSwgaG91cjogSm9iU2NoZWR1bGVUaW1lLCBkYXlPZk1vbnRoOiBKb2JTY2hlZHVsZVRpbWUsIG1vbnRoOiBKb2JTY2hlZHVsZVRpbWUsIGRheU9mV2VlazogSm9iU2NoZWR1bGVUaW1lLCBqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyA9IHt9LCBxdWU6IHN0cmluZyA9IFwibWFpblwiKTogSUpvYlRhc2sge1xuICAgICAgICBjb25zdCBleHByZXNzaW9uID0gW21pbnV0ZSwgaG91ciwgZGF5T2ZNb250aCwgbW9udGgsIGRheU9mV2Vla10ubWFwKHQgPT4ge1xuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHQpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSB0IGFzIEpvYlNjaGVkdWxlUmFuZ2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke3JhbmdlLm1pbiB8fCAwfS0ke3JhbmdlLm1heCB8fCAwfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNBcnJheSh0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0LmpvaW4oXCIsXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGAke3R9YDtcbiAgICAgICAgfSkuam9pbihcIiBcIik7XG4gICAgICAgIGNvbnN0IGpvYk5hbWUgPSBnZXRDb25zdHJ1Y3Rvck5hbWUoam9iVHlwZSk7XG4gICAgICAgIGlmICghdmFsaWRhdGUoZXhwcmVzc2lvbikpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDYW4ndCBzY2hlZHVsZSB0aGUgdGFzazogJyR7am9iTmFtZX0nIGJlY2F1c2UgdGltZSBleHByZXNzaW9uIGlzIGludmFsaWQuYCk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2NoZWR1bGUoZXhwcmVzc2lvbiwgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbnF1ZXVlKGpvYlR5cGUsIHBhcmFtcywgcXVlKS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgQ2FuJ3QgZW5xdWV1ZSBqb2I6ICcke2pvYk5hbWV9JyBiZWNhdXNlOiAke2V9YCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgc3RhcnRQcm9jZXNzaW5nKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICAgICAgICBhd2FpdCB0aGlzLndvcmtlci5jb25uZWN0KCk7XG4gICAgICAgIGF3YWl0IHRoaXMud29ya2VyLnN0YXJ0KCk7XG4gICAgICAgIGF3YWl0IHRoaXMuc2NoZWR1bGVyLmNvbm5lY3QoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5zY2hlZHVsZXIuc3RhcnQoKTtcbiAgICB9XG5cbiAgICB0cnlSZXNvbHZlKGpvYlR5cGU6IFR5cGU8SUpvYj4sIHBhcmFtczogSm9iUGFyYW1zKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3Qgam9iTmFtZSA9IGdldENvbnN0cnVjdG9yTmFtZShqb2JUeXBlKTtcbiAgICAgICAgaWYgKCF0aGlzLmpvYnNbam9iTmFtZV0pIHtcbiAgICAgICAgICAgIHRocm93IGBDYW4ndCBmaW5kIGpvYiB3aXRoIG5hbWU6ICR7am9iTmFtZX0gc28gaXQgY2FuJ3QgYmUgZW5xdWV1ZWQhYDtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdGhpcy5yZXNvbHZlSm9iSW5zdGFuY2Uoam9iVHlwZSwgcGFyYW1zKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhyb3cgYENhbid0IHJlc29sdmUgcGFyYW1zIGZvciBqb2I6ICR7am9iTmFtZX0sIHdpdGggcGFyYW1zOiAke0pTT04uc3RyaW5naWZ5KHBhcmFtcyl9LiBSZWFzb246ICR7ZX1gO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBqb2JOYW1lO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBpbml0aWFsaXplKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5xdWV1ZSkgcmV0dXJuO1xuICAgICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZztcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtwYXNzd29yZDogY29uZmlnLnJlc29sdmUoXCJyZWRpc1Bhc3N3b3JkXCIpfTtcbiAgICAgICAgY29uc3Qgc2VudGluZWxzOiBBcnJheTx7aG9zdDogc3RyaW5nLCBwb3J0OiBudW1iZXJ9PiA9IGNvbmZpZy5yZXNvbHZlKFwicmVkaXNTZW50aW5lbHNcIik7XG4gICAgICAgIGNvbnN0IHJlZGlzID0gIXNlbnRpbmVsc1xuICAgICAgICAgICAgPyBudWxsXG4gICAgICAgICAgICA6IG5ldyBJT1JlZGlzKHtcbiAgICAgICAgICAgICAgICBzZW50aW5lbHMsXG4gICAgICAgICAgICAgICAgbmFtZTogY29uZmlnLnJlc29sdmUoXCJyZWRpc0NsdXN0ZXJcIiksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHtcbiAgICAgICAgICAgIHBrZzogXCJpb3JlZGlzXCIsXG4gICAgICAgICAgICBob3N0OiBjb25maWcucmVzb2x2ZShcInJlZGlzSG9zdFwiKSxcbiAgICAgICAgICAgIHBhc3N3b3JkOiBvcHRpb25zLnBhc3N3b3JkLFxuICAgICAgICAgICAgcG9ydDogY29uZmlnLnJlc29sdmUoXCJyZWRpc1BvcnRcIiksXG4gICAgICAgICAgICBuYW1lc3BhY2U6IGNvbmZpZy5yZXNvbHZlKFwicmVkaXNOYW1lc3BhY2VcIiksXG4gICAgICAgICAgICByZWRpcyxcbiAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgcXVldWVzID0gY29uZmlnLnJlc29sdmUoXCJ3b3JrUXVldWVzXCIpO1xuICAgICAgICB0aGlzLnF1ZXVlID0gbmV3IFF1ZXVlKHtjb25uZWN0aW9ufSwgdGhpcy5qb2JzKTtcbiAgICAgICAgdGhpcy53b3JrZXIgPSBuZXcgV29ya2VyKHtjb25uZWN0aW9uLCBxdWV1ZXN9LCB0aGlzLmpvYnMpO1xuICAgICAgICB0aGlzLndvcmtlci5vbihcImpvYlwiLCAocXVldWUsIGpvYikgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYHdvcmtpbmcgam9iICR7cXVldWV9ICR7SlNPTi5zdHJpbmdpZnkoam9iKX1gKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMud29ya2VyLm9uKFwicmVFbnF1ZXVlXCIsIChxdWV1ZSwgam9iLCBwbHVnaW4pID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGByZUVucXVldWUgam9iICgke3BsdWdpbn0pICR7cXVldWV9ICR7SlNPTi5zdHJpbmdpZnkoam9iKX1gKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMud29ya2VyLm9uKFwic3VjY2Vzc1wiLCAocXVldWUsIGpvYiwgcmVzdWx0LCBkdXJhdGlvbikgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgYGpvYiBzdWNjZXNzICR7cXVldWV9ICR7SlNPTi5zdHJpbmdpZnkoam9iKX0gPj4gJHtyZXN1bHR9ICgke2R1cmF0aW9ufW1zKWBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLndvcmtlci5vbihcImZhaWx1cmVcIiwgKHF1ZXVlLCBqb2IsIGZhaWx1cmUsIGR1cmF0aW9uKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICBgam9iIGZhaWx1cmUgJHtxdWV1ZX0gJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgICAgICAgICAgam9iXG4gICAgICAgICAgICAgICAgKX0gPj4gJHtmYWlsdXJlfSAoJHtkdXJhdGlvbn1tcylgXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy53b3JrZXIub24oXCJlcnJvclwiLCAoZXJyb3IsIHF1ZXVlLCBqb2IpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBlcnJvciAke3F1ZXVlfSAke0pTT04uc3RyaW5naWZ5KGpvYil9ICA+PiAke2Vycm9yfWApO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zY2hlZHVsZXIgPSBuZXcgU2NoZWR1bGVyKHtjb25uZWN0aW9ufSwgdGhpcy5qb2JzKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgdHJ5UmVzb2x2ZUZyb21OYW1lKGpvYk5hbWU6IHN0cmluZywgcGFyYW1zOiBKb2JQYXJhbXMpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICBjb25zdCBqb2JUeXBlID0gdGhpcy5qb2JUeXBlcy5maW5kKHR5cGUgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGdldENvbnN0cnVjdG9yTmFtZSh0eXBlKSA9PSBqb2JOYW1lO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFqb2JUeXBlKSB7XG4gICAgICAgICAgICB0aHJvdyBgQ2FuJ3QgZmluZCBqb2IgdHlwZSB3aXRoIG5hbWU6ICR7am9iTmFtZX0gc28gaXQgY2FuJ3QgYmUgZW5xdWV1ZWQhYDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy50cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlLCBwYXJhbXMpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyB0cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICAgICAgICBjb25zdCBqb2JOYW1lID0gdGhpcy50cnlSZXNvbHZlKGpvYlR5cGUsIHBhcmFtcyk7XG4gICAgICAgIGF3YWl0IHRoaXMucXVldWUuY29ubmVjdCgpO1xuICAgICAgICByZXR1cm4gam9iTmFtZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcmVzb2x2ZUpvYkluc3RhbmNlKGpvYlR5cGU6IFR5cGU8SUpvYj4sIHBhcmFtczogSm9iUGFyYW1zKTogSUpvYiB7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyLmNyZWF0ZUNoaWxkQ29udGFpbmVyKCk7XG4gICAgICAgIE9iamVjdC5rZXlzKHBhcmFtcykubWFwKChuYW1lKSA9PiB7XG4gICAgICAgICAgICBjb250YWluZXIucmVnaXN0ZXIobmFtZSwge3VzZVZhbHVlOiBwYXJhbXNbbmFtZV19KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnRhaW5lci5yZWdpc3Rlcihqb2JUeXBlLCBqb2JUeXBlKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyLnJlc29sdmUoam9iVHlwZSkgYXMgSUpvYjtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgdG9QZXJmb3JtRnVuY3Rpb24oam9iVHlwZTogVHlwZTxJSm9iPik6IEZ1bmN0aW9uIHtcbiAgICAgICAgcmV0dXJuIChqb2JQYXJhbXM6IEpvYlBhcmFtcykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgam9iID0gdGhpcy5yZXNvbHZlSm9iSW5zdGFuY2Uoam9iVHlwZSwgam9iUGFyYW1zKTtcbiAgICAgICAgICAgIHJldHVybiBqb2IucHJvY2VzcygpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ import { inject, injectable, injectAll, Lifecycle, scoped } from "tsyringe";
23
+ import { Queue, Scheduler, Worker } from "node-resque";
24
+ import { schedule, validate } from "node-cron";
25
+ import ioredis from "ioredis";
26
+ import { DI_CONTAINER, JOB } from "../common-types";
27
+ import { getConstructorName, isArray, isObject } from "../utils";
28
+ import { Configuration } from "./configuration";
29
+ const IORedis = ioredis;
30
+ let JobManager = class JobManager {
31
+ constructor(config, container, jobTypes) {
32
+ this.config = config;
33
+ this.container = container;
34
+ this.jobTypes = jobTypes || [];
35
+ this.jobs = this.jobTypes.reduce((res, jobType) => {
36
+ res[getConstructorName(jobType)] = {
37
+ perform: this.toPerformFunction(jobType)
38
+ };
39
+ return res;
40
+ }, {});
41
+ }
42
+ process(jobType, params = {}) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ let instance = null;
45
+ try {
46
+ instance = this.resolveJobInstance(jobType, params);
47
+ }
48
+ catch (e) {
49
+ const jobName = getConstructorName(jobType);
50
+ throw `Can't resolve params for job: ${jobName}, with params: ${JSON.stringify(params)}. Reason: ${e}`;
51
+ }
52
+ return instance.process();
53
+ });
54
+ }
55
+ enqueueWithName(name, params = {}, que = "main") {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ const jobName = yield this.tryResolveFromName(name, params);
58
+ yield this.queue.enqueue(que, jobName, [params]);
59
+ });
60
+ }
61
+ enqueue(jobType, params = {}, que = "main") {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ const jobName = yield this.tryResolveAndConnect(jobType, params);
64
+ yield this.queue.enqueue(que, jobName, [params]);
65
+ });
66
+ }
67
+ enqueueAt(timestamp, jobType, params = {}, que = "main") {
68
+ return __awaiter(this, void 0, void 0, function* () {
69
+ const jobName = yield this.tryResolveAndConnect(jobType, params);
70
+ yield this.queue.enqueueAt(timestamp, que, jobName, [params]);
71
+ });
72
+ }
73
+ enqueueIn(time, jobType, params = {}, que = "main") {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ const jobName = yield this.tryResolveAndConnect(jobType, params);
76
+ yield this.queue.enqueueIn(time, que, jobName, [params]);
77
+ });
78
+ }
79
+ schedule(minute, hour, dayOfMonth, month, dayOfWeek, jobType, params = {}, que = "main") {
80
+ const expression = [minute, hour, dayOfMonth, month, dayOfWeek].map(t => {
81
+ if (isObject(t)) {
82
+ const range = t;
83
+ return `${range.min || 0}-${range.max || 0}`;
84
+ }
85
+ if (isArray(t)) {
86
+ return t.join(",");
87
+ }
88
+ return `${t}`;
89
+ }).join(" ");
90
+ const jobName = getConstructorName(jobType);
91
+ if (!validate(expression)) {
92
+ console.log(`Can't schedule the task: '${jobName}' because time expression is invalid.`);
93
+ return null;
94
+ }
95
+ return schedule(expression, () => {
96
+ this.enqueue(jobType, params, que).catch(e => {
97
+ console.log(`Can't enqueue job: '${jobName}' because: ${e}`);
98
+ });
99
+ });
100
+ }
101
+ startProcessing() {
102
+ return __awaiter(this, void 0, void 0, function* () {
103
+ this.initialize();
104
+ yield this.worker.connect();
105
+ yield this.worker.start();
106
+ yield this.scheduler.connect();
107
+ yield this.scheduler.start();
108
+ });
109
+ }
110
+ tryResolve(jobType, params) {
111
+ const jobName = getConstructorName(jobType);
112
+ if (!this.jobs[jobName]) {
113
+ throw `Can't find job with name: ${jobName} so it can't be enqueued!`;
114
+ }
115
+ try {
116
+ this.resolveJobInstance(jobType, params);
117
+ }
118
+ catch (e) {
119
+ throw `Can't resolve params for job: ${jobName}, with params: ${JSON.stringify(params)}. Reason: ${e}`;
120
+ }
121
+ return jobName;
122
+ }
123
+ initialize() {
124
+ if (this.queue)
125
+ return;
126
+ const config = this.config;
127
+ const options = { password: config.resolve("redisPassword") };
128
+ const sentinels = config.resolve("redisSentinels");
129
+ const redis = !sentinels
130
+ ? null
131
+ : new IORedis({
132
+ sentinels,
133
+ name: config.resolve("redisCluster"),
134
+ });
135
+ const connection = {
136
+ pkg: "ioredis",
137
+ host: config.resolve("redisHost"),
138
+ password: options.password,
139
+ port: config.resolve("redisPort"),
140
+ namespace: config.resolve("redisNamespace"),
141
+ redis,
142
+ options
143
+ };
144
+ const queues = config.resolve("workQueues");
145
+ this.queue = new Queue({ connection }, this.jobs);
146
+ this.worker = new Worker({ connection, queues }, this.jobs);
147
+ this.worker.on("job", (queue, job) => {
148
+ console.log(`working job ${queue} ${JSON.stringify(job)}`);
149
+ });
150
+ this.worker.on("reEnqueue", (queue, job, plugin) => {
151
+ console.log(`reEnqueue job (${plugin}) ${queue} ${JSON.stringify(job)}`);
152
+ });
153
+ this.worker.on("success", (queue, job, result, duration) => {
154
+ console.log(`job success ${queue} ${JSON.stringify(job)} >> ${result} (${duration}ms)`);
155
+ });
156
+ this.worker.on("failure", (queue, job, failure, duration) => {
157
+ console.log(`job failure ${queue} ${JSON.stringify(job)} >> ${failure} (${duration}ms)`);
158
+ });
159
+ this.worker.on("error", (error, queue, job) => {
160
+ console.log(`error ${queue} ${JSON.stringify(job)} >> ${error}`);
161
+ });
162
+ this.scheduler = new Scheduler({ connection }, this.jobs);
163
+ }
164
+ tryResolveFromName(jobName, params) {
165
+ const jobType = this.jobTypes.find(type => {
166
+ return getConstructorName(type) == jobName;
167
+ });
168
+ if (!jobType) {
169
+ throw `Can't find job type with name: ${jobName} so it can't be enqueued!`;
170
+ }
171
+ return this.tryResolveAndConnect(jobType, params);
172
+ }
173
+ tryResolveAndConnect(jobType, params) {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ this.initialize();
176
+ const jobName = this.tryResolve(jobType, params);
177
+ yield this.queue.connect();
178
+ return jobName;
179
+ });
180
+ }
181
+ resolveJobInstance(jobType, params) {
182
+ const container = this.container.createChildContainer();
183
+ Object.keys(params).map((name) => {
184
+ container.register(name, { useValue: params[name] });
185
+ });
186
+ container.register(jobType, jobType);
187
+ return container.resolve(jobType);
188
+ }
189
+ toPerformFunction(jobType) {
190
+ return (jobParams) => {
191
+ const job = this.resolveJobInstance(jobType, jobParams);
192
+ return job.process();
193
+ };
194
+ }
195
+ };
196
+ JobManager = __decorate([
197
+ injectable(),
198
+ scoped(Lifecycle.ContainerScoped),
199
+ __param(1, inject(DI_CONTAINER)), __param(2, injectAll(JOB)),
200
+ __metadata("design:paramtypes", [Configuration, Object, Array])
201
+ ], JobManager);
202
+ export { JobManager };
203
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvam9iLW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFzQixNQUFNLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQy9GLE9BQU8sRUFBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUNyRCxPQUFPLEVBQUMsUUFBUSxFQUFFLFFBQVEsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUM3QyxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxFQUFDLFlBQVksRUFBa0IsR0FBRyxFQUFxRCxNQUFNLGlCQUFpQixDQUFDO0FBQ3RILE9BQU8sRUFBQyxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQy9ELE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUU5QyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFJWCxVQUFVLFNBQVYsVUFBVTtJQVFuQixZQUFxQixNQUFxQixFQUFpQyxTQUE4QixFQUFrQixRQUFzQjtRQUE1SCxXQUFNLEdBQU4sTUFBTSxDQUFlO1FBQWlDLGNBQVMsR0FBVCxTQUFTLENBQXFCO1FBQ3JHLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQzlDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHO2dCQUMvQixPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9B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RUFBRSxDQUFDO1lBQzNCLE9BQU8sT0FBTyxDQUFDO1FBQ25CLENBQUM7S0FBQTtJQUVTLGtCQUFrQixDQUFDLE9BQW1CLEVBQUUsTUFBaUI7UUFDL0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQ3hELE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDN0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUN2RCxDQUFDLENBQUMsQ0FBQztRQUNILFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXJDLE9BQU8sU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQVMsQ0FBQztJQUM5QyxDQUFDO0lBRVMsaUJBQWlCLENBQUMsT0FBbUI7UUFDM0MsT0FBTyxDQUFDLFNBQW9CLEVBQUUsRUFBRTtZQUM1QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3hELE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3pCLENBQUMsQ0FBQTtJQUNMLENBQUM7Q0FDSixDQUFBO0FBN0tZLFVBQVU7SUFGdEIsVUFBVSxFQUFFO0lBQ1osTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUM7SUFTZSxXQUFBLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQSxFQUEyQyxXQUFBLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtxQ0FBN0YsYUFBYTtHQVJqQyxVQUFVLENBNkt0QjtTQTdLWSxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtEZXBlbmRlbmN5Q29udGFpbmVyLCBpbmplY3QsIGluamVjdGFibGUsIGluamVjdEFsbCwgTGlmZWN5Y2xlLCBzY29wZWR9IGZyb20gXCJ0c3lyaW5nZVwiO1xyXG5pbXBvcnQge1F1ZXVlLCBTY2hlZHVsZXIsIFdvcmtlcn0gZnJvbSBcIm5vZGUtcmVzcXVlXCI7XHJcbmltcG9ydCB7c2NoZWR1bGUsIHZhbGlkYXRlfSBmcm9tIFwibm9kZS1jcm9uXCI7XHJcbmltcG9ydCBpb3JlZGlzIGZyb20gXCJpb3JlZGlzXCI7XHJcbmltcG9ydCB7RElfQ09OVEFJTkVSLCBJSm9iLCBJSm9iVGFzaywgSk9CLCBKb2JQYXJhbXMsIEpvYlNjaGVkdWxlUmFuZ2UsIEpvYlNjaGVkdWxlVGltZSwgVHlwZX0gZnJvbSBcIi4uL2NvbW1vbi10eXBlc1wiO1xyXG5pbXBvcnQge2dldENvbnN0cnVjdG9yTmFtZSwgaXNBcnJheSwgaXNPYmplY3R9IGZyb20gXCIuLi91dGlsc1wiO1xyXG5pbXBvcnQge0NvbmZpZ3VyYXRpb259IGZyb20gXCIuL2NvbmZpZ3VyYXRpb25cIjtcclxuXHJcbmNvbnN0IElPUmVkaXMgPSBpb3JlZGlzO1xyXG5cclxuQGluamVjdGFibGUoKVxyXG5Ac2NvcGVkKExpZmVjeWNsZS5Db250YWluZXJTY29wZWQpXHJcbmV4cG9ydCBjbGFzcyBKb2JNYW5hZ2VyIHtcclxuXHJcbiAgICBwcm90ZWN0ZWQgam9iczogYW55O1xyXG4gICAgcHJvdGVjdGVkIHF1ZXVlOiBRdWV1ZTtcclxuICAgIHByb3RlY3RlZCB3b3JrZXI6IFdvcmtlcjtcclxuICAgIHByb3RlY3RlZCBzY2hlZHVsZXI6IFNjaGVkdWxlcjtcclxuICAgIHByb3RlY3RlZCBqb2JUeXBlczogVHlwZTxJSm9iPltdO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGNvbmZpZzogQ29uZmlndXJhdGlvbiwgQGluamVjdChESV9DT05UQUlORVIpIHJlYWRvbmx5IGNvbnRhaW5lcjogRGVwZW5kZW5jeUNvbnRhaW5lciwgQGluamVjdEFsbChKT0IpIGpvYlR5cGVzOiBUeXBlPElKb2I+W10pIHtcclxuICAgICAgICB0aGlzLmpvYlR5cGVzID0gam9iVHlwZXMgfHwgW107XHJcbiAgICAgICAgdGhpcy5qb2JzID0gdGhpcy5qb2JUeXBlcy5yZWR1Y2UoKHJlcywgam9iVHlwZSkgPT4ge1xyXG4gICAgICAgICAgICByZXNbZ2V0Q29uc3RydWN0b3JOYW1lKGpvYlR5cGUpXSA9IHtcclxuICAgICAgICAgICAgICAgIHBlcmZvcm06IHRoaXMudG9QZXJmb3JtRnVuY3Rpb24oam9iVHlwZSlcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgcmV0dXJuIHJlcztcclxuICAgICAgICB9LCB7fSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgcHJvY2Vzcyhqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyA9IHt9KTogUHJvbWlzZTxhbnk+IHtcclxuICAgICAgICBsZXQgaW5zdGFuY2U6IElKb2IgPSBudWxsO1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGluc3RhbmNlID0gdGhpcy5yZXNvbHZlSm9iSW5zdGFuY2Uoam9iVHlwZSwgcGFyYW1zKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGpvYk5hbWUgPSBnZXRDb25zdHJ1Y3Rvck5hbWUoam9iVHlwZSk7XHJcbiAgICAgICAgICAgIHRocm93IGBDYW4ndCByZXNvbHZlIHBhcmFtcyBmb3Igam9iOiAke2pvYk5hbWV9LCB3aXRoIHBhcmFtczogJHtKU09OLnN0cmluZ2lmeShwYXJhbXMpfS4gUmVhc29uOiAke2V9YDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlLnByb2Nlc3MoKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBlbnF1ZXVlV2l0aE5hbWUobmFtZTogc3RyaW5nLCBwYXJhbXM6IEpvYlBhcmFtcyA9IHt9LCBxdWU6IHN0cmluZyA9IFwibWFpblwiKTogUHJvbWlzZTxhbnk+IHtcclxuICAgICAgICBjb25zdCBqb2JOYW1lID0gYXdhaXQgdGhpcy50cnlSZXNvbHZlRnJvbU5hbWUobmFtZSwgcGFyYW1zKTtcclxuICAgICAgICBhd2FpdCB0aGlzLnF1ZXVlLmVucXVldWUocXVlLCBqb2JOYW1lLCBbcGFyYW1zXSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgZW5xdWV1ZShqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyA9IHt9LCBxdWU6IHN0cmluZyA9IFwibWFpblwiKTogUHJvbWlzZTxhbnk+IHtcclxuICAgICAgICBjb25zdCBqb2JOYW1lID0gYXdhaXQgdGhpcy50cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlLCBwYXJhbXMpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMucXVldWUuZW5xdWV1ZShxdWUsIGpvYk5hbWUsIFtwYXJhbXNdKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBlbnF1ZXVlQXQodGltZXN0YW1wOiBudW1iZXIsIGpvYlR5cGU6IFR5cGU8SUpvYj4sIHBhcmFtczogSm9iUGFyYW1zID0ge30sIHF1ZTogc3RyaW5nID0gXCJtYWluXCIpOiBQcm9taXNlPGFueT4ge1xyXG4gICAgICAgIGNvbnN0IGpvYk5hbWUgPSBhd2FpdCB0aGlzLnRyeVJlc29sdmVBbmRDb25uZWN0KGpvYlR5cGUsIHBhcmFtcyk7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5xdWV1ZS5lbnF1ZXVlQXQodGltZXN0YW1wLCBxdWUsIGpvYk5hbWUsIFtwYXJhbXNdKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBlbnF1ZXVlSW4odGltZTogbnVtYmVyLCBqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyA9IHt9LCBxdWU6IHN0cmluZyA9IFwibWFpblwiKTogUHJvbWlzZTxhbnk+IHtcclxuICAgICAgICBjb25zdCBqb2JOYW1lID0gYXdhaXQgdGhpcy50cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlLCBwYXJhbXMpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMucXVldWUuZW5xdWV1ZUluKHRpbWUsIHF1ZSwgam9iTmFtZSwgW3BhcmFtc10pO1xyXG4gICAgfVxyXG5cclxuICAgIHNjaGVkdWxlKG1pbnV0ZTogSm9iU2NoZWR1bGVUaW1lLCBob3VyOiBKb2JTY2hlZHVsZVRpbWUsIGRheU9mTW9udGg6IEpvYlNjaGVkdWxlVGltZSwgbW9udGg6IEpvYlNjaGVkdWxlVGltZSwgZGF5T2ZXZWVrOiBKb2JTY2hlZHVsZVRpbWUsIGpvYlR5cGU6IFR5cGU8SUpvYj4sIHBhcmFtczogSm9iUGFyYW1zID0ge30sIHF1ZTogc3RyaW5nID0gXCJtYWluXCIpOiBJSm9iVGFzayB7XHJcbiAgICAgICAgY29uc3QgZXhwcmVzc2lvbiA9IFttaW51dGUsIGhvdXIsIGRheU9mTW9udGgsIG1vbnRoLCBkYXlPZldlZWtdLm1hcCh0ID0+IHtcclxuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHQpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByYW5nZSA9IHQgYXMgSm9iU2NoZWR1bGVSYW5nZTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBgJHtyYW5nZS5taW4gfHwgMH0tJHtyYW5nZS5tYXggfHwgMH1gO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChpc0FycmF5KHQpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdC5qb2luKFwiLFwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gYCR7dH1gO1xyXG4gICAgICAgIH0pLmpvaW4oXCIgXCIpO1xyXG4gICAgICAgIGNvbnN0IGpvYk5hbWUgPSBnZXRDb25zdHJ1Y3Rvck5hbWUoam9iVHlwZSk7XHJcbiAgICAgICAgaWYgKCF2YWxpZGF0ZShleHByZXNzaW9uKSkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgQ2FuJ3Qgc2NoZWR1bGUgdGhlIHRhc2s6ICcke2pvYk5hbWV9JyBiZWNhdXNlIHRpbWUgZXhwcmVzc2lvbiBpcyBpbnZhbGlkLmApO1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHNjaGVkdWxlKGV4cHJlc3Npb24sICgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5lbnF1ZXVlKGpvYlR5cGUsIHBhcmFtcywgcXVlKS5jYXRjaChlID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDYW4ndCBlbnF1ZXVlIGpvYjogJyR7am9iTmFtZX0nIGJlY2F1c2U6ICR7ZX1gKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgc3RhcnRQcm9jZXNzaW5nKCk6IFByb21pc2U8YW55PiB7XHJcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKCk7XHJcbiAgICAgICAgYXdhaXQgdGhpcy53b3JrZXIuY29ubmVjdCgpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMud29ya2VyLnN0YXJ0KCk7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zY2hlZHVsZXIuY29ubmVjdCgpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMuc2NoZWR1bGVyLnN0YXJ0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdHJ5UmVzb2x2ZShqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3Qgam9iTmFtZSA9IGdldENvbnN0cnVjdG9yTmFtZShqb2JUeXBlKTtcclxuICAgICAgICBpZiAoIXRoaXMuam9ic1tqb2JOYW1lXSkge1xyXG4gICAgICAgICAgICB0aHJvdyBgQ2FuJ3QgZmluZCBqb2Igd2l0aCBuYW1lOiAke2pvYk5hbWV9IHNvIGl0IGNhbid0IGJlIGVucXVldWVkIWA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIHRoaXMucmVzb2x2ZUpvYkluc3RhbmNlKGpvYlR5cGUsIHBhcmFtcyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICB0aHJvdyBgQ2FuJ3QgcmVzb2x2ZSBwYXJhbXMgZm9yIGpvYjogJHtqb2JOYW1lfSwgd2l0aCBwYXJhbXM6ICR7SlNPTi5zdHJpbmdpZnkocGFyYW1zKX0uIFJlYXNvbjogJHtlfWA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBqb2JOYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCBpbml0aWFsaXplKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLnF1ZXVlKSByZXR1cm47XHJcbiAgICAgICAgY29uc3QgY29uZmlnID0gdGhpcy5jb25maWc7XHJcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtwYXNzd29yZDogY29uZmlnLnJlc29sdmUoXCJyZWRpc1Bhc3N3b3JkXCIpfTtcclxuICAgICAgICBjb25zdCBzZW50aW5lbHM6IEFycmF5PHtob3N0OiBzdHJpbmcsIHBvcnQ6IG51bWJlcn0+ID0gY29uZmlnLnJlc29sdmUoXCJyZWRpc1NlbnRpbmVsc1wiKTtcclxuICAgICAgICBjb25zdCByZWRpcyA9ICFzZW50aW5lbHNcclxuICAgICAgICAgICAgPyBudWxsXHJcbiAgICAgICAgICAgIDogbmV3IElPUmVkaXMoe1xyXG4gICAgICAgICAgICAgICAgc2VudGluZWxzLFxyXG4gICAgICAgICAgICAgICAgbmFtZTogY29uZmlnLnJlc29sdmUoXCJyZWRpc0NsdXN0ZXJcIiksXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB7XHJcbiAgICAgICAgICAgIHBrZzogXCJpb3JlZGlzXCIsXHJcbiAgICAgICAgICAgIGhvc3Q6IGNvbmZpZy5yZXNvbHZlKFwicmVkaXNIb3N0XCIpLFxyXG4gICAgICAgICAgICBwYXNzd29yZDogb3B0aW9ucy5wYXNzd29yZCxcclxuICAgICAgICAgICAgcG9ydDogY29uZmlnLnJlc29sdmUoXCJyZWRpc1BvcnRcIiksXHJcbiAgICAgICAgICAgIG5hbWVzcGFjZTogY29uZmlnLnJlc29sdmUoXCJyZWRpc05hbWVzcGFjZVwiKSxcclxuICAgICAgICAgICAgcmVkaXMsXHJcbiAgICAgICAgICAgIG9wdGlvbnNcclxuICAgICAgICB9O1xyXG4gICAgICAgIGNvbnN0IHF1ZXVlcyA9IGNvbmZpZy5yZXNvbHZlKFwid29ya1F1ZXVlc1wiKTtcclxuICAgICAgICB0aGlzLnF1ZXVlID0gbmV3IFF1ZXVlKHtjb25uZWN0aW9ufSwgdGhpcy5qb2JzKTtcclxuICAgICAgICB0aGlzLndvcmtlciA9IG5ldyBXb3JrZXIoe2Nvbm5lY3Rpb24sIHF1ZXVlc30sIHRoaXMuam9icyk7XHJcbiAgICAgICAgdGhpcy53b3JrZXIub24oXCJqb2JcIiwgKHF1ZXVlLCBqb2IpID0+IHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coYHdvcmtpbmcgam9iICR7cXVldWV9ICR7SlNPTi5zdHJpbmdpZnkoam9iKX1gKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLndvcmtlci5vbihcInJlRW5xdWV1ZVwiLCAocXVldWUsIGpvYiwgcGx1Z2luKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGByZUVucXVldWUgam9iICgke3BsdWdpbn0pICR7cXVldWV9ICR7SlNPTi5zdHJpbmdpZnkoam9iKX1gKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLndvcmtlci5vbihcInN1Y2Nlc3NcIiwgKHF1ZXVlLCBqb2IsIHJlc3VsdCwgZHVyYXRpb24pID0+IHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coXHJcbiAgICAgICAgICAgICAgICBgam9iIHN1Y2Nlc3MgJHtxdWV1ZX0gJHtKU09OLnN0cmluZ2lmeShqb2IpfSA+PiAke3Jlc3VsdH0gKCR7ZHVyYXRpb259bXMpYFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMud29ya2VyLm9uKFwiZmFpbHVyZVwiLCAocXVldWUsIGpvYiwgZmFpbHVyZSwgZHVyYXRpb24pID0+IHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coXHJcbiAgICAgICAgICAgICAgICBgam9iIGZhaWx1cmUgJHtxdWV1ZX0gJHtKU09OLnN0cmluZ2lmeShcclxuICAgICAgICAgICAgICAgICAgICBqb2JcclxuICAgICAgICAgICAgICAgICl9ID4+ICR7ZmFpbHVyZX0gKCR7ZHVyYXRpb259bXMpYFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMud29ya2VyLm9uKFwiZXJyb3JcIiwgKGVycm9yLCBxdWV1ZSwgam9iKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBlcnJvciAke3F1ZXVlfSAke0pTT04uc3RyaW5naWZ5KGpvYil9ICA+PiAke2Vycm9yfWApO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMuc2NoZWR1bGVyID0gbmV3IFNjaGVkdWxlcih7Y29ubmVjdGlvbn0sIHRoaXMuam9icyk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIHRyeVJlc29sdmVGcm9tTmFtZShqb2JOYW1lOiBzdHJpbmcsIHBhcmFtczogSm9iUGFyYW1zKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuICAgICAgICBjb25zdCBqb2JUeXBlID0gdGhpcy5qb2JUeXBlcy5maW5kKHR5cGUgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gZ2V0Q29uc3RydWN0b3JOYW1lKHR5cGUpID09IGpvYk5hbWU7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgaWYgKCFqb2JUeXBlKSB7XHJcbiAgICAgICAgICAgIHRocm93IGBDYW4ndCBmaW5kIGpvYiB0eXBlIHdpdGggbmFtZTogJHtqb2JOYW1lfSBzbyBpdCBjYW4ndCBiZSBlbnF1ZXVlZCFgO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcy50cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlLCBwYXJhbXMpO1xyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCBhc3luYyB0cnlSZXNvbHZlQW5kQ29ubmVjdChqb2JUeXBlOiBUeXBlPElKb2I+LCBwYXJhbXM6IEpvYlBhcmFtcyk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKCk7XHJcbiAgICAgICAgY29uc3Qgam9iTmFtZSA9IHRoaXMudHJ5UmVzb2x2ZShqb2JUeXBlLCBwYXJhbXMpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMucXVldWUuY29ubmVjdCgpO1xyXG4gICAgICAgIHJldHVybiBqb2JOYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCByZXNvbHZlSm9iSW5zdGFuY2Uoam9iVHlwZTogVHlwZTxJSm9iPiwgcGFyYW1zOiBKb2JQYXJhbXMpOiBJSm9iIHtcclxuICAgICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lci5jcmVhdGVDaGlsZENvbnRhaW5lcigpO1xyXG4gICAgICAgIE9iamVjdC5rZXlzKHBhcmFtcykubWFwKChuYW1lKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnRhaW5lci5yZWdpc3RlcihuYW1lLCB7dXNlVmFsdWU6IHBhcmFtc1tuYW1lXX0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGNvbnRhaW5lci5yZWdpc3Rlcihqb2JUeXBlLCBqb2JUeXBlKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lci5yZXNvbHZlKGpvYlR5cGUpIGFzIElKb2I7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIHRvUGVyZm9ybUZ1bmN0aW9uKGpvYlR5cGU6IFR5cGU8SUpvYj4pOiBGdW5jdGlvbiB7XHJcbiAgICAgICAgcmV0dXJuIChqb2JQYXJhbXM6IEpvYlBhcmFtcykgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBqb2IgPSB0aGlzLnJlc29sdmVKb2JJbnN0YW5jZShqb2JUeXBlLCBqb2JQYXJhbXMpO1xyXG4gICAgICAgICAgICByZXR1cm4gam9iLnByb2Nlc3MoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIl19