@beesolve/sqs-handler 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 ADDED
@@ -0,0 +1,13 @@
1
+ # SQS handler
2
+
3
+ ## Installation
4
+
5
+ Install the latest version of package and its peer dependencies.
6
+
7
+ ```bash
8
+ npm i @beesolve/sqs-handler
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ todo
package/dist/cdk.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { EmailAlarms } from "@beesolve/cdk-email-alarms";
2
+ import { Function } from "aws-cdk-lib/aws-lambda";
3
+ import { NodejsFunction, NodejsFunctionProps } from "aws-cdk-lib/aws-lambda-nodejs";
4
+ import { Construct } from "constructs";
5
+ interface SqsHandlerProps {
6
+ /**
7
+ * Path to file where SDK handler is exported.
8
+ */
9
+ readonly entry: string;
10
+ /**
11
+ * @default false
12
+ */
13
+ readonly isProd?: boolean;
14
+ readonly alarms: EmailAlarms;
15
+ readonly handlerProps?: Pick<NodejsFunctionProps, "memorySize" | "timeout">;
16
+ }
17
+ declare class SqsHandler extends Construct {
18
+ private readonly queue;
19
+ readonly handler: NodejsFunction;
20
+ constructor(scope: Construct, id: string, props: SqsHandlerProps);
21
+ readonly grantAccess: (grantee: Function) => void;
22
+ }
23
+ export { SqsHandlerProps, SqsHandler };
package/dist/cdk.js ADDED
@@ -0,0 +1,47 @@
1
+ // packages/sqs-handler/cdk.ts
2
+ import { Duration } from "aws-cdk-lib";
3
+ import { Architecture, Runtime } from "aws-cdk-lib/aws-lambda";
4
+ import {
5
+ NodejsFunction
6
+ } from "aws-cdk-lib/aws-lambda-nodejs";
7
+ import { Construct } from "constructs";
8
+ import { resolve } from "node:path";
9
+ var __dirname = "/Users/ivan/data/work/github.com/beesolve/p/packages/packages/sqs-handler";
10
+
11
+ class SqsHandler extends Construct {
12
+ queue;
13
+ handler;
14
+ constructor(scope, id, props) {
15
+ super(scope, id);
16
+ const { isProd = false, handlerProps = {} } = props;
17
+ this.handler = new NodejsFunction(this, "QueueHandler", {
18
+ description: "Tasks queue handler",
19
+ entry: resolve(__dirname, props.entry),
20
+ handler: "handler",
21
+ bundling: {
22
+ minify: isProd,
23
+ sourceMap: isProd,
24
+ sourcesContent: false,
25
+ target: "es2022"
26
+ },
27
+ memorySize: 1024,
28
+ timeout: Duration.seconds(30),
29
+ runtime: Runtime.NODEJS_24_X,
30
+ architecture: Architecture.ARM_64,
31
+ depsLockFilePath: resolve(`${__dirname}/../../bun.lock`),
32
+ ...handlerProps
33
+ });
34
+ this.queue = SqsWithDlq.asLambdaInput({
35
+ lambda: this.handler
36
+ });
37
+ this.handler.addEnvironment("BEESOLVE_TASKS_QUEUE_URL", this.queue.queue.queueUrl);
38
+ props.alarms.reportSqsErrors(this.queue);
39
+ }
40
+ grantAccess = (grantee) => {
41
+ this.queue.queue.grantSendMessages(grantee);
42
+ grantee.addEnvironment("BEESOLVE_TASKS_QUEUE_URL", this.queue.queue.queueUrl);
43
+ };
44
+ }
45
+ export {
46
+ SqsHandler
47
+ };
@@ -0,0 +1,29 @@
1
+ import { SQSClient } from "@aws-sdk/client-sqs";
2
+ import { SQSEvent } from "aws-lambda";
3
+ type Functions = Record<string, (...args: any[]) => Promise<void>>;
4
+ declare function createSqsHandlers<
5
+ TFunctions extends Functions,
6
+ Fifo extends boolean
7
+ >(props: {
8
+ readonly functions: TFunctions;
9
+ readonly queueUrl: string;
10
+ readonly localInvocation?: true;
11
+ readonly sqsClient: Pick<SQSClient, "send">;
12
+ readonly fifo: Fifo;
13
+ }): [(event: SQSEvent) => Promise<{
14
+ batchItemFailures: {
15
+ itemIdentifier: string;
16
+ }[];
17
+ }>, QueuedFunctions<TFunctions, Fifo>];
18
+ type QueuedFunctions<
19
+ T extends Functions,
20
+ Fifo extends boolean
21
+ > = { [key in keyof T] : AddParameters<T[key], [fifoOptions?: Fifo extends true ? {
22
+ readonly deduplicationId?: string;
23
+ readonly groupId?: string;
24
+ } : never]> };
25
+ type AddParameters<
26
+ TFunction extends (...args: any) => any,
27
+ TParameters extends [...args: any]
28
+ > = (...args: [...Parameters<TFunction>, ...TParameters]) => Promise<void>;
29
+ export { createSqsHandlers };
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ // packages/sqs-handler/index.ts
2
+ import { SendMessageCommand } from "@aws-sdk/client-sqs";
3
+ import {
4
+ decodeFromStringifiable,
5
+ encodeToStringifiable
6
+ } from "@beesolve/helpers";
7
+ import * as v from "valibot";
8
+ function createSqsHandlers(props) {
9
+ const handler = async (event) => {
10
+ const batchItemFailures = new Array;
11
+ for (const { body, messageId } of event.Records) {
12
+ try {
13
+ const result = v.safeParse(v.pipe(v.string(), v.parseJson(), v.object({
14
+ fName: v.picklist(Object.keys(props.functions)),
15
+ fArgs: v.array(v.any())
16
+ })), body);
17
+ if (!result.success)
18
+ throw new Error(`Wrong message format: ${JSON.stringify(v.flatten(result.issues), null, 2)}`);
19
+ const { fName, fArgs } = result.output;
20
+ console.info({
21
+ function: fName,
22
+ arguments: JSON.stringify(fArgs, null, 2)
23
+ });
24
+ await props.functions[fName]?.(...fArgs.map((args) => decodeFromStringifiable(args)));
25
+ } catch (error) {
26
+ console.error(error);
27
+ batchItemFailures.push({ itemIdentifier: messageId });
28
+ }
29
+ }
30
+ return { batchItemFailures };
31
+ };
32
+ const functions = Object.entries(props.functions).reduce((result, [functionName]) => ({
33
+ ...result,
34
+ [functionName](...args) {
35
+ const originalFunction = props.functions[functionName];
36
+ if (originalFunction == null)
37
+ throw Error(`Cannot invoke "${functionName}". Make sure the function is defined.`);
38
+ const functionArgs = args.slice(0, originalFunction.length);
39
+ const fifoOptions = args[originalFunction.length];
40
+ if (props.localInvocation) {
41
+ originalFunction(...functionArgs);
42
+ } else {
43
+ props.sqsClient.send(new SendMessageCommand({
44
+ QueueUrl: props.queueUrl,
45
+ MessageBody: JSON.stringify({
46
+ fName: functionName,
47
+ fArgs: functionArgs.map((args2) => encodeToStringifiable(args2))
48
+ }),
49
+ MessageDeduplicationId: fifoOptions?.deduplicationId,
50
+ MessageGroupId: fifoOptions?.groupId
51
+ }));
52
+ }
53
+ }
54
+ }), {});
55
+ return [handler, functions];
56
+ }
57
+ export {
58
+ createSqsHandlers
59
+ };
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@beesolve/sqs-handler",
3
+ "description": "",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "./cdk": {
19
+ "import": {
20
+ "types": "./dist/cdk.d.ts",
21
+ "default": "./dist/cdk.js"
22
+ }
23
+ },
24
+ "./package.json": "./package.json"
25
+ },
26
+ "homepage": "https://github.com/beesolve/packages/tree/main/packages/sqs-handler#readme",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/beesolve/packages.git"
31
+ },
32
+ "scripts": {
33
+ "type-check": "tsc --noEmit"
34
+ },
35
+ "peerDependencies": {
36
+ "typescript": "catalog:"
37
+ },
38
+ "peerDependenciesMeta": {
39
+ "typescript": {
40
+ "optional": true
41
+ }
42
+ },
43
+ "dependencies": {
44
+ "aws-cdk-lib": "catalog:",
45
+ "constructs": "catalog:",
46
+ "@aws-sdk/client-sqs": "catalog:",
47
+ "valibot": "catalog:",
48
+ "@beesolve/helpers": "workspace:*",
49
+ "@beesolve/cdk-email-alarms": "workspace:*",
50
+ "@beesolve/cdk-constructs": "workspace:*"
51
+ },
52
+ "devDependencies": {
53
+ "@types/aws-lambda": "catalog:"
54
+ }
55
+ }