velocious 1.0.249 → 1.0.251

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 (46) hide show
  1. package/README.md +46 -0
  2. package/build/src/background-jobs/main.d.ts +2 -0
  3. package/build/src/background-jobs/main.d.ts.map +1 -1
  4. package/build/src/background-jobs/main.js +34 -14
  5. package/build/src/background-jobs/scheduler.d.ts +69 -0
  6. package/build/src/background-jobs/scheduler.d.ts.map +1 -0
  7. package/build/src/background-jobs/scheduler.js +148 -0
  8. package/build/src/configuration-types.d.ts +90 -10
  9. package/build/src/configuration-types.d.ts.map +1 -1
  10. package/build/src/configuration-types.js +31 -6
  11. package/build/src/configuration.d.ts +11 -1
  12. package/build/src/configuration.d.ts.map +1 -1
  13. package/build/src/configuration.js +22 -2
  14. package/build/src/database/query/model-class-query.d.ts +5 -0
  15. package/build/src/database/query/model-class-query.d.ts.map +1 -1
  16. package/build/src/database/query/model-class-query.js +97 -1
  17. package/build/src/database/query/where-model-class-hash.d.ts.map +1 -1
  18. package/build/src/database/query/where-model-class-hash.js +15 -3
  19. package/build/src/database/record/index.d.ts +7 -0
  20. package/build/src/database/record/index.d.ts.map +1 -1
  21. package/build/src/database/record/index.js +10 -1
  22. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +3 -1
  23. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
  24. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +81 -14
  25. package/build/src/frontend-model-controller.d.ts +7 -3
  26. package/build/src/frontend-model-controller.d.ts.map +1 -1
  27. package/build/src/frontend-model-controller.js +54 -4
  28. package/build/src/frontend-model-resource/base-resource.d.ts +4 -0
  29. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  30. package/build/src/frontend-model-resource/base-resource.js +9 -1
  31. package/build/src/frontend-models/base.d.ts +12 -3
  32. package/build/src/frontend-models/base.d.ts.map +1 -1
  33. package/build/src/frontend-models/base.js +24 -9
  34. package/build/src/frontend-models/query.d.ts +7 -2
  35. package/build/src/frontend-models/query.d.ts.map +1 -1
  36. package/build/src/frontend-models/query.js +52 -2
  37. package/build/src/frontend-models/resource-definition.d.ts +17 -0
  38. package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
  39. package/build/src/frontend-models/resource-definition.js +126 -15
  40. package/build/src/routes/hooks/frontend-model-command-route-hook.d.ts.map +1 -1
  41. package/build/src/routes/hooks/frontend-model-command-route-hook.js +23 -2
  42. package/build/src/utils/ransack.d.ts +27 -0
  43. package/build/src/utils/ransack.d.ts.map +1 -0
  44. package/build/src/utils/ransack.js +346 -0
  45. package/build/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +1 -1
package/README.md CHANGED
@@ -930,6 +930,23 @@ const specificTask = await Task.where({
930
930
  }).toArray()
931
931
  ```
932
932
 
933
+ ### Ransack-style filtering
934
+
935
+ Use `.ransack(...)` on record queries, record classes, frontend-model queries, and frontend-model classes when you want Rails/Ransack-style predicate keys without hand-writing nested `where(...)` or `search(...)` calls.
936
+
937
+ Supported predicates include `_eq`, `_not_eq`, `_gt`, `_gteq`, `_lt`, `_lteq`, `_cont`, `_start`, `_end`, `_in`, `_not_in`, and `_null`.
938
+
939
+ ```js
940
+ const tasks = await Task.ransack({
941
+ name_cont: "deploy",
942
+ project_project_detail_is_active_eq: true
943
+ }).toArray()
944
+
945
+ const frontendTasks = await FrontendTask
946
+ .ransack({name_cont: "deploy", id_in: ["1", "2"]})
947
+ .toArray()
948
+ ```
949
+
933
950
  ### Raw where clauses
934
951
 
935
952
  ```js
@@ -1493,6 +1510,35 @@ await MyJob.performLaterWithOptions({
1493
1510
  })
1494
1511
  ```
1495
1512
 
1513
+ ## Scheduled jobs
1514
+
1515
+ Velocious can enqueue recurring jobs from the `background-jobs-main` process. Configure them with `scheduledBackgroundJobs` using Sidekiq Scheduler-style `every` arrays:
1516
+
1517
+ ```js
1518
+ import BuildCleanupJob from "./src/jobs/build-cleanup-job.js"
1519
+
1520
+ export default new Configuration({
1521
+ // ...
1522
+ scheduledBackgroundJobs: {
1523
+ jobs: {
1524
+ buildCleanup: {
1525
+ class: BuildCleanupJob,
1526
+ every: ["1h", {first_in: "10s"}],
1527
+ options: {forked: false}
1528
+ }
1529
+ }
1530
+ }
1531
+ })
1532
+ ```
1533
+
1534
+ Supported schedule syntax:
1535
+
1536
+ - `every: "5m"`
1537
+ - `every: ["1h", {first_in: "30s"}]`
1538
+ - `every: ["1 day", {firstIn: "5 minutes"}]`
1539
+
1540
+ `background-jobs-main` owns the schedule and enqueues the configured jobs into the normal Velocious background-jobs queue. The HTTP server does not run scheduled jobs itself.
1541
+
1496
1542
  ## Persistence and retries
1497
1543
 
1498
1544
  Jobs are persisted in the configured database (`backgroundJobs.databaseIdentifier`) in an internal `background_jobs` table. When a worker picks a job, the job is marked as handed off and the worker reports completion or failure back to the main process.
@@ -27,6 +27,7 @@ export default class BackgroundJobsMain {
27
27
  server: net.Server;
28
28
  _dispatchTimer: NodeJS.Timeout;
29
29
  _orphanTimer: NodeJS.Timeout;
30
+ scheduler: BackgroundJobsScheduler;
30
31
  /**
31
32
  * @returns {Promise<void>} - Resolves when closed.
32
33
  */
@@ -59,4 +60,5 @@ import BackgroundJobsStore from "./store.js";
59
60
  import Logger from "../logger.js";
60
61
  import JsonSocket from "./json-socket.js";
61
62
  import net from "net";
63
+ import BackgroundJobsScheduler from "./scheduler.js";
62
64
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/main.js"],"names":[],"mappings":"AAOA;IACE;;;;;OAKG;IACH,2CAJG;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO;QACvB,IAAI,GAAlB,MAAM;QACQ,IAAI,GAAlB,MAAM;KAChB,EAaA;IAXC,qDAAkC;IAElC,aAA+B;IAC/B,aAAyD;IACzD,2BAAoG;IACpG,eAA8B;IAC9B,8BAA8B;IAC9B,SADW,GAAG,CAAC,UAAU,CAAC,CACF;IACxB,8BAA8B;IAC9B,cADW,GAAG,CAAC,UAAU,CAAC,CACG;IAC7B,sBAAyB;IAG3B;;OAEG;IACH,SAFa,OAAO,CAAC,IAAI,CAAC,CAyBzB;IAnBC,mBAA0E;IAY1E,+BAEQ;IAER,6BAES;IAGX;;OAEG;IACH,QAFa,OAAO,CAAC,IAAI,CAAC,CAazB;IAED;;OAEG;IACH,WAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,0BAHW,OAAO,KAAK,EAAE,MAAM,GAClB,IAAI,CAqDhB;IAED;;;sBAcC;IAED;;;sBAYC;IAED;;;sBAcC;IAED,2BAyCC;IAED,+BAUC;CACF;gCAxO+B,YAAY;mBACzB,cAAc;uBAFV,kBAAkB;gBADzB,KAAK"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/main.js"],"names":[],"mappings":"AAQA;IACE;;;;;OAKG;IACH,2CAJG;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO;QACvB,IAAI,GAAlB,MAAM;QACQ,IAAI,GAAlB,MAAM;KAChB,EAaA;IAXC,qDAAkC;IAElC,aAA+B;IAC/B,aAAyD;IACzD,2BAAoG;IACpG,eAA8B;IAC9B,8BAA8B;IAC9B,SADW,GAAG,CAAC,UAAU,CAAC,CACF;IACxB,8BAA8B;IAC9B,cADW,GAAG,CAAC,UAAU,CAAC,CACG;IAC7B,sBAAyB;IAG3B;;OAEG;IACH,SAFa,OAAO,CAAC,IAAI,CAAC,CA2CzB;IArCC,mBAA0E;IAaxE,+BAEQ;IAER,6BAES;IAET,mCAUE;IAQN;;OAEG;IACH,QAFa,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;OAEG;IACH,WAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,0BAHW,OAAO,KAAK,EAAE,MAAM,GAClB,IAAI,CAqDhB;IAED;;;sBAcC;IAED;;;sBAYC;IAED;;;sBAcC;IAED,2BAyCC;IAED,+BAUC;CACF;gCA3P+B,YAAY;mBACzB,cAAc;uBAHV,kBAAkB;gBADzB,KAAK;oCAEe,gBAAgB"}
@@ -1,6 +1,7 @@
1
1
  // @ts-check
2
2
  import net from "net";
3
3
  import JsonSocket from "./json-socket.js";
4
+ import BackgroundJobsScheduler from "./scheduler.js";
4
5
  import BackgroundJobsStore from "./store.js";
5
6
  import Logger from "../logger.js";
6
7
  export default class BackgroundJobsMain {
@@ -31,20 +32,38 @@ export default class BackgroundJobsMain {
31
32
  await this.configuration.initialize({ type: "background-jobs-main" });
32
33
  await this.store.ensureReady();
33
34
  this.server = net.createServer((socket) => this._handleConnection(socket));
34
- await new Promise((resolve, reject) => {
35
- this.server.once("error", reject);
36
- this.server.listen(this.port, this.host, () => resolve(undefined));
37
- });
38
- const address = this.server.address();
39
- if (address && typeof address === "object") {
40
- this.port = address.port;
35
+ try {
36
+ await new Promise((resolve, reject) => {
37
+ this.server.once("error", reject);
38
+ this.server.listen(this.port, this.host, () => resolve(undefined));
39
+ });
40
+ const address = this.server.address();
41
+ if (address && typeof address === "object") {
42
+ this.port = address.port;
43
+ }
44
+ this._dispatchTimer = setInterval(() => {
45
+ void this._dispatch();
46
+ }, 1000);
47
+ this._orphanTimer = setInterval(() => {
48
+ void this._sweepOrphans();
49
+ }, 60000);
50
+ this.scheduler = new BackgroundJobsScheduler({
51
+ configuration: this.configuration,
52
+ enqueueJob: async ({ args, jobClass, options }) => {
53
+ await this.store.enqueue({
54
+ jobName: jobClass.jobName(),
55
+ args,
56
+ options
57
+ });
58
+ await this._dispatch();
59
+ }
60
+ });
61
+ await this.scheduler.start();
62
+ }
63
+ catch (error) {
64
+ await this.stop();
65
+ throw error;
41
66
  }
42
- this._dispatchTimer = setInterval(() => {
43
- void this._dispatch();
44
- }, 1000);
45
- this._orphanTimer = setInterval(() => {
46
- void this._sweepOrphans();
47
- }, 60000);
48
67
  }
49
68
  /**
50
69
  * @returns {Promise<void>} - Resolves when closed.
@@ -57,6 +76,7 @@ export default class BackgroundJobsMain {
57
76
  clearInterval(this._dispatchTimer);
58
77
  if (this._orphanTimer)
59
78
  clearInterval(this._orphanTimer);
79
+ this.scheduler?.stop();
60
80
  if (!this.server)
61
81
  return;
62
82
  await new Promise((resolve) => this.server.close(() => resolve(undefined)));
@@ -213,4 +233,4 @@ export default class BackgroundJobsMain {
213
233
  }
214
234
  }
215
235
  }
216
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvbWFpbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFBO0FBQ3JCLE9BQU8sVUFBVSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pDLE9BQU8sbUJBQW1CLE1BQU0sWUFBWSxDQUFBO0FBQzVDLE9BQU8sTUFBTSxNQUFNLGNBQWMsQ0FBQTtBQUVqQyxNQUFNLENBQUMsT0FBTyxPQUFPLGtCQUFrQjtJQUNyQzs7Ozs7T0FLRztJQUNILFlBQVksRUFBQyxhQUFhLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBQztRQUNyQyxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQTtRQUNsQyxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsdUJBQXVCLEVBQUUsQ0FBQTtRQUN0RCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFBO1FBQy9CLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUE7UUFDekQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLG1CQUFtQixDQUFDLEVBQUMsYUFBYSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxrQkFBa0IsRUFBQyxDQUFDLENBQUE7UUFDcEcsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM5Qiw4QkFBOEI7UUFDOUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO1FBQ3hCLDhCQUE4QjtRQUM5QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7UUFDN0IsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENB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QkFDZCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLGlDQUFpQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUE7WUFDcEUsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQywrQkFBK0IsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO1FBQ25FLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IG5ldCBmcm9tIFwibmV0XCJcbmltcG9ydCBKc29uU29ja2V0IGZyb20gXCIuL2pzb24tc29ja2V0LmpzXCJcbmltcG9ydCBCYWNrZ3JvdW5kSm9ic1N0b3JlIGZyb20gXCIuL3N0b3JlLmpzXCJcbmltcG9ydCBMb2dnZXIgZnJvbSBcIi4uL2xvZ2dlci5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhY2tncm91bmRKb2JzTWFpbiB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2FyZ3MuaG9zdF0gLSBIb3N0bmFtZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFthcmdzLnBvcnRdIC0gUG9ydC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb25maWd1cmF0aW9uLCBob3N0LCBwb3J0fSkge1xuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb25cbiAgICBjb25zdCBjb25maWcgPSBjb25maWd1cmF0aW9uLmdldEJhY2tncm91bmRKb2JzQ29uZmlnKClcbiAgICB0aGlzLmhvc3QgPSBob3N0IHx8IGNvbmZpZy5ob3N0XG4gICAgdGhpcy5wb3J0ID0gdHlwZW9mIHBvcnQgPT09IFwibnVtYmVyXCIgPyBwb3J0IDogY29uZmlnLnBvcnRcbiAgICB0aGlzLnN0b3JlID0gbmV3IEJhY2tncm91bmRKb2JzU3RvcmUoe2NvbmZpZ3VyYXRpb24sIGRhdGFiYXNlSWRlbnRpZmllcjogY29uZmlnLmRhdGFiYXNlSWRlbnRpZmllcn0pXG4gICAgdGhpcy5sb2dnZXIgPSBuZXcgTG9nZ2VyKHRoaXMpXG4gICAgLyoqIEB0eXBlIHtTZXQ8SnNvblNvY2tldD59ICovXG4gICAgdGhpcy53b3JrZXJzID0gbmV3IFNldCgpXG4gICAgLyoqIEB0eXBlIHtTZXQ8SnNvblNvY2tldD59ICovXG4gICAgdGhpcy5yZWFkeVdvcmtlcnMgPSBuZXcgU2V0KClcbiAgICB0aGlzLl9kaXNwYXRjaGluZyA9IGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBsaXN0ZW5pbmcuXG4gICAqL1xuICBhc3luYyBzdGFydCgpIHtcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24uc2V0Q3VycmVudCgpXG4gICAgYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmluaXRpYWxpemUoe3R5cGU6IFwiYmFja2dyb3VuZC1qb2JzLW1haW5cIn0pXG4gICAgYXdhaXQgdGhpcy5zdG9yZS5lbnN1cmVSZWFkeSgpXG4gICAgdGhpcy5zZXJ2ZXIgPSBuZXQuY3JlYXRlU2VydmVyKChzb2NrZXQpID0+IHRoaXMuX2hhbmRsZUNvbm5lY3Rpb24oc29ja2V0KSlcblxuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuc2VydmVyLm9uY2UoXCJlcnJvclwiLCByZWplY3QpXG4gICAgICB0aGlzLnNlcnZlci5saXN0ZW4odGhpcy5wb3J0LCB0aGlzLmhvc3QsICgpID0+IHJlc29sdmUodW5kZWZpbmVkKSlcbiAgICB9KVxuXG4gICAgY29uc3QgYWRkcmVzcyA9IHRoaXMuc2VydmVyLmFkZHJlc3MoKVxuICAgIGlmIChhZGRyZXNzICYmIHR5cGVvZiBhZGRyZXNzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICB0aGlzLnBvcnQgPSBhZGRyZXNzLnBvcnRcbiAgICB9XG5cbiAgICB0aGlzLl9kaXNwYXRjaFRpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgdm9pZCB0aGlzLl9kaXNwYXRjaCgpXG4gICAgfSwgMTAwMClcblxuICAgIHRoaXMuX29ycGhhblRpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgdm9pZCB0aGlzLl9zd2VlcE9ycGhhbnMoKVxuICAgIH0sIDYwMDAwKVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY2xvc2VkLlxuICAgKi9cbiAgYXN5bmMgc3RvcCgpIHtcbiAgICBmb3IgKGNvbnN0IHdvcmtlciBvZiB0aGlzLndvcmtlcnMpIHtcbiAgICAgIHdvcmtlci5jbG9zZSgpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2Rpc3BhdGNoVGltZXIpIGNsZWFySW50ZXJ2YWwodGhpcy5fZGlzcGF0Y2hUaW1lcilcbiAgICBpZiAodGhpcy5fb3JwaGFuVGltZXIpIGNsZWFySW50ZXJ2YWwodGhpcy5fb3JwaGFuVGltZXIpXG5cbiAgICBpZiAoIXRoaXMuc2VydmVyKSByZXR1cm5cblxuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB0aGlzLnNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKHVuZGVmaW5lZCkpKVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IC0gQm91bmQgcG9ydC5cbiAgICovXG4gIGdldFBvcnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucG9ydFxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwibmV0XCIpLlNvY2tldH0gc29ja2V0IC0gU29ja2V0LlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIF9oYW5kbGVDb25uZWN0aW9uKHNvY2tldCkge1xuICAgIGNvbnN0IGpzb25Tb2NrZXQgPSBuZXcgSnNvblNvY2tldChzb2NrZXQpXG4gICAgbGV0IHJvbGUgPSBudWxsXG5cbiAgICBjb25zdCBjbGVhbnVwID0gKCkgPT4ge1xuICAgICAgaWYgKHJvbGUgPT09IFwid29ya2VyXCIpIHtcbiAgICAgICAgdGhpcy53b3JrZXJzLmRlbGV0ZShqc29uU29ja2V0KVxuICAgICAgICB0aGlzLnJlYWR5V29ya2Vycy5kZWxldGUoanNvblNvY2tldClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBqc29uU29ja2V0Lm9uKFwiY2xvc2VcIiwgY2xlYW51cClcbiAgICBqc29uU29ja2V0Lm9uKFwiZXJyb3JcIiwgKGVycm9yKSA9PiB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKCgpID0+IFtcIkJhY2tncm91bmQgam9icyBjb25uZWN0aW9uIGVycm9yOlwiLCBlcnJvcl0pXG4gICAgICBjbGVhbnVwKClcbiAgICB9KVxuXG4gICAganNvblNvY2tldC5vbihcIm1lc3NhZ2VcIiwgKG1lc3NhZ2UpID0+IHtcbiAgICAgIGlmICghcm9sZSAmJiBtZXNzYWdlPy50eXBlID09PSBcImhlbGxvXCIpIHtcbiAgICAgICAgcm9sZSA9IG1lc3NhZ2Uucm9sZVxuXG4gICAgICAgIGlmIChyb2xlID09PSBcIndvcmtlclwiKSB7XG4gICAgICAgICAganNvblNvY2tldC53b3JrZXJJZCA9IG1lc3NhZ2Uud29ya2VySWRcbiAgICAgICAgICB0aGlzLndvcmtlcnMuYWRkKGpzb25Tb2NrZXQpXG4gICAgICAgICAgdGhpcy5yZWFkeVdvcmtlcnMuYWRkKGpzb25Tb2NrZXQpXG4gICAgICAgICAgdGhpcy5fZGlzcGF0Y2goKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGlmIChyb2xlID09PSBcImNsaWVudFwiICYmIG1lc3NhZ2U/LnR5cGUgPT09IFwiZW5xdWV1ZVwiKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZUVucXVldWUoe2pzb25Tb2NrZXQsIG1lc3NhZ2V9KVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgaWYgKHJvbGUgPT09IFwid29ya2VyXCIgJiYgbWVzc2FnZT8udHlwZSA9PT0gXCJyZWFkeVwiKSB7XG4gICAgICAgIHRoaXMucmVhZHlXb3JrZXJzLmFkZChqc29uU29ja2V0KVxuICAgICAgICB0aGlzLl9kaXNwYXRjaCgpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAoKHJvbGUgPT09IFwid29ya2VyXCIgfHwgcm9sZSA9PT0gXCJyZXBvcnRlclwiKSAmJiBtZXNzYWdlPy50eXBlID09PSBcImpvYi1jb21wbGV0ZVwiKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZUpvYkNvbXBsZXRlKHtqc29uU29ja2V0LCBtZXNzYWdlfSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGlmICgocm9sZSA9PT0gXCJ3b3JrZXJcIiB8fCByb2xlID09PSBcInJlcG9ydGVyXCIpICYmIG1lc3NhZ2U/LnR5cGUgPT09IFwiam9iLWZhaWxlZFwiKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZUpvYkZhaWxlZCh7anNvblNvY2tldCwgbWVzc2FnZX0pXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVFbnF1ZXVlKHtqc29uU29ja2V0LCBtZXNzYWdlfSkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBqb2JJZCA9IGF3YWl0IHRoaXMuc3RvcmUuZW5xdWV1ZSh7XG4gICAgICAgIGpvYk5hbWU6IG1lc3NhZ2Uuam9iTmFtZSxcbiAgICAgICAgYXJnczogbWVzc2FnZS5hcmdzIHx8IFtdLFxuICAgICAgICBvcHRpb25zOiBtZXNzYWdlLm9wdGlvbnMgfHwge31cbiAgICAgIH0pXG5cbiAgICAgIGpzb25Tb2NrZXQuc2VuZCh7dHlwZTogXCJlbnF1ZXVlZFwiLCBqb2JJZH0pXG4gICAgICBhd2FpdCB0aGlzLl9kaXNwYXRjaCgpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCgpID0+IFtcIkZhaWxlZCB0byBlbnF1ZXVlIGJhY2tncm91bmQgam9iOlwiLCBlcnJvcl0pXG4gICAgICBqc29uU29ja2V0LnNlbmQoe3R5cGU6IFwiZW5xdWV1ZS1lcnJvclwiLCBlcnJvcjogXCJGYWlsZWQgdG8gZW5xdWV1ZSBqb2JcIn0pXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX2hhbmRsZUpvYkNvbXBsZXRlKHtqc29uU29ja2V0LCBtZXNzYWdlfSkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3JlLm1hcmtDb21wbGV0ZWQoe1xuICAgICAgICBqb2JJZDogbWVzc2FnZS5qb2JJZCxcbiAgICAgICAgd29ya2VySWQ6IG1lc3NhZ2Uud29ya2VySWQsXG4gICAgICAgIGhhbmRlZE9mZkF0TXM6IG1lc3NhZ2UuaGFuZGVkT2ZmQXRNc1xuICAgICAgfSlcbiAgICAgIGpzb25Tb2NrZXQuc2VuZCh7dHlwZTogXCJqb2ItdXBkYXRlZFwiLCBqb2JJZDogbWVzc2FnZS5qb2JJZH0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCgpID0+IFtcIkZhaWxlZCB0byB1cGRhdGUgam9iIGNvbXBsZXRpb246XCIsIGVycm9yXSlcbiAgICAgIGpzb25Tb2NrZXQuc2VuZCh7dHlwZTogXCJqb2ItdXBkYXRlLWVycm9yXCIsIGpvYklkOiBtZXNzYWdlLmpvYklkLCBlcnJvcjogXCJGYWlsZWQgdG8gdXBkYXRlIGpvYlwifSlcbiAgICB9XG4gIH1cblxuICBhc3luYyBfaGFuZGxlSm9iRmFpbGVkKHtqc29uU29ja2V0LCBtZXNzYWdlfSkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3JlLm1hcmtGYWlsZWQoe1xuICAgICAgICBqb2JJZDogbWVzc2FnZS5qb2JJZCxcbiAgICAgICAgZXJyb3I6IG1lc3NhZ2UuZXJyb3IsXG4gICAgICAgIHdvcmtlcklkOiBtZXNzYWdlLndvcmtlcklkLFxuICAgICAgICBoYW5kZWRPZmZBdE1zOiBtZXNzYWdlLmhhbmRlZE9mZkF0TXNcbiAgICAgIH0pXG4gICAgICBqc29uU29ja2V0LnNlbmQoe3R5cGU6IFwiam9iLXVwZGF0ZWRcIiwgam9iSWQ6IG1lc3NhZ2Uuam9iSWR9KVxuICAgICAgYXdhaXQgdGhpcy5fZGlzcGF0Y2goKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbXCJGYWlsZWQgdG8gdXBkYXRlIGpvYiBmYWlsdXJlOlwiLCBlcnJvcl0pXG4gICAgICBqc29uU29ja2V0LnNlbmQoe3R5cGU6IFwiam9iLXVwZGF0ZS1lcnJvclwiLCBqb2JJZDogbWVzc2FnZS5qb2JJZCwgZXJyb3I6IFwiRmFpbGVkIHRvIHVwZGF0ZSBqb2JcIn0pXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX2Rpc3BhdGNoKCkge1xuICAgIGlmICh0aGlzLl9kaXNwYXRjaGluZykgcmV0dXJuXG4gICAgaWYgKHRoaXMucmVhZHlXb3JrZXJzLnNpemUgPT09IDApIHJldHVyblxuXG4gICAgdGhpcy5fZGlzcGF0Y2hpbmcgPSB0cnVlXG5cbiAgICB0cnkge1xuICAgICAgd2hpbGUgKHRoaXMucmVhZHlXb3JrZXJzLnNpemUgPiAwKSB7XG4gICAgICAgIGNvbnN0IGpvYiA9IGF3YWl0IHRoaXMuc3RvcmUubmV4dEF2YWlsYWJsZUpvYigpXG4gICAgICAgIGlmICgham9iKSByZXR1cm5cblxuICAgICAgICBjb25zdCBbd29ya2VyXSA9IHRoaXMucmVhZHlXb3JrZXJzXG4gICAgICAgIGlmICghd29ya2VyKSByZXR1cm5cblxuICAgICAgICB0aGlzLnJlYWR5V29ya2Vycy5kZWxldGUod29ya2VyKVxuXG4gICAgICAgIGNvbnN0IGhhbmRlZE9mZkF0TXMgPSBhd2FpdCB0aGlzLnN0b3JlLm1hcmtIYW5kZWRPZmYoe2pvYklkOiBqb2IuaWQsIHdvcmtlcklkOiB3b3JrZXIud29ya2VySWR9KVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgd29ya2VyLnNlbmQoe1xuICAgICAgICAgICAgdHlwZTogXCJqb2JcIixcbiAgICAgICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICAgICAgaWQ6IGpvYi5pZCxcbiAgICAgICAgICAgICAgam9iTmFtZTogam9iLmpvYk5hbWUsXG4gICAgICAgICAgICAgIGFyZ3M6IGpvYi5hcmdzLFxuICAgICAgICAgICAgICB3b3JrZXJJZDogd29ya2VyLndvcmtlcklkLFxuICAgICAgICAgICAgICBoYW5kZWRPZmZBdE1zLFxuICAgICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgZm9ya2VkOiBqb2IuZm9ya2VkXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oKCkgPT4gW1wiRmFpbGVkIHRvIHNlbmQgam9iIHRvIHdvcmtlciwgcmUtcXVldWVpbmc6XCIsIGVycm9yXSlcbiAgICAgICAgICBhd2FpdCB0aGlzLnN0b3JlLm1hcmtSZXR1cm5lZFRvUXVldWUoe2pvYklkOiBqb2IuaWR9KVxuICAgICAgICAgIHRoaXMucmVhZHlXb3JrZXJzLmFkZCh3b3JrZXIpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5fZGlzcGF0Y2hpbmcgPSBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIF9zd2VlcE9ycGhhbnMoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvdW50ID0gYXdhaXQgdGhpcy5zdG9yZS5tYXJrT3JwaGFuZWRKb2JzKClcblxuICAgICAgaWYgKGNvdW50ID4gMCkge1xuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKCgpID0+IFtcIk1hcmtlZCBvcnBoYW5lZCBiYWNrZ3JvdW5kIGpvYnNcIiwgY291bnRdKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbXCJGYWlsZWQgdG8gbWFyayBvcnBoYW5lZCBqb2JzOlwiLCBlcnJvcl0pXG4gICAgfVxuICB9XG59XG4iXX0=
236
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvbWFpbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFBO0FBQ3JCLE9BQU8sVUFBVSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pDLE9BQU8sdUJBQXVCLE1BQU0sZ0JBQWdCLENBQUE7QUFDcEQsT0FBTyxtQkFBbUIsTUFBTSxZQUFZLENBQUE7QUFDNUMsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFBO0FBRWpDLE1BQU0sQ0FBQyxPQUFPLE9BQU8sa0JBQWtCO0lBQ3JDOzs7OztPQUtHO0lBQ0gsWUFBWSxFQUFDLGFBQWEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO1FBQ3JDLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1FBQ2xDLE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyx1QkFBdUIsRUFBRSxDQUFBO1FBQ3RELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUE7UUFDL0IsSUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLElBQUksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQTtRQUN6RCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksbUJBQW1CLENBQUMsRUFBQyxhQUFhLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxDQUFDLGtCQUFrQixFQUFDLENBQUMsQ0FBQTtRQUNwRyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzlCLDhCQUE4QjtRQUM5QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7UUFDeEIsOEJBQThCO1FBQzlCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FB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T0FBTyxFQUFFO2dDQUNQLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTTs2QkFDbkI7eUJBQ0Y7cUJBQ0YsQ0FBQyxDQUFBO2dCQUNKLENBQUM7Z0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztvQkFDZixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLDRDQUE0QyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUE7b0JBQzdFLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxFQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQTtvQkFDckQsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7Z0JBQy9CLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUE7UUFDM0IsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsYUFBYTtRQUNqQixJQUFJLENBQUM7WUFDSCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtZQUVqRCxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDZCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLGlDQUFpQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUE7WUFDcEUsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQywrQkFBK0IsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO1FBQ25FLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IG5ldCBmcm9tIFwibmV0XCJcbmltcG9ydCBKc29uU29ja2V0IGZyb20gXCIuL2pzb24tc29ja2V0LmpzXCJcbmltcG9ydCBCYWNrZ3JvdW5kSm9ic1NjaGVkdWxlciBmcm9tIFwiLi9zY2hlZHVsZXIuanNcIlxuaW1wb3J0IEJhY2tncm91bmRKb2JzU3RvcmUgZnJvbSBcIi4vc3RvcmUuanNcIlxuaW1wb3J0IExvZ2dlciBmcm9tIFwiLi4vbG9nZ2VyLmpzXCJcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFja2dyb3VuZEpvYnNNYWluIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5ob3N0XSAtIEhvc3RuYW1lLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3MucG9ydF0gLSBQb3J0LlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb24sIGhvc3QsIHBvcnR9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIGNvbnN0IGNvbmZpZyA9IGNvbmZpZ3VyYXRpb24uZ2V0QmFja2dyb3VuZEpvYnNDb25maWcoKVxuICAgIHRoaXMuaG9zdCA9IGhvc3QgfHwgY29uZmlnLmhvc3RcbiAgICB0aGlzLnBvcnQgPSB0eXBlb2YgcG9ydCA9PT0gXCJudW1iZXJcIiA/IHBvcnQgOiBjb25maWcucG9ydFxuICAgIHRoaXMuc3RvcmUgPSBuZXcgQmFja2dyb3VuZEpvYnNTdG9yZSh7Y29uZmlndXJhdGlvbiwgZGF0YWJhc2VJZGVudGlmaWVyOiBjb25maWcuZGF0YWJhc2VJZGVudGlmaWVyfSlcbiAgICB0aGlzLmxvZ2dlciA9IG5ldyBMb2dnZXIodGhpcylcbiAgICAvKiogQHR5cGUge1NldDxKc29uU29ja2V0Pn0gKi9cbiAgICB0aGlzLndvcmtlcnMgPSBuZXcgU2V0KClcbiAgICAvKiogQHR5cGUge1NldDxKc29uU29ja2V0Pn0gKi9cbiAgICB0aGlzLnJlYWR5V29ya2VycyA9IG5ldyBTZXQoKVxuICAgIHRoaXMuX2Rpc3BhdGNoaW5nID0gZmFsc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGxpc3RlbmluZy5cbiAgICovXG4gIGFzeW5jIHN0YXJ0KCkge1xuICAgIHRoaXMuY29uZmlndXJhdGlvbi5zZXRDdXJyZW50KClcbiAgICBhd2FpdCB0aGlzLmNvbmZpZ3VyYXRpb24uaW5pdGlhbGl6ZSh7dHlwZTogXCJiYWNrZ3JvdW5kLWpvYnMtbWFpblwifSlcbiAgICBhd2FpdCB0aGlzLnN0b3JlLmVuc3VyZVJlYWR5KClcbiAgICB0aGlzLnNlcnZlciA9IG5ldC5jcmVhdGVTZXJ2ZXIoKHNvY2tldCkgPT4gdGhpcy5faGFuZGxlQ29ubmVjdGlvbihzb2NrZXQpKVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgdGhpcy5zZXJ2ZXIub25jZShcImVycm9yXCIsIHJlamVjdClcbiAgICAgICAgdGhpcy5zZXJ2ZXIubGlzdGVuKHRoaXMucG9ydCwgdGhpcy5ob3N0LCAoKSA9PiByZXNvbHZlKHVuZGVmaW5lZCkpXG4gICAgICB9KVxuXG4gICAgICBjb25zdCBhZGRyZXNzID0gdGhpcy5zZXJ2ZXIuYWRkcmVzcygpXG4gICAgICBpZiAoYWRkcmVzcyAmJiB0eXBlb2YgYWRkcmVzcyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB0aGlzLnBvcnQgPSBhZGRyZXNzLnBvcnRcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZGlzcGF0Y2hUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgdm9pZCB0aGlzLl9kaXNwYXRjaCgpXG4gICAgICB9LCAxMDAwKVxuXG4gICAgICB0aGlzLl9vcnBoYW5UaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgdm9pZCB0aGlzLl9zd2VlcE9ycGhhbnMoKVxuICAgICAgfSwgNjAwMDApXG5cbiAgICAgIHRoaXMuc2NoZWR1bGVyID0gbmV3IEJhY2tncm91bmRKb2JzU2NoZWR1bGVyKHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICBlbnF1ZXVlSm9iOiBhc3luYyAoe2FyZ3MsIGpvYkNsYXNzLCBvcHRpb25zfSkgPT4ge1xuICAgICAgICAgIGF3YWl0IHRoaXMuc3RvcmUuZW5xdWV1ZSh7XG4gICAgICAgICAgICBqb2JOYW1lOiBqb2JDbGFzcy5qb2JOYW1lKCksXG4gICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICAgIH0pXG4gICAgICAgICAgYXdhaXQgdGhpcy5fZGlzcGF0Y2goKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgYXdhaXQgdGhpcy5zY2hlZHVsZXIuc3RhcnQoKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3AoKVxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjbG9zZWQuXG4gICAqL1xuICBhc3luYyBzdG9wKCkge1xuICAgIGZvciAoY29uc3Qgd29ya2VyIG9mIHRoaXMud29ya2Vycykge1xuICAgICAgd29ya2VyLmNsb3NlKClcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZGlzcGF0Y2hUaW1lcikgY2xlYXJJbnRlcnZhbCh0aGlzLl9kaXNwYXRjaFRpbWVyKVxuICAgIGlmICh0aGlzLl9vcnBoYW5UaW1lcikgY2xlYXJJbnRlcnZhbCh0aGlzLl9vcnBoYW5UaW1lcilcbiAgICB0aGlzLnNjaGVkdWxlcj8uc3RvcCgpXG5cbiAgICBpZiAoIXRoaXMuc2VydmVyKSByZXR1cm5cblxuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB0aGlzLnNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKHVuZGVmaW5lZCkpKVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IC0gQm91bmQgcG9ydC5cbiAgICovXG4gIGdldFBvcnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucG9ydFxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwibmV0XCIpLlNvY2tldH0gc29ja2V0IC0gU29ja2V0LlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIF9oYW5kbGVDb25uZWN0aW9uKHNvY2tldCkge1xuICAgIGNvbnN0IGpzb25Tb2NrZXQgPSBuZXcgSnNvblNvY2tldChzb2NrZXQpXG4gICAgbGV0IHJvbGUgPSBudWxsXG5cbiAgICBjb25zdCBjbGVhbnVwID0gKCkgPT4ge1xuICAgICAgaWYgKHJvbGUgPT09IFwid29ya2VyXCIpIHtcbiAgICAgICAgdGhpcy53b3JrZXJzLmRlbGV0ZShqc29uU29ja2V0KVxuICAgICAgICB0aGlzLnJlYWR5V29ya2Vycy5kZWxldGUoanNvblNvY2tldClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBqc29uU29ja2V0Lm9uKFwiY2xvc2VcIiwgY2xlYW51cClcbiAgICBqc29uU29ja2V0Lm9uKFwiZXJyb3JcIiwgKGVycm9yKSA9PiB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKCgpID0+IFtcIkJhY2tncm91bmQgam9icyBjb25uZWN0aW9uIGVycm9yOlwiLCBlcnJvcl0pXG4gICAgICBjbGVhbnVwKClcbiAgICB9KVxuXG4gICAganNvblNvY2tldC5vbihcIm1lc3NhZ2VcIiwgKG1lc3NhZ2UpID0+IHtcbiAgICAgIGlmICghcm9sZSAmJiBtZXNzYWdlPy50eXBlID09PSBcImhlbGxvXCIpIHtcbiAgICAgICAgcm9sZSA9IG1lc3NhZ2Uucm9sZVxuXG4gICAgICAgIGlmIChyb2xlID09PSBcIndvcmtlclwiKSB7XG4gICAgICAgICAganNvblNvY2tldC53b3JrZXJJZCA9IG1lc3NhZ2Uud29ya2VySWRcbiAgICAgICAgICB0aGlzLndvcmtlcnMuYWRkKGpzb25Tb2NrZXQpXG4gICAgICAgICAgdGhpcy5yZWFkeVdvcmtlcnMuYWRkKGpzb25Tb2NrZXQpXG4gICAgICAgICAgdGhpcy5fZGlzcGF0Y2goKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGlmIChyb2xlID09PSBcImNsaWVudFwiICYmIG1lc3NhZ2U/LnR5cGUgPT09IFwiZW5xdWV1ZVwiKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZUVucXVldWUoe2pzb25Tb2NrZXQsIG1lc3NhZ2V9KVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgaWYgKHJvbGUgPT09IFwid29ya2VyXCIgJiYgbWVzc2FnZT8udHlwZSA9PT0gXCJyZWFkeVwiKSB7XG4gICAgICAgIHRoaXMucmVhZHlXb3JrZXJzLmFkZChqc29uU29ja2V0KVxuICAgICAgICB0aGlzLl9kaXNwYXRjaCgpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAoKHJvbGUgPT09IFwid29ya2VyXCIgfHwgcm9sZSA9PT0gXCJyZXBvcnRlclwiKSAmJiBtZXNzYWdlPy50eXBlID09PSBcImpvYi1jb21wbGV0ZVwiKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZUpvYkNvbXBsZXRlKHtqc29uU29ja2V0LCBtZXNzYWdlfSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGlmICgocm9sZSA9PT0gXCJ3b3JrZXJcIiB8fCByb2xlID09PSBcInJlcG9ydGVyXCIpICYmIG1lc3NhZ2U/LnR5cGUgPT09IFwiam9iLWZhaWxlZFwiKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZUpvYkZhaWxlZCh7anNvblNvY2tldCwgbWVzc2FnZX0pXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVFbnF1ZXVlKHtqc29uU29ja2V0LCBtZXNzYWdlfSkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBqb2JJZCA9IGF3YWl0IHRoaXMuc3RvcmUuZW5xdWV1ZSh7XG4gICAgICAgIGpvYk5hbWU6IG1lc3NhZ2Uuam9iTmFtZSxcbiAgICAgICAgYXJnczogbWVzc2FnZS5hcmdzIHx8IFtdLFxuICAgICAgICBvcHRpb25zOiBtZXNzYWdlLm9wdGlvbnMgfHwge31cbiAgICAgIH0pXG5cbiAgICAgIGpzb25Tb2NrZXQuc2VuZCh7dHlwZTogXCJlbnF1ZXVlZFwiLCBqb2JJZH0pXG4gICAgICBhd2FpdCB0aGlzLl9kaXNwYXRjaCgpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCgpID0+IFtcIkZhaWxlZCB0byBlbnF1ZXVlIGJhY2tncm91bmQgam9iOlwiLCBlcnJvcl0pXG4gICAgICBqc29uU29ja2V0LnNlbmQoe3R5cGU6IFwiZW5xdWV1ZS1lcnJvclwiLCBlcnJvcjogXCJGYWlsZWQgdG8gZW5xdWV1ZSBqb2JcIn0pXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX2hhbmRsZUpvYkNvbXBsZXRlKHtqc29uU29ja2V0LCBtZXNzYWdlfSkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3JlLm1hcmtDb21wbGV0ZWQoe1xuICAgICAgICBqb2JJZDogbWVzc2FnZS5qb2JJZCxcbiAgICAgICAgd29ya2VySWQ6IG1lc3NhZ2Uud29ya2VySWQsXG4gICAgICAgIGhhbmRlZE9mZkF0TXM6IG1lc3NhZ2UuaGFuZGVkT2ZmQXRNc1xuICAgICAgfSlcbiAgICAgIGpzb25Tb2NrZXQuc2VuZCh7dHlwZTogXCJqb2ItdXBkYXRlZFwiLCBqb2JJZDogbWVzc2FnZS5qb2JJZH0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCgpID0+IFtcIkZhaWxlZCB0byB1cGRhdGUgam9iIGNvbXBsZXRpb246XCIsIGVycm9yXSlcbiAgICAgIGpzb25Tb2NrZXQuc2VuZCh7dHlwZTogXCJqb2ItdXBkYXRlLWVycm9yXCIsIGpvYklkOiBtZXNzYWdlLmpvYklkLCBlcnJvcjogXCJGYWlsZWQgdG8gdXBkYXRlIGpvYlwifSlcbiAgICB9XG4gIH1cblxuICBhc3luYyBfaGFuZGxlSm9iRmFpbGVkKHtqc29uU29ja2V0LCBtZXNzYWdlfSkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3JlLm1hcmtGYWlsZWQoe1xuICAgICAgICBqb2JJZDogbWVzc2FnZS5qb2JJZCxcbiAgICAgICAgZXJyb3I6IG1lc3NhZ2UuZXJyb3IsXG4gICAgICAgIHdvcmtlcklkOiBtZXNzYWdlLndvcmtlcklkLFxuICAgICAgICBoYW5kZWRPZmZBdE1zOiBtZXNzYWdlLmhhbmRlZE9mZkF0TXNcbiAgICAgIH0pXG4gICAgICBqc29uU29ja2V0LnNlbmQoe3R5cGU6IFwiam9iLXVwZGF0ZWRcIiwgam9iSWQ6IG1lc3NhZ2Uuam9iSWR9KVxuICAgICAgYXdhaXQgdGhpcy5fZGlzcGF0Y2goKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbXCJGYWlsZWQgdG8gdXBkYXRlIGpvYiBmYWlsdXJlOlwiLCBlcnJvcl0pXG4gICAgICBqc29uU29ja2V0LnNlbmQoe3R5cGU6IFwiam9iLXVwZGF0ZS1lcnJvclwiLCBqb2JJZDogbWVzc2FnZS5qb2JJZCwgZXJyb3I6IFwiRmFpbGVkIHRvIHVwZGF0ZSBqb2JcIn0pXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX2Rpc3BhdGNoKCkge1xuICAgIGlmICh0aGlzLl9kaXNwYXRjaGluZykgcmV0dXJuXG4gICAgaWYgKHRoaXMucmVhZHlXb3JrZXJzLnNpemUgPT09IDApIHJldHVyblxuXG4gICAgdGhpcy5fZGlzcGF0Y2hpbmcgPSB0cnVlXG5cbiAgICB0cnkge1xuICAgICAgd2hpbGUgKHRoaXMucmVhZHlXb3JrZXJzLnNpemUgPiAwKSB7XG4gICAgICAgIGNvbnN0IGpvYiA9IGF3YWl0IHRoaXMuc3RvcmUubmV4dEF2YWlsYWJsZUpvYigpXG4gICAgICAgIGlmICgham9iKSByZXR1cm5cblxuICAgICAgICBjb25zdCBbd29ya2VyXSA9IHRoaXMucmVhZHlXb3JrZXJzXG4gICAgICAgIGlmICghd29ya2VyKSByZXR1cm5cblxuICAgICAgICB0aGlzLnJlYWR5V29ya2Vycy5kZWxldGUod29ya2VyKVxuXG4gICAgICAgIGNvbnN0IGhhbmRlZE9mZkF0TXMgPSBhd2FpdCB0aGlzLnN0b3JlLm1hcmtIYW5kZWRPZmYoe2pvYklkOiBqb2IuaWQsIHdvcmtlcklkOiB3b3JrZXIud29ya2VySWR9KVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgd29ya2VyLnNlbmQoe1xuICAgICAgICAgICAgdHlwZTogXCJqb2JcIixcbiAgICAgICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICAgICAgaWQ6IGpvYi5pZCxcbiAgICAgICAgICAgICAgam9iTmFtZTogam9iLmpvYk5hbWUsXG4gICAgICAgICAgICAgIGFyZ3M6IGpvYi5hcmdzLFxuICAgICAgICAgICAgICB3b3JrZXJJZDogd29ya2VyLndvcmtlcklkLFxuICAgICAgICAgICAgICBoYW5kZWRPZmZBdE1zLFxuICAgICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgZm9ya2VkOiBqb2IuZm9ya2VkXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oKCkgPT4gW1wiRmFpbGVkIHRvIHNlbmQgam9iIHRvIHdvcmtlciwgcmUtcXVldWVpbmc6XCIsIGVycm9yXSlcbiAgICAgICAgICBhd2FpdCB0aGlzLnN0b3JlLm1hcmtSZXR1cm5lZFRvUXVldWUoe2pvYklkOiBqb2IuaWR9KVxuICAgICAgICAgIHRoaXMucmVhZHlXb3JrZXJzLmFkZCh3b3JrZXIpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5fZGlzcGF0Y2hpbmcgPSBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIF9zd2VlcE9ycGhhbnMoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvdW50ID0gYXdhaXQgdGhpcy5zdG9yZS5tYXJrT3JwaGFuZWRKb2JzKClcblxuICAgICAgaWYgKGNvdW50ID4gMCkge1xuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKCgpID0+IFtcIk1hcmtlZCBvcnBoYW5lZCBiYWNrZ3JvdW5kIGpvYnNcIiwgY291bnRdKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbXCJGYWlsZWQgdG8gbWFyayBvcnBoYW5lZCBqb2JzOlwiLCBlcnJvcl0pXG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @param {number | string} value - Duration value.
3
+ * @param {string} fieldName - Field name for errors.
4
+ * @returns {number} - Duration in milliseconds.
5
+ */
6
+ export function parseScheduledDuration(value: number | string, fieldName: string): number;
7
+ /** Runs configured recurring background job schedules. */
8
+ export default class BackgroundJobsScheduler {
9
+ /**
10
+ * @param {object} args - Options.
11
+ * @param {import("../configuration.js").default} args.configuration - Configuration.
12
+ * @param {function({args: any[], jobClass: typeof import("./job.js").default, jobKey: string, options: import("./types.js").BackgroundJobOptions}) : Promise<void>} args.enqueueJob - Enqueue callback.
13
+ */
14
+ constructor({ configuration, enqueueJob }: {
15
+ configuration: import("../configuration.js").default;
16
+ enqueueJob: (arg0: {
17
+ args: any[];
18
+ jobClass: typeof import("./job.js").default;
19
+ jobKey: string;
20
+ options: import("./types.js").BackgroundJobOptions;
21
+ }) => Promise<void>;
22
+ });
23
+ configuration: import("../configuration.js").default;
24
+ enqueueJob: (arg0: {
25
+ args: any[];
26
+ jobClass: typeof import("./job.js").default;
27
+ jobKey: string;
28
+ options: import("./types.js").BackgroundJobOptions;
29
+ }) => Promise<void>;
30
+ logger: Logger;
31
+ /** @type {Array<ReturnType<typeof setInterval>>} */
32
+ intervalIds: Array<ReturnType<typeof setInterval>>;
33
+ /** @type {Array<ReturnType<typeof setTimeout>>} */
34
+ timeoutIds: Array<ReturnType<typeof setTimeout>>;
35
+ /** @returns {Promise<void>} */
36
+ start(): Promise<void>;
37
+ /** @returns {void} */
38
+ stop(): void;
39
+ /**
40
+ * @param {object} args - Options.
41
+ * @param {import("../configuration-types.js").ScheduledBackgroundJobConfiguration} args.jobConfiguration - Job configuration.
42
+ * @param {string} args.jobKey - Job key.
43
+ * @returns {void}
44
+ */
45
+ scheduleJob({ jobConfiguration, jobKey }: {
46
+ jobConfiguration: import("../configuration-types.js").ScheduledBackgroundJobConfiguration;
47
+ jobKey: string;
48
+ }): void;
49
+ /**
50
+ * @param {object} args - Options.
51
+ * @param {import("../configuration-types.js").ScheduledBackgroundJobConfiguration} args.jobConfiguration - Job configuration.
52
+ * @param {string} args.jobKey - Job key.
53
+ * @returns {Promise<void>}
54
+ */
55
+ enqueueScheduledJob({ jobConfiguration, jobKey }: {
56
+ jobConfiguration: import("../configuration-types.js").ScheduledBackgroundJobConfiguration;
57
+ jobKey: string;
58
+ }): Promise<void>;
59
+ /**
60
+ * @param {import("../configuration-types.js").ScheduledBackgroundJobConfiguration["every"]} every - Every config.
61
+ * @returns {{everyValue: number | string, firstInValue?: number | string}} - Normalized interval and first-run delay values.
62
+ */
63
+ normalizeEvery(every: import("../configuration-types.js").ScheduledBackgroundJobConfiguration["every"]): {
64
+ everyValue: number | string;
65
+ firstInValue?: number | string;
66
+ };
67
+ }
68
+ import Logger from "../logger.js";
69
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/scheduler.js"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,8CAJW,MAAM,GAAG,MAAM,aACf,MAAM,GACJ,MAAM,CA8BlB;AAED,0DAA0D;AAC1D;IACE;;;;OAIG;IACH,2CAHG;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO;QAC0H,UAAU,EAAzK,CAAS,IAA8H,EAA9H;YAAC,IAAI,EAAE,GAAG,EAAE,CAAC;YAAC,QAAQ,EAAE,cAAc,UAAU,EAAE,OAAO,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,OAAO,YAAY,EAAE,oBAAoB,CAAA;SAAC,KAAI,OAAO,CAAC,IAAI,CAAC;KAClK,EASA;IAPC,qDAAkC;IAClC,mBAJkB;QAAC,IAAI,EAAE,GAAG,EAAE,CAAC;QAAC,QAAQ,EAAE,cAAc,UAAU,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,YAAY,EAAE,oBAAoB,CAAA;KAAC,KAAI,OAAO,CAAC,IAAI,CAAC,CAIrI;IAC5B,eAA8B;IAC9B,oDAAoD;IACpD,aADW,KAAK,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAC3B;IACrB,mDAAmD;IACnD,YADW,KAAK,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAC3B;IAGtB,+BAA+B;IAC/B,SADc,OAAO,CAAC,IAAI,CAAC,CAiB1B;IAED,sBAAsB;IACtB,QADc,IAAI,CAYjB;IAED;;;;;OAKG;IACH,0CAJG;QAAsF,gBAAgB,EAA9F,OAAO,2BAA2B,EAAE,mCAAmC;QAC1D,MAAM,EAAnB,MAAM;KACd,GAAU,IAAI,CA0BhB;IAED;;;;;OAKG;IACH,kDAJG;QAAsF,gBAAgB,EAA9F,OAAO,2BAA2B,EAAE,mCAAmC;QAC1D,MAAM,EAAnB,MAAM;KACd,GAAU,OAAO,CAAC,IAAI,CAAC,CAazB;IAED;;;OAGG;IACH,sBAHW,OAAO,2BAA2B,EAAE,mCAAmC,CAAC,OAAO,CAAC,GAC9E;QAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,CAczE;CACF;mBA9KkB,cAAc"}
@@ -0,0 +1,148 @@
1
+ // @ts-check
2
+ import Logger from "../logger.js";
3
+ const DURATION_MULTIPLIERS = {
4
+ d: 24 * 60 * 60 * 1000,
5
+ day: 24 * 60 * 60 * 1000,
6
+ days: 24 * 60 * 60 * 1000,
7
+ h: 60 * 60 * 1000,
8
+ hour: 60 * 60 * 1000,
9
+ hours: 60 * 60 * 1000,
10
+ m: 60 * 1000,
11
+ minute: 60 * 1000,
12
+ minutes: 60 * 1000,
13
+ ms: 1,
14
+ s: 1000,
15
+ second: 1000,
16
+ seconds: 1000,
17
+ w: 7 * 24 * 60 * 60 * 1000,
18
+ week: 7 * 24 * 60 * 60 * 1000,
19
+ weeks: 7 * 24 * 60 * 60 * 1000
20
+ };
21
+ /**
22
+ * @param {number | string} value - Duration value.
23
+ * @param {string} fieldName - Field name for errors.
24
+ * @returns {number} - Duration in milliseconds.
25
+ */
26
+ export function parseScheduledDuration(value, fieldName) {
27
+ if (typeof value === "number") {
28
+ if (!Number.isFinite(value) || value < 1) {
29
+ throw new Error(`Scheduled background job ${fieldName} must be a positive number of milliseconds.`);
30
+ }
31
+ return value;
32
+ }
33
+ if (typeof value !== "string" || !value.trim()) {
34
+ throw new Error(`Scheduled background job ${fieldName} must be a non-empty string or number.`);
35
+ }
36
+ const normalizedValue = value.trim().toLowerCase();
37
+ const match = normalizedValue.match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d|w|second|seconds|minute|minutes|hour|hours|day|days|week|weeks)$/);
38
+ if (!match) {
39
+ throw new Error(`Invalid scheduled background job ${fieldName}: ${value}`);
40
+ }
41
+ const numericValue = Number(match[1]);
42
+ const multiplier = DURATION_MULTIPLIERS[match[2]];
43
+ if (!multiplier) {
44
+ throw new Error(`Invalid scheduled background job ${fieldName}: ${value}`);
45
+ }
46
+ return Math.round(numericValue * multiplier);
47
+ }
48
+ /** Runs configured recurring background job schedules. */
49
+ export default class BackgroundJobsScheduler {
50
+ /**
51
+ * @param {object} args - Options.
52
+ * @param {import("../configuration.js").default} args.configuration - Configuration.
53
+ * @param {function({args: any[], jobClass: typeof import("./job.js").default, jobKey: string, options: import("./types.js").BackgroundJobOptions}) : Promise<void>} args.enqueueJob - Enqueue callback.
54
+ */
55
+ constructor({ configuration, enqueueJob }) {
56
+ this.configuration = configuration;
57
+ this.enqueueJob = enqueueJob;
58
+ this.logger = new Logger(this);
59
+ /** @type {Array<ReturnType<typeof setInterval>>} */
60
+ this.intervalIds = [];
61
+ /** @type {Array<ReturnType<typeof setTimeout>>} */
62
+ this.timeoutIds = [];
63
+ }
64
+ /** @returns {Promise<void>} */
65
+ async start() {
66
+ const scheduledBackgroundJobsConfig = await this.configuration.getScheduledBackgroundJobsConfig();
67
+ if (!scheduledBackgroundJobsConfig?.jobs) {
68
+ return;
69
+ }
70
+ for (const jobKey of Object.keys(scheduledBackgroundJobsConfig.jobs)) {
71
+ const jobConfiguration = scheduledBackgroundJobsConfig.jobs[jobKey];
72
+ if (!jobConfiguration || jobConfiguration.enabled === false) {
73
+ continue;
74
+ }
75
+ this.scheduleJob({ jobConfiguration, jobKey });
76
+ }
77
+ }
78
+ /** @returns {void} */
79
+ stop() {
80
+ for (const intervalId of this.intervalIds) {
81
+ clearInterval(intervalId);
82
+ }
83
+ for (const timeoutId of this.timeoutIds) {
84
+ clearTimeout(timeoutId);
85
+ }
86
+ this.intervalIds = [];
87
+ this.timeoutIds = [];
88
+ }
89
+ /**
90
+ * @param {object} args - Options.
91
+ * @param {import("../configuration-types.js").ScheduledBackgroundJobConfiguration} args.jobConfiguration - Job configuration.
92
+ * @param {string} args.jobKey - Job key.
93
+ * @returns {void}
94
+ */
95
+ scheduleJob({ jobConfiguration, jobKey }) {
96
+ const { everyValue, firstInValue } = this.normalizeEvery(jobConfiguration.every);
97
+ const intervalMs = parseScheduledDuration(everyValue, `${jobKey}.every`);
98
+ const firstInMs = firstInValue !== undefined ? parseScheduledDuration(firstInValue, `${jobKey}.first_in`) : intervalMs;
99
+ if (intervalMs < 1) {
100
+ throw new Error(`Scheduled background job ${jobKey}.every must be at least 1 millisecond.`);
101
+ }
102
+ if (!jobConfiguration.class || typeof jobConfiguration.class.performLaterWithOptions !== "function") {
103
+ throw new Error(`Scheduled background job ${jobKey} must define a job class.`);
104
+ }
105
+ const timeoutId = setTimeout(() => {
106
+ void this.enqueueScheduledJob({ jobConfiguration, jobKey });
107
+ const intervalId = setInterval(() => {
108
+ void this.enqueueScheduledJob({ jobConfiguration, jobKey });
109
+ }, intervalMs);
110
+ this.intervalIds.push(intervalId);
111
+ }, firstInMs);
112
+ this.timeoutIds.push(timeoutId);
113
+ }
114
+ /**
115
+ * @param {object} args - Options.
116
+ * @param {import("../configuration-types.js").ScheduledBackgroundJobConfiguration} args.jobConfiguration - Job configuration.
117
+ * @param {string} args.jobKey - Job key.
118
+ * @returns {Promise<void>}
119
+ */
120
+ async enqueueScheduledJob({ jobConfiguration, jobKey }) {
121
+ try {
122
+ await this.enqueueJob({
123
+ args: Array.isArray(jobConfiguration.args) ? jobConfiguration.args : [],
124
+ jobClass: jobConfiguration.class,
125
+ jobKey,
126
+ options: jobConfiguration.options || {}
127
+ });
128
+ }
129
+ catch (error) {
130
+ await this.logger.error(() => ["Failed to enqueue scheduled background job", { jobKey, jobName: jobConfiguration.class.jobName() }, error]);
131
+ }
132
+ }
133
+ /**
134
+ * @param {import("../configuration-types.js").ScheduledBackgroundJobConfiguration["every"]} every - Every config.
135
+ * @returns {{everyValue: number | string, firstInValue?: number | string}} - Normalized interval and first-run delay values.
136
+ */
137
+ normalizeEvery(every) {
138
+ if (Array.isArray(every)) {
139
+ const [everyValue, everyOptions] = every;
140
+ if (!everyOptions || typeof everyOptions !== "object" || Array.isArray(everyOptions)) {
141
+ return { everyValue };
142
+ }
143
+ return { everyValue, firstInValue: everyOptions.firstIn ?? everyOptions.first_in };
144
+ }
145
+ return { everyValue: every };
146
+ }
147
+ }
148
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZWR1bGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JhY2tncm91bmQtam9icy9zY2hlZHVsZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sTUFBTSxNQUFNLGNBQWMsQ0FBQTtBQUVqQyxNQUFNLG9CQUFvQixHQUFHO0lBQzNCLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJO0lBQ3RCLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJO0lBQ3hCLElBQUksRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJO0lBQ3pCLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUk7SUFDakIsSUFBSSxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSTtJQUNwQixLQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJO0lBQ3JCLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSTtJQUNaLE1BQU0sRUFBRSxFQUFFLEdBQUcsSUFBSTtJQUNqQixPQUFPLEVBQUUsRUFBRSxHQUFHLElBQUk7SUFDbEIsRUFBRSxFQUFFLENBQUM7SUFDTCxDQUFDLEVBQUUsSUFBSTtJQUNQLE1BQU0sRUFBRSxJQUFJO0lBQ1osT0FBTyxFQUFFLElBQUk7SUFDYixDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUk7SUFDMUIsSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJO0lBQzdCLEtBQUssRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSTtDQUMvQixDQUFBO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsU0FBUztJQUNyRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN6QyxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixTQUFTLDZDQUE2QyxDQUFDLENBQUE7UUFDckcsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFBO0lBQ2QsQ0FBQztJQUVELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsU0FBUyx3Q0FBd0MsQ0FBQyxDQUFBO0lBQ2hHLENBQUM7SUFFRCxNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUE7SUFDbEQsTUFBTSxLQUFLLEdBQUcsZUFBZSxDQUFDLEtBQUssQ0FBQyxpR0FBaUcsQ0FBQyxDQUFBO0lBRXRJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLFNBQVMsS0FBSyxLQUFLLEVBQUUsQ0FBQyxDQUFBO0lBQzVFLENBQUM7SUFFRCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDckMsTUFBTSxVQUFVLEdBQUcsb0JBQW9CLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFFakQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLFNBQVMsS0FBSyxLQUFLLEVBQUUsQ0FBQyxDQUFBO0lBQzVFLENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQyxDQUFBO0FBQzlDLENBQUM7QUFFRCwwREFBMEQ7QUFDMUQsTUFBTSxDQUFDLE9BQU8sT0FBTyx1QkFBdUI7SUFDMUM7Ozs7T0FJRztJQUNILFlBQVksRUFBQyxhQUFhLEVBQUUsVUFBVSxFQUFDO1FBQ3JDLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1FBQ2xDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDOUIsb0RBQW9EO1FBQ3BELElBQUksQ0FBQyxXQUFXLEdBQUcsRUFBRSxDQUFBO1FBQ3JCLG1EQUFtRDtRQUNuRCxJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQTtJQUN0QixDQUFDO0lBRUQsK0JBQStCO0lBQy9CLEtBQUssQ0FBQyxLQUFLO1FBQ1QsTUFBTSw2QkFBNkIsR0FBRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQTtRQUVqRyxJQUFJLENBQUMsNkJBQTZCLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDekMsT0FBTTtRQUNSLENBQUM7UUFFRCxLQUFLLE1BQU0sTUFBTSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsNkJBQTZCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNyRSxNQUFNLGdCQUFnQixHQUFHLDZCQUE2QixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUVuRSxJQUFJLENBQUMsZ0JBQWdCLElBQUksZ0JBQWdCLENBQUMsT0FBTyxLQUFLLEtBQUssRUFBRSxDQUFDO2dCQUM1RCxTQUFRO1lBQ1YsQ0FBQztZQUVELElBQUksQ0FBQyxXQUFXLENBQUMsRUFBQyxnQkFBZ0IsRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFBO1FBQzlDLENBQUM7SUFDSCxDQUFDO0lBRUQsc0JBQXNCO0lBQ3RCLElBQUk7UUFDRixLQUFLLE1BQU0sVUFBVSxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUMxQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDM0IsQ0FBQztRQUVELEtBQUssTUFBTSxTQUFTLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3hDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUN6QixDQUFDO1FBRUQsSUFBSSxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUE7UUFDckIsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUE7SUFDdEIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsV0FBVyxDQUFDLEVBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFDO1FBQ3BDLE1BQU0sRUFBQyxVQUFVLEVBQUUsWUFBWSxFQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUM5RSxNQUFNLFVBQVUsR0FBRyxzQkFBc0IsQ0FBQyxVQUFVLEVBQUUsR0FBRyxNQUFNLFFBQVEsQ0FBQyxDQUFBO1FBQ3hFLE1BQU0sU0FBUyxHQUFHLFlBQVksS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLHNCQUFzQixDQUFDLFlBQVksRUFBRSxHQUFHLE1BQU0sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQTtRQUV0SCxJQUFJLFVBQVUsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixNQUFNLHdDQUF3QyxDQUFDLENBQUE7UUFDN0YsQ0FBQztRQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLElBQUksT0FBTyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDcEcsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsTUFBTSwyQkFBMkIsQ0FBQyxDQUFBO1FBQ2hGLENBQUM7UUFFRCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2hDLEtBQUssSUFBSSxDQUFDLG1CQUFtQixDQUFDLEVBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFDLENBQUMsQ0FBQTtZQUV6RCxNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO2dCQUNsQyxLQUFLLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxFQUFDLGdCQUFnQixFQUFFLE1BQU0sRUFBQyxDQUFDLENBQUE7WUFDM0QsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1lBRWQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDbkMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFBO1FBRWIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUE7SUFDakMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLG1CQUFtQixDQUFDLEVBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFDO1FBQ2xELElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDdkUsUUFBUSxFQUFFLGdCQUFnQixDQUFDLEtBQUs7Z0JBQ2hDLE1BQU07Z0JBQ04sT0FBTyxFQUFFLGdCQUFnQixDQUFDLE9BQU8sSUFBSSxFQUFFO2FBQ3hDLENBQUMsQ0FBQTtRQUNKLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLDRDQUE0QyxFQUFFLEVBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO1FBQzNJLENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLEtBQUs7UUFDbEIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDekIsTUFBTSxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsR0FBRyxLQUFLLENBQUE7WUFFeEMsSUFBSSxDQUFDLFlBQVksSUFBSSxPQUFPLFlBQVksS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO2dCQUNyRixPQUFPLEVBQUMsVUFBVSxFQUFDLENBQUE7WUFDckIsQ0FBQztZQUVELE9BQU8sRUFBQyxVQUFVLEVBQUUsWUFBWSxFQUFFLFlBQVksQ0FBQyxPQUFPLElBQUksWUFBWSxDQUFDLFFBQVEsRUFBQyxDQUFBO1FBQ2xGLENBQUM7UUFFRCxPQUFPLEVBQUMsVUFBVSxFQUFFLEtBQUssRUFBQyxDQUFBO0lBQzVCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuXG5jb25zdCBEVVJBVElPTl9NVUxUSVBMSUVSUyA9IHtcbiAgZDogMjQgKiA2MCAqIDYwICogMTAwMCxcbiAgZGF5OiAyNCAqIDYwICogNjAgKiAxMDAwLFxuICBkYXlzOiAyNCAqIDYwICogNjAgKiAxMDAwLFxuICBoOiA2MCAqIDYwICogMTAwMCxcbiAgaG91cjogNjAgKiA2MCAqIDEwMDAsXG4gIGhvdXJzOiA2MCAqIDYwICogMTAwMCxcbiAgbTogNjAgKiAxMDAwLFxuICBtaW51dGU6IDYwICogMTAwMCxcbiAgbWludXRlczogNjAgKiAxMDAwLFxuICBtczogMSxcbiAgczogMTAwMCxcbiAgc2Vjb25kOiAxMDAwLFxuICBzZWNvbmRzOiAxMDAwLFxuICB3OiA3ICogMjQgKiA2MCAqIDYwICogMTAwMCxcbiAgd2VlazogNyAqIDI0ICogNjAgKiA2MCAqIDEwMDAsXG4gIHdlZWtzOiA3ICogMjQgKiA2MCAqIDYwICogMTAwMFxufVxuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyIHwgc3RyaW5nfSB2YWx1ZSAtIER1cmF0aW9uIHZhbHVlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpZWxkTmFtZSAtIEZpZWxkIG5hbWUgZm9yIGVycm9ycy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IC0gRHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTY2hlZHVsZWREdXJhdGlvbih2YWx1ZSwgZmllbGROYW1lKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIpIHtcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZSh2YWx1ZSkgfHwgdmFsdWUgPCAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFNjaGVkdWxlZCBiYWNrZ3JvdW5kIGpvYiAke2ZpZWxkTmFtZX0gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlciBvZiBtaWxsaXNlY29uZHMuYClcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIgfHwgIXZhbHVlLnRyaW0oKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgU2NoZWR1bGVkIGJhY2tncm91bmQgam9iICR7ZmllbGROYW1lfSBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZyBvciBudW1iZXIuYClcbiAgfVxuXG4gIGNvbnN0IG5vcm1hbGl6ZWRWYWx1ZSA9IHZhbHVlLnRyaW0oKS50b0xvd2VyQ2FzZSgpXG4gIGNvbnN0IG1hdGNoID0gbm9ybWFsaXplZFZhbHVlLm1hdGNoKC9eKFxcZCsoPzpcXC5cXGQrKT8pXFxzKihtc3xzfG18aHxkfHd8c2Vjb25kfHNlY29uZHN8bWludXRlfG1pbnV0ZXN8aG91cnxob3Vyc3xkYXl8ZGF5c3x3ZWVrfHdlZWtzKSQvKVxuXG4gIGlmICghbWF0Y2gpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgc2NoZWR1bGVkIGJhY2tncm91bmQgam9iICR7ZmllbGROYW1lfTogJHt2YWx1ZX1gKVxuICB9XG5cbiAgY29uc3QgbnVtZXJpY1ZhbHVlID0gTnVtYmVyKG1hdGNoWzFdKVxuICBjb25zdCBtdWx0aXBsaWVyID0gRFVSQVRJT05fTVVMVElQTElFUlNbbWF0Y2hbMl1dXG5cbiAgaWYgKCFtdWx0aXBsaWVyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHNjaGVkdWxlZCBiYWNrZ3JvdW5kIGpvYiAke2ZpZWxkTmFtZX06ICR7dmFsdWV9YClcbiAgfVxuXG4gIHJldHVybiBNYXRoLnJvdW5kKG51bWVyaWNWYWx1ZSAqIG11bHRpcGxpZXIpXG59XG5cbi8qKiBSdW5zIGNvbmZpZ3VyZWQgcmVjdXJyaW5nIGJhY2tncm91bmQgam9iIHNjaGVkdWxlcy4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhY2tncm91bmRKb2JzU2NoZWR1bGVyIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oe2FyZ3M6IGFueVtdLCBqb2JDbGFzczogdHlwZW9mIGltcG9ydChcIi4vam9iLmpzXCIpLmRlZmF1bHQsIGpvYktleTogc3RyaW5nLCBvcHRpb25zOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JPcHRpb25zfSkgOiBQcm9taXNlPHZvaWQ+fSBhcmdzLmVucXVldWVKb2IgLSBFbnF1ZXVlIGNhbGxiYWNrLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb24sIGVucXVldWVKb2J9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIHRoaXMuZW5xdWV1ZUpvYiA9IGVucXVldWVKb2JcbiAgICB0aGlzLmxvZ2dlciA9IG5ldyBMb2dnZXIodGhpcylcbiAgICAvKiogQHR5cGUge0FycmF5PFJldHVyblR5cGU8dHlwZW9mIHNldEludGVydmFsPj59ICovXG4gICAgdGhpcy5pbnRlcnZhbElkcyA9IFtdXG4gICAgLyoqIEB0eXBlIHtBcnJheTxSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0Pj59ICovXG4gICAgdGhpcy50aW1lb3V0SWRzID0gW11cbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gKi9cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgY29uc3Qgc2NoZWR1bGVkQmFja2dyb3VuZEpvYnNDb25maWcgPSBhd2FpdCB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0U2NoZWR1bGVkQmFja2dyb3VuZEpvYnNDb25maWcoKVxuXG4gICAgaWYgKCFzY2hlZHVsZWRCYWNrZ3JvdW5kSm9ic0NvbmZpZz8uam9icykge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBqb2JLZXkgb2YgT2JqZWN0LmtleXMoc2NoZWR1bGVkQmFja2dyb3VuZEpvYnNDb25maWcuam9icykpIHtcbiAgICAgIGNvbnN0IGpvYkNvbmZpZ3VyYXRpb24gPSBzY2hlZHVsZWRCYWNrZ3JvdW5kSm9ic0NvbmZpZy5qb2JzW2pvYktleV1cblxuICAgICAgaWYgKCFqb2JDb25maWd1cmF0aW9uIHx8IGpvYkNvbmZpZ3VyYXRpb24uZW5hYmxlZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgdGhpcy5zY2hlZHVsZUpvYih7am9iQ29uZmlndXJhdGlvbiwgam9iS2V5fSlcbiAgICB9XG4gIH1cblxuICAvKiogQHJldHVybnMge3ZvaWR9ICovXG4gIHN0b3AoKSB7XG4gICAgZm9yIChjb25zdCBpbnRlcnZhbElkIG9mIHRoaXMuaW50ZXJ2YWxJZHMpIHtcbiAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWxJZClcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHRpbWVvdXRJZCBvZiB0aGlzLnRpbWVvdXRJZHMpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpXG4gICAgfVxuXG4gICAgdGhpcy5pbnRlcnZhbElkcyA9IFtdXG4gICAgdGhpcy50aW1lb3V0SWRzID0gW11cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5TY2hlZHVsZWRCYWNrZ3JvdW5kSm9iQ29uZmlndXJhdGlvbn0gYXJncy5qb2JDb25maWd1cmF0aW9uIC0gSm9iIGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmpvYktleSAtIEpvYiBrZXkuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2NoZWR1bGVKb2Ioe2pvYkNvbmZpZ3VyYXRpb24sIGpvYktleX0pIHtcbiAgICBjb25zdCB7ZXZlcnlWYWx1ZSwgZmlyc3RJblZhbHVlfSA9IHRoaXMubm9ybWFsaXplRXZlcnkoam9iQ29uZmlndXJhdGlvbi5ldmVyeSlcbiAgICBjb25zdCBpbnRlcnZhbE1zID0gcGFyc2VTY2hlZHVsZWREdXJhdGlvbihldmVyeVZhbHVlLCBgJHtqb2JLZXl9LmV2ZXJ5YClcbiAgICBjb25zdCBmaXJzdEluTXMgPSBmaXJzdEluVmFsdWUgIT09IHVuZGVmaW5lZCA/IHBhcnNlU2NoZWR1bGVkRHVyYXRpb24oZmlyc3RJblZhbHVlLCBgJHtqb2JLZXl9LmZpcnN0X2luYCkgOiBpbnRlcnZhbE1zXG5cbiAgICBpZiAoaW50ZXJ2YWxNcyA8IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU2NoZWR1bGVkIGJhY2tncm91bmQgam9iICR7am9iS2V5fS5ldmVyeSBtdXN0IGJlIGF0IGxlYXN0IDEgbWlsbGlzZWNvbmQuYClcbiAgICB9XG5cbiAgICBpZiAoIWpvYkNvbmZpZ3VyYXRpb24uY2xhc3MgfHwgdHlwZW9mIGpvYkNvbmZpZ3VyYXRpb24uY2xhc3MucGVyZm9ybUxhdGVyV2l0aE9wdGlvbnMgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTY2hlZHVsZWQgYmFja2dyb3VuZCBqb2IgJHtqb2JLZXl9IG11c3QgZGVmaW5lIGEgam9iIGNsYXNzLmApXG4gICAgfVxuXG4gICAgY29uc3QgdGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB2b2lkIHRoaXMuZW5xdWV1ZVNjaGVkdWxlZEpvYih7am9iQ29uZmlndXJhdGlvbiwgam9iS2V5fSlcblxuICAgICAgY29uc3QgaW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgdm9pZCB0aGlzLmVucXVldWVTY2hlZHVsZWRKb2Ioe2pvYkNvbmZpZ3VyYXRpb24sIGpvYktleX0pXG4gICAgICB9LCBpbnRlcnZhbE1zKVxuXG4gICAgICB0aGlzLmludGVydmFsSWRzLnB1c2goaW50ZXJ2YWxJZClcbiAgICB9LCBmaXJzdEluTXMpXG5cbiAgICB0aGlzLnRpbWVvdXRJZHMucHVzaCh0aW1lb3V0SWQpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuU2NoZWR1bGVkQmFja2dyb3VuZEpvYkNvbmZpZ3VyYXRpb259IGFyZ3Muam9iQ29uZmlndXJhdGlvbiAtIEpvYiBjb25maWd1cmF0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5qb2JLZXkgLSBKb2Iga2V5LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGVucXVldWVTY2hlZHVsZWRKb2Ioe2pvYkNvbmZpZ3VyYXRpb24sIGpvYktleX0pIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5lbnF1ZXVlSm9iKHtcbiAgICAgICAgYXJnczogQXJyYXkuaXNBcnJheShqb2JDb25maWd1cmF0aW9uLmFyZ3MpID8gam9iQ29uZmlndXJhdGlvbi5hcmdzIDogW10sXG4gICAgICAgIGpvYkNsYXNzOiBqb2JDb25maWd1cmF0aW9uLmNsYXNzLFxuICAgICAgICBqb2JLZXksXG4gICAgICAgIG9wdGlvbnM6IGpvYkNvbmZpZ3VyYXRpb24ub3B0aW9ucyB8fCB7fVxuICAgICAgfSlcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdGhpcy5sb2dnZXIuZXJyb3IoKCkgPT4gW1wiRmFpbGVkIHRvIGVucXVldWUgc2NoZWR1bGVkIGJhY2tncm91bmQgam9iXCIsIHtqb2JLZXksIGpvYk5hbWU6IGpvYkNvbmZpZ3VyYXRpb24uY2xhc3Muam9iTmFtZSgpfSwgZXJyb3JdKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuU2NoZWR1bGVkQmFja2dyb3VuZEpvYkNvbmZpZ3VyYXRpb25bXCJldmVyeVwiXX0gZXZlcnkgLSBFdmVyeSBjb25maWcuXG4gICAqIEByZXR1cm5zIHt7ZXZlcnlWYWx1ZTogbnVtYmVyIHwgc3RyaW5nLCBmaXJzdEluVmFsdWU/OiBudW1iZXIgfCBzdHJpbmd9fSAtIE5vcm1hbGl6ZWQgaW50ZXJ2YWwgYW5kIGZpcnN0LXJ1biBkZWxheSB2YWx1ZXMuXG4gICAqL1xuICBub3JtYWxpemVFdmVyeShldmVyeSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGV2ZXJ5KSkge1xuICAgICAgY29uc3QgW2V2ZXJ5VmFsdWUsIGV2ZXJ5T3B0aW9uc10gPSBldmVyeVxuXG4gICAgICBpZiAoIWV2ZXJ5T3B0aW9ucyB8fCB0eXBlb2YgZXZlcnlPcHRpb25zICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkoZXZlcnlPcHRpb25zKSkge1xuICAgICAgICByZXR1cm4ge2V2ZXJ5VmFsdWV9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7ZXZlcnlWYWx1ZSwgZmlyc3RJblZhbHVlOiBldmVyeU9wdGlvbnMuZmlyc3RJbiA/PyBldmVyeU9wdGlvbnMuZmlyc3RfaW59XG4gICAgfVxuXG4gICAgcmV0dXJuIHtldmVyeVZhbHVlOiBldmVyeX1cbiAgfVxufVxuIl19