velocious 1.0.177 → 1.0.179

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 (89) hide show
  1. package/README.md +125 -0
  2. package/build/src/background-jobs/client.d.ts +23 -0
  3. package/build/src/background-jobs/client.d.ts.map +1 -0
  4. package/build/src/background-jobs/client.js +58 -0
  5. package/build/src/background-jobs/job-record.d.ts +4 -0
  6. package/build/src/background-jobs/job-record.d.ts.map +1 -0
  7. package/build/src/background-jobs/job-record.js +11 -0
  8. package/build/src/background-jobs/job-registry.d.ts +23 -0
  9. package/build/src/background-jobs/job-registry.d.ts.map +1 -0
  10. package/build/src/background-jobs/job-registry.js +55 -0
  11. package/build/src/background-jobs/job-runner.d.ts +6 -0
  12. package/build/src/background-jobs/job-runner.d.ts.map +1 -0
  13. package/build/src/background-jobs/job-runner.js +44 -0
  14. package/build/src/background-jobs/job.d.ts +35 -0
  15. package/build/src/background-jobs/job.d.ts.map +1 -0
  16. package/build/src/background-jobs/job.js +61 -0
  17. package/build/src/background-jobs/json-socket.d.ts +27 -0
  18. package/build/src/background-jobs/json-socket.d.ts.map +1 -0
  19. package/build/src/background-jobs/json-socket.js +55 -0
  20. package/build/src/background-jobs/main.d.ts +62 -0
  21. package/build/src/background-jobs/main.d.ts.map +1 -0
  22. package/build/src/background-jobs/main.js +216 -0
  23. package/build/src/background-jobs/status-reporter.d.ts +54 -0
  24. package/build/src/background-jobs/status-reporter.d.ts.map +1 -0
  25. package/build/src/background-jobs/status-reporter.js +113 -0
  26. package/build/src/background-jobs/store.d.ts +237 -0
  27. package/build/src/background-jobs/store.d.ts.map +1 -0
  28. package/build/src/background-jobs/store.js +488 -0
  29. package/build/src/background-jobs/types.d.ts +17 -0
  30. package/build/src/background-jobs/types.d.ts.map +1 -0
  31. package/build/src/background-jobs/types.js +8 -0
  32. package/build/src/background-jobs/worker.d.ts +64 -0
  33. package/build/src/background-jobs/worker.d.ts.map +1 -0
  34. package/build/src/background-jobs/worker.js +155 -0
  35. package/build/src/cli/commands/background-jobs-main.d.ts +5 -0
  36. package/build/src/cli/commands/background-jobs-main.d.ts.map +1 -0
  37. package/build/src/cli/commands/background-jobs-main.js +7 -0
  38. package/build/src/cli/commands/background-jobs-runner.d.ts +5 -0
  39. package/build/src/cli/commands/background-jobs-runner.d.ts.map +1 -0
  40. package/build/src/cli/commands/background-jobs-runner.js +7 -0
  41. package/build/src/cli/commands/background-jobs-worker.d.ts +5 -0
  42. package/build/src/cli/commands/background-jobs-worker.d.ts.map +1 -0
  43. package/build/src/cli/commands/background-jobs-worker.js +7 -0
  44. package/build/src/configuration-types.d.ts +25 -0
  45. package/build/src/configuration-types.d.ts.map +1 -1
  46. package/build/src/configuration-types.js +8 -1
  47. package/build/src/configuration.d.ts +11 -1
  48. package/build/src/configuration.d.ts.map +1 -1
  49. package/build/src/configuration.js +26 -2
  50. package/build/src/database/drivers/mssql/sql/update.js +3 -3
  51. package/build/src/database/drivers/mysql/sql/update.js +3 -3
  52. package/build/src/database/drivers/pgsql/sql/update.js +3 -3
  53. package/build/src/database/drivers/sqlite/sql/update.js +3 -3
  54. package/build/src/database/query/update-base.d.ts +5 -0
  55. package/build/src/database/query/update-base.d.ts.map +1 -1
  56. package/build/src/database/query/update-base.js +10 -1
  57. package/build/src/database/query-parser/limit-parser.d.ts.map +1 -1
  58. package/build/src/database/query-parser/limit-parser.js +8 -7
  59. package/build/src/environment-handlers/base.d.ts +15 -0
  60. package/build/src/environment-handlers/base.d.ts.map +1 -1
  61. package/build/src/environment-handlers/base.js +22 -1
  62. package/build/src/environment-handlers/browser.d.ts.map +1 -1
  63. package/build/src/environment-handlers/browser.js +10 -1
  64. package/build/src/environment-handlers/node/cli/commands/background-jobs-main.d.ts +5 -0
  65. package/build/src/environment-handlers/node/cli/commands/background-jobs-main.d.ts.map +1 -0
  66. package/build/src/environment-handlers/node/cli/commands/background-jobs-main.js +18 -0
  67. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.d.ts +5 -0
  68. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.d.ts.map +1 -0
  69. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.js +13 -0
  70. package/build/src/environment-handlers/node/cli/commands/background-jobs-worker.d.ts +5 -0
  71. package/build/src/environment-handlers/node/cli/commands/background-jobs-worker.d.ts.map +1 -0
  72. package/build/src/environment-handlers/node/cli/commands/background-jobs-worker.js +18 -0
  73. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
  74. package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +6 -4
  75. package/build/src/environment-handlers/node/cli/commands/test.d.ts.map +1 -1
  76. package/build/src/environment-handlers/node/cli/commands/test.js +2 -116
  77. package/build/src/environment-handlers/node.d.ts.map +1 -1
  78. package/build/src/environment-handlers/node.js +25 -1
  79. package/build/src/testing/browser-test-app.d.ts +2 -0
  80. package/build/src/testing/browser-test-app.d.ts.map +1 -0
  81. package/build/src/testing/browser-test-app.js +24 -0
  82. package/build/src/testing/test-filter-parser.d.ts +16 -0
  83. package/build/src/testing/test-filter-parser.d.ts.map +1 -0
  84. package/build/src/testing/test-filter-parser.js +117 -0
  85. package/build/src/testing/test-runner.d.ts +35 -0
  86. package/build/src/testing/test-runner.d.ts.map +1 -1
  87. package/build/src/testing/test-runner.js +100 -17
  88. package/build/tsconfig.tsbuildinfo +1 -1
  89. package/package.json +4 -1
package/README.md CHANGED
@@ -64,6 +64,16 @@ describe("Tasks", () => {
64
64
  })
65
65
  ```
66
66
 
67
+ ## Browser system tests
68
+
69
+ Run browser compatibility tests via System Testing:
70
+
71
+ ```bash
72
+ npm run test:browser
73
+ ```
74
+
75
+ Browser system tests must be named `*.browser-test.js` or `*.browser-spec.js` (override with `VELOCIOUS_BROWSER_TEST_PATTERN`).
76
+
67
77
  Use beforeAll/afterAll for suite-level setup/teardown.
68
78
 
69
79
  ```js
@@ -266,6 +276,32 @@ export default class CreateEvents extends Migration {
266
276
  npx velocious db:migrate
267
277
  ```
268
278
 
279
+ ## Configure CLI commands (Node vs Browser)
280
+
281
+ Node loads CLI commands from disk automatically via the Node environment handler:
282
+
283
+ ```js
284
+ import Configuration from "velocious/build/src/configuration.js"
285
+ import NodeEnvironmentHandler from "velocious/build/src/environment-handlers/node.js"
286
+
287
+ export default new Configuration({
288
+ // ...
289
+ environmentHandler: new NodeEnvironmentHandler()
290
+ })
291
+ ```
292
+
293
+ Browser builds can still register commands, but only the browser-safe wrappers are bundled:
294
+
295
+ ```js
296
+ import Configuration from "velocious/build/src/configuration.js"
297
+ import BrowserEnvironmentHandler from "velocious/build/src/environment-handlers/browser.js"
298
+
299
+ export default new Configuration({
300
+ // ...
301
+ environmentHandler: new BrowserEnvironmentHandler()
302
+ })
303
+ ```
304
+
269
305
  ## Run migrations from anywhere if you want to:
270
306
 
271
307
  ```js
@@ -720,6 +756,95 @@ Create the file `src/routes/testing/another-action.ejs` and so something like th
720
756
  </p>
721
757
  ```
722
758
 
759
+ # Background jobs
760
+
761
+ Velocious includes a simple background jobs system inspired by Sidekiq.
762
+
763
+ ## Setup
764
+
765
+ Create a jobs directory in your app:
766
+
767
+ ```
768
+ src/jobs/
769
+ ```
770
+
771
+ Start the background jobs main process (the queue router):
772
+
773
+ ```bash
774
+ npx velocious background-jobs-main
775
+ ```
776
+
777
+ Start one or more workers:
778
+
779
+ ```bash
780
+ npx velocious background-jobs-worker
781
+ ```
782
+
783
+ ## Configuration
784
+
785
+ You can configure the main host/port in your configuration:
786
+
787
+ ```js
788
+ export default new Configuration({
789
+ // ...
790
+ backgroundJobs: {
791
+ host: "127.0.0.1",
792
+ port: 7331,
793
+ databaseIdentifier: "default"
794
+ }
795
+ })
796
+ ```
797
+
798
+ Or via env vars:
799
+
800
+ ```
801
+ VELOCIOUS_BACKGROUND_JOBS_HOST=127.0.0.1
802
+ VELOCIOUS_BACKGROUND_JOBS_PORT=7331
803
+ VELOCIOUS_BACKGROUND_JOBS_DATABASE_IDENTIFIER=default
804
+ ```
805
+
806
+ ## Defining jobs
807
+
808
+ ```js
809
+ import VelociousJob from "velocious/build/src/background-jobs/job.js"
810
+
811
+ export default class MyJob extends VelociousJob {
812
+ async perform(arg1, arg2) {
813
+ await doWork(arg1, arg2)
814
+ }
815
+ }
816
+ ```
817
+
818
+ Queue a job:
819
+
820
+ ```js
821
+ await MyJob.performLater("a", "b")
822
+ ```
823
+
824
+ Jobs are forked by default (detached from the worker). To run inline:
825
+
826
+ ```js
827
+ await MyJob.performLaterWithOptions({
828
+ args: ["a", "b"],
829
+ options: {forked: false}
830
+ })
831
+ ```
832
+
833
+ ## Persistence and retries
834
+
835
+ 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.
836
+
837
+ Failed jobs are re-queued with backoff and retried up to 10 times by default (10s, 1m, 10m, 1h, then +1h per retry). You can override the retry limit per job:
838
+
839
+ ```js
840
+ await MyJob.performLaterWithOptions({
841
+ args: ["a", "b"],
842
+ options: {maxRetries: 3}
843
+ })
844
+ ```
845
+
846
+ If a handed-off job does not report back within 2 hours, it is marked orphaned and re-queued if retries remain.
847
+
723
848
  # Running a server
724
849
 
725
850
  ```bash
@@ -0,0 +1,23 @@
1
+ export default class BackgroundJobsClient {
2
+ /**
3
+ * @param {object} [args] - Options.
4
+ * @param {import("../configuration.js").default} [args.configuration] - Configuration.
5
+ */
6
+ constructor({ configuration }?: {
7
+ configuration?: import("../configuration.js").default;
8
+ });
9
+ configurationPromise: Promise<import("../configuration.js").default>;
10
+ /**
11
+ * @param {object} args - Options.
12
+ * @param {string} args.jobName - Job name.
13
+ * @param {any[]} args.args - Job args.
14
+ * @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
15
+ * @returns {Promise<string>} - Job id.
16
+ */
17
+ enqueue({ jobName, args, options }: {
18
+ jobName: string;
19
+ args: any[];
20
+ options?: import("./types.js").BackgroundJobOptions;
21
+ }): Promise<string>;
22
+ }
23
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/client.js"],"names":[],"mappings":"AAMA;IACE;;;OAGG;IACH,gCAFG;QAAqD,aAAa,GAA1D,OAAO,qBAAqB,EAAE,OAAO;KAC/C,EAGA;IADC,qEAAoG;IAGtG;;;;;;OAMG;IACH,oCALG;QAAqB,OAAO,EAApB,MAAM;QACM,IAAI,EAAhB,GAAG,EAAE;QAC4C,OAAO,GAAxD,OAAO,YAAY,EAAE,oBAAoB;KACjD,GAAU,OAAO,CAAC,MAAM,CAAC,CA2C3B;CACF"}
@@ -0,0 +1,58 @@
1
+ // @ts-check
2
+ import net from "net";
3
+ import configurationResolver from "../configuration-resolver.js";
4
+ import JsonSocket from "./json-socket.js";
5
+ export default class BackgroundJobsClient {
6
+ /**
7
+ * @param {object} [args] - Options.
8
+ * @param {import("../configuration.js").default} [args.configuration] - Configuration.
9
+ */
10
+ constructor({ configuration } = {}) {
11
+ this.configurationPromise = configuration ? Promise.resolve(configuration) : configurationResolver();
12
+ }
13
+ /**
14
+ * @param {object} args - Options.
15
+ * @param {string} args.jobName - Job name.
16
+ * @param {any[]} args.args - Job args.
17
+ * @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
18
+ * @returns {Promise<string>} - Job id.
19
+ */
20
+ async enqueue({ jobName, args, options }) {
21
+ const configuration = await this.configurationPromise;
22
+ const { host, port } = configuration.getBackgroundJobsConfig();
23
+ const socket = net.createConnection({ host, port });
24
+ const jsonSocket = new JsonSocket(socket);
25
+ return await new Promise((resolve, reject) => {
26
+ const cleanup = () => {
27
+ jsonSocket.removeAllListeners();
28
+ };
29
+ jsonSocket.on("error", (error) => {
30
+ cleanup();
31
+ reject(error);
32
+ });
33
+ jsonSocket.on("message", (message) => {
34
+ if (message?.type === "enqueued") {
35
+ cleanup();
36
+ jsonSocket.close();
37
+ resolve(message.jobId);
38
+ return;
39
+ }
40
+ if (message?.type === "enqueue-error") {
41
+ cleanup();
42
+ jsonSocket.close();
43
+ reject(new Error(message.error || "Failed to enqueue job"));
44
+ }
45
+ });
46
+ socket.on("connect", () => {
47
+ jsonSocket.send({ type: "hello", role: "client" });
48
+ jsonSocket.send({
49
+ type: "enqueue",
50
+ jobName,
51
+ args,
52
+ options
53
+ });
54
+ });
55
+ });
56
+ }
57
+ }
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JhY2tncm91bmQtam9icy9jbGllbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sR0FBRyxNQUFNLEtBQUssQ0FBQTtBQUNyQixPQUFPLHFCQUFxQixNQUFNLDhCQUE4QixDQUFBO0FBQ2hFLE9BQU8sVUFBVSxNQUFNLGtCQUFrQixDQUFBO0FBRXpDLE1BQU0sQ0FBQyxPQUFPLE9BQU8sb0JBQW9CO0lBQ3ZDOzs7T0FHRztJQUNILFlBQVksRUFBQyxhQUFhLEVBQUMsR0FBRyxFQUFFO1FBQzlCLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixFQUFFLENBQUE7SUFDdEcsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBQztRQUNwQyxNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQTtRQUNyRCxNQUFNLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBQyxHQUFHLGFBQWEsQ0FBQyx1QkFBdUIsRUFBRSxDQUFBO1FBQzVELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFBO1FBQ2pELE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBRXpDLE9BQU8sTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUMzQyxNQUFNLE9BQU8sR0FBRyxHQUFHLEVBQUU7Z0JBQ25CLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRSxDQUFBO1lBQ2pDLENBQUMsQ0FBQTtZQUVELFVBQVUsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JBQy9CLE9BQU8sRUFBRSxDQUFBO2dCQUNULE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNmLENBQUMsQ0FBQyxDQUFBO1lBRUYsVUFBVSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQkFDbkMsSUFBSSxPQUFPLEVBQUUsSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO29CQUNqQyxPQUFPLEVBQUUsQ0FBQTtvQkFDVCxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUE7b0JBQ2xCLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7b0JBQ3RCLE9BQU07Z0JBQ1IsQ0FBQztnQkFFRCxJQUFJLE9BQU8sRUFBRSxJQUFJLEtBQUssZUFBZSxFQUFFLENBQUM7b0JBQ3RDLE9BQU8sRUFBRSxDQUFBO29CQUNULFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtvQkFDbEIsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksdUJBQXVCLENBQUMsQ0FBQyxDQUFBO2dCQUM3RCxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUE7WUFFRixNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUU7Z0JBQ3hCLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUMsQ0FBQyxDQUFBO2dCQUNoRCxVQUFVLENBQUMsSUFBSSxDQUFDO29CQUNkLElBQUksRUFBRSxTQUFTO29CQUNmLE9BQU87b0JBQ1AsSUFBSTtvQkFDSixPQUFPO2lCQUNSLENBQUMsQ0FBQTtZQUNKLENBQUMsQ0FBQyxDQUFBO1FBQ0osQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IG5ldCBmcm9tIFwibmV0XCJcbmltcG9ydCBjb25maWd1cmF0aW9uUmVzb2x2ZXIgZnJvbSBcIi4uL2NvbmZpZ3VyYXRpb24tcmVzb2x2ZXIuanNcIlxuaW1wb3J0IEpzb25Tb2NrZXQgZnJvbSBcIi4vanNvbi1zb2NrZXQuanNcIlxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYWNrZ3JvdW5kSm9ic0NsaWVudCB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gW2FyZ3NdIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IFthcmdzLmNvbmZpZ3VyYXRpb25dIC0gQ29uZmlndXJhdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb25maWd1cmF0aW9ufSA9IHt9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uUHJvbWlzZSA9IGNvbmZpZ3VyYXRpb24gPyBQcm9taXNlLnJlc29sdmUoY29uZmlndXJhdGlvbikgOiBjb25maWd1cmF0aW9uUmVzb2x2ZXIoKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Muam9iTmFtZSAtIEpvYiBuYW1lLlxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzLmFyZ3MgLSBKb2IgYXJncy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JPcHRpb25zfSBbYXJncy5vcHRpb25zXSAtIEpvYiBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIEpvYiBpZC5cbiAgICovXG4gIGFzeW5jIGVucXVldWUoe2pvYk5hbWUsIGFyZ3MsIG9wdGlvbnN9KSB7XG4gICAgY29uc3QgY29uZmlndXJhdGlvbiA9IGF3YWl0IHRoaXMuY29uZmlndXJhdGlvblByb21pc2VcbiAgICBjb25zdCB7aG9zdCwgcG9ydH0gPSBjb25maWd1cmF0aW9uLmdldEJhY2tncm91bmRKb2JzQ29uZmlnKClcbiAgICBjb25zdCBzb2NrZXQgPSBuZXQuY3JlYXRlQ29ubmVjdGlvbih7aG9zdCwgcG9ydH0pXG4gICAgY29uc3QganNvblNvY2tldCA9IG5ldyBKc29uU29ja2V0KHNvY2tldClcblxuICAgIHJldHVybiBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBjbGVhbnVwID0gKCkgPT4ge1xuICAgICAgICBqc29uU29ja2V0LnJlbW92ZUFsbExpc3RlbmVycygpXG4gICAgICB9XG5cbiAgICAgIGpzb25Tb2NrZXQub24oXCJlcnJvclwiLCAoZXJyb3IpID0+IHtcbiAgICAgICAgY2xlYW51cCgpXG4gICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgIH0pXG5cbiAgICAgIGpzb25Tb2NrZXQub24oXCJtZXNzYWdlXCIsIChtZXNzYWdlKSA9PiB7XG4gICAgICAgIGlmIChtZXNzYWdlPy50eXBlID09PSBcImVucXVldWVkXCIpIHtcbiAgICAgICAgICBjbGVhbnVwKClcbiAgICAgICAgICBqc29uU29ja2V0LmNsb3NlKClcbiAgICAgICAgICByZXNvbHZlKG1lc3NhZ2Uuam9iSWQpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWVzc2FnZT8udHlwZSA9PT0gXCJlbnF1ZXVlLWVycm9yXCIpIHtcbiAgICAgICAgICBjbGVhbnVwKClcbiAgICAgICAgICBqc29uU29ja2V0LmNsb3NlKClcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKG1lc3NhZ2UuZXJyb3IgfHwgXCJGYWlsZWQgdG8gZW5xdWV1ZSBqb2JcIikpXG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIHNvY2tldC5vbihcImNvbm5lY3RcIiwgKCkgPT4ge1xuICAgICAgICBqc29uU29ja2V0LnNlbmQoe3R5cGU6IFwiaGVsbG9cIiwgcm9sZTogXCJjbGllbnRcIn0pXG4gICAgICAgIGpzb25Tb2NrZXQuc2VuZCh7XG4gICAgICAgICAgdHlwZTogXCJlbnF1ZXVlXCIsXG4gICAgICAgICAgam9iTmFtZSxcbiAgICAgICAgICBhcmdzLFxuICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgfSlcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxufVxuIl19
@@ -0,0 +1,4 @@
1
+ export default class BackgroundJobRecord extends DatabaseRecord {
2
+ }
3
+ import DatabaseRecord from "../database/record/index.js";
4
+ //# sourceMappingURL=job-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-record.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job-record.js"],"names":[],"mappings":"AAIA;CAQC;2BAV0B,6BAA6B"}
@@ -0,0 +1,11 @@
1
+ // @ts-check
2
+ import DatabaseRecord from "../database/record/index.js";
3
+ export default class BackgroundJobRecord extends DatabaseRecord {
4
+ static tableName() {
5
+ return "background_jobs";
6
+ }
7
+ static primaryKey() {
8
+ return "id";
9
+ }
10
+ }
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLXJlY29yZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvam9iLXJlY29yZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxjQUFjLE1BQU0sNkJBQTZCLENBQUE7QUFFeEQsTUFBTSxDQUFDLE9BQU8sT0FBTyxtQkFBb0IsU0FBUSxjQUFjO0lBQzdELE1BQU0sQ0FBQyxTQUFTO1FBQ2QsT0FBTyxpQkFBaUIsQ0FBQTtJQUMxQixDQUFDO0lBRUQsTUFBTSxDQUFDLFVBQVU7UUFDZixPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgRGF0YWJhc2VSZWNvcmQgZnJvbSBcIi4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhY2tncm91bmRKb2JSZWNvcmQgZXh0ZW5kcyBEYXRhYmFzZVJlY29yZCB7XG4gIHN0YXRpYyB0YWJsZU5hbWUoKSB7XG4gICAgcmV0dXJuIFwiYmFja2dyb3VuZF9qb2JzXCJcbiAgfVxuXG4gIHN0YXRpYyBwcmltYXJ5S2V5KCkge1xuICAgIHJldHVybiBcImlkXCJcbiAgfVxufVxuIl19
@@ -0,0 +1,23 @@
1
+ export default class BackgroundJobRegistry {
2
+ /**
3
+ * @param {object} args - Options.
4
+ * @param {import("../configuration.js").default} args.configuration - Configuration.
5
+ */
6
+ constructor({ configuration }: {
7
+ configuration: import("../configuration.js").default;
8
+ });
9
+ configuration: import("../configuration.js").default;
10
+ /** @type {Map<string, typeof VelociousJob>} */
11
+ jobsByName: Map<string, typeof VelociousJob>;
12
+ /**
13
+ * @returns {Promise<void>} - Resolves when complete.
14
+ */
15
+ load(): Promise<void>;
16
+ /**
17
+ * @param {string} jobName - Job name.
18
+ * @returns {typeof VelociousJob} - Job class.
19
+ */
20
+ getJobByName(jobName: string): typeof VelociousJob;
21
+ }
22
+ import VelociousJob from "./job.js";
23
+ //# sourceMappingURL=job-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-registry.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job-registry.js"],"names":[],"mappings":"AAMA;IACE;;;OAGG;IACH,+BAFG;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO;KAC/C,EAKA;IAHC,qDAAkC;IAClC,+CAA+C;IAC/C,YADW,GAAG,CAAC,MAAM,EAAE,OAAO,YAAY,CAAC,CAChB;IAG7B;;OAEG;IACH,QAFa,OAAO,CAAC,IAAI,CAAC,CA+BzB;IAED;;;OAGG;IACH,sBAHW,MAAM,GACJ,OAAO,YAAY,CAU/B;CACF;yBA5DwB,UAAU"}
@@ -0,0 +1,55 @@
1
+ // @ts-check
2
+ import fs from "fs/promises";
3
+ import path from "path";
4
+ import VelociousJob from "./job.js";
5
+ export default class BackgroundJobRegistry {
6
+ /**
7
+ * @param {object} args - Options.
8
+ * @param {import("../configuration.js").default} args.configuration - Configuration.
9
+ */
10
+ constructor({ configuration }) {
11
+ this.configuration = configuration;
12
+ /** @type {Map<string, typeof VelociousJob>} */
13
+ this.jobsByName = new Map();
14
+ }
15
+ /**
16
+ * @returns {Promise<void>} - Resolves when complete.
17
+ */
18
+ async load() {
19
+ const directory = this.configuration.getDirectory();
20
+ const jobsDir = path.join(directory, "src", "jobs");
21
+ try {
22
+ await fs.access(jobsDir);
23
+ }
24
+ catch {
25
+ return;
26
+ }
27
+ const jobFiles = fs.glob(`${jobsDir}/**/*.js`);
28
+ for await (const jobFile of jobFiles) {
29
+ const jobImport = await import(jobFile);
30
+ const JobClass = jobImport.default;
31
+ if (!JobClass)
32
+ throw new Error(`Job file must export a default class: ${jobFile}`);
33
+ if (!(JobClass.prototype instanceof VelociousJob)) {
34
+ throw new Error(`Job class must extend VelociousJob: ${jobFile}`);
35
+ }
36
+ const jobName = JobClass.jobName();
37
+ if (this.jobsByName.has(jobName)) {
38
+ throw new Error(`Duplicate job name "${jobName}" from ${jobFile}`);
39
+ }
40
+ this.jobsByName.set(jobName, JobClass);
41
+ }
42
+ }
43
+ /**
44
+ * @param {string} jobName - Job name.
45
+ * @returns {typeof VelociousJob} - Job class.
46
+ */
47
+ getJobByName(jobName) {
48
+ const jobClass = this.jobsByName.get(jobName);
49
+ if (!jobClass) {
50
+ throw new Error(`Unknown job "${jobName}". Check src/jobs`);
51
+ }
52
+ return jobClass;
53
+ }
54
+ }
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLXJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JhY2tncm91bmQtam9icy9qb2ItcmVnaXN0cnkuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUM1QixPQUFPLElBQUksTUFBTSxNQUFNLENBQUE7QUFDdkIsT0FBTyxZQUFZLE1BQU0sVUFBVSxDQUFBO0FBRW5DLE1BQU0sQ0FBQyxPQUFPLE9BQU8scUJBQXFCO0lBQ3hDOzs7T0FHRztJQUNILFlBQVksRUFBQyxhQUFhLEVBQUM7UUFDekIsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUE7UUFDbEMsK0NBQStDO1FBQy9DLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUM3QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsSUFBSTtRQUNSLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLENBQUE7UUFDbkQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBRW5ELElBQUksQ0FBQztZQUNILE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUMxQixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTTtRQUNSLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxVQUFVLENBQUMsQ0FBQTtRQUU5QyxJQUFJLEtBQUssRUFBRSxNQUFNLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNyQyxNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUN2QyxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFBO1lBRWxDLElBQUksQ0FBQyxRQUFRO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLE9BQU8sRUFBRSxDQUFDLENBQUE7WUFDbEYsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLFNBQVMsWUFBWSxZQUFZLENBQUMsRUFBRSxDQUFDO2dCQUNsRCxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1lBQ25FLENBQUM7WUFFRCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUE7WUFFbEMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNqQyxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixPQUFPLFVBQVUsT0FBTyxFQUFFLENBQUMsQ0FBQTtZQUNwRSxDQUFDO1lBRUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFBO1FBQ3hDLENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsWUFBWSxDQUFDLE9BQU87UUFDbEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFN0MsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsT0FBTyxtQkFBbUIsQ0FBQyxDQUFBO1FBQzdELENBQUM7UUFFRCxPQUFPLFFBQVEsQ0FBQTtJQUNqQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IGZzIGZyb20gXCJmcy9wcm9taXNlc1wiXG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiXG5pbXBvcnQgVmVsb2Npb3VzSm9iIGZyb20gXCIuL2pvYi5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhY2tncm91bmRKb2JSZWdpc3RyeSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb259KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIC8qKiBAdHlwZSB7TWFwPHN0cmluZywgdHlwZW9mIFZlbG9jaW91c0pvYj59ICovXG4gICAgdGhpcy5qb2JzQnlOYW1lID0gbmV3IE1hcCgpXG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgY29uc3QgZGlyZWN0b3J5ID0gdGhpcy5jb25maWd1cmF0aW9uLmdldERpcmVjdG9yeSgpXG4gICAgY29uc3Qgam9ic0RpciA9IHBhdGguam9pbihkaXJlY3RvcnksIFwic3JjXCIsIFwiam9ic1wiKVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZzLmFjY2Vzcyhqb2JzRGlyKVxuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3Qgam9iRmlsZXMgPSBmcy5nbG9iKGAke2pvYnNEaXJ9LyoqLyouanNgKVxuXG4gICAgZm9yIGF3YWl0IChjb25zdCBqb2JGaWxlIG9mIGpvYkZpbGVzKSB7XG4gICAgICBjb25zdCBqb2JJbXBvcnQgPSBhd2FpdCBpbXBvcnQoam9iRmlsZSlcbiAgICAgIGNvbnN0IEpvYkNsYXNzID0gam9iSW1wb3J0LmRlZmF1bHRcblxuICAgICAgaWYgKCFKb2JDbGFzcykgdGhyb3cgbmV3IEVycm9yKGBKb2IgZmlsZSBtdXN0IGV4cG9ydCBhIGRlZmF1bHQgY2xhc3M6ICR7am9iRmlsZX1gKVxuICAgICAgaWYgKCEoSm9iQ2xhc3MucHJvdG90eXBlIGluc3RhbmNlb2YgVmVsb2Npb3VzSm9iKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEpvYiBjbGFzcyBtdXN0IGV4dGVuZCBWZWxvY2lvdXNKb2I6ICR7am9iRmlsZX1gKVxuICAgICAgfVxuXG4gICAgICBjb25zdCBqb2JOYW1lID0gSm9iQ2xhc3Muam9iTmFtZSgpXG5cbiAgICAgIGlmICh0aGlzLmpvYnNCeU5hbWUuaGFzKGpvYk5hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRHVwbGljYXRlIGpvYiBuYW1lIFwiJHtqb2JOYW1lfVwiIGZyb20gJHtqb2JGaWxlfWApXG4gICAgICB9XG5cbiAgICAgIHRoaXMuam9ic0J5TmFtZS5zZXQoam9iTmFtZSwgSm9iQ2xhc3MpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBqb2JOYW1lIC0gSm9iIG5hbWUuXG4gICAqIEByZXR1cm5zIHt0eXBlb2YgVmVsb2Npb3VzSm9ifSAtIEpvYiBjbGFzcy5cbiAgICovXG4gIGdldEpvYkJ5TmFtZShqb2JOYW1lKSB7XG4gICAgY29uc3Qgam9iQ2xhc3MgPSB0aGlzLmpvYnNCeU5hbWUuZ2V0KGpvYk5hbWUpXG5cbiAgICBpZiAoIWpvYkNsYXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gam9iIFwiJHtqb2JOYW1lfVwiLiBDaGVjayBzcmMvam9ic2ApXG4gICAgfVxuXG4gICAgcmV0dXJuIGpvYkNsYXNzXG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @param {object} payload - Payload.
3
+ * @returns {Promise<void>} - Resolves when complete.
4
+ */
5
+ export default function runJobPayload(payload: object): Promise<void>;
6
+ //# sourceMappingURL=job-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-runner.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job-runner.js"],"names":[],"mappings":"AAMA;;;GAGG;AACH,+CAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAuCzB"}
@@ -0,0 +1,44 @@
1
+ // @ts-check
2
+ import configurationResolver from "../configuration-resolver.js";
3
+ import BackgroundJobRegistry from "./job-registry.js";
4
+ import BackgroundJobsStatusReporter from "./status-reporter.js";
5
+ /**
6
+ * @param {object} payload - Payload.
7
+ * @returns {Promise<void>} - Resolves when complete.
8
+ */
9
+ export default async function runJobPayload(payload) {
10
+ const configuration = await configurationResolver();
11
+ configuration.setCurrent();
12
+ await configuration.initialize({ type: "background-jobs-runner" });
13
+ const reporter = new BackgroundJobsStatusReporter({ configuration });
14
+ const registry = new BackgroundJobRegistry({ configuration });
15
+ await registry.load();
16
+ const JobClass = registry.getJobByName(payload.jobName);
17
+ const jobInstance = new JobClass();
18
+ try {
19
+ await jobInstance.perform.apply(jobInstance, payload.args || []);
20
+ if (payload.id) {
21
+ await reporter.reportWithRetry({
22
+ jobId: payload.id,
23
+ status: "completed",
24
+ workerId: payload.workerId,
25
+ handedOffAtMs: payload.handedOffAtMs,
26
+ maxDurationMs: 30000
27
+ });
28
+ }
29
+ }
30
+ catch (error) {
31
+ if (payload.id) {
32
+ await reporter.reportWithRetry({
33
+ jobId: payload.id,
34
+ status: "failed",
35
+ error,
36
+ workerId: payload.workerId,
37
+ handedOffAtMs: payload.handedOffAtMs,
38
+ maxDurationMs: 30000
39
+ });
40
+ }
41
+ throw error;
42
+ }
43
+ }
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLXJ1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvam9iLXJ1bm5lci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxxQkFBcUIsTUFBTSw4QkFBOEIsQ0FBQTtBQUNoRSxPQUFPLHFCQUFxQixNQUFNLG1CQUFtQixDQUFBO0FBQ3JELE9BQU8sNEJBQTRCLE1BQU0sc0JBQXNCLENBQUE7QUFFL0Q7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLFVBQVUsYUFBYSxDQUFDLE9BQU87SUFDakQsTUFBTSxhQUFhLEdBQUcsTUFBTSxxQkFBcUIsRUFBRSxDQUFBO0lBQ25ELGFBQWEsQ0FBQyxVQUFVLEVBQUUsQ0FBQTtJQUMxQixNQUFNLGFBQWEsQ0FBQyxVQUFVLENBQUMsRUFBQyxJQUFJLEVBQUUsd0JBQXdCLEVBQUMsQ0FBQyxDQUFBO0lBQ2hFLE1BQU0sUUFBUSxHQUFHLElBQUksNEJBQTRCLENBQUMsRUFBQyxhQUFhLEVBQUMsQ0FBQyxDQUFBO0lBRWxFLE1BQU0sUUFBUSxHQUFHLElBQUkscUJBQXFCLENBQUMsRUFBQyxhQUFhLEVBQUMsQ0FBQyxDQUFBO0lBQzNELE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxDQUFBO0lBQ3JCLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ3ZELE1BQU0sV0FBVyxHQUFHLElBQUksUUFBUSxFQUFFLENBQUE7SUFFbEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxXQUFXLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQTtRQUVoRSxJQUFJLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNmLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQztnQkFDN0IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUFFO2dCQUNqQixNQUFNLEVBQUUsV0FBVztnQkFDbkIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO2dCQUMxQixhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWE7Z0JBQ3BDLGFBQWEsRUFBRSxLQUFLO2FBQ3JCLENBQUMsQ0FBQTtRQUNKLENBQUM7SUFDSCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2YsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDO2dCQUM3QixLQUFLLEVBQUUsT0FBTyxDQUFDLEVBQUU7Z0JBQ2pCLE1BQU0sRUFBRSxRQUFRO2dCQUNoQixLQUFLO2dCQUNMLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtnQkFDMUIsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhO2dCQUNwQyxhQUFhLEVBQUUsS0FBSzthQUNyQixDQUFDLENBQUE7UUFDSixDQUFDO1FBRUQsTUFBTSxLQUFLLENBQUE7SUFDYixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgY29uZmlndXJhdGlvblJlc29sdmVyIGZyb20gXCIuLi9jb25maWd1cmF0aW9uLXJlc29sdmVyLmpzXCJcbmltcG9ydCBCYWNrZ3JvdW5kSm9iUmVnaXN0cnkgZnJvbSBcIi4vam9iLXJlZ2lzdHJ5LmpzXCJcbmltcG9ydCBCYWNrZ3JvdW5kSm9ic1N0YXR1c1JlcG9ydGVyIGZyb20gXCIuL3N0YXR1cy1yZXBvcnRlci5qc1wiXG5cbi8qKlxuICogQHBhcmFtIHtvYmplY3R9IHBheWxvYWQgLSBQYXlsb2FkLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcnVuSm9iUGF5bG9hZChwYXlsb2FkKSB7XG4gIGNvbnN0IGNvbmZpZ3VyYXRpb24gPSBhd2FpdCBjb25maWd1cmF0aW9uUmVzb2x2ZXIoKVxuICBjb25maWd1cmF0aW9uLnNldEN1cnJlbnQoKVxuICBhd2FpdCBjb25maWd1cmF0aW9uLmluaXRpYWxpemUoe3R5cGU6IFwiYmFja2dyb3VuZC1qb2JzLXJ1bm5lclwifSlcbiAgY29uc3QgcmVwb3J0ZXIgPSBuZXcgQmFja2dyb3VuZEpvYnNTdGF0dXNSZXBvcnRlcih7Y29uZmlndXJhdGlvbn0pXG5cbiAgY29uc3QgcmVnaXN0cnkgPSBuZXcgQmFja2dyb3VuZEpvYlJlZ2lzdHJ5KHtjb25maWd1cmF0aW9ufSlcbiAgYXdhaXQgcmVnaXN0cnkubG9hZCgpXG4gIGNvbnN0IEpvYkNsYXNzID0gcmVnaXN0cnkuZ2V0Sm9iQnlOYW1lKHBheWxvYWQuam9iTmFtZSlcbiAgY29uc3Qgam9iSW5zdGFuY2UgPSBuZXcgSm9iQ2xhc3MoKVxuXG4gIHRyeSB7XG4gICAgYXdhaXQgam9iSW5zdGFuY2UucGVyZm9ybS5hcHBseShqb2JJbnN0YW5jZSwgcGF5bG9hZC5hcmdzIHx8IFtdKVxuXG4gICAgaWYgKHBheWxvYWQuaWQpIHtcbiAgICAgIGF3YWl0IHJlcG9ydGVyLnJlcG9ydFdpdGhSZXRyeSh7XG4gICAgICAgIGpvYklkOiBwYXlsb2FkLmlkLFxuICAgICAgICBzdGF0dXM6IFwiY29tcGxldGVkXCIsXG4gICAgICAgIHdvcmtlcklkOiBwYXlsb2FkLndvcmtlcklkLFxuICAgICAgICBoYW5kZWRPZmZBdE1zOiBwYXlsb2FkLmhhbmRlZE9mZkF0TXMsXG4gICAgICAgIG1heER1cmF0aW9uTXM6IDMwMDAwXG4gICAgICB9KVxuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAocGF5bG9hZC5pZCkge1xuICAgICAgYXdhaXQgcmVwb3J0ZXIucmVwb3J0V2l0aFJldHJ5KHtcbiAgICAgICAgam9iSWQ6IHBheWxvYWQuaWQsXG4gICAgICAgIHN0YXR1czogXCJmYWlsZWRcIixcbiAgICAgICAgZXJyb3IsXG4gICAgICAgIHdvcmtlcklkOiBwYXlsb2FkLndvcmtlcklkLFxuICAgICAgICBoYW5kZWRPZmZBdE1zOiBwYXlsb2FkLmhhbmRlZE9mZkF0TXMsXG4gICAgICAgIG1heER1cmF0aW9uTXM6IDMwMDAwXG4gICAgICB9KVxuICAgIH1cblxuICAgIHRocm93IGVycm9yXG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,35 @@
1
+ export default class VelociousJob {
2
+ /**
3
+ * @returns {string} - Job name.
4
+ */
5
+ static jobName(): string;
6
+ /**
7
+ * @param {...any} args - Job args.
8
+ * @returns {Promise<string>} - Job id.
9
+ */
10
+ static performLater(...args: any[]): Promise<string>;
11
+ /**
12
+ * @param {object} args - Options.
13
+ * @param {any[]} args.args - Job args.
14
+ * @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
15
+ * @returns {Promise<string>} - Job id.
16
+ */
17
+ static performLaterWithOptions({ args, options }: {
18
+ args: any[];
19
+ options?: import("./types.js").BackgroundJobOptions;
20
+ }): Promise<string>;
21
+ /**
22
+ * @param {any[]} args - Job args.
23
+ * @returns {{jobArgs: any[], jobOptions: import("./types.js").BackgroundJobOptions}} - Split args and options.
24
+ */
25
+ static _splitArgsAndOptions(args: any[]): {
26
+ jobArgs: any[];
27
+ jobOptions: import("./types.js").BackgroundJobOptions;
28
+ };
29
+ /**
30
+ * Override in subclasses.
31
+ * @returns {Promise<void>} - Resolves when complete.
32
+ */
33
+ perform(): Promise<void>;
34
+ }
35
+ //# sourceMappingURL=job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job.js"],"names":[],"mappings":"AAIA;IACE;;OAEG;IACH,kBAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,6BAHc,GAAG,EAAA,GACJ,OAAO,CAAC,MAAM,CAAC,CAW3B;IAED;;;;;OAKG;IACH,kDAJG;QAAoB,IAAI,EAAhB,GAAG,EAAE;QAC4C,OAAO,GAAxD,OAAO,YAAY,EAAE,oBAAoB;KACjD,GAAU,OAAO,CAAC,MAAM,CAAC,CAU3B;IAED;;;OAGG;IACH,kCAHW,GAAG,EAAE,GACH;QAAC,OAAO,EAAE,GAAG,EAAE,CAAC;QAAC,UAAU,EAAE,OAAO,YAAY,EAAE,oBAAoB,CAAA;KAAC,CAgBnF;IAED;;;OAGG;IACH,WAFa,OAAO,CAAC,IAAI,CAAC,CAIzB;CACF"}
@@ -0,0 +1,61 @@
1
+ // @ts-check
2
+ import BackgroundJobsClient from "./client.js";
3
+ export default class VelociousJob {
4
+ /**
5
+ * @returns {string} - Job name.
6
+ */
7
+ static jobName() {
8
+ return this.name;
9
+ }
10
+ /**
11
+ * @param {...any} args - Job args.
12
+ * @returns {Promise<string>} - Job id.
13
+ */
14
+ static async performLater(...args) {
15
+ const { jobArgs, jobOptions } = this._splitArgsAndOptions(args);
16
+ const client = new BackgroundJobsClient();
17
+ return await client.enqueue({
18
+ jobName: this.jobName(),
19
+ args: jobArgs,
20
+ options: jobOptions
21
+ });
22
+ }
23
+ /**
24
+ * @param {object} args - Options.
25
+ * @param {any[]} args.args - Job args.
26
+ * @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
27
+ * @returns {Promise<string>} - Job id.
28
+ */
29
+ static async performLaterWithOptions({ args, options }) {
30
+ const client = new BackgroundJobsClient();
31
+ return await client.enqueue({
32
+ jobName: this.jobName(),
33
+ args,
34
+ options
35
+ });
36
+ }
37
+ /**
38
+ * @param {any[]} args - Job args.
39
+ * @returns {{jobArgs: any[], jobOptions: import("./types.js").BackgroundJobOptions}} - Split args and options.
40
+ */
41
+ static _splitArgsAndOptions(args) {
42
+ if (args.length === 0) {
43
+ return { jobArgs: [], jobOptions: {} };
44
+ }
45
+ const lastArg = args[args.length - 1];
46
+ const isOptionsArg = lastArg && typeof lastArg === "object" && !Array.isArray(lastArg) && "jobOptions" in lastArg;
47
+ if (isOptionsArg) {
48
+ const { jobOptions } = /** @type {{jobOptions: import("./types.js").BackgroundJobOptions}} */ (lastArg);
49
+ return { jobArgs: args.slice(0, -1), jobOptions: jobOptions || {} };
50
+ }
51
+ return { jobArgs: args, jobOptions: {} };
52
+ }
53
+ /**
54
+ * Override in subclasses.
55
+ * @returns {Promise<void>} - Resolves when complete.
56
+ */
57
+ async perform() {
58
+ throw new Error("perform not implemented");
59
+ }
60
+ }
61
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JhY2tncm91bmQtam9icy9qb2IuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sb0JBQW9CLE1BQU0sYUFBYSxDQUFBO0FBRTlDLE1BQU0sQ0FBQyxPQUFPLE9BQU8sWUFBWTtJQUMvQjs7T0FFRztJQUNILE1BQU0sQ0FBQyxPQUFPO1FBQ1osT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFBO0lBQ2xCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxHQUFHLElBQUk7UUFDL0IsTUFBTSxFQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDN0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxvQkFBb0IsRUFBRSxDQUFBO1FBRXpDLE9BQU8sTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQzFCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ3ZCLElBQUksRUFBRSxPQUFPO1lBQ2IsT0FBTyxFQUFFLFVBQVU7U0FDcEIsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxFQUFDLElBQUksRUFBRSxPQUFPLEVBQUM7UUFDbEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxvQkFBb0IsRUFBRSxDQUFBO1FBRXpDLE9BQU8sTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQzFCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ3ZCLElBQUk7WUFDSixPQUFPO1NBQ1IsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJO1FBQzlCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN0QixPQUFPLEVBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFDLENBQUE7UUFDdEMsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQ3JDLE1BQU0sWUFBWSxHQUFHLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLFlBQVksSUFBSSxPQUFPLENBQUE7UUFFakgsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNqQixNQUFNLEVBQUMsVUFBVSxFQUFDLEdBQUcsc0VBQXNFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUNyRyxPQUFPLEVBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLFVBQVUsSUFBSSxFQUFFLEVBQUMsQ0FBQTtRQUNuRSxDQUFDO1FBRUQsT0FBTyxFQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBQyxDQUFBO0lBQ3hDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsT0FBTztRQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQTtJQUM1QyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IEJhY2tncm91bmRKb2JzQ2xpZW50IGZyb20gXCIuL2NsaWVudC5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlbG9jaW91c0pvYiB7XG4gIC8qKlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIEpvYiBuYW1lLlxuICAgKi9cbiAgc3RhdGljIGpvYk5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7Li4uYW55fSBhcmdzIC0gSm9iIGFyZ3MuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gSm9iIGlkLlxuICAgKi9cbiAgc3RhdGljIGFzeW5jIHBlcmZvcm1MYXRlciguLi5hcmdzKSB7XG4gICAgY29uc3Qge2pvYkFyZ3MsIGpvYk9wdGlvbnN9ID0gdGhpcy5fc3BsaXRBcmdzQW5kT3B0aW9ucyhhcmdzKVxuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBCYWNrZ3JvdW5kSm9ic0NsaWVudCgpXG5cbiAgICByZXR1cm4gYXdhaXQgY2xpZW50LmVucXVldWUoe1xuICAgICAgam9iTmFtZTogdGhpcy5qb2JOYW1lKCksXG4gICAgICBhcmdzOiBqb2JBcmdzLFxuICAgICAgb3B0aW9uczogam9iT3B0aW9uc1xuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzLmFyZ3MgLSBKb2IgYXJncy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JPcHRpb25zfSBbYXJncy5vcHRpb25zXSAtIEpvYiBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIEpvYiBpZC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBwZXJmb3JtTGF0ZXJXaXRoT3B0aW9ucyh7YXJncywgb3B0aW9uc30pIHtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgQmFja2dyb3VuZEpvYnNDbGllbnQoKVxuXG4gICAgcmV0dXJuIGF3YWl0IGNsaWVudC5lbnF1ZXVlKHtcbiAgICAgIGpvYk5hbWU6IHRoaXMuam9iTmFtZSgpLFxuICAgICAgYXJncyxcbiAgICAgIG9wdGlvbnNcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBKb2IgYXJncy5cbiAgICogQHJldHVybnMge3tqb2JBcmdzOiBhbnlbXSwgam9iT3B0aW9uczogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iT3B0aW9uc319IC0gU3BsaXQgYXJncyBhbmQgb3B0aW9ucy5cbiAgICovXG4gIHN0YXRpYyBfc3BsaXRBcmdzQW5kT3B0aW9ucyhhcmdzKSB7XG4gICAgaWYgKGFyZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4ge2pvYkFyZ3M6IFtdLCBqb2JPcHRpb25zOiB7fX1cbiAgICB9XG5cbiAgICBjb25zdCBsYXN0QXJnID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdXG4gICAgY29uc3QgaXNPcHRpb25zQXJnID0gbGFzdEFyZyAmJiB0eXBlb2YgbGFzdEFyZyA9PT0gXCJvYmplY3RcIiAmJiAhQXJyYXkuaXNBcnJheShsYXN0QXJnKSAmJiBcImpvYk9wdGlvbnNcIiBpbiBsYXN0QXJnXG5cbiAgICBpZiAoaXNPcHRpb25zQXJnKSB7XG4gICAgICBjb25zdCB7am9iT3B0aW9uc30gPSAvKiogQHR5cGUge3tqb2JPcHRpb25zOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JPcHRpb25zfX0gKi8gKGxhc3RBcmcpXG4gICAgICByZXR1cm4ge2pvYkFyZ3M6IGFyZ3Muc2xpY2UoMCwgLTEpLCBqb2JPcHRpb25zOiBqb2JPcHRpb25zIHx8IHt9fVxuICAgIH1cblxuICAgIHJldHVybiB7am9iQXJnczogYXJncywgam9iT3B0aW9uczoge319XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGUgaW4gc3ViY2xhc3Nlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHBlcmZvcm0oKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwicGVyZm9ybSBub3QgaW1wbGVtZW50ZWRcIilcbiAgfVxufVxuIl19
@@ -0,0 +1,27 @@
1
+ declare const JsonSocket_base: typeof import("eventemitter3").EventEmitter;
2
+ export default class JsonSocket extends JsonSocket_base {
3
+ /**
4
+ * @param {import("net").Socket} socket - Socket instance.
5
+ */
6
+ constructor(socket: import("net").Socket);
7
+ socket: import("net").Socket;
8
+ /** @type {string | undefined} */
9
+ workerId: string | undefined;
10
+ buffer: string;
11
+ /**
12
+ * @param {string} chunk - Data chunk.
13
+ * @returns {void}
14
+ */
15
+ _onData(chunk: string): void;
16
+ /**
17
+ * @param {unknown} message - Message to send.
18
+ * @returns {void}
19
+ */
20
+ send(message: unknown): void;
21
+ /**
22
+ * @returns {void}
23
+ */
24
+ close(): void;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=json-socket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-socket.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/json-socket.js"],"names":[],"mappings":";AAIA;IACE;;OAEG;IACH,oBAFW,OAAO,KAAK,EAAE,MAAM,EAY9B;IARC,6BAAoB;IACpB,iCAAiC;IACjC,UADW,MAAM,GAAG,SAAS,CACJ;IACzB,eAAgB;IAOlB;;;OAGG;IACH,eAHW,MAAM,GACJ,IAAI,CAqBhB;IAED;;;OAGG;IACH,cAHW,OAAO,GACL,IAAI,CAIhB;IAED;;OAEG;IACH,SAFa,IAAI,CAIhB;CACF"}
@@ -0,0 +1,55 @@
1
+ // @ts-check
2
+ import EventEmitter from "../utils/event-emitter.js";
3
+ export default class JsonSocket extends EventEmitter {
4
+ /**
5
+ * @param {import("net").Socket} socket - Socket instance.
6
+ */
7
+ constructor(socket) {
8
+ super();
9
+ this.socket = socket;
10
+ /** @type {string | undefined} */
11
+ this.workerId = undefined;
12
+ this.buffer = "";
13
+ this.socket.setEncoding("utf8");
14
+ this.socket.on("data", (chunk) => this._onData(String(chunk)));
15
+ this.socket.on("close", () => this.emit("close"));
16
+ this.socket.on("error", (error) => this.emit("error", error));
17
+ }
18
+ /**
19
+ * @param {string} chunk - Data chunk.
20
+ * @returns {void}
21
+ */
22
+ _onData(chunk) {
23
+ this.buffer += chunk;
24
+ while (true) {
25
+ const newlineIndex = this.buffer.indexOf("\n");
26
+ if (newlineIndex === -1)
27
+ break;
28
+ const line = this.buffer.slice(0, newlineIndex).trim();
29
+ this.buffer = this.buffer.slice(newlineIndex + 1);
30
+ if (!line)
31
+ continue;
32
+ try {
33
+ const message = JSON.parse(line);
34
+ this.emit("message", message);
35
+ }
36
+ catch (error) {
37
+ this.emit("error", error);
38
+ }
39
+ }
40
+ }
41
+ /**
42
+ * @param {unknown} message - Message to send.
43
+ * @returns {void}
44
+ */
45
+ send(message) {
46
+ this.socket.write(`${JSON.stringify(message)}\n`);
47
+ }
48
+ /**
49
+ * @returns {void}
50
+ */
51
+ close() {
52
+ this.socket.end();
53
+ }
54
+ }
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbi1zb2NrZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYmFja2dyb3VuZC1qb2JzL2pzb24tc29ja2V0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLFlBQVksTUFBTSwyQkFBMkIsQ0FBQTtBQUVwRCxNQUFNLENBQUMsT0FBTyxPQUFPLFVBQVcsU0FBUSxZQUFZO0lBQ2xEOztPQUVHO0lBQ0gsWUFBWSxNQUFNO1FBQ2hCLEtBQUssRUFBRSxDQUFBO1FBQ1AsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsaUNBQWlDO1FBQ2pDLElBQUksQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFBO1FBQ3pCLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFBO1FBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQy9CLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzlELElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFDakQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO0lBQy9ELENBQUM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsS0FBSztRQUNYLElBQUksQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFBO1FBRXBCLE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUM5QyxJQUFJLFlBQVksS0FBSyxDQUFDLENBQUM7Z0JBQUUsTUFBSztZQUU5QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7WUFDdEQsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxZQUFZLEdBQUcsQ0FBQyxDQUFDLENBQUE7WUFFakQsSUFBSSxDQUFDLElBQUk7Z0JBQUUsU0FBUTtZQUVuQixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQTtnQkFDaEMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUE7WUFDL0IsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDM0IsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBSSxDQUFDLE9BQU87UUFDVixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ25ELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUs7UUFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFBO0lBQ25CLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gXCIuLi91dGlscy9ldmVudC1lbWl0dGVyLmpzXCJcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSnNvblNvY2tldCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIm5ldFwiKS5Tb2NrZXR9IHNvY2tldCAtIFNvY2tldCBpbnN0YW5jZS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHNvY2tldCkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLnNvY2tldCA9IHNvY2tldFxuICAgIC8qKiBAdHlwZSB7c3RyaW5nIHwgdW5kZWZpbmVkfSAqL1xuICAgIHRoaXMud29ya2VySWQgPSB1bmRlZmluZWRcbiAgICB0aGlzLmJ1ZmZlciA9IFwiXCJcbiAgICB0aGlzLnNvY2tldC5zZXRFbmNvZGluZyhcInV0ZjhcIilcbiAgICB0aGlzLnNvY2tldC5vbihcImRhdGFcIiwgKGNodW5rKSA9PiB0aGlzLl9vbkRhdGEoU3RyaW5nKGNodW5rKSkpXG4gICAgdGhpcy5zb2NrZXQub24oXCJjbG9zZVwiLCAoKSA9PiB0aGlzLmVtaXQoXCJjbG9zZVwiKSlcbiAgICB0aGlzLnNvY2tldC5vbihcImVycm9yXCIsIChlcnJvcikgPT4gdGhpcy5lbWl0KFwiZXJyb3JcIiwgZXJyb3IpKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaHVuayAtIERhdGEgY2h1bmsuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgX29uRGF0YShjaHVuaykge1xuICAgIHRoaXMuYnVmZmVyICs9IGNodW5rXG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgbmV3bGluZUluZGV4ID0gdGhpcy5idWZmZXIuaW5kZXhPZihcIlxcblwiKVxuICAgICAgaWYgKG5ld2xpbmVJbmRleCA9PT0gLTEpIGJyZWFrXG5cbiAgICAgIGNvbnN0IGxpbmUgPSB0aGlzLmJ1ZmZlci5zbGljZSgwLCBuZXdsaW5lSW5kZXgpLnRyaW0oKVxuICAgICAgdGhpcy5idWZmZXIgPSB0aGlzLmJ1ZmZlci5zbGljZShuZXdsaW5lSW5kZXggKyAxKVxuXG4gICAgICBpZiAoIWxpbmUpIGNvbnRpbnVlXG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBKU09OLnBhcnNlKGxpbmUpXG4gICAgICAgIHRoaXMuZW1pdChcIm1lc3NhZ2VcIiwgbWVzc2FnZSlcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRoaXMuZW1pdChcImVycm9yXCIsIGVycm9yKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3Vua25vd259IG1lc3NhZ2UgLSBNZXNzYWdlIHRvIHNlbmQuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2VuZChtZXNzYWdlKSB7XG4gICAgdGhpcy5zb2NrZXQud3JpdGUoYCR7SlNPTi5zdHJpbmdpZnkobWVzc2FnZSl9XFxuYClcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGNsb3NlKCkge1xuICAgIHRoaXMuc29ja2V0LmVuZCgpXG4gIH1cbn1cbiJdfQ==