@storyshelf/queue-sqs 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/README.md +79 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.mjs +124 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# @storyshelf/queue-sqs
|
|
2
|
+
|
|
3
|
+
SQS capture job queue adapter for StoryShelf: pushes capture jobs to AWS SQS and leaves execution to a separately-assembled worker.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
nub add @storyshelf/queue-sqs
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
or
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install @storyshelf/queue-sqs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createSqsCaptureQueue } from "@storyshelf/queue-sqs";
|
|
21
|
+
import { createShelfRouter } from "@storyshelf/core";
|
|
22
|
+
|
|
23
|
+
const queue = createSqsCaptureQueue({
|
|
24
|
+
queueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/capture-jobs",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const app = createShelfRouter({
|
|
28
|
+
database, storage,
|
|
29
|
+
captureRunner: myRenderer,
|
|
30
|
+
captureQueue: queue,
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API
|
|
35
|
+
|
|
36
|
+
### `SqsCaptureQueueOptions`
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
interface SqsCaptureQueueOptions {
|
|
40
|
+
queueUrl: string; // required SQS queue URL
|
|
41
|
+
client?: SqsClient; // optional pre-configured client
|
|
42
|
+
logger?: Logger; // optional pino logger
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `createSqsCaptureQueue(options: SqsCaptureQueueOptions): CaptureQueue`
|
|
47
|
+
|
|
48
|
+
Creates an SQS-backed `CaptureQueue`. The returned adapter implements every method of the `CaptureQueue` interface (`enqueue`, `status`, `active`, `recent`). Jobs are submitted via `SendMessage` and retrieved via `ReceiveMessage`; messages are deleted after reading to prevent re-processing.
|
|
49
|
+
|
|
50
|
+
## How it fits in
|
|
51
|
+
|
|
52
|
+
`queue-sqs` is the `queue` option for `createShelfRouter` in AWS/cloud deployments. It implements the same `CaptureQueue` interface as `@storyshelf/capture/queue` (InMemoryCaptureQueue), so switching between in-process and remote queues requires no changes to router or build logic.
|
|
53
|
+
|
|
54
|
+
See `docs/architecture.md` and ADR 0009.
|
|
55
|
+
|
|
56
|
+
## SQS Queue Worker
|
|
57
|
+
|
|
58
|
+
A separate worker process (Node, Bun, etc.) polls the SQS queue and calls `executeCaptureJob` from `@storyshelf/core`:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { executeCaptureJob } from "@storyshelf/core";
|
|
62
|
+
import { SqsClient, ReceiveMessageCommand, DeleteMessageCommand } from "@aws-sdk/client-sqs";
|
|
63
|
+
|
|
64
|
+
while (true) {
|
|
65
|
+
const msg = await sqsClient.send(new ReceiveMessageCommand({ ... }));
|
|
66
|
+
const { buildId, reqId } = JSON.parse(msg.Body!);
|
|
67
|
+
await executeCaptureJob({ buildId, reqId }, jobOptions);
|
|
68
|
+
await sqsClient.send(new DeleteMessageCommand({ QueueUrl: queueUrl, ReceiptHandle: msg.ReceiptHandle }));
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
nub run build # bundle with tsdown
|
|
76
|
+
nub run fmt # format with oxfmt
|
|
77
|
+
nub run lint # type-aware lint with oxlint
|
|
78
|
+
nub run test # vitest suite
|
|
79
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { SQSClient } from "@aws-sdk/client-sqs";
|
|
4
|
+
import { CaptureQueue } from "@storyshelf/core";
|
|
5
|
+
import { Logger } from "pino";
|
|
6
|
+
//#region src/index.d.ts
|
|
7
|
+
/** Options for configuring an SQS-backed CaptureQueue. */
|
|
8
|
+
interface SqsCaptureQueueOptions {
|
|
9
|
+
/** SQS queue URL. */
|
|
10
|
+
queueUrl: string;
|
|
11
|
+
/** Optional pre-configured SQSClient. */
|
|
12
|
+
client?: SQSClient;
|
|
13
|
+
/** Optional logger for queue diagnostics. */
|
|
14
|
+
logger?: Logger;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create an SQS-backed `CaptureQueue`.
|
|
18
|
+
*
|
|
19
|
+
* Jobs are submitted via `SendMessage` and retrieved via `ReceiveMessage`;
|
|
20
|
+
* messages are deleted after reading to prevent re-processing.
|
|
21
|
+
* A separately-assembled worker polls the queue and calls
|
|
22
|
+
* `executeCaptureJob` from `@storyshelf/core`.
|
|
23
|
+
*
|
|
24
|
+
* @param options - SQS queue URL and optional client configuration.
|
|
25
|
+
* @returns A `CaptureQueue` satisfying the core interface.
|
|
26
|
+
*/
|
|
27
|
+
declare function createSqsCaptureQueue(options: SqsCaptureQueueOptions): CaptureQueue;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { SqsCaptureQueueOptions, createSqsCaptureQueue };
|
|
30
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { DeleteMessageCommand, ReceiveMessageCommand, SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs";
|
|
5
|
+
//#region src/index.ts
|
|
6
|
+
function parseBody(raw) {
|
|
7
|
+
return JSON.parse(raw);
|
|
8
|
+
}
|
|
9
|
+
function hasQueuedOrRunningStatus(body) {
|
|
10
|
+
const status = body.status ?? "queued";
|
|
11
|
+
return ["queued", "running"].includes(status);
|
|
12
|
+
}
|
|
13
|
+
function mapQueueEntry(raw) {
|
|
14
|
+
const body = parseBody(raw.Body ?? "{}");
|
|
15
|
+
return {
|
|
16
|
+
buildId: body.buildId ?? "unknown",
|
|
17
|
+
status: body.status ?? "queued",
|
|
18
|
+
queuedAt: body.queuedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create an SQS-backed `CaptureQueue`.
|
|
23
|
+
*
|
|
24
|
+
* Jobs are submitted via `SendMessage` and retrieved via `ReceiveMessage`;
|
|
25
|
+
* messages are deleted after reading to prevent re-processing.
|
|
26
|
+
* A separately-assembled worker polls the queue and calls
|
|
27
|
+
* `executeCaptureJob` from `@storyshelf/core`.
|
|
28
|
+
*
|
|
29
|
+
* @param options - SQS queue URL and optional client configuration.
|
|
30
|
+
* @returns A `CaptureQueue` satisfying the core interface.
|
|
31
|
+
*/
|
|
32
|
+
function createSqsCaptureQueue(options) {
|
|
33
|
+
const client = options.client ?? new SQSClient({});
|
|
34
|
+
return {
|
|
35
|
+
metadata: {
|
|
36
|
+
name: "SQS Queue",
|
|
37
|
+
version: "0.1.0",
|
|
38
|
+
description: "SQS-backed capture queue",
|
|
39
|
+
kind: "sqs"
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Submit a build for capture. Resolves once the message is sent to SQS.
|
|
43
|
+
*
|
|
44
|
+
* The actual capture execution happens in a separate worker that
|
|
45
|
+
* polls the queue and calls `executeCaptureJob`.
|
|
46
|
+
*/
|
|
47
|
+
async enqueue(job) {
|
|
48
|
+
await client.send(new SendMessageCommand({
|
|
49
|
+
QueueUrl: options.queueUrl,
|
|
50
|
+
MessageBody: JSON.stringify({
|
|
51
|
+
buildId: job.buildId,
|
|
52
|
+
reqId: job.reqId
|
|
53
|
+
}),
|
|
54
|
+
MessageAttributes: {
|
|
55
|
+
buildId: {
|
|
56
|
+
DataType: "String",
|
|
57
|
+
StringValue: job.buildId
|
|
58
|
+
},
|
|
59
|
+
status: {
|
|
60
|
+
DataType: "String",
|
|
61
|
+
StringValue: "queued"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}));
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Return the current status entry for a build, or null if untracked.
|
|
68
|
+
*
|
|
69
|
+
* Polls the SQS queue for a message matching the buildId. If found,
|
|
70
|
+
* the message is deleted so it is not re-processed.
|
|
71
|
+
*/
|
|
72
|
+
async status(buildId) {
|
|
73
|
+
const messages = (await client.send(new ReceiveMessageCommand({
|
|
74
|
+
QueueUrl: options.queueUrl,
|
|
75
|
+
MaxNumberOfMessages: 1,
|
|
76
|
+
MessageAttributeNames: ["All"]
|
|
77
|
+
}))).Messages ?? [];
|
|
78
|
+
if (messages.length === 0) return null;
|
|
79
|
+
const [msg] = messages;
|
|
80
|
+
if (!msg?.Body) return null;
|
|
81
|
+
const body = parseBody(msg.Body);
|
|
82
|
+
await client.send(new DeleteMessageCommand({
|
|
83
|
+
QueueUrl: options.queueUrl,
|
|
84
|
+
ReceiptHandle: msg.ReceiptHandle
|
|
85
|
+
}));
|
|
86
|
+
return {
|
|
87
|
+
buildId: body.buildId ?? buildId,
|
|
88
|
+
status: body.status ?? "queued",
|
|
89
|
+
queuedAt: body.queuedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
90
|
+
startedAt: body.startedAt,
|
|
91
|
+
finishedAt: body.finishedAt,
|
|
92
|
+
error: body.error
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
/**
|
|
96
|
+
* Return queue entries that are queued or running, newest first.
|
|
97
|
+
*
|
|
98
|
+
* Short poll for up to 10 messages. Filters by status.
|
|
99
|
+
*/
|
|
100
|
+
async active() {
|
|
101
|
+
return ((await client.send(new ReceiveMessageCommand({
|
|
102
|
+
QueueUrl: options.queueUrl,
|
|
103
|
+
MaxNumberOfMessages: 10,
|
|
104
|
+
MessageAttributeNames: ["All"]
|
|
105
|
+
}))).Messages ?? []).filter((message) => message.Body?.length && hasQueuedOrRunningStatus(parseBody(message.Body))).map((msg) => mapQueueEntry(msg)).toSorted((left, right) => right.queuedAt.localeCompare(left.queuedAt));
|
|
106
|
+
},
|
|
107
|
+
/**
|
|
108
|
+
* Return the most recent queue entries, newest first.
|
|
109
|
+
*
|
|
110
|
+
* Short poll for up to `limit` messages, sorted by queuedAt descending.
|
|
111
|
+
*/
|
|
112
|
+
async recent(limit) {
|
|
113
|
+
return ((await client.send(new ReceiveMessageCommand({
|
|
114
|
+
QueueUrl: options.queueUrl,
|
|
115
|
+
MaxNumberOfMessages: limit,
|
|
116
|
+
MessageAttributeNames: ["All"]
|
|
117
|
+
}))).Messages ?? []).map((msg) => mapQueueEntry(msg)).toSorted((left, right) => right.queuedAt.localeCompare(left.queuedAt));
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { createSqsCaptureQueue };
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n DeleteMessageCommand,\n ReceiveMessageCommand,\n SendMessageCommand,\n SQSClient,\n} from \"@aws-sdk/client-sqs\";\n\nimport type {\n CaptureJob,\n CaptureQueue,\n JobStatus,\n QueueEntry,\n} from \"@storyshelf/core\";\n\nimport type { Logger } from \"pino\";\n\ndeclare const __PKG_VERSION__: string;\n\n/** Options for configuring an SQS-backed CaptureQueue. */\nexport interface SqsCaptureQueueOptions {\n /** SQS queue URL. */\n queueUrl: string;\n /** Optional pre-configured SQSClient. */\n client?: SQSClient;\n /** Optional logger for queue diagnostics. */\n logger?: Logger;\n}\n\ninterface QueuedBody {\n buildId?: string;\n status?: JobStatus;\n queuedAt?: string;\n startedAt?: string;\n finishedAt?: string;\n error?: string;\n reqId?: string;\n}\n\nfunction parseBody(raw: string): QueuedBody {\n return JSON.parse(raw) as QueuedBody;\n}\n\nfunction hasQueuedOrRunningStatus(body: QueuedBody): boolean {\n const status = body.status ?? \"queued\";\n return [\"queued\", \"running\"].includes(status);\n}\n\nfunction mapQueueEntry(raw: { Body?: string }): QueueEntry {\n const body = parseBody(raw.Body ?? \"{}\");\n return {\n buildId: body.buildId ?? \"unknown\",\n status: body.status ?? \"queued\",\n queuedAt: body.queuedAt ?? new Date().toISOString(),\n };\n}\n\n/**\n * Create an SQS-backed `CaptureQueue`.\n *\n * Jobs are submitted via `SendMessage` and retrieved via `ReceiveMessage`;\n * messages are deleted after reading to prevent re-processing.\n * A separately-assembled worker polls the queue and calls\n * `executeCaptureJob` from `@storyshelf/core`.\n *\n * @param options - SQS queue URL and optional client configuration.\n * @returns A `CaptureQueue` satisfying the core interface.\n */\n/* oxlint-disable max-lines-per-function */\nexport function createSqsCaptureQueue(\n options: SqsCaptureQueueOptions,\n): CaptureQueue {\n const client = options.client ?? new SQSClient({});\n\n return {\n metadata: {\n name: \"SQS Queue\",\n version: typeof __PKG_VERSION__ === \"undefined\" ? \"0.0.0\" : __PKG_VERSION__, // oxlint-disable-line unicorn/no-typeof-undefined\n description: \"SQS-backed capture queue\",\n kind: \"sqs\",\n },\n /**\n * Submit a build for capture. Resolves once the message is sent to SQS.\n *\n * The actual capture execution happens in a separate worker that\n * polls the queue and calls `executeCaptureJob`.\n */\n async enqueue(job: CaptureJob): Promise<void> {\n await client.send(\n new SendMessageCommand({\n QueueUrl: options.queueUrl,\n MessageBody: JSON.stringify({\n buildId: job.buildId,\n reqId: job.reqId,\n }),\n MessageAttributes: {\n buildId: {\n DataType: \"String\",\n StringValue: job.buildId,\n },\n status: {\n DataType: \"String\",\n StringValue: \"queued\",\n },\n },\n }),\n );\n },\n\n /**\n * Return the current status entry for a build, or null if untracked.\n *\n * Polls the SQS queue for a message matching the buildId. If found,\n * the message is deleted so it is not re-processed.\n */\n async status(buildId: string): Promise<QueueEntry | null> {\n const resp = await client.send(\n new ReceiveMessageCommand({\n QueueUrl: options.queueUrl,\n MaxNumberOfMessages: 1,\n MessageAttributeNames: [\"All\"],\n }),\n );\n\n const messages = resp.Messages ?? [];\n if (messages.length === 0) {\n return null;\n }\n\n const [msg] = messages;\n if (!msg?.Body) {\n return null;\n }\n\n const body = parseBody(msg.Body);\n\n await client.send(\n new DeleteMessageCommand({\n QueueUrl: options.queueUrl,\n ReceiptHandle: msg.ReceiptHandle,\n }),\n );\n\n return {\n buildId: body.buildId ?? buildId,\n status: body.status ?? \"queued\",\n queuedAt: body.queuedAt ?? new Date().toISOString(),\n startedAt: body.startedAt,\n finishedAt: body.finishedAt,\n error: body.error,\n };\n },\n\n /**\n * Return queue entries that are queued or running, newest first.\n *\n * Short poll for up to 10 messages. Filters by status.\n */\n async active(): Promise<QueueEntry[]> {\n const resp = await client.send(\n new ReceiveMessageCommand({\n QueueUrl: options.queueUrl,\n MaxNumberOfMessages: 10,\n MessageAttributeNames: [\"All\"],\n }),\n );\n\n return (resp.Messages ?? [])\n .filter((message) => message.Body?.length && hasQueuedOrRunningStatus(parseBody(message.Body)))\n .map((msg) => mapQueueEntry(msg))\n .toSorted((left, right) => right.queuedAt.localeCompare(left.queuedAt));\n },\n\n /**\n * Return the most recent queue entries, newest first.\n *\n * Short poll for up to `limit` messages, sorted by queuedAt descending.\n */\n async recent(limit: number): Promise<QueueEntry[]> {\n const resp = await client.send(\n new ReceiveMessageCommand({\n QueueUrl: options.queueUrl,\n MaxNumberOfMessages: limit,\n MessageAttributeNames: [\"All\"],\n }),\n );\n\n return (resp.Messages ?? [])\n .map((msg) => mapQueueEntry(msg))\n .toSorted((left, right) => right.queuedAt.localeCompare(left.queuedAt));\n },\n };\n}"],"mappings":";;;;;AAsCA,SAAS,UAAU,KAAyB;CAC1C,OAAO,KAAK,MAAM,GAAG;AACvB;AAEA,SAAS,yBAAyB,MAA2B;CAC3D,MAAM,SAAS,KAAK,UAAU;CAC9B,OAAO,CAAC,UAAU,SAAS,CAAC,CAAC,SAAS,MAAM;AAC9C;AAEA,SAAS,cAAc,KAAoC;CACzD,MAAM,OAAO,UAAU,IAAI,QAAQ,IAAI;CACvC,OAAO;EACL,SAAS,KAAK,WAAW;EACzB,QAAQ,KAAK,UAAU;EACvB,UAAU,KAAK,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;CACpD;AACF;;;;;;;;;;;;AAcA,SAAgB,sBACd,SACc;CACd,MAAM,SAAS,QAAQ,UAAU,IAAI,UAAU,CAAC,CAAC;CAEjD,OAAO;EACL,UAAU;GACR,MAAM;GACN,SAAA;GACA,aAAa;GACb,MAAM;EACR;;;;;;;EAOA,MAAM,QAAQ,KAAgC;GAC5C,MAAM,OAAO,KACX,IAAI,mBAAmB;IACrB,UAAU,QAAQ;IAClB,aAAa,KAAK,UAAU;KAC1B,SAAS,IAAI;KACb,OAAO,IAAI;IACb,CAAC;IACD,mBAAmB;KACjB,SAAS;MACP,UAAU;MACV,aAAa,IAAI;KACnB;KACA,QAAQ;MACN,UAAU;MACV,aAAa;KACf;IACF;GACF,CAAC,CACH;EACF;;;;;;;EAQA,MAAM,OAAO,SAA6C;GASxD,MAAM,YAAW,MARE,OAAO,KACxB,IAAI,sBAAsB;IACxB,UAAU,QAAQ;IAClB,qBAAqB;IACrB,uBAAuB,CAAC,KAAK;GAC/B,CAAC,CACH,EAAA,CAEsB,YAAY,CAAC;GACnC,IAAI,SAAS,WAAW,GACtB,OAAO;GAGT,MAAM,CAAC,OAAO;GACd,IAAI,CAAC,KAAK,MACR,OAAO;GAGT,MAAM,OAAO,UAAU,IAAI,IAAI;GAE/B,MAAM,OAAO,KACX,IAAI,qBAAqB;IACvB,UAAU,QAAQ;IAClB,eAAe,IAAI;GACrB,CAAC,CACH;GAEA,OAAO;IACL,SAAS,KAAK,WAAW;IACzB,QAAQ,KAAK,UAAU;IACvB,UAAU,KAAK,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;IAClD,WAAW,KAAK;IAChB,YAAY,KAAK;IACjB,OAAO,KAAK;GACd;EACF;;;;;;EAOA,MAAM,SAAgC;GASpC,SAAQ,MARW,OAAO,KACxB,IAAI,sBAAsB;IACxB,UAAU,QAAQ;IAClB,qBAAqB;IACrB,uBAAuB,CAAC,KAAK;GAC/B,CAAC,CACH,EAAA,CAEa,YAAY,CAAC,EAAA,CACvB,QAAQ,YAAY,QAAQ,MAAM,UAAU,yBAAyB,UAAU,QAAQ,IAAI,CAAC,CAAC,CAAC,CAC9F,KAAK,QAAQ,cAAc,GAAG,CAAC,CAAC,CAChC,UAAU,MAAM,UAAU,MAAM,SAAS,cAAc,KAAK,QAAQ,CAAC;EAC1E;;;;;;EAOA,MAAM,OAAO,OAAsC;GASjD,SAAQ,MARW,OAAO,KACxB,IAAI,sBAAsB;IACxB,UAAU,QAAQ;IAClB,qBAAqB;IACrB,uBAAuB,CAAC,KAAK;GAC/B,CAAC,CACH,EAAA,CAEa,YAAY,CAAC,EAAA,CACvB,KAAK,QAAQ,cAAc,GAAG,CAAC,CAAC,CAChC,UAAU,MAAM,UAAU,MAAM,SAAS,cAAc,KAAK,QAAQ,CAAC;EAC1E;CACF;AACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@storyshelf/queue-sqs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "SQS capture job queue adapter for StoryShelf (AWS cloud deployments).",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Siddhant Gupta",
|
|
8
|
+
"url": "https://guptasiddhant.com"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/GuptaSiddhant/storyshelf.git",
|
|
15
|
+
"directory": "packages/queue-sqs"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/GuptaSiddhant/storyshelf#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/GuptaSiddhant/storyshelf/issues"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": "./dist/index.mjs",
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsdown",
|
|
33
|
+
"dev": "tsdown -w",
|
|
34
|
+
"fmt": "oxfmt -c ../../.oxfmtrc.json ./src",
|
|
35
|
+
"lint": "oxlint --type-aware --type-check ./src",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"prepublishOnly": "nub run build"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@aws-sdk/client-sqs": "^3.700.0",
|
|
41
|
+
"@storyshelf/core": "workspace:*"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "catalog:",
|
|
45
|
+
"@vitest/coverage-v8": "catalog:",
|
|
46
|
+
"oxfmt": "catalog:",
|
|
47
|
+
"oxlint": "catalog:",
|
|
48
|
+
"pino": "catalog:",
|
|
49
|
+
"tsdown": "catalog:",
|
|
50
|
+
"typescript": "catalog:",
|
|
51
|
+
"vitest": "catalog:"
|
|
52
|
+
},
|
|
53
|
+
"types": "./dist/index.d.mts",
|
|
54
|
+
"exports": {
|
|
55
|
+
".": {
|
|
56
|
+
"source": "./src/index.ts",
|
|
57
|
+
"default": "./dist/index.mjs"
|
|
58
|
+
},
|
|
59
|
+
"./package.json": "./package.json"
|
|
60
|
+
}
|
|
61
|
+
}
|