prisma-pgmq 0.1.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.
- package/LICENSE +21 -0
- package/README.md +402 -0
- package/dist/index.d.mts +72 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +157 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +136 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Prisma PGMQ Contributors
|
|
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,402 @@
|
|
|
1
|
+
# Prisma PGMQ
|
|
2
|
+
|
|
3
|
+
A TypeScript library that provides type-safe methods for PostgreSQL Message Queue (PGMQ) operations in your Prisma-based applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔒 **Type-safe**: Full TypeScript support with proper type definitions
|
|
8
|
+
- 📦 **Easy to use**: Simple API with functional methods
|
|
9
|
+
- 🔌 **Prisma Integration**: Seamless integration with your existing Prisma setup
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install prisma-pgmq
|
|
15
|
+
# or
|
|
16
|
+
pnpm add prisma-pgmq
|
|
17
|
+
# or
|
|
18
|
+
yarn add prisma-pgmq
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Prerequisites
|
|
22
|
+
|
|
23
|
+
- PostgreSQL database with the PGMQ extension installed
|
|
24
|
+
- Prisma Client v5.0.0 or higher
|
|
25
|
+
- Node.js 16+
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### Functional API
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { PrismaClient } from '@prisma/client';
|
|
33
|
+
import { pgmq } from 'prisma-pgmq';
|
|
34
|
+
|
|
35
|
+
const prisma = new PrismaClient();
|
|
36
|
+
|
|
37
|
+
// Create a queue
|
|
38
|
+
await prisma.$transaction(async (tx) => {
|
|
39
|
+
await pgmq.createQueue(tx, 'my-work-queue');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Send a message
|
|
43
|
+
await prisma.$transaction(async (tx) => {
|
|
44
|
+
const msgId = await pgmq.send(tx, 'my-work-queue', {
|
|
45
|
+
userId: 123,
|
|
46
|
+
action: 'send-email',
|
|
47
|
+
email: 'user@example.com'
|
|
48
|
+
});
|
|
49
|
+
console.log('Message sent with ID:', msgId);
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## API Reference
|
|
54
|
+
|
|
55
|
+
### Message Operations
|
|
56
|
+
|
|
57
|
+
#### `send(queueName, message, delay?)`
|
|
58
|
+
Send a single message to a queue.
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// Send immediately
|
|
62
|
+
const msgId = await prisma.$pgmq.send('my-queue', { data: 'hello' });
|
|
63
|
+
|
|
64
|
+
// Send with delay (seconds)
|
|
65
|
+
const msgId = await prisma.$pgmq.send('my-queue', { data: 'hello' }, 30);
|
|
66
|
+
|
|
67
|
+
// Send with specific time
|
|
68
|
+
const msgId = await prisma.$pgmq.send('my-queue', { data: 'hello' }, new Date('2024-01-01T10:00:00Z'));
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### `sendBatch(queueName, messages, delay?)`
|
|
72
|
+
Send multiple messages to a queue in a single operation.
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const msgIds = await prisma.$pgmq.sendBatch('my-queue', [
|
|
76
|
+
{ id: 1, data: 'message 1' },
|
|
77
|
+
{ id: 2, data: 'message 2' },
|
|
78
|
+
{ id: 3, data: 'message 3' }
|
|
79
|
+
]);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### `read(queueName, vt, qty?, conditional?)`
|
|
83
|
+
Read messages from a queue with visibility timeout.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Read up to 5 messages with 30 second visibility timeout
|
|
87
|
+
const messages = await prisma.$pgmq.read('my-queue', 30, 5);
|
|
88
|
+
|
|
89
|
+
// Read with conditional filtering
|
|
90
|
+
const messages = await prisma.$pgmq.read('my-queue', 30, 5, { priority: 'high' });
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### `readWithPoll(queueName, vt, qty?, maxPollSeconds?, pollIntervalMs?, conditional?)`
|
|
94
|
+
Read messages with polling (wait for messages if none available).
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Poll for up to 10 seconds, checking every 500ms
|
|
98
|
+
const messages = await prisma.$pgmq.readWithPoll('my-queue', 30, 1, 10, 500);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### `pop(queueName)`
|
|
102
|
+
Read and immediately delete a message (atomic operation).
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const messages = await prisma.$pgmq.pop('my-queue');
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Message Management
|
|
109
|
+
|
|
110
|
+
#### `deleteMessage(queueName, msgId)`
|
|
111
|
+
Delete a specific message.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const deleted = await prisma.$pgmq.deleteMessage('my-queue', 123);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### `deleteBatch(queueName, msgIds)`
|
|
118
|
+
Delete multiple messages.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const deletedIds = await prisma.$pgmq.deleteBatch('my-queue', [123, 124, 125]);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### `archive(queueName, msgId)`
|
|
125
|
+
Archive a message (move to archive table).
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const archived = await prisma.$pgmq.archive('my-queue', 123);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### `archiveBatch(queueName, msgIds)`
|
|
132
|
+
Archive multiple messages.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const archivedIds = await prisma.$pgmq.archiveBatch('my-queue', [123, 124, 125]);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Queue Management
|
|
139
|
+
|
|
140
|
+
#### `createQueue(queueName)`
|
|
141
|
+
Create a new queue.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
await prisma.$pgmq.createQueue('my-new-queue');
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### `createPartitionedQueue(queueName, partitionInterval?, retentionInterval?)`
|
|
148
|
+
Create a partitioned queue for high-throughput scenarios.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
await prisma.$pgmq.createPartitionedQueue('high-volume-queue', '10000', '100000');
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### `createUnloggedQueue(queueName)`
|
|
155
|
+
Create an unlogged queue (better performance, less durability).
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
await prisma.$pgmq.createUnloggedQueue('temp-queue');
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `dropQueue(queueName)`
|
|
162
|
+
Delete a queue and all its messages.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const dropped = await prisma.$pgmq.dropQueue('old-queue');
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### `purgeQueue(queueName)`
|
|
169
|
+
Remove all messages from a queue.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
const messageCount = await prisma.$pgmq.purgeQueue('my-queue');
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Utilities
|
|
176
|
+
|
|
177
|
+
#### `setVt(queueName, msgId, vtOffset)`
|
|
178
|
+
Set visibility timeout for a specific message.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
const message = await prisma.$pgmq.setVt('my-queue', 123, 60); // 60 seconds
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### `listQueues()`
|
|
185
|
+
Get information about all queues.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const queues = await prisma.$pgmq.listQueues();
|
|
189
|
+
console.log(queues); // [{ queue_name: 'my-queue', created_at: ..., is_partitioned: false }]
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### `metrics(queueName)`
|
|
193
|
+
Get metrics for a specific queue.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const metrics = await prisma.$pgmq.metrics('my-queue');
|
|
197
|
+
console.log(metrics);
|
|
198
|
+
// {
|
|
199
|
+
// queue_name: 'my-queue',
|
|
200
|
+
// queue_length: 5n,
|
|
201
|
+
// newest_msg_age_sec: 10,
|
|
202
|
+
// oldest_msg_age_sec: 300,
|
|
203
|
+
// total_messages: 1000n,
|
|
204
|
+
// scrape_time: 2024-01-01T10:00:00.000Z
|
|
205
|
+
// }
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### `metricsAll()`
|
|
209
|
+
Get metrics for all queues.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
const allMetrics = await prisma.$pgmq.metricsAll();
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Type Definitions
|
|
216
|
+
|
|
217
|
+
### `Task`
|
|
218
|
+
```typescript
|
|
219
|
+
type Task = Record<string, unknown>;
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### `MessageRecord`
|
|
223
|
+
```typescript
|
|
224
|
+
interface MessageRecord {
|
|
225
|
+
msg_id: number;
|
|
226
|
+
read_ct: number;
|
|
227
|
+
enqueued_at: Date;
|
|
228
|
+
vt: Date;
|
|
229
|
+
message: Task;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### `QueueMetrics`
|
|
234
|
+
```typescript
|
|
235
|
+
interface QueueMetrics {
|
|
236
|
+
queue_name: string;
|
|
237
|
+
queue_length: number;
|
|
238
|
+
newest_msg_age_sec: number | null;
|
|
239
|
+
oldest_msg_age_sec: number | null;
|
|
240
|
+
total_messages: number;
|
|
241
|
+
scrape_time: Date;
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### `QueueInfo`
|
|
246
|
+
```typescript
|
|
247
|
+
interface QueueInfo {
|
|
248
|
+
queue_name: string;
|
|
249
|
+
created_at: Date;
|
|
250
|
+
is_partitioned: boolean;
|
|
251
|
+
is_unlogged: boolean;
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Best Practices
|
|
256
|
+
|
|
257
|
+
### 1. Use Appropriate Visibility Timeouts
|
|
258
|
+
Choose visibility timeouts based on your message processing time:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// For quick operations (30 seconds)
|
|
262
|
+
const messages = await prisma.$pgmq.read('quick-tasks', 30);
|
|
263
|
+
|
|
264
|
+
// For longer operations (5 minutes)
|
|
265
|
+
const messages = await prisma.$pgmq.read('heavy-tasks', 300);
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 2. Handle Message Processing Failures
|
|
269
|
+
Always delete or archive messages after successful processing:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
const messages = await prisma.$pgmq.read('my-queue', 30, 10);
|
|
273
|
+
|
|
274
|
+
for (const message of messages) {
|
|
275
|
+
try {
|
|
276
|
+
await processMessage(message.message);
|
|
277
|
+
await prisma.$pgmq.deleteMessage('my-queue', message.msg_id);
|
|
278
|
+
} catch (error) {
|
|
279
|
+
// Handle error - message will become visible again after timeout
|
|
280
|
+
console.error('Failed to process message:', error);
|
|
281
|
+
// Optionally archive failed messages
|
|
282
|
+
await prisma.$pgmq.archive('my-queue', message.msg_id);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Examples
|
|
288
|
+
|
|
289
|
+
### Basic Worker Pattern
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
import { PrismaClient } from '@prisma/client';
|
|
293
|
+
import { pgmq } from 'prisma-pgmq';
|
|
294
|
+
|
|
295
|
+
const prisma = new PrismaClient();
|
|
296
|
+
|
|
297
|
+
// Producer
|
|
298
|
+
async function sendTask(taskData: any) {
|
|
299
|
+
await prisma.$transaction(async (tx) => {
|
|
300
|
+
await pgmq.send(tx, 'work-queue', {
|
|
301
|
+
type: 'process-user-data',
|
|
302
|
+
data: taskData,
|
|
303
|
+
timestamp: Date.now()
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Consumer
|
|
309
|
+
async function processMessages() {
|
|
310
|
+
while (true) {
|
|
311
|
+
await prisma.$transaction(async (tx) => {
|
|
312
|
+
const messages = await pgmq.readWithPoll(tx, 'work-queue', 30, 5, 10, 1000);
|
|
313
|
+
for (const message of messages) {
|
|
314
|
+
try {
|
|
315
|
+
// Process the message
|
|
316
|
+
await handleTask(message.message);
|
|
317
|
+
// Delete on success
|
|
318
|
+
await pgmq.deleteMessage(tx, 'work-queue', message.msg_id);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error('Task failed:', error);
|
|
321
|
+
// Archive failed messages for later analysis
|
|
322
|
+
await pgmq.archive(tx, 'work-queue', message.msg_id);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async function handleTask(task: any) {
|
|
330
|
+
// Your business logic here
|
|
331
|
+
console.log('Processing task:', task.type);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Delayed Message Scheduling
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// Schedule a message for later processing
|
|
339
|
+
const futureDate = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours
|
|
340
|
+
|
|
341
|
+
await prisma.$pgmq.send('scheduled-tasks', {
|
|
342
|
+
type: 'send-reminder',
|
|
343
|
+
userId: 123,
|
|
344
|
+
reminder: 'Your subscription expires tomorrow'
|
|
345
|
+
}, futureDate);
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Priority Queue Pattern
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
// Send high-priority message
|
|
352
|
+
await prisma.$pgmq.send('tasks', {
|
|
353
|
+
priority: 'high',
|
|
354
|
+
type: 'urgent-processing',
|
|
355
|
+
data: urgentData
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Read high-priority messages first
|
|
359
|
+
const highPriorityMessages = await prisma.$pgmq.read('tasks', 30, 10, { priority: 'high' });
|
|
360
|
+
|
|
361
|
+
if (highPriorityMessages.length === 0) {
|
|
362
|
+
// Fall back to normal priority
|
|
363
|
+
const normalMessages = await prisma.$pgmq.read('tasks', 30, 10, { priority: 'normal' });
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Contributing
|
|
368
|
+
|
|
369
|
+
1. Fork the repository
|
|
370
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
371
|
+
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
|
|
372
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
373
|
+
5. Open a Pull Request
|
|
374
|
+
|
|
375
|
+
### Development Setup
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
# Clone the repository
|
|
379
|
+
git clone https://github.com/your-username/prisma-pgmq.git
|
|
380
|
+
cd prisma-pgmq
|
|
381
|
+
|
|
382
|
+
# Install dependencies
|
|
383
|
+
pnpm install
|
|
384
|
+
|
|
385
|
+
# Run tests
|
|
386
|
+
pnpm test
|
|
387
|
+
|
|
388
|
+
# Build the library
|
|
389
|
+
pnpm build
|
|
390
|
+
|
|
391
|
+
# Watch for changes during development
|
|
392
|
+
pnpm dev
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
398
|
+
|
|
399
|
+
## Acknowledgments
|
|
400
|
+
|
|
401
|
+
- [PGMQ](https://github.com/pgmq/pgmq) - PostgreSQL Message Queue extension
|
|
402
|
+
- [Prisma](https://www.prisma.io/) - Next-generation ORM for TypeScript & Node.js
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Prisma } from '@prisma/client/extension';
|
|
2
|
+
|
|
3
|
+
type Task = Record<string, unknown>;
|
|
4
|
+
interface MessageRecord {
|
|
5
|
+
msg_id: number;
|
|
6
|
+
read_ct: number;
|
|
7
|
+
enqueued_at: Date;
|
|
8
|
+
vt: Date;
|
|
9
|
+
message: Task;
|
|
10
|
+
}
|
|
11
|
+
interface QueueMetrics {
|
|
12
|
+
queue_name: string;
|
|
13
|
+
queue_length: number;
|
|
14
|
+
newest_msg_age_sec: number | null;
|
|
15
|
+
oldest_msg_age_sec: number | null;
|
|
16
|
+
total_messages: number;
|
|
17
|
+
scrape_time: Date;
|
|
18
|
+
}
|
|
19
|
+
interface QueueInfo {
|
|
20
|
+
queue_name: string;
|
|
21
|
+
created_at: Date;
|
|
22
|
+
is_partitioned: boolean;
|
|
23
|
+
is_unlogged: boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function send(tx: Prisma.TransactionClient, queueName: string, msg: Task, delay?: number | Date): Promise<number>;
|
|
26
|
+
declare function sendBatch(tx: Prisma.TransactionClient, queueName: string, msgs: Task[], delay?: number | Date): Promise<number[]>;
|
|
27
|
+
declare function read(tx: Prisma.TransactionClient, queueName: string, vt: number, qty?: number, conditional?: Task): Promise<MessageRecord[]>;
|
|
28
|
+
declare function readWithPoll(tx: Prisma.TransactionClient, queueName: string, vt: number, qty?: number, maxPollSeconds?: number, pollIntervalMs?: number, conditional?: Task): Promise<MessageRecord[]>;
|
|
29
|
+
declare function pop(tx: Prisma.TransactionClient, queueName: string): Promise<MessageRecord[]>;
|
|
30
|
+
declare function deleteMessage(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean>;
|
|
31
|
+
declare function deleteBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]>;
|
|
32
|
+
declare function purgeQueue(tx: Prisma.TransactionClient, queueName: string): Promise<number>;
|
|
33
|
+
declare function archive(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean>;
|
|
34
|
+
declare function archiveBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]>;
|
|
35
|
+
declare function createQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void>;
|
|
36
|
+
declare function createPartitionedQueue(tx: Prisma.TransactionClient, queueName: string, partitionInterval?: string, retentionInterval?: string): Promise<void>;
|
|
37
|
+
declare function createUnloggedQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void>;
|
|
38
|
+
declare function detachArchive(tx: Prisma.TransactionClient, queueName: string): Promise<void>;
|
|
39
|
+
declare function dropQueue(tx: Prisma.TransactionClient, queueName: string): Promise<boolean>;
|
|
40
|
+
declare function setVt(tx: Prisma.TransactionClient, queueName: string, msgId: number, vtOffset: number): Promise<MessageRecord>;
|
|
41
|
+
declare function listQueues(tx: Prisma.TransactionClient): Promise<QueueInfo[]>;
|
|
42
|
+
declare function metrics(tx: Prisma.TransactionClient, queueName: string): Promise<QueueMetrics>;
|
|
43
|
+
declare function metricsAll(tx: Prisma.TransactionClient): Promise<QueueMetrics[]>;
|
|
44
|
+
|
|
45
|
+
type pgmq_MessageRecord = MessageRecord;
|
|
46
|
+
type pgmq_QueueInfo = QueueInfo;
|
|
47
|
+
type pgmq_QueueMetrics = QueueMetrics;
|
|
48
|
+
type pgmq_Task = Task;
|
|
49
|
+
declare const pgmq_archive: typeof archive;
|
|
50
|
+
declare const pgmq_archiveBatch: typeof archiveBatch;
|
|
51
|
+
declare const pgmq_createPartitionedQueue: typeof createPartitionedQueue;
|
|
52
|
+
declare const pgmq_createQueue: typeof createQueue;
|
|
53
|
+
declare const pgmq_createUnloggedQueue: typeof createUnloggedQueue;
|
|
54
|
+
declare const pgmq_deleteBatch: typeof deleteBatch;
|
|
55
|
+
declare const pgmq_deleteMessage: typeof deleteMessage;
|
|
56
|
+
declare const pgmq_detachArchive: typeof detachArchive;
|
|
57
|
+
declare const pgmq_dropQueue: typeof dropQueue;
|
|
58
|
+
declare const pgmq_listQueues: typeof listQueues;
|
|
59
|
+
declare const pgmq_metrics: typeof metrics;
|
|
60
|
+
declare const pgmq_metricsAll: typeof metricsAll;
|
|
61
|
+
declare const pgmq_pop: typeof pop;
|
|
62
|
+
declare const pgmq_purgeQueue: typeof purgeQueue;
|
|
63
|
+
declare const pgmq_read: typeof read;
|
|
64
|
+
declare const pgmq_readWithPoll: typeof readWithPoll;
|
|
65
|
+
declare const pgmq_send: typeof send;
|
|
66
|
+
declare const pgmq_sendBatch: typeof sendBatch;
|
|
67
|
+
declare const pgmq_setVt: typeof setVt;
|
|
68
|
+
declare namespace pgmq {
|
|
69
|
+
export { type pgmq_MessageRecord as MessageRecord, type pgmq_QueueInfo as QueueInfo, type pgmq_QueueMetrics as QueueMetrics, type pgmq_Task as Task, pgmq_archive as archive, pgmq_archiveBatch as archiveBatch, pgmq_createPartitionedQueue as createPartitionedQueue, pgmq_createQueue as createQueue, pgmq_createUnloggedQueue as createUnloggedQueue, pgmq_deleteBatch as deleteBatch, pgmq_deleteMessage as deleteMessage, pgmq_detachArchive as detachArchive, pgmq_dropQueue as dropQueue, pgmq_listQueues as listQueues, pgmq_metrics as metrics, pgmq_metricsAll as metricsAll, pgmq_pop as pop, pgmq_purgeQueue as purgeQueue, pgmq_read as read, pgmq_readWithPoll as readWithPoll, pgmq_send as send, pgmq_sendBatch as sendBatch, pgmq_setVt as setVt };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { type MessageRecord, type QueueInfo, type QueueMetrics, type Task, pgmq };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Prisma } from '@prisma/client/extension';
|
|
2
|
+
|
|
3
|
+
type Task = Record<string, unknown>;
|
|
4
|
+
interface MessageRecord {
|
|
5
|
+
msg_id: number;
|
|
6
|
+
read_ct: number;
|
|
7
|
+
enqueued_at: Date;
|
|
8
|
+
vt: Date;
|
|
9
|
+
message: Task;
|
|
10
|
+
}
|
|
11
|
+
interface QueueMetrics {
|
|
12
|
+
queue_name: string;
|
|
13
|
+
queue_length: number;
|
|
14
|
+
newest_msg_age_sec: number | null;
|
|
15
|
+
oldest_msg_age_sec: number | null;
|
|
16
|
+
total_messages: number;
|
|
17
|
+
scrape_time: Date;
|
|
18
|
+
}
|
|
19
|
+
interface QueueInfo {
|
|
20
|
+
queue_name: string;
|
|
21
|
+
created_at: Date;
|
|
22
|
+
is_partitioned: boolean;
|
|
23
|
+
is_unlogged: boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function send(tx: Prisma.TransactionClient, queueName: string, msg: Task, delay?: number | Date): Promise<number>;
|
|
26
|
+
declare function sendBatch(tx: Prisma.TransactionClient, queueName: string, msgs: Task[], delay?: number | Date): Promise<number[]>;
|
|
27
|
+
declare function read(tx: Prisma.TransactionClient, queueName: string, vt: number, qty?: number, conditional?: Task): Promise<MessageRecord[]>;
|
|
28
|
+
declare function readWithPoll(tx: Prisma.TransactionClient, queueName: string, vt: number, qty?: number, maxPollSeconds?: number, pollIntervalMs?: number, conditional?: Task): Promise<MessageRecord[]>;
|
|
29
|
+
declare function pop(tx: Prisma.TransactionClient, queueName: string): Promise<MessageRecord[]>;
|
|
30
|
+
declare function deleteMessage(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean>;
|
|
31
|
+
declare function deleteBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]>;
|
|
32
|
+
declare function purgeQueue(tx: Prisma.TransactionClient, queueName: string): Promise<number>;
|
|
33
|
+
declare function archive(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean>;
|
|
34
|
+
declare function archiveBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]>;
|
|
35
|
+
declare function createQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void>;
|
|
36
|
+
declare function createPartitionedQueue(tx: Prisma.TransactionClient, queueName: string, partitionInterval?: string, retentionInterval?: string): Promise<void>;
|
|
37
|
+
declare function createUnloggedQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void>;
|
|
38
|
+
declare function detachArchive(tx: Prisma.TransactionClient, queueName: string): Promise<void>;
|
|
39
|
+
declare function dropQueue(tx: Prisma.TransactionClient, queueName: string): Promise<boolean>;
|
|
40
|
+
declare function setVt(tx: Prisma.TransactionClient, queueName: string, msgId: number, vtOffset: number): Promise<MessageRecord>;
|
|
41
|
+
declare function listQueues(tx: Prisma.TransactionClient): Promise<QueueInfo[]>;
|
|
42
|
+
declare function metrics(tx: Prisma.TransactionClient, queueName: string): Promise<QueueMetrics>;
|
|
43
|
+
declare function metricsAll(tx: Prisma.TransactionClient): Promise<QueueMetrics[]>;
|
|
44
|
+
|
|
45
|
+
type pgmq_MessageRecord = MessageRecord;
|
|
46
|
+
type pgmq_QueueInfo = QueueInfo;
|
|
47
|
+
type pgmq_QueueMetrics = QueueMetrics;
|
|
48
|
+
type pgmq_Task = Task;
|
|
49
|
+
declare const pgmq_archive: typeof archive;
|
|
50
|
+
declare const pgmq_archiveBatch: typeof archiveBatch;
|
|
51
|
+
declare const pgmq_createPartitionedQueue: typeof createPartitionedQueue;
|
|
52
|
+
declare const pgmq_createQueue: typeof createQueue;
|
|
53
|
+
declare const pgmq_createUnloggedQueue: typeof createUnloggedQueue;
|
|
54
|
+
declare const pgmq_deleteBatch: typeof deleteBatch;
|
|
55
|
+
declare const pgmq_deleteMessage: typeof deleteMessage;
|
|
56
|
+
declare const pgmq_detachArchive: typeof detachArchive;
|
|
57
|
+
declare const pgmq_dropQueue: typeof dropQueue;
|
|
58
|
+
declare const pgmq_listQueues: typeof listQueues;
|
|
59
|
+
declare const pgmq_metrics: typeof metrics;
|
|
60
|
+
declare const pgmq_metricsAll: typeof metricsAll;
|
|
61
|
+
declare const pgmq_pop: typeof pop;
|
|
62
|
+
declare const pgmq_purgeQueue: typeof purgeQueue;
|
|
63
|
+
declare const pgmq_read: typeof read;
|
|
64
|
+
declare const pgmq_readWithPoll: typeof readWithPoll;
|
|
65
|
+
declare const pgmq_send: typeof send;
|
|
66
|
+
declare const pgmq_sendBatch: typeof sendBatch;
|
|
67
|
+
declare const pgmq_setVt: typeof setVt;
|
|
68
|
+
declare namespace pgmq {
|
|
69
|
+
export { type pgmq_MessageRecord as MessageRecord, type pgmq_QueueInfo as QueueInfo, type pgmq_QueueMetrics as QueueMetrics, type pgmq_Task as Task, pgmq_archive as archive, pgmq_archiveBatch as archiveBatch, pgmq_createPartitionedQueue as createPartitionedQueue, pgmq_createQueue as createQueue, pgmq_createUnloggedQueue as createUnloggedQueue, pgmq_deleteBatch as deleteBatch, pgmq_deleteMessage as deleteMessage, pgmq_detachArchive as detachArchive, pgmq_dropQueue as dropQueue, pgmq_listQueues as listQueues, pgmq_metrics as metrics, pgmq_metricsAll as metricsAll, pgmq_pop as pop, pgmq_purgeQueue as purgeQueue, pgmq_read as read, pgmq_readWithPoll as readWithPoll, pgmq_send as send, pgmq_sendBatch as sendBatch, pgmq_setVt as setVt };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { type MessageRecord, type QueueInfo, type QueueMetrics, type Task, pgmq };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
pgmq: () => pgmq_exports
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/pgmq.ts
|
|
28
|
+
var pgmq_exports = {};
|
|
29
|
+
__export(pgmq_exports, {
|
|
30
|
+
archive: () => archive,
|
|
31
|
+
archiveBatch: () => archiveBatch,
|
|
32
|
+
createPartitionedQueue: () => createPartitionedQueue,
|
|
33
|
+
createQueue: () => createQueue,
|
|
34
|
+
createUnloggedQueue: () => createUnloggedQueue,
|
|
35
|
+
deleteBatch: () => deleteBatch,
|
|
36
|
+
deleteMessage: () => deleteMessage,
|
|
37
|
+
detachArchive: () => detachArchive,
|
|
38
|
+
dropQueue: () => dropQueue,
|
|
39
|
+
listQueues: () => listQueues,
|
|
40
|
+
metrics: () => metrics,
|
|
41
|
+
metricsAll: () => metricsAll,
|
|
42
|
+
pop: () => pop,
|
|
43
|
+
purgeQueue: () => purgeQueue,
|
|
44
|
+
read: () => read,
|
|
45
|
+
readWithPoll: () => readWithPoll,
|
|
46
|
+
send: () => send,
|
|
47
|
+
sendBatch: () => sendBatch,
|
|
48
|
+
setVt: () => setVt
|
|
49
|
+
});
|
|
50
|
+
var import_extension = require("@prisma/client/extension");
|
|
51
|
+
var PrismaAny = import_extension.Prisma;
|
|
52
|
+
async function send(tx, queueName, msg, delay) {
|
|
53
|
+
const delayRepr = typeof delay === "number" ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;
|
|
54
|
+
const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;
|
|
55
|
+
const result = await tx.$queryRaw`SELECT pgmq.send(${queueName}, ${msg}${delaySql})`;
|
|
56
|
+
const firstResult = result[0];
|
|
57
|
+
if (!firstResult) {
|
|
58
|
+
throw new Error("No result returned from pgmq.send");
|
|
59
|
+
}
|
|
60
|
+
return firstResult.send;
|
|
61
|
+
}
|
|
62
|
+
async function sendBatch(tx, queueName, msgs, delay) {
|
|
63
|
+
const delayRepr = typeof delay === "number" ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;
|
|
64
|
+
const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;
|
|
65
|
+
const result = await tx.$queryRaw`SELECT pgmq.send_batch(${queueName}, ${msgs}${delaySql})`;
|
|
66
|
+
return result.map((a) => a.send_batch);
|
|
67
|
+
}
|
|
68
|
+
function read(tx, queueName, vt, qty = 1, conditional = {}) {
|
|
69
|
+
return tx.$queryRaw`SELECT * FROM pgmq.read(${queueName}, ${vt}::integer, ${qty}::integer, ${conditional})`;
|
|
70
|
+
}
|
|
71
|
+
function readWithPoll(tx, queueName, vt, qty = 1, maxPollSeconds = 5, pollIntervalMs = 100, conditional = {}) {
|
|
72
|
+
return tx.$queryRaw`SELECT * FROM pgmq.read_with_poll(${queueName}, ${vt}::integer, ${qty}::integer, ${maxPollSeconds}::integer, ${pollIntervalMs}::integer, ${conditional})`;
|
|
73
|
+
}
|
|
74
|
+
function pop(tx, queueName) {
|
|
75
|
+
return tx.$queryRaw`SELECT * FROM pgmq.pop(${queueName})`;
|
|
76
|
+
}
|
|
77
|
+
async function deleteMessage(tx, queueName, msgId) {
|
|
78
|
+
const result = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgId}::integer)`;
|
|
79
|
+
const firstResult = result[0];
|
|
80
|
+
if (!firstResult) {
|
|
81
|
+
throw new Error("No result returned from pgmq.delete");
|
|
82
|
+
}
|
|
83
|
+
return firstResult.delete;
|
|
84
|
+
}
|
|
85
|
+
async function deleteBatch(tx, queueName, msgIds) {
|
|
86
|
+
const result = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgIds}::integer[])`;
|
|
87
|
+
return result.map((a) => a.delete);
|
|
88
|
+
}
|
|
89
|
+
async function purgeQueue(tx, queueName) {
|
|
90
|
+
const result = await tx.$queryRaw`SELECT pgmq.purge_queue(${queueName})`;
|
|
91
|
+
const firstResult = result[0];
|
|
92
|
+
if (!firstResult) {
|
|
93
|
+
throw new Error("No result returned from pgmq.purge_queue");
|
|
94
|
+
}
|
|
95
|
+
return firstResult.purge_queue;
|
|
96
|
+
}
|
|
97
|
+
async function archive(tx, queueName, msgId) {
|
|
98
|
+
const result = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgId}::integer)`;
|
|
99
|
+
const firstResult = result[0];
|
|
100
|
+
if (!firstResult) {
|
|
101
|
+
throw new Error("No result returned from pgmq.archive");
|
|
102
|
+
}
|
|
103
|
+
return firstResult.archive;
|
|
104
|
+
}
|
|
105
|
+
async function archiveBatch(tx, queueName, msgIds) {
|
|
106
|
+
const result = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgIds}::integer[])`;
|
|
107
|
+
return result.map((a) => a.archive);
|
|
108
|
+
}
|
|
109
|
+
async function createQueue(tx, queueName) {
|
|
110
|
+
await tx.$executeRaw`SELECT pgmq.create(${queueName})`;
|
|
111
|
+
}
|
|
112
|
+
async function createPartitionedQueue(tx, queueName, partitionInterval = "10000", retentionInterval = "100000") {
|
|
113
|
+
await tx.$executeRaw`SELECT pgmq.create_partitioned(${queueName}, ${partitionInterval}, ${retentionInterval})`;
|
|
114
|
+
}
|
|
115
|
+
async function createUnloggedQueue(tx, queueName) {
|
|
116
|
+
await tx.$executeRaw`SELECT pgmq.create_unlogged(${queueName})`;
|
|
117
|
+
}
|
|
118
|
+
async function detachArchive(tx, queueName) {
|
|
119
|
+
await tx.$executeRaw`SELECT pgmq.detach_archive(${queueName})`;
|
|
120
|
+
}
|
|
121
|
+
async function dropQueue(tx, queueName) {
|
|
122
|
+
const result = await tx.$queryRaw`SELECT pgmq.drop_queue(${queueName})`;
|
|
123
|
+
const firstResult = result[0];
|
|
124
|
+
if (!firstResult) {
|
|
125
|
+
throw new Error("No result returned from pgmq.drop_queue");
|
|
126
|
+
}
|
|
127
|
+
return firstResult.drop_queue;
|
|
128
|
+
}
|
|
129
|
+
async function setVt(tx, queueName, msgId, vtOffset) {
|
|
130
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.set_vt(${queueName}, ${msgId}::integer, ${vtOffset}::integer)`;
|
|
131
|
+
const firstResult = result[0];
|
|
132
|
+
if (!firstResult) {
|
|
133
|
+
throw new Error("No result returned from pgmq.set_vt");
|
|
134
|
+
}
|
|
135
|
+
return firstResult;
|
|
136
|
+
}
|
|
137
|
+
async function listQueues(tx) {
|
|
138
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.list_queues()`;
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
async function metrics(tx, queueName) {
|
|
142
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.metrics(${queueName})`;
|
|
143
|
+
const firstResult = result[0];
|
|
144
|
+
if (!firstResult) {
|
|
145
|
+
throw new Error("No result returned from pgmq.metrics");
|
|
146
|
+
}
|
|
147
|
+
return firstResult;
|
|
148
|
+
}
|
|
149
|
+
async function metricsAll(tx) {
|
|
150
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.metrics_all()`;
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
154
|
+
0 && (module.exports = {
|
|
155
|
+
pgmq
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/pgmq.ts"],"sourcesContent":["export { \n Task,\n MessageRecord,\n QueueInfo,\n QueueMetrics,\n } from './pgmq';\n \nexport * as pgmq from './pgmq';","import { Prisma } from '@prisma/client/extension';\n\nexport type Task = Record<string, unknown>;\n\n// Message record type based on PGMQ documentation\nexport interface MessageRecord {\n msg_id: number;\n read_ct: number;\n enqueued_at: Date;\n vt: Date;\n message: Task;\n}\n\n// Queue metrics type\nexport interface QueueMetrics {\n queue_name: string;\n queue_length: number;\n newest_msg_age_sec: number | null;\n oldest_msg_age_sec: number | null;\n total_messages: number;\n scrape_time: Date;\n}\n\n// Queue info type\nexport interface QueueInfo {\n queue_name: string;\n created_at: Date;\n is_partitioned: boolean;\n is_unlogged: boolean;\n}\n\n// I expect that Prisma has `sql` defined\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst PrismaAny = Prisma as any;\n\nexport async function send(tx: Prisma.TransactionClient, queueName: string, msg: Task, delay?: number | Date): Promise<number> {\n const delayRepr = typeof delay === 'number' ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;\n const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;\n const result: { send: number }[] = await tx.$queryRaw`SELECT pgmq.send(${queueName}, ${msg}${delaySql})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.send');\n }\n return firstResult.send;\n}\n\nexport async function sendBatch(tx: Prisma.TransactionClient, queueName: string, msgs: Task[], delay?: number | Date): Promise<number[]> {\n const delayRepr = typeof delay === 'number' ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;\n const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;\n const result: { send_batch: number }[] = await tx.$queryRaw`SELECT pgmq.send_batch(${queueName}, ${msgs}${delaySql})`;\n return result.map(a => a.send_batch);\n}\n\n// Reading Messages\n\nexport function read(\n tx: Prisma.TransactionClient, \n queueName: string, \n vt: number, \n qty: number = 1, \n conditional: Task = {}\n): Promise<MessageRecord[]> {\n return tx.$queryRaw`SELECT * FROM pgmq.read(${queueName}, ${vt}::integer, ${qty}::integer, ${conditional})` as Promise<MessageRecord[]>;\n}\n\nexport function readWithPoll(\n tx: Prisma.TransactionClient,\n queueName: string,\n vt: number,\n qty: number = 1,\n maxPollSeconds: number = 5,\n pollIntervalMs: number = 100,\n conditional: Task = {}\n): Promise<MessageRecord[]> {\n return tx.$queryRaw`SELECT * FROM pgmq.read_with_poll(${queueName}, ${vt}::integer, ${qty}::integer, ${maxPollSeconds}::integer, ${pollIntervalMs}::integer, ${conditional})` as Promise<MessageRecord[]>;\n}\n\nexport function pop(tx: Prisma.TransactionClient, queueName: string): Promise<MessageRecord[]> {\n return tx.$queryRaw`SELECT * FROM pgmq.pop(${queueName})` as Promise<MessageRecord[]>;\n}\n\n// Deleting/Archiving Messages\n\nexport async function deleteMessage(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean> {\n const result: { delete: boolean }[] = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgId}::integer)`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.delete');\n }\n return firstResult.delete;\n}\n\nexport async function deleteBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]> {\n const result: { delete: number }[] = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgIds}::integer[])`;\n return result.map(a => a.delete);\n}\n\nexport async function purgeQueue(tx: Prisma.TransactionClient, queueName: string): Promise<number> {\n const result: { purge_queue: number }[] = await tx.$queryRaw`SELECT pgmq.purge_queue(${queueName})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.purge_queue');\n }\n return firstResult.purge_queue;\n}\n\nexport async function archive(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean> {\n const result: { archive: boolean }[] = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgId}::integer)`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.archive');\n }\n return firstResult.archive;\n}\n\nexport async function archiveBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]> {\n const result: { archive: number }[] = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgIds}::integer[])`;\n return result.map(a => a.archive);\n}\n\n// Queue Management\n\nexport async function createQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.create(${queueName})`;\n}\n\nexport async function createPartitionedQueue(\n tx: Prisma.TransactionClient, \n queueName: string, \n partitionInterval: string = '10000', \n retentionInterval: string = '100000'\n): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.create_partitioned(${queueName}, ${partitionInterval}, ${retentionInterval})`;\n}\n\nexport async function createUnloggedQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.create_unlogged(${queueName})`;\n}\n\nexport async function detachArchive(tx: Prisma.TransactionClient, queueName: string): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.detach_archive(${queueName})`;\n}\n\nexport async function dropQueue(tx: Prisma.TransactionClient, queueName: string): Promise<boolean> {\n const result: { drop_queue: boolean }[] = await tx.$queryRaw`SELECT pgmq.drop_queue(${queueName})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.drop_queue');\n }\n return firstResult.drop_queue;\n}\n\n// Utilities\n\nexport async function setVt(\n tx: Prisma.TransactionClient, \n queueName: string, \n msgId: number, \n vtOffset: number\n): Promise<MessageRecord> {\n const result: MessageRecord[] = await tx.$queryRaw`SELECT * FROM pgmq.set_vt(${queueName}, ${msgId}::integer, ${vtOffset}::integer)`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.set_vt');\n }\n return firstResult;\n}\n\nexport async function listQueues(tx: Prisma.TransactionClient): Promise<QueueInfo[]> {\n const result: QueueInfo[] = await tx.$queryRaw`SELECT * FROM pgmq.list_queues()`;\n return result;\n}\n\nexport async function metrics(tx: Prisma.TransactionClient, queueName: string): Promise<QueueMetrics> {\n const result: QueueMetrics[] = await tx.$queryRaw`SELECT * FROM pgmq.metrics(${queueName})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.metrics');\n }\n return firstResult;\n}\n\nexport async function metricsAll(tx: Prisma.TransactionClient): Promise<QueueMetrics[]> {\n const result: QueueMetrics[] = await tx.$queryRaw`SELECT * FROM pgmq.metrics_all()`;\n return result;\n}"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/pgmq.ts
|
|
8
|
+
var pgmq_exports = {};
|
|
9
|
+
__export(pgmq_exports, {
|
|
10
|
+
archive: () => archive,
|
|
11
|
+
archiveBatch: () => archiveBatch,
|
|
12
|
+
createPartitionedQueue: () => createPartitionedQueue,
|
|
13
|
+
createQueue: () => createQueue,
|
|
14
|
+
createUnloggedQueue: () => createUnloggedQueue,
|
|
15
|
+
deleteBatch: () => deleteBatch,
|
|
16
|
+
deleteMessage: () => deleteMessage,
|
|
17
|
+
detachArchive: () => detachArchive,
|
|
18
|
+
dropQueue: () => dropQueue,
|
|
19
|
+
listQueues: () => listQueues,
|
|
20
|
+
metrics: () => metrics,
|
|
21
|
+
metricsAll: () => metricsAll,
|
|
22
|
+
pop: () => pop,
|
|
23
|
+
purgeQueue: () => purgeQueue,
|
|
24
|
+
read: () => read,
|
|
25
|
+
readWithPoll: () => readWithPoll,
|
|
26
|
+
send: () => send,
|
|
27
|
+
sendBatch: () => sendBatch,
|
|
28
|
+
setVt: () => setVt
|
|
29
|
+
});
|
|
30
|
+
import { Prisma } from "@prisma/client/extension";
|
|
31
|
+
var PrismaAny = Prisma;
|
|
32
|
+
async function send(tx, queueName, msg, delay) {
|
|
33
|
+
const delayRepr = typeof delay === "number" ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;
|
|
34
|
+
const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;
|
|
35
|
+
const result = await tx.$queryRaw`SELECT pgmq.send(${queueName}, ${msg}${delaySql})`;
|
|
36
|
+
const firstResult = result[0];
|
|
37
|
+
if (!firstResult) {
|
|
38
|
+
throw new Error("No result returned from pgmq.send");
|
|
39
|
+
}
|
|
40
|
+
return firstResult.send;
|
|
41
|
+
}
|
|
42
|
+
async function sendBatch(tx, queueName, msgs, delay) {
|
|
43
|
+
const delayRepr = typeof delay === "number" ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;
|
|
44
|
+
const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;
|
|
45
|
+
const result = await tx.$queryRaw`SELECT pgmq.send_batch(${queueName}, ${msgs}${delaySql})`;
|
|
46
|
+
return result.map((a) => a.send_batch);
|
|
47
|
+
}
|
|
48
|
+
function read(tx, queueName, vt, qty = 1, conditional = {}) {
|
|
49
|
+
return tx.$queryRaw`SELECT * FROM pgmq.read(${queueName}, ${vt}::integer, ${qty}::integer, ${conditional})`;
|
|
50
|
+
}
|
|
51
|
+
function readWithPoll(tx, queueName, vt, qty = 1, maxPollSeconds = 5, pollIntervalMs = 100, conditional = {}) {
|
|
52
|
+
return tx.$queryRaw`SELECT * FROM pgmq.read_with_poll(${queueName}, ${vt}::integer, ${qty}::integer, ${maxPollSeconds}::integer, ${pollIntervalMs}::integer, ${conditional})`;
|
|
53
|
+
}
|
|
54
|
+
function pop(tx, queueName) {
|
|
55
|
+
return tx.$queryRaw`SELECT * FROM pgmq.pop(${queueName})`;
|
|
56
|
+
}
|
|
57
|
+
async function deleteMessage(tx, queueName, msgId) {
|
|
58
|
+
const result = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgId}::integer)`;
|
|
59
|
+
const firstResult = result[0];
|
|
60
|
+
if (!firstResult) {
|
|
61
|
+
throw new Error("No result returned from pgmq.delete");
|
|
62
|
+
}
|
|
63
|
+
return firstResult.delete;
|
|
64
|
+
}
|
|
65
|
+
async function deleteBatch(tx, queueName, msgIds) {
|
|
66
|
+
const result = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgIds}::integer[])`;
|
|
67
|
+
return result.map((a) => a.delete);
|
|
68
|
+
}
|
|
69
|
+
async function purgeQueue(tx, queueName) {
|
|
70
|
+
const result = await tx.$queryRaw`SELECT pgmq.purge_queue(${queueName})`;
|
|
71
|
+
const firstResult = result[0];
|
|
72
|
+
if (!firstResult) {
|
|
73
|
+
throw new Error("No result returned from pgmq.purge_queue");
|
|
74
|
+
}
|
|
75
|
+
return firstResult.purge_queue;
|
|
76
|
+
}
|
|
77
|
+
async function archive(tx, queueName, msgId) {
|
|
78
|
+
const result = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgId}::integer)`;
|
|
79
|
+
const firstResult = result[0];
|
|
80
|
+
if (!firstResult) {
|
|
81
|
+
throw new Error("No result returned from pgmq.archive");
|
|
82
|
+
}
|
|
83
|
+
return firstResult.archive;
|
|
84
|
+
}
|
|
85
|
+
async function archiveBatch(tx, queueName, msgIds) {
|
|
86
|
+
const result = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgIds}::integer[])`;
|
|
87
|
+
return result.map((a) => a.archive);
|
|
88
|
+
}
|
|
89
|
+
async function createQueue(tx, queueName) {
|
|
90
|
+
await tx.$executeRaw`SELECT pgmq.create(${queueName})`;
|
|
91
|
+
}
|
|
92
|
+
async function createPartitionedQueue(tx, queueName, partitionInterval = "10000", retentionInterval = "100000") {
|
|
93
|
+
await tx.$executeRaw`SELECT pgmq.create_partitioned(${queueName}, ${partitionInterval}, ${retentionInterval})`;
|
|
94
|
+
}
|
|
95
|
+
async function createUnloggedQueue(tx, queueName) {
|
|
96
|
+
await tx.$executeRaw`SELECT pgmq.create_unlogged(${queueName})`;
|
|
97
|
+
}
|
|
98
|
+
async function detachArchive(tx, queueName) {
|
|
99
|
+
await tx.$executeRaw`SELECT pgmq.detach_archive(${queueName})`;
|
|
100
|
+
}
|
|
101
|
+
async function dropQueue(tx, queueName) {
|
|
102
|
+
const result = await tx.$queryRaw`SELECT pgmq.drop_queue(${queueName})`;
|
|
103
|
+
const firstResult = result[0];
|
|
104
|
+
if (!firstResult) {
|
|
105
|
+
throw new Error("No result returned from pgmq.drop_queue");
|
|
106
|
+
}
|
|
107
|
+
return firstResult.drop_queue;
|
|
108
|
+
}
|
|
109
|
+
async function setVt(tx, queueName, msgId, vtOffset) {
|
|
110
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.set_vt(${queueName}, ${msgId}::integer, ${vtOffset}::integer)`;
|
|
111
|
+
const firstResult = result[0];
|
|
112
|
+
if (!firstResult) {
|
|
113
|
+
throw new Error("No result returned from pgmq.set_vt");
|
|
114
|
+
}
|
|
115
|
+
return firstResult;
|
|
116
|
+
}
|
|
117
|
+
async function listQueues(tx) {
|
|
118
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.list_queues()`;
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
async function metrics(tx, queueName) {
|
|
122
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.metrics(${queueName})`;
|
|
123
|
+
const firstResult = result[0];
|
|
124
|
+
if (!firstResult) {
|
|
125
|
+
throw new Error("No result returned from pgmq.metrics");
|
|
126
|
+
}
|
|
127
|
+
return firstResult;
|
|
128
|
+
}
|
|
129
|
+
async function metricsAll(tx) {
|
|
130
|
+
const result = await tx.$queryRaw`SELECT * FROM pgmq.metrics_all()`;
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
export {
|
|
134
|
+
pgmq_exports as pgmq
|
|
135
|
+
};
|
|
136
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pgmq.ts"],"sourcesContent":["import { Prisma } from '@prisma/client/extension';\n\nexport type Task = Record<string, unknown>;\n\n// Message record type based on PGMQ documentation\nexport interface MessageRecord {\n msg_id: number;\n read_ct: number;\n enqueued_at: Date;\n vt: Date;\n message: Task;\n}\n\n// Queue metrics type\nexport interface QueueMetrics {\n queue_name: string;\n queue_length: number;\n newest_msg_age_sec: number | null;\n oldest_msg_age_sec: number | null;\n total_messages: number;\n scrape_time: Date;\n}\n\n// Queue info type\nexport interface QueueInfo {\n queue_name: string;\n created_at: Date;\n is_partitioned: boolean;\n is_unlogged: boolean;\n}\n\n// I expect that Prisma has `sql` defined\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst PrismaAny = Prisma as any;\n\nexport async function send(tx: Prisma.TransactionClient, queueName: string, msg: Task, delay?: number | Date): Promise<number> {\n const delayRepr = typeof delay === 'number' ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;\n const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;\n const result: { send: number }[] = await tx.$queryRaw`SELECT pgmq.send(${queueName}, ${msg}${delaySql})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.send');\n }\n return firstResult.send;\n}\n\nexport async function sendBatch(tx: Prisma.TransactionClient, queueName: string, msgs: Task[], delay?: number | Date): Promise<number[]> {\n const delayRepr = typeof delay === 'number' ? PrismaAny.sql`${delay}::integer` : PrismaAny.sql`${delay}`;\n const delaySql = delay ? PrismaAny.sql`, ${delayRepr}` : PrismaAny.sql``;\n const result: { send_batch: number }[] = await tx.$queryRaw`SELECT pgmq.send_batch(${queueName}, ${msgs}${delaySql})`;\n return result.map(a => a.send_batch);\n}\n\n// Reading Messages\n\nexport function read(\n tx: Prisma.TransactionClient, \n queueName: string, \n vt: number, \n qty: number = 1, \n conditional: Task = {}\n): Promise<MessageRecord[]> {\n return tx.$queryRaw`SELECT * FROM pgmq.read(${queueName}, ${vt}::integer, ${qty}::integer, ${conditional})` as Promise<MessageRecord[]>;\n}\n\nexport function readWithPoll(\n tx: Prisma.TransactionClient,\n queueName: string,\n vt: number,\n qty: number = 1,\n maxPollSeconds: number = 5,\n pollIntervalMs: number = 100,\n conditional: Task = {}\n): Promise<MessageRecord[]> {\n return tx.$queryRaw`SELECT * FROM pgmq.read_with_poll(${queueName}, ${vt}::integer, ${qty}::integer, ${maxPollSeconds}::integer, ${pollIntervalMs}::integer, ${conditional})` as Promise<MessageRecord[]>;\n}\n\nexport function pop(tx: Prisma.TransactionClient, queueName: string): Promise<MessageRecord[]> {\n return tx.$queryRaw`SELECT * FROM pgmq.pop(${queueName})` as Promise<MessageRecord[]>;\n}\n\n// Deleting/Archiving Messages\n\nexport async function deleteMessage(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean> {\n const result: { delete: boolean }[] = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgId}::integer)`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.delete');\n }\n return firstResult.delete;\n}\n\nexport async function deleteBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]> {\n const result: { delete: number }[] = await tx.$queryRaw`SELECT pgmq.delete(${queueName}, ${msgIds}::integer[])`;\n return result.map(a => a.delete);\n}\n\nexport async function purgeQueue(tx: Prisma.TransactionClient, queueName: string): Promise<number> {\n const result: { purge_queue: number }[] = await tx.$queryRaw`SELECT pgmq.purge_queue(${queueName})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.purge_queue');\n }\n return firstResult.purge_queue;\n}\n\nexport async function archive(tx: Prisma.TransactionClient, queueName: string, msgId: number): Promise<boolean> {\n const result: { archive: boolean }[] = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgId}::integer)`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.archive');\n }\n return firstResult.archive;\n}\n\nexport async function archiveBatch(tx: Prisma.TransactionClient, queueName: string, msgIds: number[]): Promise<number[]> {\n const result: { archive: number }[] = await tx.$queryRaw`SELECT pgmq.archive(${queueName}, ${msgIds}::integer[])`;\n return result.map(a => a.archive);\n}\n\n// Queue Management\n\nexport async function createQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.create(${queueName})`;\n}\n\nexport async function createPartitionedQueue(\n tx: Prisma.TransactionClient, \n queueName: string, \n partitionInterval: string = '10000', \n retentionInterval: string = '100000'\n): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.create_partitioned(${queueName}, ${partitionInterval}, ${retentionInterval})`;\n}\n\nexport async function createUnloggedQueue(tx: Prisma.TransactionClient, queueName: string): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.create_unlogged(${queueName})`;\n}\n\nexport async function detachArchive(tx: Prisma.TransactionClient, queueName: string): Promise<void> {\n await tx.$executeRaw`SELECT pgmq.detach_archive(${queueName})`;\n}\n\nexport async function dropQueue(tx: Prisma.TransactionClient, queueName: string): Promise<boolean> {\n const result: { drop_queue: boolean }[] = await tx.$queryRaw`SELECT pgmq.drop_queue(${queueName})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.drop_queue');\n }\n return firstResult.drop_queue;\n}\n\n// Utilities\n\nexport async function setVt(\n tx: Prisma.TransactionClient, \n queueName: string, \n msgId: number, \n vtOffset: number\n): Promise<MessageRecord> {\n const result: MessageRecord[] = await tx.$queryRaw`SELECT * FROM pgmq.set_vt(${queueName}, ${msgId}::integer, ${vtOffset}::integer)`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.set_vt');\n }\n return firstResult;\n}\n\nexport async function listQueues(tx: Prisma.TransactionClient): Promise<QueueInfo[]> {\n const result: QueueInfo[] = await tx.$queryRaw`SELECT * FROM pgmq.list_queues()`;\n return result;\n}\n\nexport async function metrics(tx: Prisma.TransactionClient, queueName: string): Promise<QueueMetrics> {\n const result: QueueMetrics[] = await tx.$queryRaw`SELECT * FROM pgmq.metrics(${queueName})`;\n const firstResult = result[0];\n if (!firstResult) {\n throw new Error('No result returned from pgmq.metrics');\n }\n return firstResult;\n}\n\nexport async function metricsAll(tx: Prisma.TransactionClient): Promise<QueueMetrics[]> {\n const result: QueueMetrics[] = await tx.$queryRaw`SELECT * FROM pgmq.metrics_all()`;\n return result;\n}"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,cAAc;AAiCvB,IAAM,YAAY;AAElB,eAAsB,KAAK,IAA8B,WAAmB,KAAW,OAAwC;AAC3H,QAAM,YAAY,OAAO,UAAU,WAAW,UAAU,MAAM,KAAK,cAAc,UAAU,MAAM,KAAK;AACtG,QAAM,WAAW,QAAQ,UAAU,QAAQ,SAAS,KAAK,UAAU;AACnE,QAAM,SAA6B,MAAM,GAAG,6BAA6B,SAAS,KAAK,GAAG,GAAG,QAAQ;AACrG,QAAM,cAAc,OAAO,CAAC;AAC5B,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACvD;AACA,SAAO,YAAY;AACvB;AAEA,eAAsB,UAAU,IAA8B,WAAmB,MAAc,OAA0C;AACrI,QAAM,YAAY,OAAO,UAAU,WAAW,UAAU,MAAM,KAAK,cAAc,UAAU,MAAM,KAAK;AACtG,QAAM,WAAW,QAAQ,UAAU,QAAQ,SAAS,KAAK,UAAU;AACnE,QAAM,SAAmC,MAAM,GAAG,mCAAmC,SAAS,KAAK,IAAI,GAAG,QAAQ;AAClH,SAAO,OAAO,IAAI,OAAK,EAAE,UAAU;AACvC;AAIO,SAAS,KACZ,IACA,WACA,IACA,MAAc,GACd,cAAoB,CAAC,GACG;AACxB,SAAO,GAAG,oCAAoC,SAAS,KAAK,EAAE,cAAc,GAAG,cAAc,WAAW;AAC5G;AAEO,SAAS,aACZ,IACA,WACA,IACA,MAAc,GACd,iBAAyB,GACzB,iBAAyB,KACzB,cAAoB,CAAC,GACG;AACxB,SAAO,GAAG,8CAA8C,SAAS,KAAK,EAAE,cAAc,GAAG,cAAc,cAAc,cAAc,cAAc,cAAc,WAAW;AAC9K;AAEO,SAAS,IAAI,IAA8B,WAA6C;AAC3F,SAAO,GAAG,mCAAmC,SAAS;AAC1D;AAIA,eAAsB,cAAc,IAA8B,WAAmB,OAAiC;AAClH,QAAM,SAAgC,MAAM,GAAG,+BAA+B,SAAS,KAAK,KAAK;AACjG,QAAM,cAAc,OAAO,CAAC;AAC5B,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACzD;AACA,SAAO,YAAY;AACvB;AAEA,eAAsB,YAAY,IAA8B,WAAmB,QAAqC;AACpH,QAAM,SAA+B,MAAM,GAAG,+BAA+B,SAAS,KAAK,MAAM;AACjG,SAAO,OAAO,IAAI,OAAK,EAAE,MAAM;AACnC;AAEA,eAAsB,WAAW,IAA8B,WAAoC;AAC/F,QAAM,SAAoC,MAAM,GAAG,oCAAoC,SAAS;AAChG,QAAM,cAAc,OAAO,CAAC;AAC5B,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC9D;AACA,SAAO,YAAY;AACvB;AAEA,eAAsB,QAAQ,IAA8B,WAAmB,OAAiC;AAC5G,QAAM,SAAiC,MAAM,GAAG,gCAAgC,SAAS,KAAK,KAAK;AACnG,QAAM,cAAc,OAAO,CAAC;AAC5B,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,sCAAsC;AAAA,EAC1D;AACA,SAAO,YAAY;AACvB;AAEA,eAAsB,aAAa,IAA8B,WAAmB,QAAqC;AACrH,QAAM,SAAgC,MAAM,GAAG,gCAAgC,SAAS,KAAK,MAAM;AACnG,SAAO,OAAO,IAAI,OAAK,EAAE,OAAO;AACpC;AAIA,eAAsB,YAAY,IAA8B,WAAkC;AAC9F,QAAM,GAAG,iCAAiC,SAAS;AACvD;AAEA,eAAsB,uBAClB,IACA,WACA,oBAA4B,SAC5B,oBAA4B,UACf;AACb,QAAM,GAAG,6CAA6C,SAAS,KAAK,iBAAiB,KAAK,iBAAiB;AAC/G;AAEA,eAAsB,oBAAoB,IAA8B,WAAkC;AACtG,QAAM,GAAG,0CAA0C,SAAS;AAChE;AAEA,eAAsB,cAAc,IAA8B,WAAkC;AAChG,QAAM,GAAG,yCAAyC,SAAS;AAC/D;AAEA,eAAsB,UAAU,IAA8B,WAAqC;AAC/F,QAAM,SAAoC,MAAM,GAAG,mCAAmC,SAAS;AAC/F,QAAM,cAAc,OAAO,CAAC;AAC5B,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC7D;AACA,SAAO,YAAY;AACvB;AAIA,eAAsB,MAClB,IACA,WACA,OACA,UACsB;AACtB,QAAM,SAA0B,MAAM,GAAG,sCAAsC,SAAS,KAAK,KAAK,cAAc,QAAQ;AACxH,QAAM,cAAc,OAAO,CAAC;AAC5B,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACzD;AACA,SAAO;AACX;AAEA,eAAsB,WAAW,IAAoD;AACjF,QAAM,SAAsB,MAAM,GAAG;AACrC,SAAO;AACX;AAEA,eAAsB,QAAQ,IAA8B,WAA0C;AAClG,QAAM,SAAyB,MAAM,GAAG,uCAAuC,SAAS;AACxF,QAAM,cAAc,OAAO,CAAC;AAC5B,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,sCAAsC;AAAA,EAC1D;AACA,SAAO;AACX;AAEA,eAAsB,WAAW,IAAuD;AACpF,QAAM,SAAyB,MAAM,GAAG;AACxC,SAAO;AACX;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prisma-pgmq",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A Prisma PGMQ implementation providing type-safe message queue operations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"prisma",
|
|
15
|
+
"postgresql",
|
|
16
|
+
"message-queue",
|
|
17
|
+
"pgmq",
|
|
18
|
+
"queue",
|
|
19
|
+
"background-jobs",
|
|
20
|
+
"database",
|
|
21
|
+
"typescript"
|
|
22
|
+
],
|
|
23
|
+
"author": "Dan Volkov <volkv.dan@gmail.com>",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/dvlkv/prisma-pgmq.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/dvlkv/prisma-pgmq/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/dvlkv/prisma-pgmq#readme",
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@prisma/client": ">=5.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@eslint/js": "^9.29.0",
|
|
38
|
+
"@prisma/client": "^5.0.0",
|
|
39
|
+
"@types/node": "^24.0.4",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^8.35.0",
|
|
41
|
+
"@typescript-eslint/parser": "^8.35.0",
|
|
42
|
+
"eslint": "^9.29.0",
|
|
43
|
+
"prisma": "^5.0.0",
|
|
44
|
+
"rimraf": "^6.0.1",
|
|
45
|
+
"tsup": "^8.5.0",
|
|
46
|
+
"typescript": "^5.8.3",
|
|
47
|
+
"typescript-eslint": "^8.35.0"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=16.0.0"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"build:watch": "tsup --watch",
|
|
55
|
+
"lint": "eslint --ext .ts,.tsx",
|
|
56
|
+
"lint:fix": "eslint --ext .ts,.tsx --fix",
|
|
57
|
+
"typecheck": "tsc --noEmit",
|
|
58
|
+
"dev": "pnpm build:watch",
|
|
59
|
+
"clean": "rimraf dist"
|
|
60
|
+
}
|
|
61
|
+
}
|