glasswork 0.12.1 → 0.13.0

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 (114) hide show
  1. package/dist/auth/abilities.d.ts +41 -0
  2. package/dist/auth/abilities.d.ts.map +1 -0
  3. package/dist/auth/abilities.js +62 -0
  4. package/dist/auth/abilities.js.map +1 -0
  5. package/dist/auth/assert.d.ts +20 -0
  6. package/dist/auth/assert.d.ts.map +1 -0
  7. package/dist/auth/assert.js +28 -0
  8. package/dist/auth/assert.js.map +1 -0
  9. package/dist/auth/better-auth-provider.d.ts +56 -0
  10. package/dist/auth/better-auth-provider.d.ts.map +1 -0
  11. package/dist/auth/better-auth-provider.js +62 -0
  12. package/dist/auth/better-auth-provider.js.map +1 -0
  13. package/dist/auth/index.d.ts +6 -0
  14. package/dist/auth/index.d.ts.map +1 -0
  15. package/dist/auth/index.js +5 -0
  16. package/dist/auth/index.js.map +1 -0
  17. package/dist/auth/middleware.d.ts +31 -0
  18. package/dist/auth/middleware.d.ts.map +1 -0
  19. package/dist/auth/middleware.js +92 -0
  20. package/dist/auth/middleware.js.map +1 -0
  21. package/dist/auth/types.d.ts +54 -0
  22. package/dist/auth/types.d.ts.map +1 -0
  23. package/dist/auth/types.js +2 -0
  24. package/dist/auth/types.js.map +1 -0
  25. package/dist/core/bootstrap.d.ts.map +1 -1
  26. package/dist/core/bootstrap.js +5 -2
  27. package/dist/core/bootstrap.js.map +1 -1
  28. package/dist/core/types.d.ts +14 -3
  29. package/dist/core/types.d.ts.map +1 -1
  30. package/dist/http/route-helpers.d.ts +47 -9
  31. package/dist/http/route-helpers.d.ts.map +1 -1
  32. package/dist/http/route-helpers.js +91 -40
  33. package/dist/http/route-helpers.js.map +1 -1
  34. package/dist/index.d.ts +9 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +7 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/jobs/define-job.d.ts +57 -0
  39. package/dist/jobs/define-job.d.ts.map +1 -0
  40. package/dist/jobs/define-job.js +12 -0
  41. package/dist/jobs/define-job.js.map +1 -0
  42. package/dist/jobs/drivers/eventbridge-scheduler-driver.d.ts +75 -0
  43. package/dist/jobs/drivers/eventbridge-scheduler-driver.d.ts.map +1 -0
  44. package/dist/jobs/drivers/eventbridge-scheduler-driver.js +135 -0
  45. package/dist/jobs/drivers/eventbridge-scheduler-driver.js.map +1 -0
  46. package/dist/jobs/drivers/mock-driver.d.ts +73 -0
  47. package/dist/jobs/drivers/mock-driver.d.ts.map +1 -0
  48. package/dist/jobs/drivers/mock-driver.js +95 -0
  49. package/dist/jobs/drivers/mock-driver.js.map +1 -0
  50. package/dist/jobs/drivers/sqs-driver.d.ts +59 -0
  51. package/dist/jobs/drivers/sqs-driver.d.ts.map +1 -0
  52. package/dist/jobs/drivers/sqs-driver.js +176 -0
  53. package/dist/jobs/drivers/sqs-driver.js.map +1 -0
  54. package/dist/jobs/errors.d.ts +44 -0
  55. package/dist/jobs/errors.d.ts.map +1 -0
  56. package/dist/jobs/errors.js +67 -0
  57. package/dist/jobs/errors.js.map +1 -0
  58. package/dist/jobs/index.d.ts +12 -0
  59. package/dist/jobs/index.d.ts.map +1 -0
  60. package/dist/jobs/index.js +11 -0
  61. package/dist/jobs/index.js.map +1 -0
  62. package/dist/jobs/job-registry.d.ts +33 -0
  63. package/dist/jobs/job-registry.d.ts.map +1 -0
  64. package/dist/jobs/job-registry.js +56 -0
  65. package/dist/jobs/job-registry.js.map +1 -0
  66. package/dist/jobs/job-service.d.ts +44 -0
  67. package/dist/jobs/job-service.d.ts.map +1 -0
  68. package/dist/jobs/job-service.js +105 -0
  69. package/dist/jobs/job-service.js.map +1 -0
  70. package/dist/jobs/periodic-job.d.ts +6 -0
  71. package/dist/jobs/periodic-job.d.ts.map +1 -0
  72. package/dist/jobs/periodic-job.js +11 -0
  73. package/dist/jobs/periodic-job.js.map +1 -0
  74. package/dist/jobs/schedule-constants.d.ts +5 -0
  75. package/dist/jobs/schedule-constants.d.ts.map +1 -0
  76. package/dist/jobs/schedule-constants.js +5 -0
  77. package/dist/jobs/schedule-constants.js.map +1 -0
  78. package/dist/jobs/scheduler.d.ts +17 -0
  79. package/dist/jobs/scheduler.d.ts.map +1 -0
  80. package/dist/jobs/scheduler.js +83 -0
  81. package/dist/jobs/scheduler.js.map +1 -0
  82. package/dist/jobs/types.d.ts +165 -0
  83. package/dist/jobs/types.d.ts.map +1 -0
  84. package/dist/jobs/types.js +2 -0
  85. package/dist/jobs/types.js.map +1 -0
  86. package/dist/jobs/utils.d.ts +15 -0
  87. package/dist/jobs/utils.d.ts.map +1 -0
  88. package/dist/jobs/utils.js +49 -0
  89. package/dist/jobs/utils.js.map +1 -0
  90. package/dist/jobs/worker.d.ts +35 -0
  91. package/dist/jobs/worker.d.ts.map +1 -0
  92. package/dist/jobs/worker.js +361 -0
  93. package/dist/jobs/worker.js.map +1 -0
  94. package/dist/list-query/casl.d.ts +18 -19
  95. package/dist/list-query/casl.d.ts.map +1 -1
  96. package/dist/list-query/casl.js +40 -46
  97. package/dist/list-query/casl.js.map +1 -1
  98. package/dist/uploads/file-upload.d.ts +44 -0
  99. package/dist/uploads/file-upload.d.ts.map +1 -0
  100. package/dist/uploads/file-upload.js +145 -0
  101. package/dist/uploads/file-upload.js.map +1 -0
  102. package/dist/uploads/index.d.ts +6 -0
  103. package/dist/uploads/index.d.ts.map +1 -0
  104. package/dist/uploads/index.js +7 -0
  105. package/dist/uploads/index.js.map +1 -0
  106. package/dist/uploads/uploads.service.d.ts +98 -0
  107. package/dist/uploads/uploads.service.d.ts.map +1 -0
  108. package/dist/uploads/uploads.service.js +134 -0
  109. package/dist/uploads/uploads.service.js.map +1 -0
  110. package/dist/uploads/validators.d.ts +41 -0
  111. package/dist/uploads/validators.d.ts.map +1 -0
  112. package/dist/uploads/validators.js +94 -0
  113. package/dist/uploads/validators.js.map +1 -0
  114. package/package.json +34 -3
@@ -0,0 +1,75 @@
1
+ import type { EnqueueResult, JobMessage } from '../types.js';
2
+ export interface EventBridgeSchedulerConfig {
3
+ /** AWS region */
4
+ region: string;
5
+ /** IAM role ARN that EventBridge Scheduler assumes to send messages to SQS */
6
+ roleArn: string;
7
+ /** Optional schedule group name for organization (default: 'default') */
8
+ scheduleGroupName?: string;
9
+ /** Custom endpoint (for LocalStack) */
10
+ endpoint?: string;
11
+ }
12
+ export interface ScheduledJobConfig {
13
+ /** Target SQS queue URL */
14
+ queueUrl: string;
15
+ /** Job message */
16
+ message: JobMessage;
17
+ /** When to run the job */
18
+ scheduledAt: Date;
19
+ }
20
+ /**
21
+ * Result of scheduling a job with EventBridge Scheduler.
22
+ */
23
+ export interface ScheduleResult extends EnqueueResult {
24
+ /** EventBridge Scheduler schedule ARN */
25
+ scheduleArn: string;
26
+ /** Schedule name (can be used for cancellation) */
27
+ scheduleName: string;
28
+ }
29
+ /**
30
+ * EventBridge Scheduler driver for scheduling jobs with delays longer than 15 minutes.
31
+ *
32
+ * Uses one-off schedules with `at()` expressions that target an SQS queue.
33
+ * Schedules are automatically deleted after execution.
34
+ */
35
+ export declare class EventBridgeSchedulerDriver {
36
+ private readonly config;
37
+ private client;
38
+ constructor(config: EventBridgeSchedulerConfig);
39
+ /**
40
+ * Lazily initialize the Scheduler client.
41
+ */
42
+ private getClient;
43
+ /**
44
+ * Schedule a job to be executed at a specific time.
45
+ *
46
+ * Creates a one-off EventBridge Scheduler schedule that sends a message
47
+ * to the specified SQS queue at the scheduled time.
48
+ *
49
+ * @param config - The scheduled job configuration
50
+ * @returns Schedule result with ARN and name
51
+ */
52
+ scheduleAt(config: ScheduledJobConfig): Promise<ScheduleResult>;
53
+ /**
54
+ * Cancel a scheduled job.
55
+ *
56
+ * @param scheduleName - The name of the schedule to cancel
57
+ */
58
+ cancel(scheduleName: string): Promise<void>;
59
+ /**
60
+ * Dispose of the driver and release AWS SDK client resources.
61
+ * Call this when you're done using the driver to prevent memory leaks.
62
+ */
63
+ dispose(): Promise<void>;
64
+ /**
65
+ * Convert an SQS queue URL to its ARN.
66
+ *
67
+ * Supports both standard AWS and LocalStack URL formats:
68
+ * - AWS: https://sqs.{region}.amazonaws.com/{accountId}/{queueName}
69
+ * - LocalStack: http://localhost:4566/{accountId}/{queueName}
70
+ *
71
+ * ARN format: arn:aws:sqs:{region}:{accountId}:{queueName}
72
+ */
73
+ private sqsArnFromUrl;
74
+ }
75
+ //# sourceMappingURL=eventbridge-scheduler-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventbridge-scheduler-driver.d.ts","sourceRoot":"","sources":["../../../src/jobs/drivers/eventbridge-scheduler-driver.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAO7D,MAAM,WAAW,0BAA0B;IACzC,iBAAiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,0BAA0B;IAC1B,WAAW,EAAE,IAAI,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,qBAAa,0BAA0B;IAGzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,MAAM,CAAgC;gBAEjB,MAAM,EAAE,0BAA0B;IAE/D;;OAEG;YACW,SAAS;IAWvB;;;;;;;;OAQG;IACG,UAAU,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC;IAsDrE;;;;OAIG;IACG,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;CAwBtB"}
@@ -0,0 +1,135 @@
1
+ import { generateJobId } from '../utils.js';
2
+ /**
3
+ * EventBridge Scheduler driver for scheduling jobs with delays longer than 15 minutes.
4
+ *
5
+ * Uses one-off schedules with `at()` expressions that target an SQS queue.
6
+ * Schedules are automatically deleted after execution.
7
+ */
8
+ export class EventBridgeSchedulerDriver {
9
+ config;
10
+ client = null;
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ /**
15
+ * Lazily initialize the Scheduler client.
16
+ */
17
+ async getClient() {
18
+ if (!this.client) {
19
+ const { SchedulerClient } = await import('@aws-sdk/client-scheduler');
20
+ this.client = new SchedulerClient({
21
+ region: this.config.region,
22
+ ...(this.config.endpoint && { endpoint: this.config.endpoint }),
23
+ });
24
+ }
25
+ return this.client;
26
+ }
27
+ /**
28
+ * Schedule a job to be executed at a specific time.
29
+ *
30
+ * Creates a one-off EventBridge Scheduler schedule that sends a message
31
+ * to the specified SQS queue at the scheduled time.
32
+ *
33
+ * @param config - The scheduled job configuration
34
+ * @returns Schedule result with ARN and name
35
+ */
36
+ async scheduleAt(config) {
37
+ const client = await this.getClient();
38
+ const { CreateScheduleCommand } = await import('@aws-sdk/client-scheduler');
39
+ const jobId = config.message.jobId ?? generateJobId();
40
+ const scheduleName = `glasswork-${jobId}`;
41
+ // Format: at(yyyy-mm-ddThh:mm:ss)
42
+ const scheduleExpression = `at(${config.scheduledAt.toISOString().slice(0, 19)})`;
43
+ // Build the SQS message payload
44
+ const messageBody = JSON.stringify({
45
+ jobName: config.message.jobName,
46
+ payload: config.message.payload,
47
+ jobId,
48
+ metadata: config.message.metadata,
49
+ enqueuedAt: new Date().toISOString(),
50
+ });
51
+ const command = new CreateScheduleCommand({
52
+ Name: scheduleName,
53
+ GroupName: this.config.scheduleGroupName ?? 'default',
54
+ ScheduleExpression: scheduleExpression,
55
+ ScheduleExpressionTimezone: 'UTC',
56
+ FlexibleTimeWindow: {
57
+ Mode: 'OFF',
58
+ },
59
+ Target: {
60
+ Arn: this.sqsArnFromUrl(config.queueUrl),
61
+ RoleArn: this.config.roleArn,
62
+ Input: messageBody,
63
+ SqsParameters: {
64
+ MessageGroupId: config.message.queue ?? config.message.jobName,
65
+ },
66
+ },
67
+ // Auto-delete the schedule after it runs
68
+ ActionAfterCompletion: 'DELETE',
69
+ });
70
+ const result = await client.send(command);
71
+ const scheduleArn = result.ScheduleArn;
72
+ if (!scheduleArn) {
73
+ throw new Error('EventBridge Scheduler did not return a schedule ARN');
74
+ }
75
+ return {
76
+ messageId: jobId,
77
+ jobId,
78
+ scheduleArn,
79
+ scheduleName,
80
+ };
81
+ }
82
+ /**
83
+ * Cancel a scheduled job.
84
+ *
85
+ * @param scheduleName - The name of the schedule to cancel
86
+ */
87
+ async cancel(scheduleName) {
88
+ const client = await this.getClient();
89
+ const { DeleteScheduleCommand } = await import('@aws-sdk/client-scheduler');
90
+ const command = new DeleteScheduleCommand({
91
+ Name: scheduleName,
92
+ GroupName: this.config.scheduleGroupName ?? 'default',
93
+ });
94
+ await client.send(command);
95
+ }
96
+ /**
97
+ * Dispose of the driver and release AWS SDK client resources.
98
+ * Call this when you're done using the driver to prevent memory leaks.
99
+ */
100
+ async dispose() {
101
+ if (this.client) {
102
+ this.client.destroy();
103
+ this.client = null;
104
+ }
105
+ }
106
+ /**
107
+ * Convert an SQS queue URL to its ARN.
108
+ *
109
+ * Supports both standard AWS and LocalStack URL formats:
110
+ * - AWS: https://sqs.{region}.amazonaws.com/{accountId}/{queueName}
111
+ * - LocalStack: http://localhost:4566/{accountId}/{queueName}
112
+ *
113
+ * ARN format: arn:aws:sqs:{region}:{accountId}:{queueName}
114
+ */
115
+ sqsArnFromUrl(queueUrl) {
116
+ const url = new URL(queueUrl);
117
+ const pathParts = url.pathname.split('/').filter(Boolean);
118
+ if (pathParts.length < 2) {
119
+ throw new Error(`Invalid SQS queue URL format: ${queueUrl}`);
120
+ }
121
+ const accountId = pathParts[0];
122
+ const queueName = pathParts[1];
123
+ // Determine region from URL or fall back to configured region
124
+ // Standard AWS format: sqs.{region}.amazonaws.com
125
+ // LocalStack format: localhost:4566 (no region in hostname)
126
+ let region = this.config.region;
127
+ const hostParts = url.hostname.split('.');
128
+ const isAwsUrl = url.hostname.includes('amazonaws.com');
129
+ if (isAwsUrl && hostParts.length >= 2 && hostParts[0] === 'sqs') {
130
+ region = hostParts[1];
131
+ }
132
+ return `arn:aws:sqs:${region}:${accountId}:${queueName}`;
133
+ }
134
+ }
135
+ //# sourceMappingURL=eventbridge-scheduler-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventbridge-scheduler-driver.js","sourceRoot":"","sources":["../../../src/jobs/drivers/eventbridge-scheduler-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import type { JobRegistry } from '../job-registry.js';
2
+ import type { Duration, EnqueueResult, JobMessage, QueueDriver } from '../types.js';
3
+ export interface MockEnqueuedJob {
4
+ message: JobMessage & {
5
+ jobId: string;
6
+ };
7
+ at?: Date;
8
+ delay?: Duration;
9
+ }
10
+ /**
11
+ * Configuration for MockQueueDriver.
12
+ */
13
+ export interface MockQueueDriverConfig {
14
+ /**
15
+ * Execute jobs synchronously when enqueued.
16
+ * Useful for local development to test job handlers immediately.
17
+ * @default false
18
+ */
19
+ executeImmediately?: boolean;
20
+ /**
21
+ * Job registry for looking up job definitions.
22
+ * Required when executeImmediately is true.
23
+ */
24
+ registry?: JobRegistry;
25
+ /**
26
+ * Resolver to get DI services for job execution.
27
+ * Called when a job is executed, returning the services container.
28
+ * Required when executeImmediately is true.
29
+ */
30
+ serviceResolver?: () => Record<string, unknown>;
31
+ }
32
+ /**
33
+ * In-memory queue driver for testing and local development.
34
+ *
35
+ * @example Testing mode (default)
36
+ * ```typescript
37
+ * const driver = new MockQueueDriver();
38
+ * await jobService.enqueue(myJob, payload);
39
+ * expect(driver.enqueued).toHaveLength(1);
40
+ * ```
41
+ *
42
+ * @example Development mode with immediate execution
43
+ * ```typescript
44
+ * const driver = new MockQueueDriver({
45
+ * executeImmediately: true,
46
+ * registry: createJobRegistry([myJob]),
47
+ * serviceResolver: () => diContainer,
48
+ * });
49
+ * ```
50
+ */
51
+ export declare class MockQueueDriver implements QueueDriver {
52
+ readonly name = "mock";
53
+ private counter;
54
+ private failNext?;
55
+ private readonly executeImmediately;
56
+ private readonly registry?;
57
+ private readonly serviceResolver?;
58
+ readonly enqueued: MockEnqueuedJob[];
59
+ constructor(config?: MockQueueDriverConfig);
60
+ /**
61
+ * Simulate the next enqueue call failing.
62
+ */
63
+ simulateFailure(error?: Error): void;
64
+ /**
65
+ * Clear stored jobs and reset counters.
66
+ */
67
+ clear(): void;
68
+ get lastJob(): MockEnqueuedJob | undefined;
69
+ enqueue(message: JobMessage): Promise<EnqueueResult>;
70
+ enqueueAt(message: JobMessage, at: Date): Promise<EnqueueResult>;
71
+ enqueueIn(message: JobMessage, delay: Duration): Promise<EnqueueResult>;
72
+ }
73
+ //# sourceMappingURL=mock-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-driver.d.ts","sourceRoot":"","sources":["../../../src/jobs/drivers/mock-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAc,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGhG,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,EAAE,CAAC,EAAE,IAAI,CAAC;IACV,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC;IAEvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,QAAQ,CAAC,IAAI,UAAU;IACvB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAgC;IACjE,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAM;gBAE9B,MAAM,GAAE,qBAA0B;IAM9C;;OAEG;IACH,eAAe,CAAC,KAAK,QAAoC,GAAG,IAAI;IAIhE;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb,IAAI,OAAO,IAAI,eAAe,GAAG,SAAS,CAEzC;IAEK,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAgCpD,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAShE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;CAQ9E"}
@@ -0,0 +1,95 @@
1
+ import { generateJobId } from '../utils.js';
2
+ /**
3
+ * In-memory queue driver for testing and local development.
4
+ *
5
+ * @example Testing mode (default)
6
+ * ```typescript
7
+ * const driver = new MockQueueDriver();
8
+ * await jobService.enqueue(myJob, payload);
9
+ * expect(driver.enqueued).toHaveLength(1);
10
+ * ```
11
+ *
12
+ * @example Development mode with immediate execution
13
+ * ```typescript
14
+ * const driver = new MockQueueDriver({
15
+ * executeImmediately: true,
16
+ * registry: createJobRegistry([myJob]),
17
+ * serviceResolver: () => diContainer,
18
+ * });
19
+ * ```
20
+ */
21
+ export class MockQueueDriver {
22
+ name = 'mock';
23
+ counter = 0;
24
+ failNext;
25
+ executeImmediately;
26
+ registry;
27
+ serviceResolver;
28
+ enqueued = [];
29
+ constructor(config = {}) {
30
+ this.executeImmediately = config.executeImmediately ?? false;
31
+ this.registry = config.registry;
32
+ this.serviceResolver = config.serviceResolver;
33
+ }
34
+ /**
35
+ * Simulate the next enqueue call failing.
36
+ */
37
+ simulateFailure(error = new Error('Mock enqueue failure')) {
38
+ this.failNext = error;
39
+ }
40
+ /**
41
+ * Clear stored jobs and reset counters.
42
+ */
43
+ clear() {
44
+ this.enqueued.length = 0;
45
+ this.counter = 0;
46
+ this.failNext = undefined;
47
+ }
48
+ get lastJob() {
49
+ return this.enqueued.at(-1);
50
+ }
51
+ async enqueue(message) {
52
+ if (this.failNext) {
53
+ const error = this.failNext;
54
+ this.failNext = undefined;
55
+ throw error;
56
+ }
57
+ const jobId = message.jobId ?? generateJobId();
58
+ const result = {
59
+ messageId: `mock-${++this.counter}`,
60
+ jobId,
61
+ };
62
+ this.enqueued.push({
63
+ message: { ...message, jobId },
64
+ });
65
+ // Execute immediately if configured
66
+ if (this.executeImmediately && this.registry && this.serviceResolver) {
67
+ const job = this.registry.getOrThrow(message.jobName);
68
+ const context = {
69
+ services: this.serviceResolver(),
70
+ jobId,
71
+ attemptNumber: 1,
72
+ enqueuedAt: new Date(),
73
+ };
74
+ await job.handler(message.payload, context);
75
+ }
76
+ return result;
77
+ }
78
+ async enqueueAt(message, at) {
79
+ const result = await this.enqueue(message);
80
+ const last = this.enqueued[this.enqueued.length - 1];
81
+ if (last) {
82
+ last.at = at;
83
+ }
84
+ return result;
85
+ }
86
+ async enqueueIn(message, delay) {
87
+ const result = await this.enqueue(message);
88
+ const last = this.enqueued[this.enqueued.length - 1];
89
+ if (last) {
90
+ last.delay = delay;
91
+ }
92
+ return result;
93
+ }
94
+ }
95
+ //# sourceMappingURL=mock-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-driver.js","sourceRoot":"","sources":["../../../src/jobs/drivers/mock-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { SQSClient as SQSClientType } from '@aws-sdk/client-sqs';
2
+ import type { Duration, EnqueueResult, JobMessage, QueueDriver } from '../types.js';
3
+ import { type EventBridgeSchedulerConfig } from './eventbridge-scheduler-driver.js';
4
+ export interface SQSDriverConfig {
5
+ /** AWS region */
6
+ region: string;
7
+ /** Queue URL mapping (queue name -> URL) */
8
+ queues: Record<string, string>;
9
+ /** Default queue name */
10
+ defaultQueue?: string;
11
+ /** Custom endpoint (for LocalStack) */
12
+ endpoint?: string;
13
+ /**
14
+ * EventBridge Scheduler configuration for delays over 15 minutes.
15
+ * Required when using enqueueAt or enqueueIn with delays exceeding SQS maximum.
16
+ */
17
+ scheduler?: EventBridgeSchedulerConfig;
18
+ /** Optional pre-configured SQS client */
19
+ client?: SQSClientType;
20
+ }
21
+ /**
22
+ * AWS SQS queue driver with EventBridge Scheduler support for long delays.
23
+ *
24
+ * For delays up to 15 minutes, uses native SQS delay.
25
+ * For delays over 15 minutes, uses EventBridge Scheduler to create a one-off
26
+ * schedule that sends the job to SQS at the specified time.
27
+ */
28
+ export declare class SQSQueueDriver implements QueueDriver {
29
+ private readonly config;
30
+ readonly name = "sqs";
31
+ readonly defaultQueue: string;
32
+ private client;
33
+ private schedulerDriver;
34
+ private disposed;
35
+ constructor(config: SQSDriverConfig);
36
+ /**
37
+ * Lazily initialize the SQS client.
38
+ * @throws Error if the driver has been disposed
39
+ */
40
+ private getClient;
41
+ enqueue(message: JobMessage): Promise<EnqueueResult>;
42
+ enqueueAt(message: JobMessage, at: Date): Promise<EnqueueResult>;
43
+ enqueueIn(message: JobMessage, delay: Duration): Promise<EnqueueResult>;
44
+ /**
45
+ * Cancel a scheduled job. Only works for jobs scheduled with EventBridge Scheduler.
46
+ *
47
+ * @param scheduleName - The schedule name from the ScheduleResult
48
+ */
49
+ cancelSchedule(scheduleName: string): Promise<void>;
50
+ /**
51
+ * Dispose of the driver and release AWS SDK client resources.
52
+ * Call this when you're done using the driver to prevent memory leaks.
53
+ */
54
+ dispose(): Promise<void>;
55
+ private getQueueUrl;
56
+ private enqueueWithDelay;
57
+ private scheduleWithEventBridge;
58
+ }
59
+ //# sourceMappingURL=sqs-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqs-driver.d.ts","sourceRoot":"","sources":["../../../src/jobs/drivers/sqs-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,IAAI,aAAa,EAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEpF,OAAO,EACL,KAAK,0BAA0B,EAGhC,MAAM,mCAAmC,CAAC;AAK3C,MAAM,WAAW,eAAe;IAC9B,iBAAiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,yBAAyB;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,0BAA0B,CAAC;IACvC,yCAAyC;IACzC,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;;;;GAMG;AACH,qBAAa,cAAe,YAAW,WAAW;IAOpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IANnC,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,QAAQ,CAAS;gBAEI,MAAM,EAAE,eAAe;IAUpD;;;OAGG;YACW,SAAS;IAcjB,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAqCpD,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAWhE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IAS7E;;;;OAIG;IACG,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,OAAO,CAAC,WAAW;YASL,gBAAgB;YAyChB,uBAAuB;CAgBtC"}
@@ -0,0 +1,176 @@
1
+ import { MAX_SQS_DELAY_SECONDS } from '../schedule-constants.js';
2
+ import { durationToSeconds, generateJobId } from '../utils.js';
3
+ import { EventBridgeSchedulerDriver, } from './eventbridge-scheduler-driver.js';
4
+ /**
5
+ * AWS SQS queue driver with EventBridge Scheduler support for long delays.
6
+ *
7
+ * For delays up to 15 minutes, uses native SQS delay.
8
+ * For delays over 15 minutes, uses EventBridge Scheduler to create a one-off
9
+ * schedule that sends the job to SQS at the specified time.
10
+ */
11
+ export class SQSQueueDriver {
12
+ config;
13
+ name = 'sqs';
14
+ defaultQueue;
15
+ client = null;
16
+ schedulerDriver = null;
17
+ disposed = false;
18
+ constructor(config) {
19
+ this.config = config;
20
+ this.defaultQueue = config.defaultQueue ?? 'default';
21
+ if (config.client) {
22
+ this.client = config.client;
23
+ }
24
+ if (config.scheduler) {
25
+ this.schedulerDriver = new EventBridgeSchedulerDriver(config.scheduler);
26
+ }
27
+ }
28
+ /**
29
+ * Lazily initialize the SQS client.
30
+ * @throws Error if the driver has been disposed
31
+ */
32
+ async getClient() {
33
+ if (this.disposed) {
34
+ throw new Error('SQSQueueDriver has been disposed');
35
+ }
36
+ if (!this.client) {
37
+ const { SQSClient } = await import('@aws-sdk/client-sqs');
38
+ this.client = new SQSClient({
39
+ region: this.config.region,
40
+ ...(this.config.endpoint && { endpoint: this.config.endpoint }),
41
+ });
42
+ }
43
+ return this.client;
44
+ }
45
+ async enqueue(message) {
46
+ const client = await this.getClient();
47
+ const { SendMessageCommand } = await import('@aws-sdk/client-sqs');
48
+ const queueUrl = this.getQueueUrl(message.queue);
49
+ const jobId = message.jobId ?? generateJobId();
50
+ const isFifo = queueUrl.endsWith('.fifo');
51
+ const command = new SendMessageCommand({
52
+ QueueUrl: queueUrl,
53
+ MessageBody: JSON.stringify({
54
+ jobName: message.jobName,
55
+ payload: message.payload,
56
+ jobId,
57
+ metadata: message.metadata,
58
+ enqueuedAt: new Date().toISOString(),
59
+ }),
60
+ MessageAttributes: {
61
+ JobName: { DataType: 'String', StringValue: message.jobName },
62
+ },
63
+ ...(isFifo && {
64
+ MessageGroupId: message.queue ?? message.jobName,
65
+ MessageDeduplicationId: jobId,
66
+ }),
67
+ });
68
+ const result = await client.send(command);
69
+ const messageId = result.MessageId;
70
+ if (!messageId) {
71
+ throw new Error('SQS did not return a message ID');
72
+ }
73
+ return {
74
+ messageId,
75
+ jobId,
76
+ };
77
+ }
78
+ async enqueueAt(message, at) {
79
+ const delaySeconds = Math.max(0, Math.floor((at.getTime() - Date.now()) / 1000));
80
+ if (delaySeconds <= 0) {
81
+ return this.enqueue(message);
82
+ }
83
+ if (delaySeconds <= MAX_SQS_DELAY_SECONDS) {
84
+ return this.enqueueWithDelay(message, delaySeconds);
85
+ }
86
+ return this.scheduleWithEventBridge(message, at);
87
+ }
88
+ async enqueueIn(message, delay) {
89
+ const delaySeconds = durationToSeconds(delay);
90
+ if (delaySeconds <= MAX_SQS_DELAY_SECONDS) {
91
+ return this.enqueueWithDelay(message, delaySeconds);
92
+ }
93
+ const at = new Date(Date.now() + delaySeconds * 1000);
94
+ return this.scheduleWithEventBridge(message, at);
95
+ }
96
+ /**
97
+ * Cancel a scheduled job. Only works for jobs scheduled with EventBridge Scheduler.
98
+ *
99
+ * @param scheduleName - The schedule name from the ScheduleResult
100
+ */
101
+ async cancelSchedule(scheduleName) {
102
+ if (!this.schedulerDriver) {
103
+ throw new Error('EventBridge Scheduler is not configured');
104
+ }
105
+ await this.schedulerDriver.cancel(scheduleName);
106
+ }
107
+ /**
108
+ * Dispose of the driver and release AWS SDK client resources.
109
+ * Call this when you're done using the driver to prevent memory leaks.
110
+ */
111
+ async dispose() {
112
+ this.disposed = true;
113
+ if (this.client) {
114
+ this.client.destroy();
115
+ this.client = null;
116
+ }
117
+ if (this.schedulerDriver) {
118
+ await this.schedulerDriver.dispose();
119
+ }
120
+ }
121
+ getQueueUrl(queue) {
122
+ const queueName = queue ?? this.defaultQueue;
123
+ const queueUrl = this.config.queues[queueName];
124
+ if (!queueUrl) {
125
+ throw new Error(`Queue "${queueName}" is not configured for SQS driver`);
126
+ }
127
+ return queueUrl;
128
+ }
129
+ async enqueueWithDelay(message, delaySeconds) {
130
+ const client = await this.getClient();
131
+ const { SendMessageCommand } = await import('@aws-sdk/client-sqs');
132
+ const queueUrl = this.getQueueUrl(message.queue);
133
+ const jobId = message.jobId ?? generateJobId();
134
+ const isFifo = queueUrl.endsWith('.fifo');
135
+ const command = new SendMessageCommand({
136
+ QueueUrl: queueUrl,
137
+ MessageBody: JSON.stringify({
138
+ jobName: message.jobName,
139
+ payload: message.payload,
140
+ jobId,
141
+ metadata: message.metadata,
142
+ enqueuedAt: new Date().toISOString(),
143
+ }),
144
+ DelaySeconds: Math.min(MAX_SQS_DELAY_SECONDS, Math.max(0, Math.floor(delaySeconds))),
145
+ MessageAttributes: {
146
+ JobName: { DataType: 'String', StringValue: message.jobName },
147
+ },
148
+ ...(isFifo && {
149
+ MessageGroupId: message.queue ?? message.jobName,
150
+ MessageDeduplicationId: jobId,
151
+ }),
152
+ });
153
+ const result = await client.send(command);
154
+ const messageId = result.MessageId;
155
+ if (!messageId) {
156
+ throw new Error('SQS did not return a message ID');
157
+ }
158
+ return {
159
+ messageId,
160
+ jobId,
161
+ };
162
+ }
163
+ async scheduleWithEventBridge(message, at) {
164
+ if (!this.schedulerDriver) {
165
+ throw new Error('EventBridge Scheduler configuration is required for delays over 15 minutes. ' +
166
+ 'Configure the `scheduler` option in SQSDriverConfig.');
167
+ }
168
+ const queueUrl = this.getQueueUrl(message.queue);
169
+ return this.schedulerDriver.scheduleAt({
170
+ queueUrl,
171
+ message,
172
+ scheduledAt: at,
173
+ });
174
+ }
175
+ }
176
+ //# sourceMappingURL=sqs-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqs-driver.js","sourceRoot":"","sources":["../../../src/jobs/drivers/sqs-driver.ts"],"names":[],"mappings":"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"}