@bgord/bun 1.16.2 → 1.16.4

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 (96) hide show
  1. package/dist/cron-expression.vo.d.ts +12 -0
  2. package/dist/cron-expression.vo.d.ts.map +1 -0
  3. package/dist/cron-expression.vo.js +17 -0
  4. package/dist/cron-expression.vo.js.map +1 -0
  5. package/dist/cron-scheduler-croner.adapter.d.ts +15 -0
  6. package/dist/cron-scheduler-croner.adapter.d.ts.map +1 -0
  7. package/dist/cron-scheduler-croner.adapter.js +23 -0
  8. package/dist/cron-scheduler-croner.adapter.js.map +1 -0
  9. package/dist/cron-scheduler-noop.adapter.d.ts +7 -0
  10. package/dist/cron-scheduler-noop.adapter.d.ts.map +1 -0
  11. package/dist/cron-scheduler-noop.adapter.js +7 -0
  12. package/dist/cron-scheduler-noop.adapter.js.map +1 -0
  13. package/dist/cron-scheduler.port.d.ts +6 -0
  14. package/dist/cron-scheduler.port.d.ts.map +1 -0
  15. package/dist/cron-scheduler.port.js +2 -0
  16. package/dist/cron-scheduler.port.js.map +1 -0
  17. package/dist/cron-task-handler-bare.strategy.d.ts +13 -0
  18. package/dist/cron-task-handler-bare.strategy.d.ts.map +1 -0
  19. package/dist/cron-task-handler-bare.strategy.js +14 -0
  20. package/dist/cron-task-handler-bare.strategy.js.map +1 -0
  21. package/dist/cron-task-handler-noop.strategy.d.ts +6 -0
  22. package/dist/cron-task-handler-noop.strategy.d.ts.map +1 -0
  23. package/dist/cron-task-handler-noop.strategy.js +6 -0
  24. package/dist/cron-task-handler-noop.strategy.js.map +1 -0
  25. package/dist/{job-handler-with-logger.strategy.d.ts → cron-task-handler-with-logger.strategy.d.ts} +5 -4
  26. package/dist/cron-task-handler-with-logger.strategy.d.ts.map +1 -0
  27. package/dist/cron-task-handler-with-logger.strategy.js +38 -0
  28. package/dist/cron-task-handler-with-logger.strategy.js.map +1 -0
  29. package/dist/cron-task-handler.strategy.d.ts +5 -0
  30. package/dist/cron-task-handler.strategy.d.ts.map +1 -0
  31. package/dist/cron-task-handler.strategy.js +2 -0
  32. package/dist/cron-task-handler.strategy.js.map +1 -0
  33. package/dist/cron-task.vo.d.ts +7 -0
  34. package/dist/cron-task.vo.d.ts.map +1 -0
  35. package/dist/cron-task.vo.js +2 -0
  36. package/dist/cron-task.vo.js.map +1 -0
  37. package/dist/index.d.ts +10 -6
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +10 -6
  40. package/dist/index.js.map +1 -1
  41. package/dist/modules/system/services/passage-of-time-hourly.service.d.ts +2 -8
  42. package/dist/modules/system/services/passage-of-time-hourly.service.d.ts.map +1 -1
  43. package/dist/modules/system/services/passage-of-time-hourly.service.js +9 -13
  44. package/dist/modules/system/services/passage-of-time-hourly.service.js.map +1 -1
  45. package/dist/modules/system/services/passage-of-time-minute.service.d.ts +2 -8
  46. package/dist/modules/system/services/passage-of-time-minute.service.d.ts.map +1 -1
  47. package/dist/modules/system/services/passage-of-time-minute.service.js +9 -13
  48. package/dist/modules/system/services/passage-of-time-minute.service.js.map +1 -1
  49. package/dist/prerequisite-verifier-cron-scheduler.adapter.d.ts +13 -0
  50. package/dist/prerequisite-verifier-cron-scheduler.adapter.d.ts.map +1 -0
  51. package/dist/prerequisite-verifier-cron-scheduler.adapter.js +16 -0
  52. package/dist/prerequisite-verifier-cron-scheduler.adapter.js.map +1 -0
  53. package/package.json +7 -2
  54. package/readme.md +10 -6
  55. package/src/cron-expression.vo.ts +23 -0
  56. package/src/cron-scheduler-croner.adapter.ts +34 -0
  57. package/src/cron-scheduler-noop.adapter.ts +10 -0
  58. package/src/cron-scheduler.port.ts +7 -0
  59. package/src/cron-task-handler-bare.strategy.ts +17 -0
  60. package/src/cron-task-handler-noop.strategy.ts +8 -0
  61. package/src/cron-task-handler-with-logger.strategy.ts +46 -0
  62. package/src/cron-task-handler.strategy.ts +5 -0
  63. package/src/cron-task.vo.ts +3 -0
  64. package/src/index.ts +10 -6
  65. package/src/modules/system/services/passage-of-time-hourly.service.ts +10 -14
  66. package/src/modules/system/services/passage-of-time-minute.service.ts +10 -14
  67. package/src/prerequisite-verifier-cron-scheduler.adapter.ts +21 -0
  68. package/dist/job-handler-bare.strategy.d.ts +0 -12
  69. package/dist/job-handler-bare.strategy.d.ts.map +0 -1
  70. package/dist/job-handler-bare.strategy.js +0 -12
  71. package/dist/job-handler-bare.strategy.js.map +0 -1
  72. package/dist/job-handler-noop.strategy.d.ts +0 -5
  73. package/dist/job-handler-noop.strategy.d.ts.map +0 -1
  74. package/dist/job-handler-noop.strategy.js +0 -6
  75. package/dist/job-handler-noop.strategy.js.map +0 -1
  76. package/dist/job-handler-with-logger.strategy.d.ts.map +0 -1
  77. package/dist/job-handler-with-logger.strategy.js +0 -35
  78. package/dist/job-handler-with-logger.strategy.js.map +0 -1
  79. package/dist/job-handler.strategy.d.ts +0 -9
  80. package/dist/job-handler.strategy.d.ts.map +0 -1
  81. package/dist/job-handler.strategy.js +0 -2
  82. package/dist/job-handler.strategy.js.map +0 -1
  83. package/dist/jobs.service.d.ts +0 -15
  84. package/dist/jobs.service.d.ts.map +0 -1
  85. package/dist/jobs.service.js +0 -10
  86. package/dist/jobs.service.js.map +0 -1
  87. package/dist/prerequisite-verifier-jobs.adapter.d.ts +0 -13
  88. package/dist/prerequisite-verifier-jobs.adapter.d.ts.map +0 -1
  89. package/dist/prerequisite-verifier-jobs.adapter.js +0 -17
  90. package/dist/prerequisite-verifier-jobs.adapter.js.map +0 -1
  91. package/src/job-handler-bare.strategy.ts +0 -15
  92. package/src/job-handler-noop.strategy.ts +0 -7
  93. package/src/job-handler-with-logger.strategy.ts +0 -43
  94. package/src/job-handler.strategy.ts +0 -10
  95. package/src/jobs.service.ts +0 -15
  96. package/src/prerequisite-verifier-jobs.adapter.ts +0 -21
@@ -1,17 +1,13 @@
1
+ import { CronExpressionSchedules } from "../../../cron-expression.vo";
1
2
  import { event } from "../../../event-envelope";
2
- import { Jobs } from "../../../jobs.service";
3
3
  import { MinuteHasPassedEvent } from "../events/MINUTE_HAS_PASSED_EVENT";
4
- export class PassageOfTimeMinute {
5
- deps;
6
- constructor(deps) {
7
- this.deps = deps;
8
- }
9
- static cron = Jobs.SCHEDULES.EVERY_MINUTE;
10
- label = "PassageOfTime";
11
- async process() {
12
- await this.deps.EventStore.save([
13
- event(MinuteHasPassedEvent, "passage_of_time", { timestamp: this.deps.Clock.now().ms }, this.deps),
4
+ export const PassageOfTimeMinute = (deps) => ({
5
+ label: "PassageOfTimeMinute",
6
+ cron: CronExpressionSchedules.EVERY_MINUTE,
7
+ handler: async () => {
8
+ await deps.EventStore.save([
9
+ event(MinuteHasPassedEvent, "passage_of_time", { timestamp: deps.Clock.now().ms }, deps),
14
10
  ]);
15
- }
16
- }
11
+ },
12
+ });
17
13
  //# sourceMappingURL=passage-of-time-minute.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"passage-of-time-minute.service.js","sourceRoot":"","sources":["../../../../src/modules/system/services/passage-of-time-minute.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAIhD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAiC,MAAM,mCAAmC,CAAC;AAQxG,MAAM,OAAO,mBAAmB;IACD;IAA7B,YAA6B,IAAkB;QAAlB,SAAI,GAAJ,IAAI,CAAc;IAAG,CAAC;IAEnD,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;IAE1C,KAAK,GAAG,eAAe,CAAC;IAExB,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAC9B,KAAK,CAAC,oBAAoB,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC;SACnG,CAAC,CAAC;IACL,CAAC"}
1
+ {"version":3,"file":"passage-of-time-minute.service.js","sourceRoot":"","sources":["../../../../src/modules/system/services/passage-of-time-minute.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAGhD,OAAO,EAAE,oBAAoB,EAAiC,MAAM,mCAAmC,CAAC;AAQxG,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAkB,EAAY,EAAE,CAAC,CAAC;IACpE,KAAK,EAAE,qBAAqB;IAC5B,IAAI,EAAE,uBAAuB,CAAC,YAAY;IAC1C,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACzB,KAAK,CAAC,oBAAoB,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC;SACzF,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { CronSchedulerPort } from "./cron-scheduler.port";
2
+ import { type PrerequisiteVerificationResult, type PrerequisiteVerifierPort } from "./prerequisite-verifier.port";
3
+ type Dependencies = {
4
+ CronScheduler: CronSchedulerPort;
5
+ };
6
+ export declare class PrerequisiteVerifierCronSchedulerAdapter implements PrerequisiteVerifierPort {
7
+ private readonly deps;
8
+ constructor(deps: Dependencies);
9
+ verify(): Promise<PrerequisiteVerificationResult>;
10
+ get kind(): string;
11
+ }
12
+ export {};
13
+ //# sourceMappingURL=prerequisite-verifier-cron-scheduler.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prerequisite-verifier-cron-scheduler.adapter.d.ts","sourceRoot":"","sources":["../src/prerequisite-verifier-cron-scheduler.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,wBAAwB,EAC9B,MAAM,8BAA8B,CAAC;AAEtC,KAAK,YAAY,GAAG;IAAE,aAAa,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAEzD,qBAAa,wCAAyC,YAAW,wBAAwB;IAC3E,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,YAAY;IAEzC,MAAM,IAAI,OAAO,CAAC,8BAA8B,CAAC;IAKvD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,16 @@
1
+ import { PrerequisiteVerification, } from "./prerequisite-verifier.port";
2
+ export class PrerequisiteVerifierCronSchedulerAdapter {
3
+ deps;
4
+ constructor(deps) {
5
+ this.deps = deps;
6
+ }
7
+ async verify() {
8
+ if (await this.deps.CronScheduler.verify())
9
+ return PrerequisiteVerification.success;
10
+ return PrerequisiteVerification.failure();
11
+ }
12
+ get kind() {
13
+ return "cron-scheduler";
14
+ }
15
+ }
16
+ //# sourceMappingURL=prerequisite-verifier-cron-scheduler.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prerequisite-verifier-cron-scheduler.adapter.js","sourceRoot":"","sources":["../src/prerequisite-verifier-cron-scheduler.adapter.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,GAGzB,MAAM,8BAA8B,CAAC;AAItC,MAAM,OAAO,wCAAwC;IACtB;IAA7B,YAA6B,IAAkB;QAAlB,SAAI,GAAJ,IAAI,CAAc;IAAG,CAAC;IAEnD,KAAK,CAAC,MAAM;QACV,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;YAAE,OAAO,wBAAwB,CAAC,OAAO,CAAC;QACpF,OAAO,wBAAwB,CAAC,OAAO,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,IAAI;QACN,OAAO,gBAAgB,CAAC;IAC1B,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgord/bun",
3
- "version": "1.16.2",
3
+ "version": "1.16.4",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Bartosz Gordon",
@@ -33,7 +33,8 @@
33
33
  "better-auth": "1.5.6",
34
34
  "cspell": "9.7.0",
35
35
  "csv": "6.5.1",
36
- "knip": "6.0.6",
36
+ "croner": "10.0.1",
37
+ "knip": "6.1.0",
37
38
  "lefthook": "2.1.4",
38
39
  "lockfile-lint": "5.0.0",
39
40
  "nodemailer": "8.0.4",
@@ -53,6 +54,7 @@
53
54
  "peerDependencies": {
54
55
  "better-auth": "1.5.6",
55
56
  "csv": "6.5.1",
57
+ "croner": "10.0.1",
56
58
  "nodemailer": "8.0.4",
57
59
  "resend": "6.9.4",
58
60
  "sharp": "0.34.5",
@@ -65,6 +67,9 @@
65
67
  "csv": {
66
68
  "optional": true
67
69
  },
70
+ "croner": {
71
+ "optional": true
72
+ },
68
73
  "nodemailer": {
69
74
  "optional": true
70
75
  },
package/readme.md CHANGED
@@ -91,6 +91,15 @@ src/
91
91
  ├── correlation-id.vo.ts
92
92
  ├── correlation-storage.service.ts
93
93
  ├── correlation.middleware.ts
94
+ ├── cron-expression.vo.ts
95
+ ├── cron-scheduler-croner.adapter.ts
96
+ ├── cron-scheduler-noop.adapter.ts
97
+ ├── cron-scheduler.port.ts
98
+ ├── cron-task-handler-bare.strategy.ts
99
+ ├── cron-task-handler-noop.strategy.ts
100
+ ├── cron-task-handler-with-logger.strategy.ts
101
+ ├── cron-task-handler.strategy.ts
102
+ ├── cron-task.vo.ts
94
103
  ├── crypto-aes-gcm.service.ts
95
104
  ├── crypto-key-provider-file.adapter.ts
96
105
  ├── crypto-key-provider-memory.adapter.ts
@@ -251,11 +260,6 @@ src/
251
260
  ├── instrumentation.service.ts
252
261
  ├── invariant-error-handler.service.ts
253
262
  ├── invariant.service.ts
254
- ├── job-handler-bare.strategy.ts
255
- ├── job-handler-noop.strategy.ts
256
- ├── job-handler-with-logger.strategy.ts
257
- ├── job-handler.strategy.ts
258
- ├── jobs.service.ts
259
263
  ├── language-detector-cookie.strategy.ts
260
264
  ├── language-detector-header.strategy.ts
261
265
  ├── language-detector-hono.middleware.ts
@@ -353,11 +357,11 @@ src/
353
357
  ├── prerequisite-verifier-binary.adapter.ts
354
358
  ├── prerequisite-verifier-bun.adapter.ts
355
359
  ├── prerequisite-verifier-clock-drift.adapter.ts
360
+ ├── prerequisite-verifier-cron-scheduler.adapter.ts
356
361
  ├── prerequisite-verifier-directory.adapter.ts
357
362
  ├── prerequisite-verifier-dns.adapter.ts
358
363
  ├── prerequisite-verifier-external-api.adapter.ts
359
364
  ├── prerequisite-verifier-file.adapter.ts
360
- ├── prerequisite-verifier-jobs.adapter.ts
361
365
  ├── prerequisite-verifier-mailer.adapter.ts
362
366
  ├── prerequisite-verifier-memory.adapter.ts
363
367
  ├── prerequisite-verifier-node.adapter.ts
@@ -0,0 +1,23 @@
1
+ import * as v from "valibot";
2
+
3
+ export const CronExpressionError = { Type: "cron.expression.type", Invalid: "cron.expression.invalid" };
4
+
5
+ export const CronExpression = v.pipe(
6
+ v.string(CronExpressionError.Type),
7
+ v.check((value) => {
8
+ try {
9
+ return Bun.cron.parse(value) !== null;
10
+ } catch {
11
+ return false;
12
+ }
13
+ }, CronExpressionError.Invalid),
14
+ // Stryker disable next-line StringLiteral
15
+ v.brand("CronExpression"),
16
+ );
17
+
18
+ export type CronExpressionType = v.InferOutput<typeof CronExpression>;
19
+
20
+ export const CronExpressionSchedules = {
21
+ EVERY_MINUTE: v.parse(CronExpression, "* * * * *"),
22
+ EVERY_HOUR: v.parse(CronExpression, "0 * * * *"),
23
+ } as const;
@@ -0,0 +1,34 @@
1
+ import type { CronSchedulerPort } from "./cron-scheduler.port";
2
+ import type { CronTask } from "./cron-task.vo";
3
+ import { DynamicImport } from "./dynamic-import.service";
4
+
5
+ export const CronSchedulerCronerAdapterError = {
6
+ MissingDependency: "cron.scheduler.croner.adapter.error.missing.dependency",
7
+ };
8
+
9
+ type CronerLibrary = typeof import("croner");
10
+
11
+ export class CronSchedulerCronerAdapter implements CronSchedulerPort {
12
+ private static readonly importer = DynamicImport.for<CronerLibrary>(
13
+ "croner",
14
+ CronSchedulerCronerAdapterError.MissingDependency,
15
+ );
16
+
17
+ private readonly tasks: Array<InstanceType<CronerLibrary["Cron"]>> = [];
18
+
19
+ private constructor(private readonly croner: CronerLibrary) {}
20
+
21
+ static async build(): Promise<CronSchedulerCronerAdapter> {
22
+ const dependency = await CronSchedulerCronerAdapter.importer.resolve();
23
+
24
+ return new CronSchedulerCronerAdapter(dependency);
25
+ }
26
+
27
+ schedule(task: CronTask): void {
28
+ this.tasks.push(new this.croner.Cron(task.cron, {}, task.handler));
29
+ }
30
+
31
+ async verify(): Promise<boolean> {
32
+ return this.tasks.every((task) => task.isRunning());
33
+ }
34
+ }
@@ -0,0 +1,10 @@
1
+ import type { CronSchedulerPort } from "./cron-scheduler.port";
2
+ import type { CronTask } from "./cron-task.vo";
3
+
4
+ export class CronSchedulerNoopAdapter implements CronSchedulerPort {
5
+ schedule(_task: CronTask): void {}
6
+
7
+ async verify(): Promise<boolean> {
8
+ return true;
9
+ }
10
+ }
@@ -0,0 +1,7 @@
1
+ import type { CronTask } from "./cron-task.vo";
2
+
3
+ export interface CronSchedulerPort {
4
+ schedule(task: CronTask): void;
5
+
6
+ verify(): Promise<boolean>;
7
+ }
@@ -0,0 +1,17 @@
1
+ import { CorrelationStorage } from "./correlation-storage.service";
2
+ import type { CronTask } from "./cron-task.vo";
3
+ import type { CronTaskHandlerStrategy } from "./cron-task-handler.strategy";
4
+ import type { IdProviderPort } from "./id-provider.port";
5
+
6
+ type Dependencies = { IdProvider: IdProviderPort };
7
+
8
+ export class CronTaskHandlerBareStrategy implements CronTaskHandlerStrategy {
9
+ constructor(private readonly deps: Dependencies) {}
10
+
11
+ handle(task: CronTask): CronTask {
12
+ return {
13
+ ...task,
14
+ handler: async () => CorrelationStorage.run(this.deps.IdProvider.generate(), task.handler),
15
+ };
16
+ }
17
+ }
@@ -0,0 +1,8 @@
1
+ import type { CronTask } from "./cron-task.vo";
2
+ import type { CronTaskHandlerStrategy } from "./cron-task-handler.strategy";
3
+
4
+ export class CronTaskHandlerNoopStrategy implements CronTaskHandlerStrategy {
5
+ handle(task: CronTask): CronTask {
6
+ return { ...task, handler: async () => {} };
7
+ }
8
+ }
@@ -0,0 +1,46 @@
1
+ import type { ClockPort } from "./clock.port";
2
+ import { CorrelationStorage } from "./correlation-storage.service";
3
+ import type { CronTask } from "./cron-task.vo";
4
+ import type { CronTaskHandlerStrategy } from "./cron-task-handler.strategy";
5
+ import type { IdProviderPort } from "./id-provider.port";
6
+ import type { LoggerPort } from "./logger.port";
7
+ import { Stopwatch } from "./stopwatch.service";
8
+
9
+ type Dependencies = { Logger: LoggerPort; IdProvider: IdProviderPort; Clock: ClockPort };
10
+
11
+ export class CronTaskHandlerWithLoggerStrategy implements CronTaskHandlerStrategy {
12
+ private readonly base = { component: "infra", operation: "cron_task_handler" };
13
+
14
+ constructor(private readonly deps: Dependencies) {}
15
+
16
+ handle(task: CronTask): CronTask {
17
+ return {
18
+ ...task,
19
+ handler: async () => {
20
+ const correlationId = this.deps.IdProvider.generate();
21
+ const duration = new Stopwatch(this.deps);
22
+
23
+ try {
24
+ this.deps.Logger.info({ message: `${task.label} start`, correlationId, ...this.base });
25
+
26
+ await CorrelationStorage.run(correlationId, task.handler);
27
+
28
+ this.deps.Logger.info({
29
+ message: `${task.label} success`,
30
+ correlationId,
31
+ metadata: duration.stop(),
32
+ ...this.base,
33
+ });
34
+ } catch (error) {
35
+ this.deps.Logger.error({
36
+ message: `${task.label} error`,
37
+ correlationId,
38
+ error,
39
+ metadata: duration.stop(),
40
+ ...this.base,
41
+ });
42
+ }
43
+ },
44
+ };
45
+ }
46
+ }
@@ -0,0 +1,5 @@
1
+ import type { CronTask } from "./cron-task.vo";
2
+
3
+ export interface CronTaskHandlerStrategy {
4
+ handle(task: CronTask): CronTask;
5
+ }
@@ -0,0 +1,3 @@
1
+ import type { CronExpressionType } from "./cron-expression.vo";
2
+
3
+ export type CronTask = { label: string; cron: CronExpressionType; handler: () => Promise<void> };
package/src/index.ts CHANGED
@@ -65,6 +65,15 @@ export * from "./correlation.middleware";
65
65
  export * from "./correlation-hono.middleware";
66
66
  export * from "./correlation-id.vo";
67
67
  export * from "./correlation-storage.service";
68
+ export * from "./cron-expression.vo";
69
+ export * from "./cron-scheduler.port";
70
+ export * from "./cron-scheduler-croner.adapter";
71
+ export * from "./cron-scheduler-noop.adapter";
72
+ export * from "./cron-task.vo";
73
+ export * from "./cron-task-handler.strategy";
74
+ export * from "./cron-task-handler-bare.strategy";
75
+ export * from "./cron-task-handler-noop.strategy";
76
+ export * from "./cron-task-handler-with-logger.strategy";
68
77
  export * from "./crypto-key-provider.port";
69
78
  export * from "./crypto-key-provider-file.adapter";
70
79
  export * from "./crypto-key-provider-memory.adapter";
@@ -224,11 +233,6 @@ export * from "./in-flight-requests-tracker.service";
224
233
  export * from "./instrumentation.service";
225
234
  export * from "./invariant.service";
226
235
  export * from "./invariant-error-handler.service";
227
- export * from "./job-handler.strategy";
228
- export * from "./job-handler-bare.strategy";
229
- export * from "./job-handler-noop.strategy";
230
- export * from "./job-handler-with-logger.strategy";
231
- export * from "./jobs.service";
232
236
  export * from "./language-detector.middleware";
233
237
  export * from "./language-detector.strategy";
234
238
  export * from "./language-detector-cookie.strategy";
@@ -292,11 +296,11 @@ export * from "./prerequisite-verifier.port";
292
296
  export * from "./prerequisite-verifier-binary.adapter";
293
297
  export * from "./prerequisite-verifier-bun.adapter";
294
298
  export * from "./prerequisite-verifier-clock-drift.adapter";
299
+ export * from "./prerequisite-verifier-cron-scheduler.adapter";
295
300
  export * from "./prerequisite-verifier-directory.adapter";
296
301
  export * from "./prerequisite-verifier-dns.adapter";
297
302
  export * from "./prerequisite-verifier-external-api.adapter";
298
303
  export * from "./prerequisite-verifier-file.adapter";
299
- export * from "./prerequisite-verifier-jobs.adapter";
300
304
  export * from "./prerequisite-verifier-mailer.adapter";
301
305
  export * from "./prerequisite-verifier-memory.adapter";
302
306
  export * from "./prerequisite-verifier-node.adapter";
@@ -1,9 +1,9 @@
1
1
  import type { ClockPort } from "../../../clock.port";
2
+ import { CronExpressionSchedules } from "../../../cron-expression.vo";
3
+ import type { CronTask } from "../../../cron-task.vo";
2
4
  import { event } from "../../../event-envelope";
3
5
  import type { EventStorePort } from "../../../event-store.port";
4
6
  import type { IdProviderPort } from "../../../id-provider.port";
5
- import type { UnitOfWork } from "../../../job-handler.strategy";
6
- import { Jobs } from "../../../jobs.service";
7
7
  import { HourHasPassedEvent, type HourHasPassedEventType } from "../events/HOUR_HAS_PASSED_EVENT";
8
8
 
9
9
  type Dependencies = {
@@ -12,16 +12,12 @@ type Dependencies = {
12
12
  IdProvider: IdProviderPort;
13
13
  };
14
14
 
15
- export class PassageOfTimeHourly implements UnitOfWork {
16
- constructor(private readonly deps: Dependencies) {}
17
-
18
- static cron = Jobs.SCHEDULES.EVERY_HOUR;
19
-
20
- label = "PassageOfTime";
21
-
22
- async process() {
23
- await this.deps.EventStore.save([
24
- event(HourHasPassedEvent, "passage_of_time", { timestamp: this.deps.Clock.now().ms }, this.deps),
15
+ export const PassageOfTimeHourly = (deps: Dependencies): CronTask => ({
16
+ label: "PassageOfTimeHourly",
17
+ cron: CronExpressionSchedules.EVERY_HOUR,
18
+ handler: async () => {
19
+ await deps.EventStore.save([
20
+ event(HourHasPassedEvent, "passage_of_time", { timestamp: deps.Clock.now().ms }, deps),
25
21
  ]);
26
- }
27
- }
22
+ },
23
+ });
@@ -1,9 +1,9 @@
1
1
  import type { ClockPort } from "../../../clock.port";
2
+ import { CronExpressionSchedules } from "../../../cron-expression.vo";
3
+ import type { CronTask } from "../../../cron-task.vo";
2
4
  import { event } from "../../../event-envelope";
3
5
  import type { EventStorePort } from "../../../event-store.port";
4
6
  import type { IdProviderPort } from "../../../id-provider.port";
5
- import type { UnitOfWork } from "../../../job-handler.strategy";
6
- import { Jobs } from "../../../jobs.service";
7
7
  import { MinuteHasPassedEvent, type MinuteHasPassedEventType } from "../events/MINUTE_HAS_PASSED_EVENT";
8
8
 
9
9
  type Dependencies = {
@@ -12,16 +12,12 @@ type Dependencies = {
12
12
  IdProvider: IdProviderPort;
13
13
  };
14
14
 
15
- export class PassageOfTimeMinute implements UnitOfWork {
16
- constructor(private readonly deps: Dependencies) {}
17
-
18
- static cron = Jobs.SCHEDULES.EVERY_MINUTE;
19
-
20
- label = "PassageOfTime";
21
-
22
- async process() {
23
- await this.deps.EventStore.save([
24
- event(MinuteHasPassedEvent, "passage_of_time", { timestamp: this.deps.Clock.now().ms }, this.deps),
15
+ export const PassageOfTimeMinute = (deps: Dependencies): CronTask => ({
16
+ label: "PassageOfTimeMinute",
17
+ cron: CronExpressionSchedules.EVERY_MINUTE,
18
+ handler: async () => {
19
+ await deps.EventStore.save([
20
+ event(MinuteHasPassedEvent, "passage_of_time", { timestamp: deps.Clock.now().ms }, deps),
25
21
  ]);
26
- }
27
- }
22
+ },
23
+ });
@@ -0,0 +1,21 @@
1
+ import type { CronSchedulerPort } from "./cron-scheduler.port";
2
+ import {
3
+ PrerequisiteVerification,
4
+ type PrerequisiteVerificationResult,
5
+ type PrerequisiteVerifierPort,
6
+ } from "./prerequisite-verifier.port";
7
+
8
+ type Dependencies = { CronScheduler: CronSchedulerPort };
9
+
10
+ export class PrerequisiteVerifierCronSchedulerAdapter implements PrerequisiteVerifierPort {
11
+ constructor(private readonly deps: Dependencies) {}
12
+
13
+ async verify(): Promise<PrerequisiteVerificationResult> {
14
+ if (await this.deps.CronScheduler.verify()) return PrerequisiteVerification.success;
15
+ return PrerequisiteVerification.failure();
16
+ }
17
+
18
+ get kind(): string {
19
+ return "cron-scheduler";
20
+ }
21
+ }
@@ -1,12 +0,0 @@
1
- import type { IdProviderPort } from "./id-provider.port";
2
- import type { JobHandlerStrategy, UnitOfWork } from "./job-handler.strategy";
3
- type Dependencies = {
4
- IdProvider: IdProviderPort;
5
- };
6
- export declare class JobHandlerBareStrategy implements JobHandlerStrategy {
7
- private readonly deps;
8
- constructor(deps: Dependencies);
9
- handle(uow: UnitOfWork): () => Promise<void>;
10
- }
11
- export {};
12
- //# sourceMappingURL=job-handler-bare.strategy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler-bare.strategy.d.ts","sourceRoot":"","sources":["../src/job-handler-bare.strategy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE7E,KAAK,YAAY,GAAG;IAAE,UAAU,EAAE,cAAc,CAAA;CAAE,CAAC;AAEnD,qBAAa,sBAAuB,YAAW,kBAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,YAAY;IAE/C,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;CAK7C"}
@@ -1,12 +0,0 @@
1
- import { CorrelationStorage } from "./correlation-storage.service";
2
- export class JobHandlerBareStrategy {
3
- deps;
4
- constructor(deps) {
5
- this.deps = deps;
6
- }
7
- handle(uow) {
8
- const correlationId = this.deps.IdProvider.generate();
9
- return async () => CorrelationStorage.run(correlationId, async () => uow.process());
10
- }
11
- }
12
- //# sourceMappingURL=job-handler-bare.strategy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler-bare.strategy.js","sourceRoot":"","sources":["../src/job-handler-bare.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAMnE,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,IAAkB;QAAlB,SAAI,GAAJ,IAAI,CAAc;IAAG,CAAC;IAEnD,MAAM,CAAC,GAAe;QACpB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;QAEtD,OAAO,KAAK,IAAI,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;CACF"}
@@ -1,5 +0,0 @@
1
- import type { JobHandlerStrategy, UnitOfWork } from "./job-handler.strategy";
2
- export declare class JobHandlerNoopStrategy implements JobHandlerStrategy {
3
- handle(_uow: UnitOfWork): () => Promise<void>;
4
- }
5
- //# sourceMappingURL=job-handler-noop.strategy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler-noop.strategy.d.ts","sourceRoot":"","sources":["../src/job-handler-noop.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE7E,qBAAa,sBAAuB,YAAW,kBAAkB;IAC/D,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;CAG9C"}
@@ -1,6 +0,0 @@
1
- export class JobHandlerNoopStrategy {
2
- handle(_uow) {
3
- return async () => { };
4
- }
5
- }
6
- //# sourceMappingURL=job-handler-noop.strategy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler-noop.strategy.js","sourceRoot":"","sources":["../src/job-handler-noop.strategy.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,sBAAsB;IACjC,MAAM,CAAC,IAAgB;QACrB,OAAO,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;IACxB,CAAC;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler-with-logger.strategy.d.ts","sourceRoot":"","sources":["../src/job-handler-with-logger.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,KAAK,YAAY,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAEzF,qBAAa,4BAA6B,YAAW,kBAAkB;IAGzD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoD;gBAE5C,IAAI,EAAE,YAAY;IAE/C,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;CA4B7C"}
@@ -1,35 +0,0 @@
1
- import { CorrelationStorage } from "./correlation-storage.service";
2
- import { Stopwatch } from "./stopwatch.service";
3
- export class JobHandlerWithLoggerStrategy {
4
- deps;
5
- base = { component: "infra", operation: "job_handler" };
6
- constructor(deps) {
7
- this.deps = deps;
8
- }
9
- handle(uow) {
10
- const correlationId = this.deps.IdProvider.generate();
11
- return async () => {
12
- const duration = new Stopwatch(this.deps);
13
- try {
14
- this.deps.Logger.info({ message: `${uow.label} start`, correlationId, ...this.base });
15
- await CorrelationStorage.run(correlationId, async () => uow.process());
16
- this.deps.Logger.info({
17
- message: `${uow.label} success`,
18
- correlationId,
19
- metadata: duration.stop(),
20
- ...this.base,
21
- });
22
- }
23
- catch (error) {
24
- this.deps.Logger.error({
25
- message: `${uow.label} error`,
26
- correlationId,
27
- error,
28
- metadata: duration.stop(),
29
- ...this.base,
30
- });
31
- }
32
- };
33
- }
34
- }
35
- //# sourceMappingURL=job-handler-with-logger.strategy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler-with-logger.strategy.js","sourceRoot":"","sources":["../src/job-handler-with-logger.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAInE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAIhD,MAAM,OAAO,4BAA4B;IAGV;IAFZ,IAAI,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAEzE,YAA6B,IAAkB;QAAlB,SAAI,GAAJ,IAAI,CAAc;IAAG,CAAC;IAEnD,MAAM,CAAC,GAAe;QACpB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;QAEtD,OAAO,KAAK,IAAI,EAAE;YAChB,MAAM,QAAQ,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE1C,IAAI,CAAC;gBACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,KAAK,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBAEtF,MAAM,kBAAkB,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBAEvE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBACpB,OAAO,EAAE,GAAG,GAAG,CAAC,KAAK,UAAU;oBAC/B,aAAa;oBACb,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;oBACzB,GAAG,IAAI,CAAC,IAAI;iBACb,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;oBACrB,OAAO,EAAE,GAAG,GAAG,CAAC,KAAK,QAAQ;oBAC7B,aAAa;oBACb,KAAK;oBACL,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;oBACzB,GAAG,IAAI,CAAC,IAAI;iBACb,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;CACF"}
@@ -1,9 +0,0 @@
1
- import type { JobNameType } from "./jobs.service";
2
- export interface UnitOfWork {
3
- label: JobNameType;
4
- process: () => Promise<void>;
5
- }
6
- export interface JobHandlerStrategy {
7
- handle(uow: UnitOfWork): () => Promise<void>;
8
- }
9
- //# sourceMappingURL=job-handler.strategy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler.strategy.d.ts","sourceRoot":"","sources":["../src/job-handler.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=job-handler.strategy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"job-handler.strategy.js","sourceRoot":"","sources":["../src/job-handler.strategy.ts"],"names":[],"mappings":""}
@@ -1,15 +0,0 @@
1
- export type JobNameType = string;
2
- export type JobType = {
3
- stop: () => void;
4
- isRunning: () => boolean;
5
- };
6
- export type MultipleJobsType = Record<JobNameType, JobType>;
7
- export declare class Jobs {
8
- static SCHEDULES: {
9
- EVERY_MINUTE: string;
10
- EVERY_HOUR: string;
11
- };
12
- static stopAll(jobs: MultipleJobsType): void;
13
- static areAllRunning(jobs: MultipleJobsType): boolean;
14
- }
15
- //# sourceMappingURL=jobs.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jobs.service.d.ts","sourceRoot":"","sources":["../src/jobs.service.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AACjC,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,OAAO,CAAA;CAAE,CAAC;AACrE,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAE5D,qBAAa,IAAI;IACf,MAAM,CAAC,SAAS;;;MAA0D;IAE1E,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB;IAIrC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO;CAGtD"}
@@ -1,10 +0,0 @@
1
- export class Jobs {
2
- static SCHEDULES = { EVERY_MINUTE: "* * * * *", EVERY_HOUR: "0 * * * *" };
3
- static stopAll(jobs) {
4
- Object.values(jobs).forEach((job) => job.stop());
5
- }
6
- static areAllRunning(jobs) {
7
- return Object.values(jobs).every((job) => job.isRunning());
8
- }
9
- }
10
- //# sourceMappingURL=jobs.service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jobs.service.js","sourceRoot":"","sources":["../src/jobs.service.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,IAAI;IACf,MAAM,CAAC,SAAS,GAAG,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IAE1E,MAAM,CAAC,OAAO,CAAC,IAAsB;QACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,IAAsB;QACzC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7D,CAAC"}
@@ -1,13 +0,0 @@
1
- import { type MultipleJobsType } from "./jobs.service";
2
- import { type PrerequisiteVerificationResult, type PrerequisiteVerifierPort } from "./prerequisite-verifier.port";
3
- type Config = {
4
- Jobs: MultipleJobsType;
5
- };
6
- export declare class PrerequisiteVerifierJobsAdapter implements PrerequisiteVerifierPort {
7
- private readonly config;
8
- constructor(config: Config);
9
- verify(): Promise<PrerequisiteVerificationResult>;
10
- get kind(): string;
11
- }
12
- export {};
13
- //# sourceMappingURL=prerequisite-verifier-jobs.adapter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prerequisite-verifier-jobs.adapter.d.ts","sourceRoot":"","sources":["../src/prerequisite-verifier-jobs.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,wBAAwB,EAC9B,MAAM,8BAA8B,CAAC;AAEtC,KAAK,MAAM,GAAG;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEzC,qBAAa,+BAAgC,YAAW,wBAAwB;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAErC,MAAM,IAAI,OAAO,CAAC,8BAA8B,CAAC;IAKvD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}