@lafken/queue 0.10.1
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.
- package/LICENCE +21 -0
- package/README.md +247 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +17 -0
- package/lib/main/event/event.d.ts +99 -0
- package/lib/main/event/event.js +125 -0
- package/lib/main/event/event.types.d.ts +89 -0
- package/lib/main/event/event.types.js +2 -0
- package/lib/main/event/index.d.ts +2 -0
- package/lib/main/event/index.js +18 -0
- package/lib/main/index.d.ts +2 -0
- package/lib/main/index.js +18 -0
- package/lib/main/queue/index.d.ts +2 -0
- package/lib/main/queue/index.js +18 -0
- package/lib/main/queue/queue.d.ts +65 -0
- package/lib/main/queue/queue.js +129 -0
- package/lib/main/queue/queue.types.d.ts +105 -0
- package/lib/main/queue/queue.types.js +2 -0
- package/lib/resolver/index.d.ts +1 -0
- package/lib/resolver/index.js +17 -0
- package/lib/resolver/queue/queue.d.ts +19 -0
- package/lib/resolver/queue/queue.js +86 -0
- package/lib/resolver/queue/queue.types.d.ts +7 -0
- package/lib/resolver/queue/queue.types.js +2 -0
- package/lib/resolver/resolver.d.ts +6 -0
- package/lib/resolver/resolver.js +29 -0
- package/lib/service/client/client.d.ts +2 -0
- package/lib/service/client/client.js +5 -0
- package/lib/service/commands/send-message/send-message.d.ts +7 -0
- package/lib/service/commands/send-message/send-message.js +25 -0
- package/lib/service/commands/send-message/send-message.types.d.ts +14 -0
- package/lib/service/commands/send-message/send-message.types.js +2 -0
- package/lib/service/commands/send-message-base/send-message-base.d.ts +5 -0
- package/lib/service/commands/send-message-base/send-message-base.js +26 -0
- package/lib/service/commands/send-message-batch/send-message-batch.d.ts +7 -0
- package/lib/service/commands/send-message-batch/send-message-batch.js +28 -0
- package/lib/service/commands/send-message-batch/send-message-batch.types.d.ts +5 -0
- package/lib/service/commands/send-message-batch/send-message-batch.types.js +2 -0
- package/lib/service/index.d.ts +6 -0
- package/lib/service/index.js +16 -0
- package/package.json +93 -0
package/LICENCE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aníbal Emilio Jorquera Cornejo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# @lafken/queue
|
|
2
|
+
|
|
3
|
+
Define and consume Amazon SQS queues using TypeScript decorators. `@lafken/queue` lets you declare Standard and FIFO queues, map message data to typed handler parameters, and send messages at runtime through a built-in service client.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lafken/queue
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
Define a queue class with `@Queue`, add consumer methods with `@Standard` or `@Fifo`, and register everything through `QueueResolver`:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createApp, createModule } from '@lafken/main';
|
|
17
|
+
import { QueueResolver } from '@lafken/queue/resolver';
|
|
18
|
+
import { Queue, Standard, Payload, Param, Event } from '@lafken/queue/main';
|
|
19
|
+
|
|
20
|
+
// 1. Define the message payload
|
|
21
|
+
@Payload()
|
|
22
|
+
export class OrderMessage {
|
|
23
|
+
@Param({ source: 'body', parse: true })
|
|
24
|
+
orderId: string;
|
|
25
|
+
|
|
26
|
+
@Param({ source: 'body', parse: true })
|
|
27
|
+
total: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Define the queue and its consumer
|
|
31
|
+
@Queue()
|
|
32
|
+
export class OrderQueue {
|
|
33
|
+
@Standard({ batchSize: 5, visibilityTimeout: 60 })
|
|
34
|
+
processOrder(@Event(OrderMessage) message: OrderMessage) {
|
|
35
|
+
console.log(`Processing order ${message.orderId}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 3. Register in a module
|
|
40
|
+
const orderModule = createModule({
|
|
41
|
+
name: 'order',
|
|
42
|
+
resources: [OrderQueue],
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// 4. Add the resolver to the app
|
|
46
|
+
createApp({
|
|
47
|
+
name: 'my-app',
|
|
48
|
+
resolvers: [new QueueResolver()],
|
|
49
|
+
modules: [orderModule],
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Each `@Standard` or `@Fifo` method becomes an independent Lambda function with its own SQS queue and event source mapping.
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
### Queue Class
|
|
58
|
+
|
|
59
|
+
Use the `@Queue` decorator to group related queue consumers in a single class. A queue class can contain multiple `@Standard` and `@Fifo` handlers:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { Queue, Standard, Fifo } from '@lafken/queue/main';
|
|
63
|
+
|
|
64
|
+
@Queue()
|
|
65
|
+
export class NotificationQueue {
|
|
66
|
+
@Standard({ queueName: 'email-notifications' })
|
|
67
|
+
sendEmail() { }
|
|
68
|
+
|
|
69
|
+
@Fifo({ queueName: 'sms-notifications', contentBasedDeduplication: true })
|
|
70
|
+
sendSms() { }
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Standard Queues
|
|
75
|
+
|
|
76
|
+
Use the `@Standard` decorator to create a standard (non-FIFO) SQS queue consumer. Messages are delivered at least once with best-effort ordering:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
@Standard({
|
|
80
|
+
queueName: 'reports',
|
|
81
|
+
batchSize: 10,
|
|
82
|
+
visibilityTimeout: 120,
|
|
83
|
+
maxConcurrency: 5,
|
|
84
|
+
})
|
|
85
|
+
generateReport(@Event(ReportMessage) message: ReportMessage) {
|
|
86
|
+
// Process up to 10 messages per invocation
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
If `queueName` is omitted, the method name is used as the queue name.
|
|
91
|
+
|
|
92
|
+
#### Standard Queue Options
|
|
93
|
+
|
|
94
|
+
| Option | Type | Description |
|
|
95
|
+
| --------------------- | -------- | ------------------------------------------------------------------ |
|
|
96
|
+
| `queueName` | `string` | Queue name (defaults to the method name) |
|
|
97
|
+
| `batchSize` | `1–10` | Number of messages per Lambda invocation |
|
|
98
|
+
| `visibilityTimeout` | `number` | Seconds a message is hidden from other consumers while processing |
|
|
99
|
+
| `deliveryDelay` | `number` | Seconds to delay message delivery after it is sent |
|
|
100
|
+
| `retentionPeriod` | `number` | Seconds messages are retained before automatic deletion |
|
|
101
|
+
| `maxMessageSizeBytes` | `number` | Maximum message size in bytes |
|
|
102
|
+
| `maxConcurrency` | `number` | Maximum concurrent Lambda invocations for this queue |
|
|
103
|
+
| `maxBatchingWindow` | `number` | Seconds to wait gathering messages into a batch before invoking |
|
|
104
|
+
| `lambda` | `object` | Lambda-specific configuration (memory, timeout, etc.) |
|
|
105
|
+
|
|
106
|
+
### FIFO Queues
|
|
107
|
+
|
|
108
|
+
Use the `@Fifo` decorator for FIFO (First-In-First-Out) queues. FIFO queues guarantee exactly-once processing and strict message ordering. The queue name automatically gets a `.fifo` suffix:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
@Fifo({
|
|
112
|
+
queueName: 'payment-processing',
|
|
113
|
+
contentBasedDeduplication: true,
|
|
114
|
+
batchSize: 1,
|
|
115
|
+
})
|
|
116
|
+
processPayment(@Event(PaymentMessage) message: PaymentMessage) {
|
|
117
|
+
// Messages are processed in exact send order
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
FIFO queues support all standard queue options plus:
|
|
122
|
+
|
|
123
|
+
| Option | Type | Description |
|
|
124
|
+
| --------------------------- | --------- | --------------------------------------------------------------- |
|
|
125
|
+
| `contentBasedDeduplication` | `boolean` | Use message content to generate deduplication IDs automatically |
|
|
126
|
+
|
|
127
|
+
> [!NOTE]
|
|
128
|
+
> FIFO queues automatically enable `ReportBatchItemFailures`, allowing partial batch failure reporting.
|
|
129
|
+
|
|
130
|
+
### Message Payload
|
|
131
|
+
|
|
132
|
+
Use `@Payload` on a class to define the structure of SQS messages. Decorate each property with `@Param` to specify where the value is extracted from in the SQS record:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { Payload, Param } from '@lafken/queue/main';
|
|
136
|
+
|
|
137
|
+
@Payload()
|
|
138
|
+
export class TaskMessage {
|
|
139
|
+
@Param({ source: 'attribute', type: String })
|
|
140
|
+
correlationId: string;
|
|
141
|
+
|
|
142
|
+
@Param({ source: 'body', parse: true })
|
|
143
|
+
taskName: string;
|
|
144
|
+
|
|
145
|
+
@Param({ source: 'body', parse: true })
|
|
146
|
+
priority: number;
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### @Param Options
|
|
151
|
+
|
|
152
|
+
| Option | Type | Default | Description |
|
|
153
|
+
| -------- | ------------------------- | ------------- | ------------------------------------------------ |
|
|
154
|
+
| `source` | `'attribute' \| 'body'` | `'attribute'` | Where to extract the value from the SQS record |
|
|
155
|
+
| `parse` | `boolean` | `false` | JSON-parse the message body before extraction |
|
|
156
|
+
| `type` | `String \| Number \| ...` | inferred | Data type of the extracted value |
|
|
157
|
+
| `name` | `string` | property name | Override the field name used for extraction |
|
|
158
|
+
|
|
159
|
+
- **`source: 'attribute'`** — reads from SQS message attributes (supports `String` and `Number` types)
|
|
160
|
+
- **`source: 'body'`** — reads from the message body. Set `parse: true` to JSON-parse the body and extract a specific field
|
|
161
|
+
|
|
162
|
+
> [!NOTE]
|
|
163
|
+
> Only one `@Param` with `source: 'body'` and `parse: false` (raw body) is allowed per handler.
|
|
164
|
+
|
|
165
|
+
#### @Field Decorator
|
|
166
|
+
|
|
167
|
+
Use `@Field` to include a property in the payload schema without specifying an extraction source:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { Payload, Field } from '@lafken/queue/main';
|
|
171
|
+
|
|
172
|
+
@Payload()
|
|
173
|
+
export class SimpleMessage {
|
|
174
|
+
@Field()
|
|
175
|
+
action: string;
|
|
176
|
+
|
|
177
|
+
@Field()
|
|
178
|
+
timestamp: number;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Consuming Messages
|
|
183
|
+
|
|
184
|
+
Bind a typed payload to a handler method using the `@Event` parameter decorator. Pass the payload class so the framework can automatically extract and map fields from the SQS record at runtime:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { Queue, Standard, Event } from '@lafken/queue/main';
|
|
188
|
+
|
|
189
|
+
@Queue()
|
|
190
|
+
export class AlertQueue {
|
|
191
|
+
@Standard({ queueName: 'alerts', batchSize: 5 })
|
|
192
|
+
processAlert(@Event(AlertMessage) alert: AlertMessage) {
|
|
193
|
+
console.log(`Alert from ${alert.source}: ${alert.message}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Sending Messages
|
|
199
|
+
|
|
200
|
+
Use `QueueService` at runtime to send messages to any SQS queue:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { QueueService } from '@lafken/queue/service';
|
|
204
|
+
|
|
205
|
+
// Send a single message
|
|
206
|
+
await QueueService.sendMessage({
|
|
207
|
+
url: 'https://sqs.us-east-1.amazonaws.com/123456789/orders',
|
|
208
|
+
body: { orderId: 'ord-123', total: 49.99 },
|
|
209
|
+
delay: 10,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Send to a FIFO queue
|
|
213
|
+
await QueueService.sendMessage({
|
|
214
|
+
url: 'https://sqs.us-east-1.amazonaws.com/123456789/payments.fifo',
|
|
215
|
+
body: { paymentId: 'pay-456', amount: 100 },
|
|
216
|
+
groupId: 'customer-789',
|
|
217
|
+
deduplicationId: 'pay-456',
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### SendMessage Options
|
|
222
|
+
|
|
223
|
+
| Option | Type | Description |
|
|
224
|
+
| ------------------- | ---------------------------------- | -------------------------------------------------- |
|
|
225
|
+
| `url` | `string` | Full SQS queue URL |
|
|
226
|
+
| `body` | `any` | Message body (automatically JSON-stringified) |
|
|
227
|
+
| `attributes` | `Record<string, string \| number>` | SQS message attributes |
|
|
228
|
+
| `delay` | `number` | Delay in seconds before the message becomes visible |
|
|
229
|
+
| `groupId` | `string` | Message group ID (FIFO queues only) |
|
|
230
|
+
| `deduplicationId` | `string` | Deduplication ID (FIFO queues only) |
|
|
231
|
+
|
|
232
|
+
### Sending Batch Messages
|
|
233
|
+
|
|
234
|
+
Send multiple messages in a single API call:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { QueueService } from '@lafken/queue/service';
|
|
238
|
+
|
|
239
|
+
await QueueService.sendBatchMessage({
|
|
240
|
+
url: 'https://sqs.us-east-1.amazonaws.com/123456789/tasks',
|
|
241
|
+
messages: [
|
|
242
|
+
{ body: { task: 'resize-image', fileId: 'f1' } },
|
|
243
|
+
{ body: { task: 'resize-image', fileId: 'f2' }, delay: 30 },
|
|
244
|
+
{ body: { task: 'generate-thumbnail', fileId: 'f3' } },
|
|
245
|
+
],
|
|
246
|
+
});
|
|
247
|
+
```
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './main';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./main"), exports);
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { ParamProps } from './event.types';
|
|
2
|
+
export declare const queueFieldKey: string;
|
|
3
|
+
export declare const queuePayloadKey: string;
|
|
4
|
+
/**
|
|
5
|
+
* Class decorator that declares a class as an SQS message payload.
|
|
6
|
+
*
|
|
7
|
+
* The decorated class defines the structure of data carried in a queue
|
|
8
|
+
* message. Use `@Param` or `@Field` on its properties to describe
|
|
9
|
+
* where each value is extracted from in the SQS record (message
|
|
10
|
+
* attributes or body).
|
|
11
|
+
*
|
|
12
|
+
* Works both at build time and at Lambda invocation time, so the
|
|
13
|
+
* same class can be used for sending and receiving messages.
|
|
14
|
+
*
|
|
15
|
+
* @param props - Optional payload configuration (e.g. a custom `name`).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* @Payload()
|
|
20
|
+
* export class OrderMessage {
|
|
21
|
+
* @Param({ source: 'attribute' })
|
|
22
|
+
* orderId: string;
|
|
23
|
+
*
|
|
24
|
+
* @Param({ source: 'body', parse: true })
|
|
25
|
+
* details: OrderDetails;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const Payload: (props?: import("@lafken/common").PayloadProps | undefined) => (target: Function) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Property decorator that maps a class field to a value extracted
|
|
32
|
+
* from an SQS message.
|
|
33
|
+
*
|
|
34
|
+
* By default the value is read from a **message attribute** whose name
|
|
35
|
+
* matches the property. Set `source: 'body'` to extract it from the
|
|
36
|
+
* message body instead, and optionally enable `parse: true` to
|
|
37
|
+
* JSON-parse the body before extraction.
|
|
38
|
+
*
|
|
39
|
+
* @param props - Optional extraction configuration (source, type, parse).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* @Payload()
|
|
44
|
+
* export class NotificationMessage {
|
|
45
|
+
* @Param({ source: 'attribute', type: String })
|
|
46
|
+
* userId: string;
|
|
47
|
+
*
|
|
48
|
+
* @Param({ source: 'body', parse: true })
|
|
49
|
+
* content: NotificationContent;
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare const Param: (props?: ParamProps | undefined) => (target: any, destinationName: string) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Property decorator that registers a class field as a generic
|
|
56
|
+
* queue message field.
|
|
57
|
+
*
|
|
58
|
+
* Unlike `@Param`, this decorator does not configure a specific
|
|
59
|
+
* extraction source or parsing behaviour — it simply marks the
|
|
60
|
+
* property for inclusion in the message payload schema.
|
|
61
|
+
*
|
|
62
|
+
* @param props - Optional field configuration (e.g. a custom `name` or `type`).
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* @Payload()
|
|
67
|
+
* export class SimpleMessage {
|
|
68
|
+
* @Field()
|
|
69
|
+
* action: string;
|
|
70
|
+
*
|
|
71
|
+
* @Field()
|
|
72
|
+
* timestamp: number;
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare const Field: (props?: import("@lafken/common").FieldProps | undefined) => (target: any, destinationName: string) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Parameter decorator that binds the incoming SQS event to a typed
|
|
79
|
+
* payload class on a handler method argument.
|
|
80
|
+
*
|
|
81
|
+
* Pass a class decorated with `@Payload` so the framework can
|
|
82
|
+
* automatically extract and map each field from the raw SQS record
|
|
83
|
+
* into a strongly-typed object at runtime.
|
|
84
|
+
*
|
|
85
|
+
* @param eventField - The payload class describing the expected
|
|
86
|
+
* message structure.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* @Queue()
|
|
91
|
+
* export class OrderQueue {
|
|
92
|
+
* @Consumer()
|
|
93
|
+
* process(@Event(OrderMessage) msg: OrderMessage) {
|
|
94
|
+
* // msg fields are extracted from the SQS record
|
|
95
|
+
* }
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare const Event: (eventField: Function) => (target: any, methodName: string, _number: number) => void;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Event = exports.Field = exports.Param = exports.Payload = exports.queuePayloadKey = exports.queueFieldKey = void 0;
|
|
4
|
+
const common_1 = require("@lafken/common");
|
|
5
|
+
const queue_1 = require("../queue");
|
|
6
|
+
exports.queueFieldKey = (0, common_1.createFieldName)(queue_1.RESOURCE_TYPE, common_1.FieldProperties.field);
|
|
7
|
+
exports.queuePayloadKey = (0, common_1.createFieldName)(queue_1.RESOURCE_TYPE, common_1.FieldProperties.payload);
|
|
8
|
+
/**
|
|
9
|
+
* Class decorator that declares a class as an SQS message payload.
|
|
10
|
+
*
|
|
11
|
+
* The decorated class defines the structure of data carried in a queue
|
|
12
|
+
* message. Use `@Param` or `@Field` on its properties to describe
|
|
13
|
+
* where each value is extracted from in the SQS record (message
|
|
14
|
+
* attributes or body).
|
|
15
|
+
*
|
|
16
|
+
* Works both at build time and at Lambda invocation time, so the
|
|
17
|
+
* same class can be used for sending and receiving messages.
|
|
18
|
+
*
|
|
19
|
+
* @param props - Optional payload configuration (e.g. a custom `name`).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* @Payload()
|
|
24
|
+
* export class OrderMessage {
|
|
25
|
+
* @Param({ source: 'attribute' })
|
|
26
|
+
* orderId: string;
|
|
27
|
+
*
|
|
28
|
+
* @Param({ source: 'body', parse: true })
|
|
29
|
+
* details: OrderDetails;
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
exports.Payload = (0, common_1.createPayloadDecorator)({
|
|
34
|
+
prefix: queue_1.RESOURCE_TYPE,
|
|
35
|
+
createUniqueId: false,
|
|
36
|
+
enableInLambdaInvocation: true,
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Property decorator that maps a class field to a value extracted
|
|
40
|
+
* from an SQS message.
|
|
41
|
+
*
|
|
42
|
+
* By default the value is read from a **message attribute** whose name
|
|
43
|
+
* matches the property. Set `source: 'body'` to extract it from the
|
|
44
|
+
* message body instead, and optionally enable `parse: true` to
|
|
45
|
+
* JSON-parse the body before extraction.
|
|
46
|
+
*
|
|
47
|
+
* @param props - Optional extraction configuration (source, type, parse).
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* @Payload()
|
|
52
|
+
* export class NotificationMessage {
|
|
53
|
+
* @Param({ source: 'attribute', type: String })
|
|
54
|
+
* userId: string;
|
|
55
|
+
*
|
|
56
|
+
* @Param({ source: 'body', parse: true })
|
|
57
|
+
* content: NotificationContent;
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
exports.Param = (0, common_1.createFieldDecorator)({
|
|
62
|
+
prefix: queue_1.RESOURCE_TYPE,
|
|
63
|
+
enableInLambdaInvocation: true,
|
|
64
|
+
getMetadata: (props) => {
|
|
65
|
+
const source = props?.source || 'attribute';
|
|
66
|
+
return {
|
|
67
|
+
source,
|
|
68
|
+
parse: props?.source === 'body' && !!props?.parse,
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* Property decorator that registers a class field as a generic
|
|
74
|
+
* queue message field.
|
|
75
|
+
*
|
|
76
|
+
* Unlike `@Param`, this decorator does not configure a specific
|
|
77
|
+
* extraction source or parsing behaviour — it simply marks the
|
|
78
|
+
* property for inclusion in the message payload schema.
|
|
79
|
+
*
|
|
80
|
+
* @param props - Optional field configuration (e.g. a custom `name` or `type`).
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* @Payload()
|
|
85
|
+
* export class SimpleMessage {
|
|
86
|
+
* @Field()
|
|
87
|
+
* action: string;
|
|
88
|
+
*
|
|
89
|
+
* @Field()
|
|
90
|
+
* timestamp: number;
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
exports.Field = (0, common_1.createFieldDecorator)({
|
|
95
|
+
prefix: queue_1.RESOURCE_TYPE,
|
|
96
|
+
enableInLambdaInvocation: true,
|
|
97
|
+
getMetadata: () => ({}),
|
|
98
|
+
});
|
|
99
|
+
/**
|
|
100
|
+
* Parameter decorator that binds the incoming SQS event to a typed
|
|
101
|
+
* payload class on a handler method argument.
|
|
102
|
+
*
|
|
103
|
+
* Pass a class decorated with `@Payload` so the framework can
|
|
104
|
+
* automatically extract and map each field from the raw SQS record
|
|
105
|
+
* into a strongly-typed object at runtime.
|
|
106
|
+
*
|
|
107
|
+
* @param eventField - The payload class describing the expected
|
|
108
|
+
* message structure.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* @Queue()
|
|
113
|
+
* export class OrderQueue {
|
|
114
|
+
* @Consumer()
|
|
115
|
+
* process(@Event(OrderMessage) msg: OrderMessage) {
|
|
116
|
+
* // msg fields are extracted from the SQS record
|
|
117
|
+
* }
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
const Event = (eventField) => (0, common_1.createEventDecorator)({
|
|
122
|
+
prefix: queue_1.RESOURCE_TYPE,
|
|
123
|
+
enableInLambdaInvocation: true,
|
|
124
|
+
})(eventField);
|
|
125
|
+
exports.Event = Event;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ArrayField, BooleanField, FieldProps, NumberField, ObjectField, StringField } from '@lafken/common';
|
|
2
|
+
export interface ParamAttributeProps extends Omit<FieldProps, 'type'> {
|
|
3
|
+
/**
|
|
4
|
+
* Attribute source.
|
|
5
|
+
*
|
|
6
|
+
* Specifies the source from which to obtain the attribute value.
|
|
7
|
+
* This can be used to map values from the event
|
|
8
|
+
* when processing messages.
|
|
9
|
+
*/
|
|
10
|
+
source?: 'attribute';
|
|
11
|
+
/**
|
|
12
|
+
* Attribute type.
|
|
13
|
+
*
|
|
14
|
+
* Specifies the data type of the attribute. This can be used to
|
|
15
|
+
* enforce the type of the value extracted from the source before
|
|
16
|
+
* passing it to the consumer or processing logic.
|
|
17
|
+
*/
|
|
18
|
+
type?: NumberConstructor | StringConstructor;
|
|
19
|
+
}
|
|
20
|
+
export interface ParamBodyUnparsedProps extends Omit<FieldProps, 'type'> {
|
|
21
|
+
/**
|
|
22
|
+
* Attribute source.
|
|
23
|
+
*
|
|
24
|
+
* Specifies the source from which to obtain the attribute value.
|
|
25
|
+
* This can be used to map values from the event
|
|
26
|
+
* when processing messages.
|
|
27
|
+
*/
|
|
28
|
+
source: 'body';
|
|
29
|
+
/**
|
|
30
|
+
* Parse message body.
|
|
31
|
+
*
|
|
32
|
+
* Specifies whether the message body should be parsed and converted
|
|
33
|
+
* into a JavaScript object before being passed to the consumer.
|
|
34
|
+
*/
|
|
35
|
+
parse?: false;
|
|
36
|
+
/**
|
|
37
|
+
* Attribute type.
|
|
38
|
+
*
|
|
39
|
+
* Specifies the data type of the attribute. This can be used to
|
|
40
|
+
* enforce the type of the value extracted from the source before
|
|
41
|
+
* passing it to the consumer or processing logic.
|
|
42
|
+
*/
|
|
43
|
+
type?: StringConstructor;
|
|
44
|
+
}
|
|
45
|
+
export interface ParamBodyParsedProps extends Omit<FieldProps, 'type'> {
|
|
46
|
+
/**
|
|
47
|
+
* Attribute source.
|
|
48
|
+
*
|
|
49
|
+
* Specifies the source from which to obtain the attribute value.
|
|
50
|
+
* This can be used to map values from the event
|
|
51
|
+
* when processing messages.
|
|
52
|
+
*/
|
|
53
|
+
source: 'body';
|
|
54
|
+
/**
|
|
55
|
+
* Parse message body.
|
|
56
|
+
*
|
|
57
|
+
* Specifies whether the message body should be parsed and converted
|
|
58
|
+
* into a JavaScript object before being passed to the consumer.
|
|
59
|
+
*/
|
|
60
|
+
parse: true;
|
|
61
|
+
/**
|
|
62
|
+
* Attribute type.
|
|
63
|
+
*
|
|
64
|
+
* Specifies the data type of the attribute. This can be used to
|
|
65
|
+
* enforce the type of the value extracted from the source before
|
|
66
|
+
* passing it to the consumer or processing logic.
|
|
67
|
+
*/
|
|
68
|
+
type?: StringConstructor | Function | [Function];
|
|
69
|
+
}
|
|
70
|
+
export type ParamProps = ParamAttributeProps | ParamBodyUnparsedProps | ParamBodyParsedProps;
|
|
71
|
+
export type Source = Exclude<ParamProps['source'], undefined>;
|
|
72
|
+
interface QueueParamBase {
|
|
73
|
+
source: Source;
|
|
74
|
+
parse: boolean;
|
|
75
|
+
}
|
|
76
|
+
export interface QueueStringParam extends StringField, QueueParamBase {
|
|
77
|
+
}
|
|
78
|
+
export interface QueueNumberParam extends NumberField, QueueParamBase {
|
|
79
|
+
}
|
|
80
|
+
export interface QueueBooleanParam extends BooleanField, QueueParamBase {
|
|
81
|
+
}
|
|
82
|
+
export interface QueueObjectParam extends Omit<ObjectField, 'properties'>, QueueParamBase {
|
|
83
|
+
properties: QueueParamMetadata[];
|
|
84
|
+
}
|
|
85
|
+
export interface QueueArrayParam extends Omit<ArrayField, 'items'>, QueueParamBase {
|
|
86
|
+
items: QueueParamMetadata;
|
|
87
|
+
}
|
|
88
|
+
export type QueueParamMetadata = QueueStringParam | QueueNumberParam | QueueBooleanParam | QueueObjectParam | QueueArrayParam;
|
|
89
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./event"), exports);
|
|
18
|
+
__exportStar(require("./event.types"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./event"), exports);
|
|
18
|
+
__exportStar(require("./queue"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./queue"), exports);
|
|
18
|
+
__exportStar(require("./queue.types"), exports);
|