From 129dc1496ec9635fb3286631f95e1bc63163a667 Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 6 Feb 2026 13:29:21 +0545 Subject: [PATCH 01/19] feat: add package for fastify worker --- packages/worker/.gitignore | 2 ++ packages/worker/README.md | 1 + packages/worker/eslint.config.js | 3 ++ packages/worker/package.json | 56 ++++++++++++++++++++++++++++++ packages/worker/src/index.ts | 11 ++++++ packages/worker/src/types/index.ts | 5 +++ packages/worker/tsconfig.json | 11 ++++++ packages/worker/vite.config.ts | 54 ++++++++++++++++++++++++++++ pnpm-lock.yaml | 41 ++++++++++++++++++++++ 9 files changed, 184 insertions(+) create mode 100644 packages/worker/.gitignore create mode 100644 packages/worker/README.md create mode 100644 packages/worker/eslint.config.js create mode 100644 packages/worker/package.json create mode 100644 packages/worker/src/index.ts create mode 100644 packages/worker/src/types/index.ts create mode 100644 packages/worker/tsconfig.json create mode 100644 packages/worker/vite.config.ts diff --git a/packages/worker/.gitignore b/packages/worker/.gitignore new file mode 100644 index 000000000..b94707787 --- /dev/null +++ b/packages/worker/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/packages/worker/README.md b/packages/worker/README.md new file mode 100644 index 000000000..17b34f39f --- /dev/null +++ b/packages/worker/README.md @@ -0,0 +1 @@ +# @prefabs.tech/fastify-worker diff --git a/packages/worker/eslint.config.js b/packages/worker/eslint.config.js new file mode 100644 index 000000000..48a1291a4 --- /dev/null +++ b/packages/worker/eslint.config.js @@ -0,0 +1,3 @@ +import fastifyConfig from "@prefabs.tech/eslint-config/fastify.js"; + +export default fastifyConfig; diff --git a/packages/worker/package.json b/packages/worker/package.json new file mode 100644 index 000000000..ae74b777c --- /dev/null +++ b/packages/worker/package.json @@ -0,0 +1,56 @@ +{ + "name": "@prefabs.tech/fastify-worker", + "version": "0.93.4", + "description": "Fastify worker plugin", + "homepage": "https://github.com/prefabs-tech/fastify/tree/main/packages/worker#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/prefabs-tech/fastify.git", + "directory": "packages/worker" + }, + "license": "MIT", + "exports": { + ".": { + "import": "./dist/prefabs-tech-fastify-worker.js", + "require": "./dist/prefabs-tech-fastify-worker.cjs" + } + }, + "main": "./dist/prefabs-tech-fastify-worker.cjs", + "module": "./dist/prefabs-tech-fastify-worker.js", + "types": "./dist/types/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "vite build && tsc --emitDeclarationOnly && mv dist/src dist/types", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "sort-package": "npx sort-package-json", + "typecheck": "tsc --noEmit -p tsconfig.json --composite false" + }, + "dependencies": { + "zod": "3.25.76" + }, + "devDependencies": { + "@prefabs.tech/eslint-config": "0.4.0", + "@prefabs.tech/tsconfig": "0.2.0", + "@prefabs.tech/fastify-config": "0.93.4", + "eslint": "9.39.2", + "fastify": "5.6.1", + "fastify-plugin": "5.1.0", + "prettier": "3.6.2", + "supertokens-node": "14.1.4", + "typescript": "5.9.3", + "vite": "6.4.1", + "vitest": "3.2.4" + }, + "peerDependencies": { + "@prefabs.tech/fastify-config": "0.93.4", + "fastify": ">=5.2.1", + "fastify-plugin": ">=5.0.1", + "supertokens-node": ">=14.1.3" + }, + "engines": { + "node": ">=20" + } +} diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts new file mode 100644 index 000000000..c4a5476e6 --- /dev/null +++ b/packages/worker/src/index.ts @@ -0,0 +1,11 @@ +import "@prefabs.tech/fastify-config"; + +import { WorkerConfig } from "./types"; + +declare module "@prefabs.tech/fastify-config" { + interface ApiConfig { + worker: WorkerConfig; + } +} + +export type { WorkerConfig } from "./types"; diff --git a/packages/worker/src/types/index.ts b/packages/worker/src/types/index.ts new file mode 100644 index 000000000..40e599874 --- /dev/null +++ b/packages/worker/src/types/index.ts @@ -0,0 +1,5 @@ +export interface WorkerConfig { + cronJobs?: { + expression: string; + }[]; +} diff --git a/packages/worker/tsconfig.json b/packages/worker/tsconfig.json new file mode 100644 index 000000000..380daccb6 --- /dev/null +++ b/packages/worker/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@prefabs.tech/tsconfig/fastify.json", + "exclude": [ + "src/**/__test__/**/*", + ], + "compilerOptions": { + "baseUrl": "./", + "outDir": "dist", + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/worker/vite.config.ts b/packages/worker/vite.config.ts new file mode 100644 index 000000000..cad5f275e --- /dev/null +++ b/packages/worker/vite.config.ts @@ -0,0 +1,54 @@ +import { resolve, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { defineConfig, loadEnv } from "vite"; + +import { dependencies, peerDependencies } from "./package.json"; + +// https://vitejs.dev/config/ +export default defineConfig(({ mode }) => { + process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }; + + return { + build: { + lib: { + entry: resolve(dirname(fileURLToPath(import.meta.url)), "src/index.ts"), + fileName: "prefabs-tech-fastify-worker", + formats: ["cjs", "es"], + name: "PrefabsTechFastifyWorker", + }, + rollupOptions: { + external: [ + ...Object.keys(dependencies), + ...Object.keys(peerDependencies), + ], + output: { + exports: "named", + globals: { + "@prefabs.tech/fastify-error-handler": + "PrefabsTechFastifyErrorHandler", + "@prefabs.tech/fastify-slonik": "PrefabsTechFastifySlonik", + "@prefabs.tech/fastify-graphql": "PrefabsTechFastifyGraphql", + fastify: "Fastify", + "fastify-plugin": "FastifyPlugin", + mercurius: "mercurius", + slonik: "Slonik", + zod: "zod", + }, + }, + }, + target: "es2022", + }, + resolve: { + alias: { + "@/": new URL("src/", import.meta.url).pathname, + }, + }, + test: { + coverage: { + provider: "istanbul", + reporter: ["text", "json", "html"], + }, + }, + }; +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a403f6a62..b0a8201af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -310,6 +310,46 @@ importers: specifier: 3.2.4 version: 3.2.4(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) + packages/processor: + dependencies: + zod: + specifier: 3.25.76 + version: 3.25.76 + devDependencies: + '@prefabs.tech/eslint-config': + specifier: 0.4.0 + version: 0.4.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(prettier@3.6.2)(typescript@5.9.3) + '@prefabs.tech/fastify-config': + specifier: 0.93.4 + version: link:../config + '@prefabs.tech/tsconfig': + specifier: 0.2.0 + version: 0.2.0(@types/node@24.10.0) + eslint: + specifier: 9.39.2 + version: 9.39.2(jiti@2.6.1) + fastify: + specifier: 5.6.1 + version: 5.6.1 + fastify-plugin: + specifier: 5.1.0 + version: 5.1.0 + prettier: + specifier: 3.6.2 + version: 3.6.2 + supertokens-node: + specifier: 14.1.4 + version: 14.1.4 + typescript: + specifier: 5.9.3 + version: 5.9.3 + vite: + specifier: 6.4.1 + version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) + vitest: + specifier: 3.2.4 + version: 3.2.4(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) + packages/s3: dependencies: '@aws-sdk/client-s3': @@ -5169,6 +5209,7 @@ packages: scmp@2.1.0: resolution: {integrity: sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==} + deprecated: Just use Node.js's crypto.timingSafeEqual() secure-json-parse@4.1.0: resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} From cb915fffd99c8dcb97a88cc9a0ba4c4e3cc169fd Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 6 Feb 2026 13:32:33 +0545 Subject: [PATCH 02/19] chore: add package depedencies --- pnpm-lock.yaml | 80 +++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b0a8201af..54db3f40c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -310,46 +310,6 @@ importers: specifier: 3.2.4 version: 3.2.4(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) - packages/processor: - dependencies: - zod: - specifier: 3.25.76 - version: 3.25.76 - devDependencies: - '@prefabs.tech/eslint-config': - specifier: 0.4.0 - version: 0.4.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(prettier@3.6.2)(typescript@5.9.3) - '@prefabs.tech/fastify-config': - specifier: 0.93.4 - version: link:../config - '@prefabs.tech/tsconfig': - specifier: 0.2.0 - version: 0.2.0(@types/node@24.10.0) - eslint: - specifier: 9.39.2 - version: 9.39.2(jiti@2.6.1) - fastify: - specifier: 5.6.1 - version: 5.6.1 - fastify-plugin: - specifier: 5.1.0 - version: 5.1.0 - prettier: - specifier: 3.6.2 - version: 3.6.2 - supertokens-node: - specifier: 14.1.4 - version: 14.1.4 - typescript: - specifier: 5.9.3 - version: 5.9.3 - vite: - specifier: 6.4.1 - version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) - vitest: - specifier: 3.2.4 - version: 3.2.4(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) - packages/s3: dependencies: '@aws-sdk/client-s3': @@ -636,6 +596,46 @@ importers: specifier: 3.25.76 version: 3.25.76 + packages/worker: + dependencies: + zod: + specifier: 3.25.76 + version: 3.25.76 + devDependencies: + '@prefabs.tech/eslint-config': + specifier: 0.4.0 + version: 0.4.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(prettier@3.6.2)(typescript@5.9.3) + '@prefabs.tech/fastify-config': + specifier: 0.93.4 + version: link:../config + '@prefabs.tech/tsconfig': + specifier: 0.2.0 + version: 0.2.0(@types/node@24.10.0) + eslint: + specifier: 9.39.2 + version: 9.39.2(jiti@2.6.1) + fastify: + specifier: 5.6.1 + version: 5.6.1 + fastify-plugin: + specifier: 5.1.0 + version: 5.1.0 + prettier: + specifier: 3.6.2 + version: 3.6.2 + supertokens-node: + specifier: 14.1.4 + version: 14.1.4 + typescript: + specifier: 5.9.3 + version: 5.9.3 + vite: + specifier: 6.4.1 + version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) + vitest: + specifier: 3.2.4 + version: 3.2.4(@types/node@24.10.0)(jiti@2.6.1)(yaml@2.8.1) + packages: '@actions/core@1.11.1': From aafddd9e13fc32ded730757fafb30a811ac9ed1e Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 6 Feb 2026 15:53:28 +0545 Subject: [PATCH 03/19] feat: add cron scheduling support --- packages/worker/package.json | 3 ++- packages/worker/src/cron/index.ts | 1 + packages/worker/src/cron/setup.ts | 17 +++++++++++++++++ packages/worker/src/plugin.ts | 22 ++++++++++++++++++++++ packages/worker/src/types/cron.ts | 7 +++++++ packages/worker/src/types/index.ts | 6 +++--- pnpm-lock.yaml | 14 +++++++++++++- 7 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 packages/worker/src/cron/index.ts create mode 100644 packages/worker/src/cron/setup.ts create mode 100644 packages/worker/src/plugin.ts create mode 100644 packages/worker/src/types/cron.ts diff --git a/packages/worker/package.json b/packages/worker/package.json index ae74b777c..0376c1f2c 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -29,12 +29,13 @@ "typecheck": "tsc --noEmit -p tsconfig.json --composite false" }, "dependencies": { + "node-cron": "^4.2.1", "zod": "3.25.76" }, "devDependencies": { "@prefabs.tech/eslint-config": "0.4.0", - "@prefabs.tech/tsconfig": "0.2.0", "@prefabs.tech/fastify-config": "0.93.4", + "@prefabs.tech/tsconfig": "0.2.0", "eslint": "9.39.2", "fastify": "5.6.1", "fastify-plugin": "5.1.0", diff --git a/packages/worker/src/cron/index.ts b/packages/worker/src/cron/index.ts new file mode 100644 index 000000000..dcdc3e6c7 --- /dev/null +++ b/packages/worker/src/cron/index.ts @@ -0,0 +1 @@ +export * from "./setup"; diff --git a/packages/worker/src/cron/setup.ts b/packages/worker/src/cron/setup.ts new file mode 100644 index 000000000..ff1a67dfe --- /dev/null +++ b/packages/worker/src/cron/setup.ts @@ -0,0 +1,17 @@ +import cron from "node-cron"; + +import { WorkerConfig } from "src/types"; + +const setupCronJobs = (config: WorkerConfig) => { + if (!config.cronJobs || config.cronJobs.length === 0) { + return; + } + + const { cronJobs } = config; + + for (const job of cronJobs) { + cron.schedule(job.expression, job.task, job.options); + } +}; + +export default setupCronJobs; diff --git a/packages/worker/src/plugin.ts b/packages/worker/src/plugin.ts new file mode 100644 index 000000000..71909cf03 --- /dev/null +++ b/packages/worker/src/plugin.ts @@ -0,0 +1,22 @@ +import { FastifyInstance } from "fastify"; +import fastifyPlugin from "fastify-plugin"; + +import setupCronJobs from "./cron/setup"; + +const plugin = async (fastify: FastifyInstance) => { + const { config, log } = fastify; + + if (!config.worker) { + log.warn("Worker configuration is missing. Skipping plugin registration"); + + return; + } + + log.info("Registering worker plugin"); + + if (config.worker.cronJobs) { + setupCronJobs(config.worker); + } +}; + +export default fastifyPlugin(plugin); diff --git a/packages/worker/src/types/cron.ts b/packages/worker/src/types/cron.ts new file mode 100644 index 000000000..c0d477013 --- /dev/null +++ b/packages/worker/src/types/cron.ts @@ -0,0 +1,7 @@ +import { TaskOptions } from "node-cron"; + +export interface CronJob { + expression: string; + task: () => Promise; + options?: TaskOptions; +} diff --git a/packages/worker/src/types/index.ts b/packages/worker/src/types/index.ts index 40e599874..e693618a1 100644 --- a/packages/worker/src/types/index.ts +++ b/packages/worker/src/types/index.ts @@ -1,5 +1,5 @@ +import { CronJob } from "./cron"; + export interface WorkerConfig { - cronJobs?: { - expression: string; - }[]; + cronJobs?: CronJob[]; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54db3f40c..0601e3d36 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -598,6 +598,9 @@ importers: packages/worker: dependencies: + node-cron: + specifier: ^4.2.1 + version: 4.2.1 zod: specifier: 3.25.76 version: 3.25.76 @@ -716,6 +719,7 @@ packages: '@aws-sdk/credential-provider-web-identity@3.917.0': resolution: {integrity: sha512-pZncQhFbwW04pB0jcD5OFv3x2gAddDYCVxyJVixgyhSw7bKCYxqu6ramfq1NxyVpmm+qsw+ijwi/3cCmhUHF/A==} engines: {node: '>=18.0.0'} + deprecated: This version contains a compilation TypeScript error https://github.com/aws/aws-sdk-js-v3/issues/7457 - please use @aws-sdk/credential-providers@3.918.0 or higher '@aws-sdk/lib-storage@3.917.0': resolution: {integrity: sha512-Z8mRzfP6PgUoybJHx/tH40aop42yeh66cW7wLM8R88egB2UYQ0IgxDoRynqlLi5uceI21wss/CIDkhzO9p1cOg==} @@ -3449,16 +3453,18 @@ packages: glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@11.0.3: resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} @@ -4447,6 +4453,10 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-cron@4.2.1: + resolution: {integrity: sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==} + engines: {node: '>=6.0.0'} + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -11116,6 +11126,8 @@ snapshots: lower-case: 2.0.2 tslib: 2.8.1 + node-cron@4.2.1: {} + node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 From 45520ae25b2c909a35a8d9341caaf9251ef7a47c Mon Sep 17 00:00:00 2001 From: sudeep Date: Tue, 17 Feb 2026 13:37:35 +0545 Subject: [PATCH 04/19] feat: define queue config --- packages/worker/package.json | 2 + packages/worker/src/enum/index.ts | 4 + packages/worker/src/types/index.ts | 2 + packages/worker/src/types/queue.ts | 20 + pnpm-lock.yaml | 1046 +++++++++++++++++++++++++++- 5 files changed, 1059 insertions(+), 15 deletions(-) create mode 100644 packages/worker/src/enum/index.ts create mode 100644 packages/worker/src/types/queue.ts diff --git a/packages/worker/package.json b/packages/worker/package.json index 0376c1f2c..9a9a8b496 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -29,6 +29,8 @@ "typecheck": "tsc --noEmit -p tsconfig.json --composite false" }, "dependencies": { + "@aws-sdk/client-sqs": "3.991.0", + "bullmq": "5.69.3", "node-cron": "^4.2.1", "zod": "3.25.76" }, diff --git a/packages/worker/src/enum/index.ts b/packages/worker/src/enum/index.ts new file mode 100644 index 000000000..eeee861ce --- /dev/null +++ b/packages/worker/src/enum/index.ts @@ -0,0 +1,4 @@ +export enum QueueProvider { + SQS = "sqs", + BULLMQ = "bullmq", +} diff --git a/packages/worker/src/types/index.ts b/packages/worker/src/types/index.ts index e693618a1..982a656c5 100644 --- a/packages/worker/src/types/index.ts +++ b/packages/worker/src/types/index.ts @@ -1,5 +1,7 @@ import { CronJob } from "./cron"; +import { QueueConfig } from "./queue"; export interface WorkerConfig { cronJobs?: CronJob[]; + queues?: QueueConfig[]; } diff --git a/packages/worker/src/types/queue.ts b/packages/worker/src/types/queue.ts new file mode 100644 index 000000000..691098678 --- /dev/null +++ b/packages/worker/src/types/queue.ts @@ -0,0 +1,20 @@ +import { RedisOptions } from "bullmq"; + +import { QueueProvider } from "../enum"; + +export interface QueueConfig { + bullmqConfig?: { + connection: RedisOptions; + defaultJobOptions?: { + attempts?: number; + backoff?: { + type: string; + delay: number; + }; + removeOnComplete?: boolean | number; + removeOnFail?: boolean | number; + }; + }; + name: string; + provider: QueueProvider; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0601e3d36..d23376174 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -598,6 +598,12 @@ importers: packages/worker: dependencies: + '@aws-sdk/client-sqs': + specifier: 3.991.0 + version: 3.991.0 + bullmq: + specifier: 5.69.3 + version: 5.69.3 node-cron: specifier: ^4.2.1 version: 4.2.1 @@ -684,43 +690,87 @@ packages: resolution: {integrity: sha512-6koN6wERmY5mTgK/yQ8sPH72jrHBD4BiYKhKHGg+hK5yn700iK5keoWK60CfQM4JJkhx49cHraO4dSW//3WiyA==} engines: {node: '>=18.0.0'} + '@aws-sdk/client-sqs@3.991.0': + resolution: {integrity: sha512-7apQczqvynhNt4BRyMge+CuMLzQxSr8aj1DrKIk+YN0Qd4phiq8XGWDiclVEAyKfg7JUuYK6YIWoUYl3QdIkNg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/client-sso@3.916.0': resolution: {integrity: sha512-Eu4PtEUL1MyRvboQnoq5YKg0Z9vAni3ccebykJy615xokVZUdA3di2YxHM/hykDQX7lcUC62q9fVIvh0+UNk/w==} engines: {node: '>=18.0.0'} + '@aws-sdk/client-sso@3.990.0': + resolution: {integrity: sha512-xTEaPjZwOqVjGbLOP7qzwbdOWJOo1ne2mUhTZwEBBkPvNk4aXB/vcYwWwrjoSWUqtit4+GDbO75ePc/S6TUJYQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/core@3.916.0': resolution: {integrity: sha512-1JHE5s6MD5PKGovmx/F1e01hUbds/1y3X8rD+Gvi/gWVfdg5noO7ZCerpRsWgfzgvCMZC9VicopBqNHCKLykZA==} engines: {node: '>=18.0.0'} + '@aws-sdk/core@3.973.10': + resolution: {integrity: sha512-4u/FbyyT3JqzfsESI70iFg6e2yp87MB5kS2qcxIA66m52VSTN1fvuvbCY1h/LKq1LvuxIrlJ1ItcyjvcKoaPLg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-env@3.916.0': resolution: {integrity: sha512-3gDeqOXcBRXGHScc6xb7358Lyf64NRG2P08g6Bu5mv1Vbg9PKDyCAZvhKLkG7hkdfAM8Yc6UJNhbFxr1ud/tCQ==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-env@3.972.8': + resolution: {integrity: sha512-r91OOPAcHnLCSxaeu/lzZAVRCZ/CtTNuwmJkUwpwSDshUrP7bkX1OmFn2nUMWd9kN53Q4cEo8b7226G4olt2Mg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-http@3.916.0': resolution: {integrity: sha512-NmooA5Z4/kPFJdsyoJgDxuqXC1C6oPMmreJjbOPqcwo6E/h2jxaG8utlQFgXe5F9FeJsMx668dtxVxSYnAAqHQ==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-http@3.972.10': + resolution: {integrity: sha512-DTtuyXSWB+KetzLcWaSahLJCtTUe/3SXtlGp4ik9PCe9xD6swHEkG8n8/BNsQ9dsihb9nhFvuUB4DpdBGDcvVg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-ini@3.917.0': resolution: {integrity: sha512-rvQ0QamLySRq+Okc0ZqFHZ3Fbvj3tYuWNIlzyEKklNmw5X5PM1idYKlOJflY2dvUGkIqY3lUC9SC2WL+1s7KIw==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-ini@3.972.8': + resolution: {integrity: sha512-n2dMn21gvbBIEh00E8Nb+j01U/9rSqFIamWRdGm/mE5e+vHQ9g0cBNdrYFlM6AAiryKVHZmShWT9D1JAWJ3ISw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.8': + resolution: {integrity: sha512-rMFuVids8ICge/X9DF5pRdGMIvkVhDV9IQFQ8aTYk6iF0rl9jOUa1C3kjepxiXUlpgJQT++sLZkT9n0TMLHhQw==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-node@3.917.0': resolution: {integrity: sha512-n7HUJ+TgU9wV/Z46yR1rqD9hUjfG50AKi+b5UXTlaDlVD8bckg40i77ROCllp53h32xQj/7H0yBIYyphwzLtmg==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-node@3.972.9': + resolution: {integrity: sha512-LfJfO0ClRAq2WsSnA9JuUsNyIicD2eyputxSlSL0EiMrtxOxELLRG6ZVYDf/a1HCepaYPXeakH4y8D5OLCauag==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-process@3.916.0': resolution: {integrity: sha512-SXDyDvpJ1+WbotZDLJW1lqP6gYGaXfZJrgFSXIuZjHb75fKeNRgPkQX/wZDdUvCwdrscvxmtyJorp2sVYkMcvA==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-process@3.972.8': + resolution: {integrity: sha512-6cg26ffFltxM51OOS8NH7oE41EccaYiNlbd5VgUYwhiGCySLfHoGuGrLm2rMB4zhy+IO5nWIIG0HiodX8zdvHA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-sso@3.916.0': resolution: {integrity: sha512-gu9D+c+U/Dp1AKBcVxYHNNoZF9uD4wjAKYCjgSN37j4tDsazwMEylbbZLuRNuxfbXtizbo4/TiaxBXDbWM7AkQ==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-sso@3.972.8': + resolution: {integrity: sha512-35kqmFOVU1n26SNv+U37sM8b2TzG8LyqAcd6iM9gprqxyHEh/8IM3gzN4Jzufs3qM6IrH8e43ryZWYdvfVzzKQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-web-identity@3.917.0': resolution: {integrity: sha512-pZncQhFbwW04pB0jcD5OFv3x2gAddDYCVxyJVixgyhSw7bKCYxqu6ramfq1NxyVpmm+qsw+ijwi/3cCmhUHF/A==} engines: {node: '>=18.0.0'} deprecated: This version contains a compilation TypeScript error https://github.com/aws/aws-sdk-js-v3/issues/7457 - please use @aws-sdk/credential-providers@3.918.0 or higher + '@aws-sdk/credential-provider-web-identity@3.972.8': + resolution: {integrity: sha512-CZhN1bOc1J3ubQPqbmr5b4KaMJBgdDvYsmEIZuX++wFlzmZsKj1bwkaiTEb5U2V7kXuzLlpF5HJSOM9eY/6nGA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/lib-storage@3.917.0': resolution: {integrity: sha512-Z8mRzfP6PgUoybJHx/tH40aop42yeh66cW7wLM8R88egB2UYQ0IgxDoRynqlLi5uceI21wss/CIDkhzO9p1cOg==} engines: {node: '>=18.0.0'} @@ -743,6 +793,10 @@ packages: resolution: {integrity: sha512-7r9ToySQ15+iIgXMF/h616PcQStByylVkCshmQqcdeynD/lCn2l667ynckxW4+ql0Q+Bo/URljuhJRxVJzydNA==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-host-header@3.972.3': + resolution: {integrity: sha512-aknPTb2M+G3s+0qLCx4Li/qGZH8IIYjugHMv15JTYMe6mgZO8VBpYgeGYsNMGCqCZOcWzuf900jFBG5bopfzmA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-location-constraint@3.914.0': resolution: {integrity: sha512-Mpd0Sm9+GN7TBqGnZg1+dO5QZ/EOYEcDTo7KfvoyrXScMlxvYm9fdrUVMmLdPn/lntweZGV3uNrs+huasGOOTA==} engines: {node: '>=18.0.0'} @@ -751,14 +805,26 @@ packages: resolution: {integrity: sha512-/gaW2VENS5vKvJbcE1umV4Ag3NuiVzpsANxtrqISxT3ovyro29o1RezW/Avz/6oJqjnmgz8soe9J1t65jJdiNg==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-logger@3.972.3': + resolution: {integrity: sha512-Ftg09xNNRqaz9QNzlfdQWfpqMCJbsQdnZVJP55jfhbKi1+FTWxGuvfPoBhDHIovqWKjqbuiew3HuhxbJ0+OjgA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-recursion-detection@3.914.0': resolution: {integrity: sha512-yiAjQKs5S2JKYc+GrkvGMwkUvhepXDigEXpSJqUseR/IrqHhvGNuOxDxq+8LbDhM4ajEW81wkiBbU+Jl9G82yQ==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-recursion-detection@3.972.3': + resolution: {integrity: sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-sdk-s3@3.916.0': resolution: {integrity: sha512-pjmzzjkEkpJObzmTthqJPq/P13KoNFuEi/x5PISlzJtHofCNcyXeVAQ90yvY2dQ6UXHf511Rh1/ytiKy2A8M0g==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-sdk-sqs@3.972.7': + resolution: {integrity: sha512-DcJLYE4sRjgUyb2SupQGaRgBYc+j89N9nXeMT0PwwVvaBGmKqcxa7PFvz0kBnQrBckPWlfrPyyyMwOeT5BEp6Q==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-ssec@3.914.0': resolution: {integrity: sha512-V1Oae/oLVbpNb9uWs+v80GKylZCdsbqs2c2Xb1FsAUPtYeSnxFuAWsF3/2AEMSSpFe0dTC5KyWr/eKl2aim9VQ==} engines: {node: '>=18.0.0'} @@ -767,14 +833,26 @@ packages: resolution: {integrity: sha512-mzF5AdrpQXc2SOmAoaQeHpDFsK2GE6EGcEACeNuoESluPI2uYMpuuNMYrUufdnIAIyqgKlis0NVxiahA5jG42w==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-user-agent@3.972.10': + resolution: {integrity: sha512-bBEL8CAqPQkI91ZM5a9xnFAzedpzH6NYCOtNyLarRAzTUTFN2DKqaC60ugBa7pnU1jSi4mA7WAXBsrod7nJltg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/nested-clients@3.916.0': resolution: {integrity: sha512-tgg8e8AnVAer0rcgeWucFJ/uNN67TbTiDHfD+zIOPKep0Z61mrHEoeT/X8WxGIOkEn4W6nMpmS4ii8P42rNtnA==} engines: {node: '>=18.0.0'} + '@aws-sdk/nested-clients@3.990.0': + resolution: {integrity: sha512-3NA0s66vsy8g7hPh36ZsUgO4SiMyrhwcYvuuNK1PezO52vX3hXDW4pQrC6OQLGKGJV0o6tbEyQtXb/mPs8zg8w==} + engines: {node: '>=20.0.0'} + '@aws-sdk/region-config-resolver@3.914.0': resolution: {integrity: sha512-KlmHhRbn1qdwXUdsdrJ7S/MAkkC1jLpQ11n+XvxUUUCGAJd1gjC7AjxPZUM7ieQ2zcb8bfEzIU7al+Q3ZT0u7Q==} engines: {node: '>=18.0.0'} + '@aws-sdk/region-config-resolver@3.972.3': + resolution: {integrity: sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow==} + engines: {node: '>=20.0.0'} + '@aws-sdk/s3-request-presigner@3.917.0': resolution: {integrity: sha512-V1cSM6yQv8lV1Obrp5ti8iXLCRKq45OQETANkiMWRbAwTbzKQml0EfP08BFS+LKtSl2gJfO9tH7O2RgRuqhUuQ==} engines: {node: '>=18.0.0'} @@ -787,10 +865,18 @@ packages: resolution: {integrity: sha512-13GGOEgq5etbXulFCmYqhWtpcEQ6WI6U53dvXbheW0guut8fDFJZmEv7tKMTJgiybxh7JHd0rWcL9JQND8DwoQ==} engines: {node: '>=18.0.0'} + '@aws-sdk/token-providers@3.990.0': + resolution: {integrity: sha512-L3BtUb2v9XmYgQdfGBzbBtKMXaP5fV973y3Qdxeevs6oUTVXFmi/mV1+LnScA/1wVPJC9/hlK+1o5vbt7cG7EQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/types@3.914.0': resolution: {integrity: sha512-kQWPsRDmom4yvAfyG6L1lMmlwnTzm1XwMHOU+G5IFlsP4YEaMtXidDzW/wiivY0QFrhfCz/4TVmu0a2aPU57ug==} engines: {node: '>=18.0.0'} + '@aws-sdk/types@3.973.1': + resolution: {integrity: sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/util-arn-parser@3.893.0': resolution: {integrity: sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==} engines: {node: '>=18.0.0'} @@ -799,6 +885,14 @@ packages: resolution: {integrity: sha512-bAgUQwvixdsiGNcuZSDAOWbyHlnPtg8G8TyHD6DTfTmKTHUW6tAn+af/ZYJPXEzXhhpwgJqi58vWnsiDhmr7NQ==} engines: {node: '>=18.0.0'} + '@aws-sdk/util-endpoints@3.990.0': + resolution: {integrity: sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.991.0': + resolution: {integrity: sha512-m8tcZ3SbqG3NRDv0Py3iBKdb4/FlpOCP4CQ6wRtsk4vs3UypZ0nFdZwCRVnTN7j+ldj+V72xVi/JBlxFBDE7Sg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/util-format-url@3.914.0': resolution: {integrity: sha512-QpdkoQjvPaYyzZwgk41vFyHQM5s0DsrsbQ8IoPUggQt4HaJUvmL1ShwMcSldbgdzwiRMqXUK8q7jrqUvkYkY6w==} engines: {node: '>=18.0.0'} @@ -810,6 +904,9 @@ packages: '@aws-sdk/util-user-agent-browser@3.914.0': resolution: {integrity: sha512-rMQUrM1ECH4kmIwlGl9UB0BtbHy6ZuKdWFrIknu8yGTRI/saAucqNTh5EI1vWBxZ0ElhK5+g7zOnUuhSmVQYUA==} + '@aws-sdk/util-user-agent-browser@3.972.3': + resolution: {integrity: sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw==} + '@aws-sdk/util-user-agent-node@3.916.0': resolution: {integrity: sha512-CwfWV2ch6UdjuSV75ZU99N03seEUb31FIUrXBnwa6oONqj/xqXwrxtlUMLx6WH3OJEE4zI3zt5PjlTdGcVwf4g==} engines: {node: '>=18.0.0'} @@ -819,14 +916,31 @@ packages: aws-crt: optional: true + '@aws-sdk/util-user-agent-node@3.972.8': + resolution: {integrity: sha512-XJZuT0LWsFCW1C8dEpPAXSa7h6Pb3krr2y//1X0Zidpcl0vmgY5nL/X0JuBZlntpBzaN3+U4hvKjuijyiiR8zw==} + engines: {node: '>=20.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + '@aws-sdk/xml-builder@3.914.0': resolution: {integrity: sha512-k75evsBD5TcIjedycYS7QXQ98AmOtbnxRJOPtCo0IwYRmy7UvqgS/gBL5SmrIqeV6FDSYRQMgdBxSMp6MLmdew==} engines: {node: '>=18.0.0'} + '@aws-sdk/xml-builder@3.972.4': + resolution: {integrity: sha512-0zJ05ANfYqI6+rGqj8samZBFod0dPPousBjLEqg8WdxSgbMAkRgLyn81lP215Do0rFJ/17LIXwr7q0yK24mP6Q==} + engines: {node: '>=20.0.0'} + '@aws/lambda-invoke-store@0.0.1': resolution: {integrity: sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw==} engines: {node: '>=18.0.0'} + '@aws/lambda-invoke-store@0.2.3': + resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -1332,6 +1446,9 @@ packages: resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==} engines: {node: '>=6.9.0'} + '@ioredis/commands@1.5.0': + resolution: {integrity: sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==} + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -1371,6 +1488,36 @@ packages: resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} engines: {node: '>=8'} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + cpu: [arm64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + cpu: [x64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + cpu: [arm64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + cpu: [arm] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + cpu: [x64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + cpu: [x64] + os: [win32] + '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} @@ -1669,6 +1816,10 @@ packages: resolution: {integrity: sha512-xWL9Mf8b7tIFuAlpjKtRPnHrR8XVrwTj5NPYO/QwZPtc0SDLsPxb56V5tzi5yspSMytISHybifez+4jlrx0vkQ==} engines: {node: '>=18.0.0'} + '@smithy/abort-controller@4.2.8': + resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} + engines: {node: '>=18.0.0'} + '@smithy/chunked-blob-reader-native@4.2.1': resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} engines: {node: '>=18.0.0'} @@ -1681,14 +1832,26 @@ packages: resolution: {integrity: sha512-Kkmz3Mup2PGp/HNJxhCWkLNdlajJORLSjwkcfrj0E7nu6STAEdcMR1ir5P9/xOmncx8xXfru0fbUYLlZog/cFg==} engines: {node: '>=18.0.0'} + '@smithy/config-resolver@4.4.6': + resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} + engines: {node: '>=18.0.0'} + '@smithy/core@3.17.1': resolution: {integrity: sha512-V4Qc2CIb5McABYfaGiIYLTmo/vwNIK7WXI5aGveBd9UcdhbOMwcvIMxIw/DJj1S9QgOMa/7FBkarMdIC0EOTEQ==} engines: {node: '>=18.0.0'} + '@smithy/core@3.23.0': + resolution: {integrity: sha512-Yq4UPVoQICM9zHnByLmG8632t2M0+yap4T7ANVw482J0W7HW0pOuxwVmeOwzJqX2Q89fkXz0Vybz55Wj2Xzrsg==} + engines: {node: '>=18.0.0'} + '@smithy/credential-provider-imds@4.2.3': resolution: {integrity: sha512-hA1MQ/WAHly4SYltJKitEsIDVsNmXcQfYBRv2e+q04fnqtAX5qXaybxy/fhUeAMCnQIdAjaGDb04fMHQefWRhw==} engines: {node: '>=18.0.0'} + '@smithy/credential-provider-imds@4.2.8': + resolution: {integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==} + engines: {node: '>=18.0.0'} + '@smithy/eventstream-codec@4.2.3': resolution: {integrity: sha512-rcr0VH0uNoMrtgKuY7sMfyKqbHc4GQaQ6Yp4vwgm+Z6psPuOgL+i/Eo/QWdXRmMinL3EgFM0Z1vkfyPyfzLmjw==} engines: {node: '>=18.0.0'} @@ -1713,6 +1876,10 @@ packages: resolution: {integrity: sha512-bwigPylvivpRLCm+YK9I5wRIYjFESSVwl8JQ1vVx/XhCw0PtCi558NwTnT2DaVCl5pYlImGuQTSwMsZ+pIavRw==} engines: {node: '>=18.0.0'} + '@smithy/fetch-http-handler@5.3.9': + resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==} + engines: {node: '>=18.0.0'} + '@smithy/hash-blob-browser@4.2.4': resolution: {integrity: sha512-W7eIxD+rTNsLB/2ynjmbdeP7TgxRXprfvqQxKFEfy9HW2HeD7t+g+KCIrY0pIn/GFjA6/fIpH+JQnfg5TTk76Q==} engines: {node: '>=18.0.0'} @@ -1721,6 +1888,10 @@ packages: resolution: {integrity: sha512-6+NOdZDbfuU6s1ISp3UOk5Rg953RJ2aBLNLLBEcamLjHAg1Po9Ha7QIB5ZWhdRUVuOUrT8BVFR+O2KIPmw027g==} engines: {node: '>=18.0.0'} + '@smithy/hash-node@4.2.8': + resolution: {integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==} + engines: {node: '>=18.0.0'} + '@smithy/hash-stream-node@4.2.3': resolution: {integrity: sha512-EXMSa2yiStVII3x/+BIynyOAZlS7dGvI7RFrzXa/XssBgck/7TXJIvnjnCu328GY/VwHDC4VeDyP1S4rqwpYag==} engines: {node: '>=18.0.0'} @@ -1729,6 +1900,10 @@ packages: resolution: {integrity: sha512-Cc9W5DwDuebXEDMpOpl4iERo8I0KFjTnomK2RMdhhR87GwrSmUmwMxS4P5JdRf+LsjOdIqumcerwRgYMr/tZ9Q==} engines: {node: '>=18.0.0'} + '@smithy/invalid-dependency@4.2.8': + resolution: {integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==} + engines: {node: '>=18.0.0'} + '@smithy/is-array-buffer@2.2.0': resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} engines: {node: '>=14.0.0'} @@ -1741,14 +1916,30 @@ packages: resolution: {integrity: sha512-5+4bUEJQi/NRgzdA5SVXvAwyvEnD0ZAiKzV3yLO6dN5BG8ScKBweZ8mxXXUtdxq+Dx5k6EshKk0XJ7vgvIPSnA==} engines: {node: '>=18.0.0'} + '@smithy/md5-js@4.2.8': + resolution: {integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==} + engines: {node: '>=18.0.0'} + '@smithy/middleware-content-length@4.2.3': resolution: {integrity: sha512-/atXLsT88GwKtfp5Jr0Ks1CSa4+lB+IgRnkNrrYP0h1wL4swHNb0YONEvTceNKNdZGJsye+W2HH8W7olbcPUeA==} engines: {node: '>=18.0.0'} + '@smithy/middleware-content-length@4.2.8': + resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} + engines: {node: '>=18.0.0'} + '@smithy/middleware-endpoint@4.3.5': resolution: {integrity: sha512-SIzKVTvEudFWJbxAaq7f2GvP3jh2FHDpIFI6/VAf4FOWGFZy0vnYMPSRj8PGYI8Hjt29mvmwSRgKuO3bK4ixDw==} engines: {node: '>=18.0.0'} + '@smithy/middleware-endpoint@4.4.14': + resolution: {integrity: sha512-FUFNE5KVeaY6U/GL0nzAAHkaCHzXLZcY1EhtQnsAqhD8Du13oPKtMB9/0WK4/LK6a/T5OZ24wPoSShff5iI6Ag==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.31': + resolution: {integrity: sha512-RXBzLpMkIrxBPe4C8OmEOHvS8aH9RUuCOH++Acb5jZDEblxDjyg6un72X9IcbrGTJoiUwmI7hLypNfuDACypbg==} + engines: {node: '>=18.0.0'} + '@smithy/middleware-retry@4.4.5': resolution: {integrity: sha512-DCaXbQqcZ4tONMvvdz+zccDE21sLcbwWoNqzPLFlZaxt1lDtOE2tlVpRSwcTOJrjJSUThdgEYn7HrX5oLGlK9A==} engines: {node: '>=18.0.0'} @@ -1757,14 +1948,30 @@ packages: resolution: {integrity: sha512-8g4NuUINpYccxiCXM5s1/V+uLtts8NcX4+sPEbvYQDZk4XoJfDpq5y2FQxfmUL89syoldpzNzA0R9nhzdtdKnQ==} engines: {node: '>=18.0.0'} + '@smithy/middleware-serde@4.2.9': + resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==} + engines: {node: '>=18.0.0'} + '@smithy/middleware-stack@4.2.3': resolution: {integrity: sha512-iGuOJkH71faPNgOj/gWuEGS6xvQashpLwWB1HjHq1lNNiVfbiJLpZVbhddPuDbx9l4Cgl0vPLq5ltRfSaHfspA==} engines: {node: '>=18.0.0'} + '@smithy/middleware-stack@4.2.8': + resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==} + engines: {node: '>=18.0.0'} + '@smithy/node-config-provider@4.3.3': resolution: {integrity: sha512-NzI1eBpBSViOav8NVy1fqOlSfkLgkUjUTlohUSgAEhHaFWA3XJiLditvavIP7OpvTjDp5u2LhtlBhkBlEisMwA==} engines: {node: '>=18.0.0'} + '@smithy/node-config-provider@4.3.8': + resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.4.10': + resolution: {integrity: sha512-u4YeUwOWRZaHbWaebvrs3UhwQwj+2VNmcVCwXcYTvPIuVyM7Ex1ftAj+fdbG/P4AkBwLq/+SKn+ydOI4ZJE9PA==} + engines: {node: '>=18.0.0'} + '@smithy/node-http-handler@4.4.3': resolution: {integrity: sha512-MAwltrDB0lZB/H6/2M5PIsISSwdI5yIh6DaBB9r0Flo9nx3y0dzl/qTMJPd7tJvPdsx6Ks/cwVzheGNYzXyNbQ==} engines: {node: '>=18.0.0'} @@ -1773,34 +1980,70 @@ packages: resolution: {integrity: sha512-+1EZ+Y+njiefCohjlhyOcy1UNYjT+1PwGFHCxA/gYctjg3DQWAU19WigOXAco/Ql8hZokNehpzLd0/+3uCreqQ==} engines: {node: '>=18.0.0'} + '@smithy/property-provider@4.2.8': + resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==} + engines: {node: '>=18.0.0'} + '@smithy/protocol-http@5.3.3': resolution: {integrity: sha512-Mn7f/1aN2/jecywDcRDvWWWJF4uwg/A0XjFMJtj72DsgHTByfjRltSqcT9NyE9RTdBSN6X1RSXrhn/YWQl8xlw==} engines: {node: '>=18.0.0'} + '@smithy/protocol-http@5.3.8': + resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==} + engines: {node: '>=18.0.0'} + '@smithy/querystring-builder@4.2.3': resolution: {integrity: sha512-LOVCGCmwMahYUM/P0YnU/AlDQFjcu+gWbFJooC417QRB/lDJlWSn8qmPSDp+s4YVAHOgtgbNG4sR+SxF/VOcJQ==} engines: {node: '>=18.0.0'} + '@smithy/querystring-builder@4.2.8': + resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==} + engines: {node: '>=18.0.0'} + '@smithy/querystring-parser@4.2.3': resolution: {integrity: sha512-cYlSNHcTAX/wc1rpblli3aUlLMGgKZ/Oqn8hhjFASXMCXjIqeuQBei0cnq2JR8t4RtU9FpG6uyl6PxyArTiwKA==} engines: {node: '>=18.0.0'} + '@smithy/querystring-parser@4.2.8': + resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==} + engines: {node: '>=18.0.0'} + '@smithy/service-error-classification@4.2.3': resolution: {integrity: sha512-NkxsAxFWwsPsQiwFG2MzJ/T7uIR6AQNh1SzcxSUnmmIqIQMlLRQDKhc17M7IYjiuBXhrQRjQTo3CxX+DobS93g==} engines: {node: '>=18.0.0'} + '@smithy/service-error-classification@4.2.8': + resolution: {integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==} + engines: {node: '>=18.0.0'} + '@smithy/shared-ini-file-loader@4.3.3': resolution: {integrity: sha512-9f9Ixej0hFhroOK2TxZfUUDR13WVa8tQzhSzPDgXe5jGL3KmaM9s8XN7RQwqtEypI82q9KHnKS71CJ+q/1xLtQ==} engines: {node: '>=18.0.0'} + '@smithy/shared-ini-file-loader@4.4.3': + resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==} + engines: {node: '>=18.0.0'} + '@smithy/signature-v4@5.3.3': resolution: {integrity: sha512-CmSlUy+eEYbIEYN5N3vvQTRfqt0lJlQkaQUIf+oizu7BbDut0pozfDjBGecfcfWf7c62Yis4JIEgqQ/TCfodaA==} engines: {node: '>=18.0.0'} + '@smithy/signature-v4@5.3.8': + resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.11.3': + resolution: {integrity: sha512-Q7kY5sDau8OoE6Y9zJoRGgje8P4/UY0WzH8R2ok0PDh+iJ+ZnEKowhjEqYafVcubkbYxQVaqwm3iufktzhprGg==} + engines: {node: '>=18.0.0'} + '@smithy/smithy-client@4.9.1': resolution: {integrity: sha512-Ngb95ryR5A9xqvQFT5mAmYkCwbXvoLavLFwmi7zVg/IowFPCfiqRfkOKnbc/ZRL8ZKJ4f+Tp6kSu6wjDQb8L/g==} engines: {node: '>=18.0.0'} + '@smithy/types@4.12.0': + resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==} + engines: {node: '>=18.0.0'} + '@smithy/types@4.8.0': resolution: {integrity: sha512-QpELEHLO8SsQVtqP+MkEgCYTFW0pleGozfs3cZ183ZBj9z3VC1CX1/wtFMK64p+5bhtZo41SeLK1rBRtd25nHQ==} engines: {node: '>=18.0.0'} @@ -1809,6 +2052,10 @@ packages: resolution: {integrity: sha512-I066AigYvY3d9VlU3zG9XzZg1yT10aNqvCaBTw9EPgu5GrsEl1aUkcMvhkIXascYH1A8W0LQo3B1Kr1cJNcQEw==} engines: {node: '>=18.0.0'} + '@smithy/url-parser@4.2.8': + resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==} + engines: {node: '>=18.0.0'} + '@smithy/util-base64@4.3.0': resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} engines: {node: '>=18.0.0'} @@ -1833,10 +2080,18 @@ packages: resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} engines: {node: '>=18.0.0'} + '@smithy/util-defaults-mode-browser@4.3.30': + resolution: {integrity: sha512-cMni0uVU27zxOiU8TuC8pQLC1pYeZ/xEMxvchSK/ILwleRd1ugobOcIRr5vXtcRqKd4aBLWlpeBoDPJJ91LQng==} + engines: {node: '>=18.0.0'} + '@smithy/util-defaults-mode-browser@4.3.4': resolution: {integrity: sha512-qI5PJSW52rnutos8Bln8nwQZRpyoSRN6k2ajyoUHNMUzmWqHnOJCnDELJuV6m5PML0VkHI+XcXzdB+6awiqYUw==} engines: {node: '>=18.0.0'} + '@smithy/util-defaults-mode-node@4.2.33': + resolution: {integrity: sha512-LEb2aq5F4oZUSzWBG7S53d4UytZSkOEJPXcBq/xbG2/TmK9EW5naUZ8lKu1BEyWMzdHIzEVN16M3k8oxDq+DJA==} + engines: {node: '>=18.0.0'} + '@smithy/util-defaults-mode-node@4.2.6': resolution: {integrity: sha512-c6M/ceBTm31YdcFpgfgQAJaw3KbaLuRKnAz91iMWFLSrgxRpYm03c3bu5cpYojNMfkV9arCUelelKA7XQT36SQ==} engines: {node: '>=18.0.0'} @@ -1845,6 +2100,10 @@ packages: resolution: {integrity: sha512-aCfxUOVv0CzBIkU10TubdgKSx5uRvzH064kaiPEWfNIvKOtNpu642P4FP1hgOFkjQIkDObrfIDnKMKkeyrejvQ==} engines: {node: '>=18.0.0'} + '@smithy/util-endpoints@3.2.8': + resolution: {integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==} + engines: {node: '>=18.0.0'} + '@smithy/util-hex-encoding@4.2.0': resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} engines: {node: '>=18.0.0'} @@ -1853,10 +2112,22 @@ packages: resolution: {integrity: sha512-v5ObKlSe8PWUHCqEiX2fy1gNv6goiw6E5I/PN2aXg3Fb/hse0xeaAnSpXDiWl7x6LamVKq7senB+m5LOYHUAHw==} engines: {node: '>=18.0.0'} + '@smithy/util-middleware@4.2.8': + resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==} + engines: {node: '>=18.0.0'} + '@smithy/util-retry@4.2.3': resolution: {integrity: sha512-lLPWnakjC0q9z+OtiXk+9RPQiYPNAovt2IXD3CP4LkOnd9NpUsxOjMx1SnoUVB7Orb7fZp67cQMtTBKMFDvOGg==} engines: {node: '>=18.0.0'} + '@smithy/util-retry@4.2.8': + resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.12': + resolution: {integrity: sha512-D8tgkrmhAX/UNeCZbqbEO3uqyghUnEmmoO9YEvRuwxjlkKKUE7FOgCJnqpTlQPe9MApdWPky58mNQQHbnCzoNg==} + engines: {node: '>=18.0.0'} + '@smithy/util-stream@4.5.4': resolution: {integrity: sha512-+qDxSkiErejw1BAIXUFBSfM5xh3arbz1MmxlbMCKanDDZtVEQ7PSKW9FQS0Vud1eI/kYn0oCTVKyNzRlq+9MUw==} engines: {node: '>=18.0.0'} @@ -2438,6 +2709,9 @@ packages: resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} engines: {node: '>=18.20'} + bullmq@5.69.3: + resolution: {integrity: sha512-P9uLsR7fDvejH/1m6uur6j7U9mqY6nNt+XvhlhStOUe7jdwbZoP/c2oWNtE+8ljOlubw4pRUKymtRqkyvloc4A==} + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -2573,6 +2847,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -2692,6 +2970,10 @@ packages: resolution: {integrity: sha512-JfZ9NPLsU9ejTYgZ7fM+5TIMfTwROTxpi2Twh597GxmiVDwIGZSjaor+zsQBKZ0mmCKOFb9EZZLVeKNf/5UaGg==} engines: {node: '>=8.0'} + cron-parser@4.9.0: + resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} + engines: {node: '>=12.0.0'} + cross-fetch@3.2.0: resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} @@ -2796,6 +3078,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -2807,6 +3093,10 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} @@ -3234,6 +3524,10 @@ packages: resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} hasBin: true + fast-xml-parser@5.3.4: + resolution: {integrity: sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==} + hasBin: true + fastify-plugin@5.1.0: resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} @@ -3718,6 +4012,10 @@ packages: resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} engines: {node: '>= 0.10'} + ioredis@5.9.2: + resolution: {integrity: sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ==} + engines: {node: '>=12.22.0'} + ipaddr.js@2.2.0: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} @@ -4098,9 +4396,15 @@ packages: lodash.clonedeep@4.5.0: resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + lodash.isboolean@3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} @@ -4178,6 +4482,10 @@ packages: lru-memoizer@2.3.0: resolution: {integrity: sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==} + luxon@3.7.2: + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} + engines: {node: '>=12'} + macos-release@2.5.1: resolution: {integrity: sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==} engines: {node: '>=6'} @@ -4417,6 +4725,13 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + msgpackr-extract@3.0.3: + resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + hasBin: true + + msgpackr@1.11.5: + resolution: {integrity: sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA==} + mustache@4.2.0: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true @@ -4453,6 +4768,9 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + node-cron@4.2.1: resolution: {integrity: sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==} engines: {node: '>=6.0.0'} @@ -4470,6 +4788,10 @@ packages: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} + node-gyp-build-optional-packages@5.2.2: + resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} + hasBin: true + node-releases@2.0.26: resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==} @@ -5095,6 +5417,14 @@ packages: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -5247,6 +5577,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + sentence-case@3.0.4: resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} @@ -5417,6 +5752,9 @@ packages: stacktracey@2.1.8: resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -6126,7 +6464,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.914.0 + '@aws-sdk/types': 3.973.1 '@aws-sdk/util-locate-window': 3.893.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -6134,7 +6472,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.914.0 + '@aws-sdk/types': 3.973.1 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -6254,6 +6592,52 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/client-sqs@3.991.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/credential-provider-node': 3.972.9 + '@aws-sdk/middleware-host-header': 3.972.3 + '@aws-sdk/middleware-logger': 3.972.3 + '@aws-sdk/middleware-recursion-detection': 3.972.3 + '@aws-sdk/middleware-sdk-sqs': 3.972.7 + '@aws-sdk/middleware-user-agent': 3.972.10 + '@aws-sdk/region-config-resolver': 3.972.3 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.991.0 + '@aws-sdk/util-user-agent-browser': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.8 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.23.0 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/md5-js': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.14 + '@smithy/middleware-retry': 4.4.31 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.10 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.30 + '@smithy/util-defaults-mode-node': 4.2.33 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/client-sso@3.916.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 @@ -6297,6 +6681,49 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/client-sso@3.990.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/middleware-host-header': 3.972.3 + '@aws-sdk/middleware-logger': 3.972.3 + '@aws-sdk/middleware-recursion-detection': 3.972.3 + '@aws-sdk/middleware-user-agent': 3.972.10 + '@aws-sdk/region-config-resolver': 3.972.3 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.990.0 + '@aws-sdk/util-user-agent-browser': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.8 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.23.0 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.14 + '@smithy/middleware-retry': 4.4.31 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.10 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.30 + '@smithy/util-defaults-mode-node': 4.2.33 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/core@3.916.0': dependencies: '@aws-sdk/types': 3.914.0 @@ -6313,6 +6740,22 @@ snapshots: '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 + '@aws-sdk/core@3.973.10': + dependencies: + '@aws-sdk/types': 3.973.1 + '@aws-sdk/xml-builder': 3.972.4 + '@smithy/core': 3.23.0 + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/signature-v4': 5.3.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-env@3.916.0': dependencies: '@aws-sdk/core': 3.916.0 @@ -6321,6 +6764,14 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/credential-provider-env@3.972.8': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.916.0': dependencies: '@aws-sdk/core': 3.916.0 @@ -6334,6 +6785,19 @@ snapshots: '@smithy/util-stream': 4.5.4 tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.972.10': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/types': 3.973.1 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/node-http-handler': 4.4.10 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + '@smithy/util-stream': 4.5.12 + tslib: 2.8.1 + '@aws-sdk/credential-provider-ini@3.917.0': dependencies: '@aws-sdk/core': 3.916.0 @@ -6352,6 +6816,38 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-ini@3.972.8': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/credential-provider-env': 3.972.8 + '@aws-sdk/credential-provider-http': 3.972.10 + '@aws-sdk/credential-provider-login': 3.972.8 + '@aws-sdk/credential-provider-process': 3.972.8 + '@aws-sdk/credential-provider-sso': 3.972.8 + '@aws-sdk/credential-provider-web-identity': 3.972.8 + '@aws-sdk/nested-clients': 3.990.0 + '@aws-sdk/types': 3.973.1 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.972.8': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/nested-clients': 3.990.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/credential-provider-node@3.917.0': dependencies: '@aws-sdk/credential-provider-env': 3.916.0 @@ -6369,6 +6865,23 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-node@3.972.9': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.8 + '@aws-sdk/credential-provider-http': 3.972.10 + '@aws-sdk/credential-provider-ini': 3.972.8 + '@aws-sdk/credential-provider-process': 3.972.8 + '@aws-sdk/credential-provider-sso': 3.972.8 + '@aws-sdk/credential-provider-web-identity': 3.972.8 + '@aws-sdk/types': 3.973.1 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/credential-provider-process@3.916.0': dependencies: '@aws-sdk/core': 3.916.0 @@ -6378,6 +6891,15 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/credential-provider-process@3.972.8': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-sso@3.916.0': dependencies: '@aws-sdk/client-sso': 3.916.0 @@ -6391,6 +6913,19 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-sso@3.972.8': + dependencies: + '@aws-sdk/client-sso': 3.990.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/token-providers': 3.990.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/credential-provider-web-identity@3.917.0': dependencies: '@aws-sdk/core': 3.916.0 @@ -6403,6 +6938,18 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-web-identity@3.972.8': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/nested-clients': 3.990.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/lib-storage@3.917.0(@aws-sdk/client-s3@3.917.0)': dependencies: '@aws-sdk/client-s3': 3.917.0 @@ -6454,6 +7001,13 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/middleware-host-header@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/middleware-location-constraint@3.914.0': dependencies: '@aws-sdk/types': 3.914.0 @@ -6466,6 +7020,12 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/middleware-logger@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/middleware-recursion-detection@3.914.0': dependencies: '@aws-sdk/types': 3.914.0 @@ -6474,6 +7034,14 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/middleware-recursion-detection@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@aws/lambda-invoke-store': 0.2.3 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/middleware-sdk-s3@3.916.0': dependencies: '@aws-sdk/core': 3.916.0 @@ -6491,6 +7059,15 @@ snapshots: '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 + '@aws-sdk/middleware-sdk-sqs@3.972.7': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + '@aws-sdk/middleware-ssec@3.914.0': dependencies: '@aws-sdk/types': 3.914.0 @@ -6507,6 +7084,16 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/middleware-user-agent@3.972.10': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.990.0 + '@smithy/core': 3.23.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/nested-clients@3.916.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 @@ -6550,6 +7137,49 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/nested-clients@3.990.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/middleware-host-header': 3.972.3 + '@aws-sdk/middleware-logger': 3.972.3 + '@aws-sdk/middleware-recursion-detection': 3.972.3 + '@aws-sdk/middleware-user-agent': 3.972.10 + '@aws-sdk/region-config-resolver': 3.972.3 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.990.0 + '@aws-sdk/util-user-agent-browser': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.8 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.23.0 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.14 + '@smithy/middleware-retry': 4.4.31 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.10 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.30 + '@smithy/util-defaults-mode-node': 4.2.33 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/region-config-resolver@3.914.0': dependencies: '@aws-sdk/types': 3.914.0 @@ -6557,6 +7187,14 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/region-config-resolver@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/config-resolver': 4.4.6 + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/s3-request-presigner@3.917.0': dependencies: '@aws-sdk/signature-v4-multi-region': 3.916.0 @@ -6589,11 +7227,28 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/token-providers@3.990.0': + dependencies: + '@aws-sdk/core': 3.973.10 + '@aws-sdk/nested-clients': 3.990.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/types@3.914.0': dependencies: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/types@3.973.1': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/util-arn-parser@3.893.0': dependencies: tslib: 2.8.1 @@ -6606,6 +7261,22 @@ snapshots: '@smithy/util-endpoints': 3.2.3 tslib: 2.8.1 + '@aws-sdk/util-endpoints@3.990.0': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-endpoints': 3.2.8 + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.991.0': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-endpoints': 3.2.8 + tslib: 2.8.1 + '@aws-sdk/util-format-url@3.914.0': dependencies: '@aws-sdk/types': 3.914.0 @@ -6624,6 +7295,13 @@ snapshots: bowser: 2.12.1 tslib: 2.8.1 + '@aws-sdk/util-user-agent-browser@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + bowser: 2.12.1 + tslib: 2.8.1 + '@aws-sdk/util-user-agent-node@3.916.0': dependencies: '@aws-sdk/middleware-user-agent': 3.916.0 @@ -6632,14 +7310,30 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@aws-sdk/util-user-agent-node@3.972.8': + dependencies: + '@aws-sdk/middleware-user-agent': 3.972.10 + '@aws-sdk/types': 3.973.1 + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@aws-sdk/xml-builder@3.914.0': dependencies: '@smithy/types': 4.8.0 fast-xml-parser: 5.2.5 tslib: 2.8.1 + '@aws-sdk/xml-builder@3.972.4': + dependencies: + '@smithy/types': 4.12.0 + fast-xml-parser: 5.3.4 + tslib: 2.8.1 + '@aws/lambda-invoke-store@0.0.1': {} + '@aws/lambda-invoke-store@0.2.3': {} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -6786,7 +7480,7 @@ snapshots: '@commitlint/is-ignored@19.8.1': dependencies: '@commitlint/types': 19.8.1 - semver: 7.7.3 + semver: 7.7.4 '@commitlint/lint@19.8.1': dependencies: @@ -7234,6 +7928,8 @@ snapshots: '@hutson/parse-repository-url@3.0.2': {} + '@ioredis/commands@1.5.0': {} + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -7275,6 +7971,24 @@ snapshots: '@lukeed/ms@2.0.2': {} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + optional: true + '@napi-rs/wasm-runtime@0.2.12': dependencies: '@emnapi/core': 1.8.1 @@ -7631,6 +8345,11 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/abort-controller@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/chunked-blob-reader-native@4.2.1': dependencies: '@smithy/util-base64': 4.3.0 @@ -7649,6 +8368,15 @@ snapshots: '@smithy/util-middleware': 4.2.3 tslib: 2.8.1 + '@smithy/config-resolver@4.4.6': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + tslib: 2.8.1 + '@smithy/core@3.17.1': dependencies: '@smithy/middleware-serde': 4.2.3 @@ -7662,6 +8390,19 @@ snapshots: '@smithy/uuid': 1.1.0 tslib: 2.8.1 + '@smithy/core@3.23.0': + dependencies: + '@smithy/middleware-serde': 4.2.9 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-stream': 4.5.12 + '@smithy/util-utf8': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + '@smithy/credential-provider-imds@4.2.3': dependencies: '@smithy/node-config-provider': 4.3.3 @@ -7670,6 +8411,14 @@ snapshots: '@smithy/url-parser': 4.2.3 tslib: 2.8.1 + '@smithy/credential-provider-imds@4.2.8': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + tslib: 2.8.1 + '@smithy/eventstream-codec@4.2.3': dependencies: '@aws-crypto/crc32': 5.2.0 @@ -7708,6 +8457,14 @@ snapshots: '@smithy/util-base64': 4.3.0 tslib: 2.8.1 + '@smithy/fetch-http-handler@5.3.9': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/querystring-builder': 4.2.8 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + '@smithy/hash-blob-browser@4.2.4': dependencies: '@smithy/chunked-blob-reader': 5.2.0 @@ -7722,6 +8479,13 @@ snapshots: '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 + '@smithy/hash-node@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + '@smithy/hash-stream-node@4.2.3': dependencies: '@smithy/types': 4.8.0 @@ -7733,6 +8497,11 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/invalid-dependency@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/is-array-buffer@2.2.0': dependencies: tslib: 2.8.1 @@ -7747,12 +8516,24 @@ snapshots: '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 + '@smithy/md5-js@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + '@smithy/middleware-content-length@4.2.3': dependencies: '@smithy/protocol-http': 5.3.3 '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/middleware-content-length@4.2.8': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/middleware-endpoint@4.3.5': dependencies: '@smithy/core': 3.17.1 @@ -7764,6 +8545,29 @@ snapshots: '@smithy/util-middleware': 4.2.3 tslib: 2.8.1 + '@smithy/middleware-endpoint@4.4.14': + dependencies: + '@smithy/core': 3.23.0 + '@smithy/middleware-serde': 4.2.9 + '@smithy/node-config-provider': 4.3.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-middleware': 4.2.8 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.31': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/service-error-classification': 4.2.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + '@smithy/middleware-retry@4.4.5': dependencies: '@smithy/node-config-provider': 4.3.3 @@ -7782,11 +8586,22 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/middleware-serde@4.2.9': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/middleware-stack@4.2.3': dependencies: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/middleware-stack@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/node-config-provider@4.3.3': dependencies: '@smithy/property-provider': 4.2.3 @@ -7794,6 +8609,21 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/node-config-provider@4.3.8': + dependencies: + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.4.10': + dependencies: + '@smithy/abort-controller': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/querystring-builder': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/node-http-handler@4.4.3': dependencies: '@smithy/abort-controller': 4.2.3 @@ -7807,31 +8637,61 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/property-provider@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/protocol-http@5.3.3': dependencies: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/protocol-http@5.3.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/querystring-builder@4.2.3': dependencies: '@smithy/types': 4.8.0 '@smithy/util-uri-escape': 4.2.0 tslib: 2.8.1 + '@smithy/querystring-builder@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-uri-escape': 4.2.0 + tslib: 2.8.1 + '@smithy/querystring-parser@4.2.3': dependencies: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/querystring-parser@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/service-error-classification@4.2.3': dependencies: '@smithy/types': 4.8.0 + '@smithy/service-error-classification@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/shared-ini-file-loader@4.3.3': dependencies: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/shared-ini-file-loader@4.4.3': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/signature-v4@5.3.3': dependencies: '@smithy/is-array-buffer': 4.2.0 @@ -7843,6 +8703,27 @@ snapshots: '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 + '@smithy/signature-v4@5.3.8': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-uri-escape': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.11.3': + dependencies: + '@smithy/core': 3.23.0 + '@smithy/middleware-endpoint': 4.4.14 + '@smithy/middleware-stack': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-stream': 4.5.12 + tslib: 2.8.1 + '@smithy/smithy-client@4.9.1': dependencies: '@smithy/core': 3.17.1 @@ -7853,6 +8734,10 @@ snapshots: '@smithy/util-stream': 4.5.4 tslib: 2.8.1 + '@smithy/types@4.12.0': + dependencies: + tslib: 2.8.1 + '@smithy/types@4.8.0': dependencies: tslib: 2.8.1 @@ -7863,6 +8748,12 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/url-parser@4.2.8': + dependencies: + '@smithy/querystring-parser': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/util-base64@4.3.0': dependencies: '@smithy/util-buffer-from': 4.2.0 @@ -7891,6 +8782,13 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/util-defaults-mode-browser@4.3.30': + dependencies: + '@smithy/property-provider': 4.2.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/util-defaults-mode-browser@4.3.4': dependencies: '@smithy/property-provider': 4.2.3 @@ -7898,6 +8796,16 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/util-defaults-mode-node@4.2.33': + dependencies: + '@smithy/config-resolver': 4.4.6 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/smithy-client': 4.11.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/util-defaults-mode-node@4.2.6': dependencies: '@smithy/config-resolver': 4.4.0 @@ -7914,6 +8822,12 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/util-endpoints@3.2.8': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/util-hex-encoding@4.2.0': dependencies: tslib: 2.8.1 @@ -7923,12 +8837,34 @@ snapshots: '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/util-middleware@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + '@smithy/util-retry@4.2.3': dependencies: '@smithy/service-error-classification': 4.2.3 '@smithy/types': 4.8.0 tslib: 2.8.1 + '@smithy/util-retry@4.2.8': + dependencies: + '@smithy/service-error-classification': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.12': + dependencies: + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/node-http-handler': 4.4.10 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + '@smithy/util-stream@4.5.4': dependencies: '@smithy/fetch-http-handler': 5.3.4 @@ -8190,7 +9126,7 @@ snapshots: '@typescript-eslint/visitor-keys': 8.54.0 debug: 4.4.3 minimatch: 9.0.5 - semver: 7.7.3 + semver: 7.7.4 tinyglobby: 0.2.15 ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 @@ -8588,6 +9524,18 @@ snapshots: builtin-modules@5.0.0: {} + bullmq@5.69.3: + dependencies: + cron-parser: 4.9.0 + ioredis: 5.9.2 + msgpackr: 1.11.5 + node-abort-controller: 3.1.1 + semver: 7.7.4 + tslib: 2.8.1 + uuid: 11.1.0 + transitivePeerDependencies: + - supports-color + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -8764,6 +9712,8 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cluster-key-slot@1.1.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -8899,6 +9849,10 @@ snapshots: crack-json@1.3.0: {} + cron-parser@4.9.0: + dependencies: + luxon: 3.7.2 + cross-fetch@3.2.0: dependencies: node-fetch: 2.7.0 @@ -8998,12 +9952,17 @@ snapshots: delayed-stream@1.0.0: {} + denque@2.1.0: {} + depd@2.0.0: {} deprecation@2.3.1: {} dequal@2.0.3: {} + detect-libc@2.1.2: + optional: true + detect-node@2.1.0: {} dir-glob@3.0.1: @@ -9091,7 +10050,7 @@ snapshots: '@one-ini/wasm': 0.1.1 commander: 10.0.1 minimatch: 9.0.1 - semver: 7.7.3 + semver: 7.7.4 ejs@3.1.10: dependencies: @@ -9254,7 +10213,7 @@ snapshots: eslint-compat-utils@0.5.1(eslint@9.39.2(jiti@2.6.1)): dependencies: eslint: 9.39.2(jiti@2.6.1) - semver: 7.7.3 + semver: 7.7.4 eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)): dependencies: @@ -9352,7 +10311,7 @@ snapshots: globals: 15.15.0 ignore: 5.3.2 minimatch: 9.0.5 - semver: 7.7.3 + semver: 7.7.4 ts-declaration-location: 1.0.7(typescript@5.9.3) transitivePeerDependencies: - supports-color @@ -9400,7 +10359,7 @@ snapshots: pluralize: 8.0.0 regexp-tree: 0.1.27 regjsparser: 0.13.0 - semver: 7.7.3 + semver: 7.7.4 strip-indent: 4.1.1 eslint-plugin-vue@10.7.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1))): @@ -9410,7 +10369,7 @@ snapshots: natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 7.1.1 - semver: 7.7.3 + semver: 7.7.4 vue-eslint-parser: 10.2.0(eslint@9.39.2(jiti@2.6.1)) xml-name-validator: 4.0.0 optionalDependencies: @@ -9587,6 +10546,10 @@ snapshots: dependencies: strnum: 2.1.1 + fast-xml-parser@5.3.4: + dependencies: + strnum: 2.1.1 + fastify-plugin@5.1.0: {} fastify@5.6.1: @@ -10198,6 +11161,20 @@ snapshots: interpret@1.4.0: {} + ioredis@5.9.2: + dependencies: + '@ioredis/commands': 1.5.0 + cluster-key-slot: 1.1.2 + debug: 4.4.3 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + ipaddr.js@2.2.0: {} is-array-buffer@3.0.5: @@ -10235,7 +11212,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.3 + semver: 7.7.4 is-callable@1.2.7: {} @@ -10372,7 +11349,7 @@ snapshots: '@babel/parser': 7.28.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.7.3 + semver: 7.7.4 transitivePeerDependencies: - supports-color @@ -10498,7 +11475,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.3 + semver: 7.7.4 juice@10.0.1: dependencies: @@ -10596,8 +11573,12 @@ snapshots: lodash.clonedeep@4.5.0: {} + lodash.defaults@4.2.0: {} + lodash.includes@4.3.0: {} + lodash.isarguments@3.1.0: {} + lodash.isboolean@3.0.3: {} lodash.isinteger@4.0.4: {} @@ -10658,6 +11639,8 @@ snapshots: lodash.clonedeep: 4.5.0 lru-cache: 6.0.0 + luxon@3.7.2: {} + macos-release@2.5.1: {} magic-string@0.30.21: @@ -10676,7 +11659,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.3 + semver: 7.7.4 map-obj@1.0.1: {} @@ -11096,6 +12079,22 @@ snapshots: ms@2.1.3: {} + msgpackr-extract@3.0.3: + dependencies: + node-gyp-build-optional-packages: 5.2.2 + optionalDependencies: + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + optional: true + + msgpackr@1.11.5: + optionalDependencies: + msgpackr-extract: 3.0.3 + mustache@4.2.0: {} mute-stream@0.0.8: {} @@ -11126,6 +12125,8 @@ snapshots: lower-case: 2.0.2 tslib: 2.8.1 + node-abort-controller@3.1.1: {} + node-cron@4.2.1: {} node-fetch@2.7.0: @@ -11134,6 +12135,11 @@ snapshots: node-forge@1.3.1: {} + node-gyp-build-optional-packages@5.2.2: + dependencies: + detect-libc: 2.1.2 + optional: true + node-releases@2.0.26: {} node-releases@2.0.27: {} @@ -11169,7 +12175,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.1 - semver: 7.7.3 + semver: 7.7.4 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -11731,6 +12737,12 @@ snapshots: indent-string: 4.0.0 strip-indent: 3.0.0 + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -11896,6 +12908,8 @@ snapshots: semver@7.7.3: {} + semver@7.7.4: {} + sentence-case@3.0.4: dependencies: no-case: 3.0.4 @@ -12119,6 +13133,8 @@ snapshots: as-table: 1.0.55 get-source: 2.0.12 + standard-as-callback@2.1.0: {} + statuses@2.0.1: {} std-env@3.10.0: {} @@ -12672,7 +13688,7 @@ snapshots: eslint-visitor-keys: 4.2.1 espree: 10.4.0 esquery: 1.6.0 - semver: 7.7.3 + semver: 7.7.4 transitivePeerDependencies: - supports-color From 8acc9bcf75d710c32b25cd7394a59c9f682ec6a3 Mon Sep 17 00:00:00 2001 From: sudeep Date: Tue, 17 Feb 2026 14:45:37 +0545 Subject: [PATCH 05/19] feat: add bullmq client --- packages/worker/src/queue/bullmq.ts | 66 +++++++++++++++++++++++++++++ packages/worker/src/queue/index.ts | 16 +++++++ 2 files changed, 82 insertions(+) create mode 100644 packages/worker/src/queue/bullmq.ts create mode 100644 packages/worker/src/queue/index.ts diff --git a/packages/worker/src/queue/bullmq.ts b/packages/worker/src/queue/bullmq.ts new file mode 100644 index 000000000..95dcf88c4 --- /dev/null +++ b/packages/worker/src/queue/bullmq.ts @@ -0,0 +1,66 @@ +import { Queue as BullQueue, Worker, Job, RedisOptions } from "bullmq"; + +import { QueueConfig } from "../types/queue"; + +import { Queue } from "."; + +class BullMQQueue extends Queue { + private queue: BullQueue; + private worker?: Worker; + private connection: RedisOptions; + + constructor(config: Required>) { + super(config.name); + + this.connection = config.bullmqConfig.connection; + this.queue = new BullQueue(this.queueName, { + connection: this.connection, + defaultJobOptions: config.bullmqConfig.defaultJobOptions, + }); + } + + async push(data: T, options?: Record): Promise { + try { + const job = await this.queue.add(this.queueName, data, options); + + return job.id!; + } catch (error) { + throw new Error( + `Failed to push job to BullMQ queue: ${this.queueName}. Error: ${(error as Error).message}`, + ); + } + } + + process(handler: (data: T) => Promise, concurrency = 1): void { + try { + this.worker = new Worker( + this.queueName, + async (job: Job) => { + await handler(job.data as T); + }, + { + connection: this.connection, + concurrency, + }, + ); + + this.worker.on("error", (error) => { + console.error( + `Error in BullMQ worker for queue: ${this.queueName}. Error: ${(error as Error).message}`, + ); + }); + + this.worker.on("failed", (job, error) => { + console.error( + `Job failed in BullMQ queue: ${this.queueName}. Job ID: ${job?.id}. Error: ${(error as Error).message}`, + ); + }); + } catch (error) { + throw new Error( + `Failed to process jobs from BullMQ queue: ${this.queueName}. Error: ${(error as Error).message}`, + ); + } + } +} + +export default BullMQQueue; diff --git a/packages/worker/src/queue/index.ts b/packages/worker/src/queue/index.ts new file mode 100644 index 000000000..8d45b4721 --- /dev/null +++ b/packages/worker/src/queue/index.ts @@ -0,0 +1,16 @@ +abstract class Queue { + protected queueName: string; + + constructor(name: string) { + this.queueName = name; + } + + abstract push(data: T, options?: Record): Promise; + + abstract process( + handler: (data: T) => Promise, + concurrency?: number, + ): void; +} + +export { Queue }; From c32876f84909b39c7fed57a7de09958031ec2b18 Mon Sep 17 00:00:00 2001 From: sudeep Date: Tue, 17 Feb 2026 16:50:27 +0545 Subject: [PATCH 06/19] feat: add support for triggering bullmq queue from app --- packages/worker/package.json | 1 + packages/worker/src/index.ts | 6 +++++ packages/worker/src/plugin.ts | 9 +++++-- packages/worker/src/queue/bullmq.ts | 11 +++++--- packages/worker/src/queue/index.ts | 26 +++++++++++++++++- packages/worker/src/queue/setup.ts | 41 +++++++++++++++++++++++++++++ packages/worker/src/types/queue.ts | 4 ++- 7 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 packages/worker/src/queue/setup.ts diff --git a/packages/worker/package.json b/packages/worker/package.json index 9bd731f7a..287a15487 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -9,6 +9,7 @@ "directory": "packages/worker" }, "license": "MIT", + "type": "module", "exports": { ".": { "import": "./dist/prefabs-tech-fastify-worker.js", diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index c4a5476e6..7cd985e69 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -8,4 +8,10 @@ declare module "@prefabs.tech/fastify-config" { } } +export * from "./enum"; + +export { default } from "./plugin"; + +export { addToQueue } from "./queue"; + export type { WorkerConfig } from "./types"; diff --git a/packages/worker/src/plugin.ts b/packages/worker/src/plugin.ts index 71909cf03..96e82b160 100644 --- a/packages/worker/src/plugin.ts +++ b/packages/worker/src/plugin.ts @@ -1,7 +1,8 @@ import { FastifyInstance } from "fastify"; -import fastifyPlugin from "fastify-plugin"; +import FastifyPlugin from "fastify-plugin"; import setupCronJobs from "./cron/setup"; +import setupQueues from "./queue/setup"; const plugin = async (fastify: FastifyInstance) => { const { config, log } = fastify; @@ -17,6 +18,10 @@ const plugin = async (fastify: FastifyInstance) => { if (config.worker.cronJobs) { setupCronJobs(config.worker); } + + if (config.worker.queues) { + setupQueues(config.worker); + } }; -export default fastifyPlugin(plugin); +export default FastifyPlugin(plugin); diff --git a/packages/worker/src/queue/bullmq.ts b/packages/worker/src/queue/bullmq.ts index 95dcf88c4..e3b9ea6f6 100644 --- a/packages/worker/src/queue/bullmq.ts +++ b/packages/worker/src/queue/bullmq.ts @@ -9,7 +9,10 @@ class BullMQQueue extends Queue { private worker?: Worker; private connection: RedisOptions; - constructor(config: Required>) { + constructor( + config: Required> & + Pick, + ) { super(config.name); this.connection = config.bullmqConfig.connection; @@ -17,6 +20,8 @@ class BullMQQueue extends Queue { connection: this.connection, defaultJobOptions: config.bullmqConfig.defaultJobOptions, }); + + this.process(config.handler, config.concurrency); } async push(data: T, options?: Record): Promise { @@ -31,12 +36,12 @@ class BullMQQueue extends Queue { } } - process(handler: (data: T) => Promise, concurrency = 1): void { + process(handler: (job: Job) => Promise, concurrency = 1): void { try { this.worker = new Worker( this.queueName, async (job: Job) => { - await handler(job.data as T); + await handler(job); }, { connection: this.connection, diff --git a/packages/worker/src/queue/index.ts b/packages/worker/src/queue/index.ts index 8d45b4721..272f993da 100644 --- a/packages/worker/src/queue/index.ts +++ b/packages/worker/src/queue/index.ts @@ -13,4 +13,28 @@ abstract class Queue { ): void; } -export { Queue }; +const queueRegistry = new Map(); + +const registerQueue = (name: string, queue: Queue): void => { + queueRegistry.set(name, queue); +}; + +const getQueue = (name: string): Queue | undefined => { + return queueRegistry.get(name); +}; + +const addToQueue = async ( + queueName: string, + data: T, + options?: Record, +): Promise => { + const queue = getQueue(queueName); + + if (!queue) { + throw new Error(`Queue not found: ${queueName}`); + } + + return queue.push(data, options); +}; + +export { Queue, registerQueue, addToQueue }; diff --git a/packages/worker/src/queue/setup.ts b/packages/worker/src/queue/setup.ts new file mode 100644 index 000000000..50ba263d9 --- /dev/null +++ b/packages/worker/src/queue/setup.ts @@ -0,0 +1,41 @@ +import { QueueProvider } from "../enum"; +import { WorkerConfig } from "../types"; +import BullMQQueue from "./bullmq"; + +import { registerQueue } from "."; + +const setupQueues = (config: WorkerConfig) => { + if (!config.queues || config.queues.length === 0) { + return; + } + + const { queues } = config; + + for (const queueConfig of queues) { + switch (queueConfig.provider) { + case QueueProvider.BULLMQ: { + if (!queueConfig.bullmqConfig) { + throw new Error( + `BullMQ configuration is required for queue: ${queueConfig.name}`, + ); + } + + const queue = new BullMQQueue({ + name: queueConfig.name, + bullmqConfig: queueConfig.bullmqConfig, + handler: queueConfig.handler, + concurrency: queueConfig.concurrency, + }); + + registerQueue(queueConfig.name, queue); + + break; + } + default: { + throw new Error(`Unsupported queue provider: ${queueConfig.provider}`); + } + } + } +}; + +export default setupQueues; diff --git a/packages/worker/src/types/queue.ts b/packages/worker/src/types/queue.ts index 691098678..a554e6c56 100644 --- a/packages/worker/src/types/queue.ts +++ b/packages/worker/src/types/queue.ts @@ -1,4 +1,4 @@ -import { RedisOptions } from "bullmq"; +import { RedisOptions, Job } from "bullmq"; import { QueueProvider } from "../enum"; @@ -15,6 +15,8 @@ export interface QueueConfig { removeOnFail?: boolean | number; }; }; + handler: (job: Job) => Promise; + concurrency?: number; name: string; provider: QueueProvider; } From 89e313daeebb3b24a97d515afea0d8768bdca45a Mon Sep 17 00:00:00 2001 From: Sudeep Bashistha <32100152+BashisthaSudeep@users.noreply.github.com> Date: Thu, 19 Feb 2026 10:14:17 +0545 Subject: [PATCH 07/19] feat: add sqs support for queue processing in worker (#1068) --- packages/worker/src/queue/bullmq.ts | 7 +- packages/worker/src/queue/index.ts | 12 ++-- packages/worker/src/queue/setup.ts | 20 +++++- packages/worker/src/queue/sqs.ts | 99 +++++++++++++++++++++++++++++ packages/worker/src/types/queue.ts | 14 +++- 5 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 packages/worker/src/queue/sqs.ts diff --git a/packages/worker/src/queue/bullmq.ts b/packages/worker/src/queue/bullmq.ts index e3b9ea6f6..c7e986610 100644 --- a/packages/worker/src/queue/bullmq.ts +++ b/packages/worker/src/queue/bullmq.ts @@ -9,10 +9,7 @@ class BullMQQueue extends Queue { private worker?: Worker; private connection: RedisOptions; - constructor( - config: Required> & - Pick, - ) { + constructor(config: Required>) { super(config.name); this.connection = config.bullmqConfig.connection; @@ -21,7 +18,7 @@ class BullMQQueue extends Queue { defaultJobOptions: config.bullmqConfig.defaultJobOptions, }); - this.process(config.handler, config.concurrency); + this.process(config.bullmqConfig.handler, config.bullmqConfig.concurrency); } async push(data: T, options?: Record): Promise { diff --git a/packages/worker/src/queue/index.ts b/packages/worker/src/queue/index.ts index 272f993da..317cb1d76 100644 --- a/packages/worker/src/queue/index.ts +++ b/packages/worker/src/queue/index.ts @@ -5,24 +5,24 @@ abstract class Queue { this.queueName = name; } - abstract push(data: T, options?: Record): Promise; - abstract process( handler: (data: T) => Promise, concurrency?: number, ): void; + + abstract push(data: T, options?: Record): Promise; } const queueRegistry = new Map(); -const registerQueue = (name: string, queue: Queue): void => { - queueRegistry.set(name, queue); -}; - const getQueue = (name: string): Queue | undefined => { return queueRegistry.get(name); }; +const registerQueue = (name: string, queue: Queue): void => { + queueRegistry.set(name, queue); +}; + const addToQueue = async ( queueName: string, data: T, diff --git a/packages/worker/src/queue/setup.ts b/packages/worker/src/queue/setup.ts index 50ba263d9..e102999a3 100644 --- a/packages/worker/src/queue/setup.ts +++ b/packages/worker/src/queue/setup.ts @@ -1,6 +1,7 @@ import { QueueProvider } from "../enum"; import { WorkerConfig } from "../types"; import BullMQQueue from "./bullmq"; +import SQSQueue from "./sqs"; import { registerQueue } from "."; @@ -23,8 +24,23 @@ const setupQueues = (config: WorkerConfig) => { const queue = new BullMQQueue({ name: queueConfig.name, bullmqConfig: queueConfig.bullmqConfig, - handler: queueConfig.handler, - concurrency: queueConfig.concurrency, + }); + + registerQueue(queueConfig.name, queue); + + break; + } + + case QueueProvider.SQS: { + if (!queueConfig.sqsConfig) { + throw new Error( + `SQS configuration is required for queue: ${queueConfig.name}`, + ); + } + + const queue = new SQSQueue({ + name: queueConfig.name, + sqsConfig: queueConfig.sqsConfig, }); registerQueue(queueConfig.name, queue); diff --git a/packages/worker/src/queue/sqs.ts b/packages/worker/src/queue/sqs.ts new file mode 100644 index 000000000..4647afa3d --- /dev/null +++ b/packages/worker/src/queue/sqs.ts @@ -0,0 +1,99 @@ +import { + DeleteMessageCommand, + Message, + ReceiveMessageCommand, + SendMessageCommand, + SQSClient, +} from "@aws-sdk/client-sqs"; + +import { QueueConfig } from "src/types/queue"; + +import { Queue } from "."; + +class SQSQueue extends Queue { + private config: Required>; + private client: SQSClient; + private queueUrl: string; + private isPooling: boolean = false; + + constructor(config: Required>) { + super(config.name); + + this.config = config; + this.client = new SQSClient(config.sqsConfig.clientConfig); + this.queueUrl = config.sqsConfig.queueUrl; + + this.process(config.sqsConfig.handler); + } + + async process(handler: (data: T) => Promise): Promise { + if (this.isPooling) { + return; + } + + this.isPooling = true; + + const pool = async () => { + while (this.isPooling) { + try { + const command = new ReceiveMessageCommand({ + QueueUrl: this.queueUrl, + MaxNumberOfMessages: this.config.sqsConfig.maxNumberOfMessages, + WaitTimeSeconds: this.config.sqsConfig.waitTimeSeconds, + }); + + const response = await this.client.send(command); + + if (response.Messages && response.Messages.length > 0) { + await Promise.all( + response.Messages.map(async (message: Message) => { + try { + const data = JSON.parse(message.Body!) as T; + + await handler(data); + + await this.client.send( + new DeleteMessageCommand({ + QueueUrl: this.queueUrl, + ReceiptHandle: message.ReceiptHandle, + }), + ); + } catch (error) { + console.error( + `Error processing message from SQS queue: ${this.queueName}. Message ID: ${message.MessageId}. Error: ${(error as Error).message}`, + ); + } + }), + ); + } + } catch (error) { + console.error( + `Error processing job from SQS queue: ${this.queueName}. Error: ${(error as Error).message}`, + ); + } + } + }; + + pool(); + } + + async push(data: T, options?: Record): Promise { + try { + const command = new SendMessageCommand({ + QueueUrl: this.queueUrl, + MessageBody: JSON.stringify(data), + ...options, + }); + + const response = await this.client.send(command); + + return response.MessageId!; + } catch (error) { + throw new Error( + `Failed to push job to SQS queue: ${this.queueName}. Error: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } +} + +export default SQSQueue; diff --git a/packages/worker/src/types/queue.ts b/packages/worker/src/types/queue.ts index a554e6c56..c37cde871 100644 --- a/packages/worker/src/types/queue.ts +++ b/packages/worker/src/types/queue.ts @@ -1,10 +1,12 @@ +import { SQSClientConfig } from "@aws-sdk/client-sqs"; import { RedisOptions, Job } from "bullmq"; import { QueueProvider } from "../enum"; -export interface QueueConfig { +export interface QueueConfig { bullmqConfig?: { connection: RedisOptions; + concurrency?: number; defaultJobOptions?: { attempts?: number; backoff?: { @@ -14,9 +16,15 @@ export interface QueueConfig { removeOnComplete?: boolean | number; removeOnFail?: boolean | number; }; + handler: (job: Job) => Promise; }; - handler: (job: Job) => Promise; - concurrency?: number; name: string; provider: QueueProvider; + sqsConfig?: { + clientConfig: SQSClientConfig; + handler: (data: T) => Promise; + maxNumberOfMessages: number; + waitTimeSeconds: number; + queueUrl: string; + }; } From 970a362b0a4c8919079dc073de722be863fc8923 Mon Sep 17 00:00:00 2001 From: sudeep Date: Thu, 19 Feb 2026 11:08:54 +0545 Subject: [PATCH 08/19] refactor: return queue client --- packages/worker/src/index.ts | 8 +++++--- packages/worker/src/queue/bullmq.ts | 10 +++++++--- packages/worker/src/queue/index.ts | 4 +++- packages/worker/src/queue/sqs.ts | 8 ++++++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index 7cd985e69..dcc8edda0 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -8,10 +8,12 @@ declare module "@prefabs.tech/fastify-config" { } } -export * from "./enum"; - export { default } from "./plugin"; -export { addToQueue } from "./queue"; +export * from "./enum"; +export * from "./queue"; + +export { SQSClient } from "@aws-sdk/client-sqs"; +export { Job, Queue } from "bullmq"; export type { WorkerConfig } from "./types"; diff --git a/packages/worker/src/queue/bullmq.ts b/packages/worker/src/queue/bullmq.ts index c7e986610..1e9e180a3 100644 --- a/packages/worker/src/queue/bullmq.ts +++ b/packages/worker/src/queue/bullmq.ts @@ -4,9 +4,9 @@ import { QueueConfig } from "../types/queue"; import { Queue } from "."; -class BullMQQueue extends Queue { - private queue: BullQueue; - private worker?: Worker; +class BullMQQueue extends Queue { + public queue: BullQueue; + public worker?: Worker; private connection: RedisOptions; constructor(config: Required>) { @@ -21,6 +21,10 @@ class BullMQQueue extends Queue { this.process(config.bullmqConfig.handler, config.bullmqConfig.concurrency); } + getClient(): BullQueue { + return this.queue; + } + async push(data: T, options?: Record): Promise { try { const job = await this.queue.add(this.queueName, data, options); diff --git a/packages/worker/src/queue/index.ts b/packages/worker/src/queue/index.ts index 317cb1d76..0207d0551 100644 --- a/packages/worker/src/queue/index.ts +++ b/packages/worker/src/queue/index.ts @@ -5,6 +5,8 @@ abstract class Queue { this.queueName = name; } + abstract getClient(): T; + abstract process( handler: (data: T) => Promise, concurrency?: number, @@ -37,4 +39,4 @@ const addToQueue = async ( return queue.push(data, options); }; -export { Queue, registerQueue, addToQueue }; +export { Queue, registerQueue, addToQueue, getQueue }; diff --git a/packages/worker/src/queue/sqs.ts b/packages/worker/src/queue/sqs.ts index 4647afa3d..6c57714eb 100644 --- a/packages/worker/src/queue/sqs.ts +++ b/packages/worker/src/queue/sqs.ts @@ -10,9 +10,9 @@ import { QueueConfig } from "src/types/queue"; import { Queue } from "."; -class SQSQueue extends Queue { +class SQSQueue extends Queue { private config: Required>; - private client: SQSClient; + public client: SQSClient; private queueUrl: string; private isPooling: boolean = false; @@ -26,6 +26,10 @@ class SQSQueue extends Queue { this.process(config.sqsConfig.handler); } + getClient(): SQSClient { + return this.client; + } + async process(handler: (data: T) => Promise): Promise { if (this.isPooling) { return; From dcfb208052cd0058475c3b0a19a27e647c5887b6 Mon Sep 17 00:00:00 2001 From: sudeep Date: Thu, 19 Feb 2026 17:55:23 +0545 Subject: [PATCH 09/19] refactor: update structure for queues --- packages/worker/src/index.ts | 9 ++- packages/worker/src/queue/clients/base.ts | 21 +++++++ .../src/queue/{bullmq.ts => clients/bull.ts} | 9 ++- packages/worker/src/queue/clients/index.ts | 3 + .../worker/src/queue/{ => clients}/sqs.ts | 18 +++--- packages/worker/src/queue/index.ts | 46 ++------------ packages/worker/src/queue/processor.ts | 62 +++++++++++++++++++ packages/worker/src/queue/registry.ts | 30 +++++++++ packages/worker/src/queue/setup.ts | 46 ++------------ packages/worker/src/types/index.ts | 3 + pnpm-lock.yaml | 3 + 11 files changed, 148 insertions(+), 102 deletions(-) create mode 100644 packages/worker/src/queue/clients/base.ts rename packages/worker/src/queue/{bullmq.ts => clients/bull.ts} (92%) create mode 100644 packages/worker/src/queue/clients/index.ts rename packages/worker/src/queue/{ => clients}/sqs.ts (86%) create mode 100644 packages/worker/src/queue/processor.ts create mode 100644 packages/worker/src/queue/registry.ts diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index dcc8edda0..4b4285f6b 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -8,12 +8,11 @@ declare module "@prefabs.tech/fastify-config" { } } +export { SQSClient } from "@aws-sdk/client-sqs"; +export { Job, Queue } from "bullmq"; + export { default } from "./plugin"; export * from "./enum"; export * from "./queue"; - -export { SQSClient } from "@aws-sdk/client-sqs"; -export { Job, Queue } from "bullmq"; - -export type { WorkerConfig } from "./types"; +export * from "./types"; diff --git a/packages/worker/src/queue/clients/base.ts b/packages/worker/src/queue/clients/base.ts new file mode 100644 index 000000000..aa725d966 --- /dev/null +++ b/packages/worker/src/queue/clients/base.ts @@ -0,0 +1,21 @@ +abstract class BaseQueueClient { + public queueName: string; + + constructor(name: string) { + this.queueName = name; + } + + abstract getClient(): Payload; + + abstract process( + handler: (data: Payload) => Promise, + concurrency?: number, + ): void; + + abstract push( + data: Payload, + options?: Record, + ): Promise; +} + +export default BaseQueueClient; diff --git a/packages/worker/src/queue/bullmq.ts b/packages/worker/src/queue/clients/bull.ts similarity index 92% rename from packages/worker/src/queue/bullmq.ts rename to packages/worker/src/queue/clients/bull.ts index 1e9e180a3..ff37f8ca4 100644 --- a/packages/worker/src/queue/bullmq.ts +++ b/packages/worker/src/queue/clients/bull.ts @@ -1,10 +1,9 @@ import { Queue as BullQueue, Worker, Job, RedisOptions } from "bullmq"; -import { QueueConfig } from "../types/queue"; +import BaseQueueClient from "./base"; +import { QueueConfig } from "../../types"; -import { Queue } from "."; - -class BullMQQueue extends Queue { +class BullMqClient extends BaseQueueClient { public queue: BullQueue; public worker?: Worker; private connection: RedisOptions; @@ -69,4 +68,4 @@ class BullMQQueue extends Queue { } } -export default BullMQQueue; +export default BullMqClient; diff --git a/packages/worker/src/queue/clients/index.ts b/packages/worker/src/queue/clients/index.ts new file mode 100644 index 000000000..7ccf0cd53 --- /dev/null +++ b/packages/worker/src/queue/clients/index.ts @@ -0,0 +1,3 @@ +export { default as BaseQueueClient } from "./base"; +export { default as BullMQQueueClient } from "./bull"; +export { default as SQSQueueClient } from "./sqs"; diff --git a/packages/worker/src/queue/sqs.ts b/packages/worker/src/queue/clients/sqs.ts similarity index 86% rename from packages/worker/src/queue/sqs.ts rename to packages/worker/src/queue/clients/sqs.ts index 6c57714eb..94ad99112 100644 --- a/packages/worker/src/queue/sqs.ts +++ b/packages/worker/src/queue/clients/sqs.ts @@ -6,11 +6,10 @@ import { SQSClient, } from "@aws-sdk/client-sqs"; -import { QueueConfig } from "src/types/queue"; +import BaseQueueClient from "./base"; +import { QueueConfig } from "../../types"; -import { Queue } from "."; - -class SQSQueue extends Queue { +class SQSQueueClient extends BaseQueueClient { private config: Required>; public client: SQSClient; private queueUrl: string; @@ -30,7 +29,7 @@ class SQSQueue extends Queue { return this.client; } - async process(handler: (data: T) => Promise): Promise { + async process(handler: (data: Payload) => Promise): Promise { if (this.isPooling) { return; } @@ -52,7 +51,7 @@ class SQSQueue extends Queue { await Promise.all( response.Messages.map(async (message: Message) => { try { - const data = JSON.parse(message.Body!) as T; + const data = JSON.parse(message.Body!) as Payload; await handler(data); @@ -81,7 +80,10 @@ class SQSQueue extends Queue { pool(); } - async push(data: T, options?: Record): Promise { + async push( + data: Payload, + options?: Record, + ): Promise { try { const command = new SendMessageCommand({ QueueUrl: this.queueUrl, @@ -100,4 +102,4 @@ class SQSQueue extends Queue { } } -export default SQSQueue; +export default SQSQueueClient; diff --git a/packages/worker/src/queue/index.ts b/packages/worker/src/queue/index.ts index 0207d0551..52c41df32 100644 --- a/packages/worker/src/queue/index.ts +++ b/packages/worker/src/queue/index.ts @@ -1,42 +1,4 @@ -abstract class Queue { - protected queueName: string; - - constructor(name: string) { - this.queueName = name; - } - - abstract getClient(): T; - - abstract process( - handler: (data: T) => Promise, - concurrency?: number, - ): void; - - abstract push(data: T, options?: Record): Promise; -} - -const queueRegistry = new Map(); - -const getQueue = (name: string): Queue | undefined => { - return queueRegistry.get(name); -}; - -const registerQueue = (name: string, queue: Queue): void => { - queueRegistry.set(name, queue); -}; - -const addToQueue = async ( - queueName: string, - data: T, - options?: Record, -): Promise => { - const queue = getQueue(queueName); - - if (!queue) { - throw new Error(`Queue not found: ${queueName}`); - } - - return queue.push(data, options); -}; - -export { Queue, registerQueue, addToQueue, getQueue }; +export * from "./clients"; +export { default as setupQueues } from "./setup"; +export { default as QueueProcessor } from "./processor"; +export { default as QueueProcessorRegistry } from "./registry"; diff --git a/packages/worker/src/queue/processor.ts b/packages/worker/src/queue/processor.ts new file mode 100644 index 000000000..5714d3c56 --- /dev/null +++ b/packages/worker/src/queue/processor.ts @@ -0,0 +1,62 @@ +import { QueueProvider } from "../enum"; +import { BaseQueueClient, BullMQQueueClient, SQSQueueClient } from "./clients"; +import { QueueConfig } from "../types/queue"; + +class QueueProcessor { + private queueClient: BaseQueueClient; + + constructor(config: QueueConfig) { + this.queueClient = this.initializeQueueClient(config); + } + + protected initializeQueueClient(config: QueueConfig) { + let queueClient: BaseQueueClient; + + switch (config.provider) { + case QueueProvider.BULLMQ: { + if (!config.bullmqConfig) { + throw new Error( + `BullMQ configuration is required for queue: ${config.name}`, + ); + } + + queueClient = new BullMQQueueClient({ + name: config.name, + bullmqConfig: config.bullmqConfig, + }); + + break; + } + + case QueueProvider.SQS: { + if (!config.sqsConfig) { + throw new Error( + `SQS configuration is required for queue: ${config.name}`, + ); + } + + queueClient = new SQSQueueClient({ + name: config.name, + sqsConfig: config.sqsConfig, + }); + + break; + } + default: { + throw new Error(`Unsupported queue provider: ${config.provider}`); + } + } + + return queueClient; + } + + public getQueueClient() { + return this.queueClient; + } + + public getName() { + return this.queueClient.queueName; + } +} + +export default QueueProcessor; diff --git a/packages/worker/src/queue/registry.ts b/packages/worker/src/queue/registry.ts new file mode 100644 index 000000000..acc150bf2 --- /dev/null +++ b/packages/worker/src/queue/registry.ts @@ -0,0 +1,30 @@ +import QueueProcessor from "./processor"; + +class QueueProcessorRegistry { + public static queueProcessors: Map = new Map(); + + public static add(queueProcessor: QueueProcessor) { + QueueProcessorRegistry.queueProcessors.set( + queueProcessor.getName(), + queueProcessor, + ); + } + + public static get(queueName: string): QueueProcessor | undefined { + return QueueProcessorRegistry.queueProcessors.get(queueName); + } + + public static getAll(): QueueProcessor[] { + return [...QueueProcessorRegistry.queueProcessors.values()]; + } + + public static has(queueName: string): boolean { + return QueueProcessorRegistry.queueProcessors.has(queueName); + } + + public static remove(queueName: string): void { + QueueProcessorRegistry.queueProcessors.delete(queueName); + } +} + +export default QueueProcessorRegistry; diff --git a/packages/worker/src/queue/setup.ts b/packages/worker/src/queue/setup.ts index e102999a3..5dc0e60ff 100644 --- a/packages/worker/src/queue/setup.ts +++ b/packages/worker/src/queue/setup.ts @@ -1,9 +1,6 @@ -import { QueueProvider } from "../enum"; import { WorkerConfig } from "../types"; -import BullMQQueue from "./bullmq"; -import SQSQueue from "./sqs"; - -import { registerQueue } from "."; +import QueueProcessor from "./processor"; +import QueueProcessorRegistry from "./registry"; const setupQueues = (config: WorkerConfig) => { if (!config.queues || config.queues.length === 0) { @@ -13,44 +10,9 @@ const setupQueues = (config: WorkerConfig) => { const { queues } = config; for (const queueConfig of queues) { - switch (queueConfig.provider) { - case QueueProvider.BULLMQ: { - if (!queueConfig.bullmqConfig) { - throw new Error( - `BullMQ configuration is required for queue: ${queueConfig.name}`, - ); - } - - const queue = new BullMQQueue({ - name: queueConfig.name, - bullmqConfig: queueConfig.bullmqConfig, - }); - - registerQueue(queueConfig.name, queue); - - break; - } - - case QueueProvider.SQS: { - if (!queueConfig.sqsConfig) { - throw new Error( - `SQS configuration is required for queue: ${queueConfig.name}`, - ); - } - - const queue = new SQSQueue({ - name: queueConfig.name, - sqsConfig: queueConfig.sqsConfig, - }); - - registerQueue(queueConfig.name, queue); + const queueProcessor = new QueueProcessor(queueConfig); - break; - } - default: { - throw new Error(`Unsupported queue provider: ${queueConfig.provider}`); - } - } + QueueProcessorRegistry.add(queueProcessor); } }; diff --git a/packages/worker/src/types/index.ts b/packages/worker/src/types/index.ts index 982a656c5..098c70183 100644 --- a/packages/worker/src/types/index.ts +++ b/packages/worker/src/types/index.ts @@ -5,3 +5,6 @@ export interface WorkerConfig { cronJobs?: CronJob[]; queues?: QueueConfig[]; } + +export * from "./cron"; +export * from "./queue"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8221b45f4..5aac5ddf0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -617,6 +617,9 @@ importers: '@prefabs.tech/fastify-config': specifier: 0.93.5 version: link:../config + '@prefabs.tech/fastify-error-handler': + specifier: 0.93.5 + version: link:../error-handler '@prefabs.tech/tsconfig': specifier: 0.5.0 version: 0.5.0(@types/node@24.10.13) From fd50d5c251756d1b455a8603c3abe2e527a735ba Mon Sep 17 00:00:00 2001 From: sudeep Date: Thu, 19 Feb 2026 17:58:07 +0545 Subject: [PATCH 10/19] chore: update pnpm-lock --- pnpm-lock.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5aac5ddf0..8221b45f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -617,9 +617,6 @@ importers: '@prefabs.tech/fastify-config': specifier: 0.93.5 version: link:../config - '@prefabs.tech/fastify-error-handler': - specifier: 0.93.5 - version: link:../error-handler '@prefabs.tech/tsconfig': specifier: 0.5.0 version: 0.5.0(@types/node@24.10.13) From 3eee54f87fd182ada847c8f7335146245b8d94fe Mon Sep 17 00:00:00 2001 From: sudeep Date: Thu, 19 Feb 2026 18:07:25 +0545 Subject: [PATCH 11/19] chore: add readme for worker package --- packages/worker/README.md | 141 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/packages/worker/README.md b/packages/worker/README.md index 17b34f39f..dc74acc42 100644 --- a/packages/worker/README.md +++ b/packages/worker/README.md @@ -1 +1,142 @@ # @prefabs.tech/fastify-worker + +A [Fastify](https://github.com/fastify/fastify) plugin for managing queue processes and cron tasks. It provides a unified interface for working with queues (BullMQ, SQS) and scheduling recurring tasks. + +## Features + +- **Cron Jobs**: Schedule recurring tasks using standard cron expressions +- **Queue System**: Basic queue management with support for BullMQ and AWS SQS +- **BullMQ Integration**: Redis-based message queues for high-performance background processing +- **AWS SQS Integration**: Support for Amazon Simple Queue Service + +## Requirements + +- [@prefabs.tech/fastify-config](https://www.npmjs.com/package/@prefabs.tech/fastify-config) + +## Usage + +### Register Plugin + +Register the worker plugin with your Fastify instance: + +```typescript +import workerPlugin from "@prefabs.tech/fastify-worker"; +import configPlugin from "@prefabs.tech/fastify-config"; +import Fastify from "fastify"; + +import config from "./config"; + +const start = async () => { + // Create fastify instance + const fastify = Fastify({ + logger: config.logger, + }); + + // Register fastify-config plugin + await fastify.register(configPlugin, { config }); + + // Register worker plugin + await fastify.register(workerPlugin); + + await fastify.listen({ + port: config.port, + host: "0.0.0.0", + }); +}; + +start(); +``` + +## Configuration + +Add worker configuration to your config: + +```typescript +import { QueueProvider } from "@prefabs.tech/fastify-worker"; +import type { ApiConfig } from "@prefabs.tech/fastify-config"; + +const config: ApiConfig = { + // ...other config + worker: { + cronJobs: [ + { + expression: "0 0 * * *", // Run daily at midnight + task: async () => { + console.log("Running daily cleanup..."); + }, + options: { + scheduled: true, + timezone: "UTC", + }, + }, + ], + queues: [ + { + name: "email-queue", + provider: QueueProvider.BULLMQ, + bullmqConfig: { + connection: { + host: "localhost", + port: 6379, + }, + concurrency: 5, + defaultJobOptions: { + attempts: 3, + backoff: { + type: "exponential", + delay: 1000, + }, + }, + handler: async (job) => { + console.log(`Processing email job ${job.id}`); + // Send email logic here + }, + }, + }, + { + name: "audit-log-queue", + provider: QueueProvider.SQS, + sqsConfig: { + clientConfig: { + region: "us-east-1", + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID!, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!, + }, + }, + queueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/audit-logs", + maxNumberOfMessages: 10, + waitTimeSeconds: 20, + handler: async (message) => { + console.log("Processing audit log", message); + }, + }, + }, + ], + }, +}; +``` + +## Adding Jobs to Queues + +To add jobs to a registered queue, use the `QueueProcessorRegistry` to access the queue client: + +```typescript +import { QueueProcessorRegistry } from "@prefabs.tech/fastify-worker"; + +// Get the processor for a specific queue +const processor = QueueProcessorRegistry.get("email-queue"); + +if (processor) { + // Add a job to the queue + await processor.getQueueClient().push({ + to: "user@example.com", + subject: "Welcome!", + body: "Hello from Fastify Worker", + }); + + console.log("Job added to email-queue"); +} else { + console.error("Queue not found"); +} +``` From 2f81b91c458472f5cb3d7313518c7111922a0e3d Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 20 Feb 2026 09:33:06 +0545 Subject: [PATCH 12/19] refactor: update queue error handling and config --- packages/worker/README.md | 4 +-- packages/worker/src/queue/clients/bull.ts | 35 ++++++++++++++++------- packages/worker/src/queue/clients/sqs.ts | 19 +++++++----- packages/worker/src/types/queue.ts | 13 +++++---- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/packages/worker/README.md b/packages/worker/README.md index dc74acc42..e37a5e449 100644 --- a/packages/worker/README.md +++ b/packages/worker/README.md @@ -105,8 +105,8 @@ const config: ApiConfig = { }, }, queueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/audit-logs", - maxNumberOfMessages: 10, - waitTimeSeconds: 20, + maxNumberOfMessages: 10, // Defines maximum number of messages SQS ReceiveMessage action will return in a single call. Default: 10 + waitTimeSeconds: 20, // Defines how long a ReceiveMessage API call waits for a message to arrive before returning. Default: 0 handler: async (message) => { console.log("Processing audit log", message); }, diff --git a/packages/worker/src/queue/clients/bull.ts b/packages/worker/src/queue/clients/bull.ts index ff37f8ca4..700ad2fd1 100644 --- a/packages/worker/src/queue/clients/bull.ts +++ b/packages/worker/src/queue/clients/bull.ts @@ -3,7 +3,7 @@ import { Queue as BullQueue, Worker, Job, RedisOptions } from "bullmq"; import BaseQueueClient from "./base"; import { QueueConfig } from "../../types"; -class BullMqClient extends BaseQueueClient { +class BullMqClient extends BaseQueueClient { public queue: BullQueue; public worker?: Worker; private connection: RedisOptions; @@ -17,14 +17,22 @@ class BullMqClient extends BaseQueueClient { defaultJobOptions: config.bullmqConfig.defaultJobOptions, }); - this.process(config.bullmqConfig.handler, config.bullmqConfig.concurrency); + this.process( + config.bullmqConfig.handler, + config.bullmqConfig.concurrency, + config.bullmqConfig.onError, + config.bullmqConfig.onFailed, + ); } getClient(): BullQueue { return this.queue; } - async push(data: T, options?: Record): Promise { + async push( + data: Payload, + options?: Record, + ): Promise { try { const job = await this.queue.add(this.queueName, data, options); @@ -36,11 +44,16 @@ class BullMqClient extends BaseQueueClient { } } - process(handler: (job: Job) => Promise, concurrency = 1): void { + process( + handler: (job: Job) => Promise, + concurrency = 1, + onError?: (error: Error) => void, + onFailed?: (job: Job, error: Error) => void, + ): void { try { this.worker = new Worker( this.queueName, - async (job: Job) => { + async (job: Job) => { await handler(job); }, { @@ -50,15 +63,15 @@ class BullMqClient extends BaseQueueClient { ); this.worker.on("error", (error) => { - console.error( - `Error in BullMQ worker for queue: ${this.queueName}. Error: ${(error as Error).message}`, - ); + if (onError) { + onError(error); + } }); this.worker.on("failed", (job, error) => { - console.error( - `Job failed in BullMQ queue: ${this.queueName}. Job ID: ${job?.id}. Error: ${(error as Error).message}`, - ); + if (onFailed) { + onFailed(job as Job, error); + } }); } catch (error) { throw new Error( diff --git a/packages/worker/src/queue/clients/sqs.ts b/packages/worker/src/queue/clients/sqs.ts index 94ad99112..a1ca02209 100644 --- a/packages/worker/src/queue/clients/sqs.ts +++ b/packages/worker/src/queue/clients/sqs.ts @@ -51,7 +51,7 @@ class SQSQueueClient extends BaseQueueClient { await Promise.all( response.Messages.map(async (message: Message) => { try { - const data = JSON.parse(message.Body!) as Payload; + const data = JSON.parse(message.Body ?? "{}") as Payload; await handler(data); @@ -62,17 +62,22 @@ class SQSQueueClient extends BaseQueueClient { }), ); } catch (error) { - console.error( - `Error processing message from SQS queue: ${this.queueName}. Message ID: ${message.MessageId}. Error: ${(error as Error).message}`, - ); + if (this.config.sqsConfig.onError) { + this.config.sqsConfig.onError( + error instanceof Error ? error : new Error(String(error)), + message, + ); + } } }), ); } } catch (error) { - console.error( - `Error processing job from SQS queue: ${this.queueName}. Error: ${(error as Error).message}`, - ); + if (this.config.sqsConfig.onError) { + this.config.sqsConfig.onError( + error instanceof Error ? error : new Error(String(error)), + ); + } } } }; diff --git a/packages/worker/src/types/queue.ts b/packages/worker/src/types/queue.ts index c37cde871..d9fe3e4de 100644 --- a/packages/worker/src/types/queue.ts +++ b/packages/worker/src/types/queue.ts @@ -1,30 +1,33 @@ -import { SQSClientConfig } from "@aws-sdk/client-sqs"; +import { Message, SQSClientConfig } from "@aws-sdk/client-sqs"; import { RedisOptions, Job } from "bullmq"; import { QueueProvider } from "../enum"; export interface QueueConfig { bullmqConfig?: { - connection: RedisOptions; concurrency?: number; + connection: RedisOptions; defaultJobOptions?: { attempts?: number; backoff?: { - type: string; delay: number; + type: string; }; removeOnComplete?: boolean | number; removeOnFail?: boolean | number; }; handler: (job: Job) => Promise; + onError?: (error: Error) => void; + onFailed?: (job: Job, error: Error) => void; }; name: string; provider: QueueProvider; sqsConfig?: { clientConfig: SQSClientConfig; handler: (data: T) => Promise; - maxNumberOfMessages: number; - waitTimeSeconds: number; + maxNumberOfMessages?: number; + onError?: (error: Error, message?: Message) => void; queueUrl: string; + waitTimeSeconds?: number; }; } From 7df2d60b9e472df550d495f8cb4828ca38a662c9 Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 20 Feb 2026 10:33:47 +0545 Subject: [PATCH 13/19] feat: add ability to initialize queue outside plugin --- packages/worker/src/cron/index.ts | 2 +- packages/worker/src/cron/setup.ts | 8 +++----- packages/worker/src/index.ts | 1 + packages/worker/src/lib/index.ts | 1 + packages/worker/src/lib/initialize.ts | 17 +++++++++++++++++ packages/worker/src/plugin.ts | 15 ++++++--------- packages/worker/src/queue/index.ts | 3 ++- packages/worker/src/queue/setup.ts | 12 +++++------- 8 files changed, 36 insertions(+), 23 deletions(-) create mode 100644 packages/worker/src/lib/index.ts create mode 100644 packages/worker/src/lib/initialize.ts diff --git a/packages/worker/src/cron/index.ts b/packages/worker/src/cron/index.ts index dcdc3e6c7..503f327dc 100644 --- a/packages/worker/src/cron/index.ts +++ b/packages/worker/src/cron/index.ts @@ -1 +1 @@ -export * from "./setup"; +export { default as setupCronJobs } from "./setup"; diff --git a/packages/worker/src/cron/setup.ts b/packages/worker/src/cron/setup.ts index ff1a67dfe..e1199497f 100644 --- a/packages/worker/src/cron/setup.ts +++ b/packages/worker/src/cron/setup.ts @@ -1,14 +1,12 @@ import cron from "node-cron"; -import { WorkerConfig } from "src/types"; +import { CronJob } from "src/types"; -const setupCronJobs = (config: WorkerConfig) => { - if (!config.cronJobs || config.cronJobs.length === 0) { +const setupCronJobs = (cronJobs: CronJob[]) => { + if (cronJobs.length === 0) { return; } - const { cronJobs } = config; - for (const job of cronJobs) { cron.schedule(job.expression, job.task, job.options); } diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index 4b4285f6b..d287ce467 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -14,5 +14,6 @@ export { Job, Queue } from "bullmq"; export { default } from "./plugin"; export * from "./enum"; +export * from "./lib"; export * from "./queue"; export * from "./types"; diff --git a/packages/worker/src/lib/index.ts b/packages/worker/src/lib/index.ts new file mode 100644 index 000000000..048cfe5bb --- /dev/null +++ b/packages/worker/src/lib/index.ts @@ -0,0 +1 @@ +export * from "./initialize"; diff --git a/packages/worker/src/lib/initialize.ts b/packages/worker/src/lib/initialize.ts new file mode 100644 index 000000000..36ade4bd8 --- /dev/null +++ b/packages/worker/src/lib/initialize.ts @@ -0,0 +1,17 @@ +import { setupCronJobs } from "../cron"; +import { setupQueueProcessors } from "../queue"; +import { CronJob, QueueConfig } from "../types"; + +const initializeCronJobs = async (cronConfigs?: CronJob[]) => { + if (!cronConfigs) return; + + setupCronJobs(cronConfigs); +}; + +const initializeQueueProcessors = async (queueConfigs?: QueueConfig[]) => { + if (!queueConfigs) return; + + setupQueueProcessors(queueConfigs); +}; + +export { initializeCronJobs, initializeQueueProcessors }; diff --git a/packages/worker/src/plugin.ts b/packages/worker/src/plugin.ts index 96e82b160..8e20d7333 100644 --- a/packages/worker/src/plugin.ts +++ b/packages/worker/src/plugin.ts @@ -1,8 +1,10 @@ import { FastifyInstance } from "fastify"; import FastifyPlugin from "fastify-plugin"; -import setupCronJobs from "./cron/setup"; -import setupQueues from "./queue/setup"; +import { + initializeCronJobs, + initializeQueueProcessors, +} from "./lib/initialize"; const plugin = async (fastify: FastifyInstance) => { const { config, log } = fastify; @@ -15,13 +17,8 @@ const plugin = async (fastify: FastifyInstance) => { log.info("Registering worker plugin"); - if (config.worker.cronJobs) { - setupCronJobs(config.worker); - } - - if (config.worker.queues) { - setupQueues(config.worker); - } + initializeCronJobs(config.worker.cronJobs); + initializeQueueProcessors(config.worker.queues); }; export default FastifyPlugin(plugin); diff --git a/packages/worker/src/queue/index.ts b/packages/worker/src/queue/index.ts index 52c41df32..4b887b5e2 100644 --- a/packages/worker/src/queue/index.ts +++ b/packages/worker/src/queue/index.ts @@ -1,4 +1,5 @@ export * from "./clients"; -export { default as setupQueues } from "./setup"; + +export { default as setupQueueProcessors } from "./setup"; export { default as QueueProcessor } from "./processor"; export { default as QueueProcessorRegistry } from "./registry"; diff --git a/packages/worker/src/queue/setup.ts b/packages/worker/src/queue/setup.ts index 5dc0e60ff..ae7cdabb0 100644 --- a/packages/worker/src/queue/setup.ts +++ b/packages/worker/src/queue/setup.ts @@ -1,19 +1,17 @@ -import { WorkerConfig } from "../types"; import QueueProcessor from "./processor"; import QueueProcessorRegistry from "./registry"; +import { QueueConfig } from "../types"; -const setupQueues = (config: WorkerConfig) => { - if (!config.queues || config.queues.length === 0) { +const setupQueueProcessors = (queueConfigs: QueueConfig[]) => { + if (queueConfigs.length === 0) { return; } - const { queues } = config; - - for (const queueConfig of queues) { + for (const queueConfig of queueConfigs) { const queueProcessor = new QueueProcessor(queueConfig); QueueProcessorRegistry.add(queueProcessor); } }; -export default setupQueues; +export default setupQueueProcessors; From b0df3eca50e6efc6bb383c629384f71f66b29abc Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 20 Feb 2026 12:27:35 +0545 Subject: [PATCH 14/19] refactor: update queue client type --- packages/worker/src/queue/clients/bull.ts | 67 ++++++++++++----------- packages/worker/src/queue/clients/sqs.ts | 34 +++++++----- packages/worker/src/queue/processor.ts | 10 +--- packages/worker/src/types/queue.ts | 33 ++--------- 4 files changed, 64 insertions(+), 80 deletions(-) diff --git a/packages/worker/src/queue/clients/bull.ts b/packages/worker/src/queue/clients/bull.ts index 700ad2fd1..24b6d3d5a 100644 --- a/packages/worker/src/queue/clients/bull.ts +++ b/packages/worker/src/queue/clients/bull.ts @@ -1,28 +1,41 @@ -import { Queue as BullQueue, Worker, Job, RedisOptions } from "bullmq"; +import { + Queue as BullQueue, + Worker, + Job, + QueueOptions, + WorkerOptions, +} from "bullmq"; import BaseQueueClient from "./base"; -import { QueueConfig } from "../../types"; + +export interface BullMQClientConfig { + queueOptions: QueueOptions; + workerOptions?: WorkerOptions; + handler: (job: Job) => Promise; + onError?: (error: Error) => void; + onFailed?: (job: Job, error: Error) => void; +} class BullMqClient extends BaseQueueClient { public queue: BullQueue; public worker?: Worker; - private connection: RedisOptions; + private queueOptions: QueueOptions; + private workerOptions?: WorkerOptions; + private handler: (job: Job) => Promise; + private onError?: (error: Error) => void; + private onFailed?: (job: Job, error: Error) => void; - constructor(config: Required>) { - super(config.name); + constructor(name: string, config: BullMQClientConfig) { + super(name); - this.connection = config.bullmqConfig.connection; - this.queue = new BullQueue(this.queueName, { - connection: this.connection, - defaultJobOptions: config.bullmqConfig.defaultJobOptions, - }); + this.queueOptions = config.queueOptions; + this.workerOptions = config.workerOptions; + this.handler = config.handler; + this.onError = config.onError; + this.onFailed = config.onFailed; - this.process( - config.bullmqConfig.handler, - config.bullmqConfig.concurrency, - config.bullmqConfig.onError, - config.bullmqConfig.onFailed, - ); + this.queue = new BullQueue(this.queueName, this.queueOptions); + this.process(); } getClient(): BullQueue { @@ -44,33 +57,25 @@ class BullMqClient extends BaseQueueClient { } } - process( - handler: (job: Job) => Promise, - concurrency = 1, - onError?: (error: Error) => void, - onFailed?: (job: Job, error: Error) => void, - ): void { + process(): void { try { this.worker = new Worker( this.queueName, async (job: Job) => { - await handler(job); - }, - { - connection: this.connection, - concurrency, + await this.handler(job); }, + this.workerOptions, ); this.worker.on("error", (error) => { - if (onError) { - onError(error); + if (this.onError) { + this.onError(error); } }); this.worker.on("failed", (job, error) => { - if (onFailed) { - onFailed(job as Job, error); + if (this.onFailed) { + this.onFailed(job as Job, error); } }); } catch (error) { diff --git a/packages/worker/src/queue/clients/sqs.ts b/packages/worker/src/queue/clients/sqs.ts index a1ca02209..7094e8841 100644 --- a/packages/worker/src/queue/clients/sqs.ts +++ b/packages/worker/src/queue/clients/sqs.ts @@ -2,27 +2,36 @@ import { DeleteMessageCommand, Message, ReceiveMessageCommand, + ReceiveMessageCommandInput, SendMessageCommand, SQSClient, + SQSClientConfig, } from "@aws-sdk/client-sqs"; import BaseQueueClient from "./base"; -import { QueueConfig } from "../../types"; + +export interface SQSQueueClientConfig { + clientConfig: SQSClientConfig; + handler: (data: unknown) => Promise; + receiveMessageOptions?: ReceiveMessageCommandInput; + onError?: (error: Error, message?: Message) => void; + queueUrl: string; +} class SQSQueueClient extends BaseQueueClient { - private config: Required>; + private config: SQSQueueClientConfig; public client: SQSClient; private queueUrl: string; private isPooling: boolean = false; - constructor(config: Required>) { - super(config.name); + constructor(name: string, config: SQSQueueClientConfig) { + super(name); this.config = config; - this.client = new SQSClient(config.sqsConfig.clientConfig); - this.queueUrl = config.sqsConfig.queueUrl; + this.client = new SQSClient(config.clientConfig); + this.queueUrl = config.queueUrl; - this.process(config.sqsConfig.handler); + this.process(config.handler); } getClient(): SQSClient { @@ -41,8 +50,7 @@ class SQSQueueClient extends BaseQueueClient { try { const command = new ReceiveMessageCommand({ QueueUrl: this.queueUrl, - MaxNumberOfMessages: this.config.sqsConfig.maxNumberOfMessages, - WaitTimeSeconds: this.config.sqsConfig.waitTimeSeconds, + ...this.config.receiveMessageOptions, }); const response = await this.client.send(command); @@ -62,8 +70,8 @@ class SQSQueueClient extends BaseQueueClient { }), ); } catch (error) { - if (this.config.sqsConfig.onError) { - this.config.sqsConfig.onError( + if (this.config.onError) { + this.config.onError( error instanceof Error ? error : new Error(String(error)), message, ); @@ -73,8 +81,8 @@ class SQSQueueClient extends BaseQueueClient { ); } } catch (error) { - if (this.config.sqsConfig.onError) { - this.config.sqsConfig.onError( + if (this.config.onError) { + this.config.onError( error instanceof Error ? error : new Error(String(error)), ); } diff --git a/packages/worker/src/queue/processor.ts b/packages/worker/src/queue/processor.ts index 5714d3c56..0da9efb16 100644 --- a/packages/worker/src/queue/processor.ts +++ b/packages/worker/src/queue/processor.ts @@ -20,10 +20,7 @@ class QueueProcessor { ); } - queueClient = new BullMQQueueClient({ - name: config.name, - bullmqConfig: config.bullmqConfig, - }); + queueClient = new BullMQQueueClient(config.name, config.bullmqConfig); break; } @@ -35,10 +32,7 @@ class QueueProcessor { ); } - queueClient = new SQSQueueClient({ - name: config.name, - sqsConfig: config.sqsConfig, - }); + queueClient = new SQSQueueClient(config.name, config.sqsConfig); break; } diff --git a/packages/worker/src/types/queue.ts b/packages/worker/src/types/queue.ts index d9fe3e4de..623bf27e8 100644 --- a/packages/worker/src/types/queue.ts +++ b/packages/worker/src/types/queue.ts @@ -1,33 +1,10 @@ -import { Message, SQSClientConfig } from "@aws-sdk/client-sqs"; -import { RedisOptions, Job } from "bullmq"; - import { QueueProvider } from "../enum"; +import { BullMQClientConfig } from "../queue/clients/bull"; +import { SQSQueueClientConfig } from "../queue/clients/sqs"; -export interface QueueConfig { - bullmqConfig?: { - concurrency?: number; - connection: RedisOptions; - defaultJobOptions?: { - attempts?: number; - backoff?: { - delay: number; - type: string; - }; - removeOnComplete?: boolean | number; - removeOnFail?: boolean | number; - }; - handler: (job: Job) => Promise; - onError?: (error: Error) => void; - onFailed?: (job: Job, error: Error) => void; - }; +export interface QueueConfig { + bullmqConfig?: BullMQClientConfig; name: string; provider: QueueProvider; - sqsConfig?: { - clientConfig: SQSClientConfig; - handler: (data: T) => Promise; - maxNumberOfMessages?: number; - onError?: (error: Error, message?: Message) => void; - queueUrl: string; - waitTimeSeconds?: number; - }; + sqsConfig?: SQSQueueClientConfig; } From fab8a3947bfd75cacb188e6c5dd1a2db4b5c8835 Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 20 Feb 2026 13:12:43 +0545 Subject: [PATCH 15/19] chore: update readme --- packages/worker/README.md | 38 +++++++++-------------- packages/worker/src/queue/clients/bull.ts | 6 ++-- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/worker/README.md b/packages/worker/README.md index e37a5e449..70c19e983 100644 --- a/packages/worker/README.md +++ b/packages/worker/README.md @@ -72,44 +72,36 @@ const config: ApiConfig = { ], queues: [ { - name: "email-queue", + name: "bull-queue", provider: QueueProvider.BULLMQ, bullmqConfig: { - connection: { - host: "localhost", - port: 6379, + handler: async (job) => { + // }, - concurrency: 5, - defaultJobOptions: { - attempts: 3, - backoff: { - type: "exponential", - delay: 1000, + queueOptions: { + connection: { + host: "localhost", + port: 6379, }, }, - handler: async (job) => { - console.log(`Processing email job ${job.id}`); - // Send email logic here - }, }, }, { - name: "audit-log-queue", + name: "sqs-queue", provider: QueueProvider.SQS, sqsConfig: { clientConfig: { - region: "us-east-1", credentials: { - accessKeyId: process.env.AWS_ACCESS_KEY_ID!, - secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!, + accessKeyId: "", + secretAccessKey: "", }, + endpoint: "", + region: "", }, - queueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/audit-logs", - maxNumberOfMessages: 10, // Defines maximum number of messages SQS ReceiveMessage action will return in a single call. Default: 10 - waitTimeSeconds: 20, // Defines how long a ReceiveMessage API call waits for a message to arrive before returning. Default: 0 - handler: async (message) => { - console.log("Processing audit log", message); + handler: async (message: any) => { + // }, + queueUrl: "", }, }, ], diff --git a/packages/worker/src/queue/clients/bull.ts b/packages/worker/src/queue/clients/bull.ts index 24b6d3d5a..bc509e001 100644 --- a/packages/worker/src/queue/clients/bull.ts +++ b/packages/worker/src/queue/clients/bull.ts @@ -29,11 +29,13 @@ class BullMqClient extends BaseQueueClient { super(name); this.queueOptions = config.queueOptions; - this.workerOptions = config.workerOptions; + this.workerOptions = { + connection: config.queueOptions.connection, + ...config.workerOptions, + }; this.handler = config.handler; this.onError = config.onError; this.onFailed = config.onFailed; - this.queue = new BullQueue(this.queueName, this.queueOptions); this.process(); } From eb4f9129d81cfa7a1926065d7f306c79b8d7f9fa Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 20 Feb 2026 13:21:33 +0545 Subject: [PATCH 16/19] fix: update bull mq job type --- packages/worker/src/queue/clients/bull.ts | 10 ++++------ packages/worker/src/queue/clients/sqs.ts | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/worker/src/queue/clients/bull.ts b/packages/worker/src/queue/clients/bull.ts index bc509e001..a62c4290d 100644 --- a/packages/worker/src/queue/clients/bull.ts +++ b/packages/worker/src/queue/clients/bull.ts @@ -4,6 +4,7 @@ import { Job, QueueOptions, WorkerOptions, + JobsOptions, } from "bullmq"; import BaseQueueClient from "./base"; @@ -19,11 +20,11 @@ export interface BullMQClientConfig { class BullMqClient extends BaseQueueClient { public queue: BullQueue; public worker?: Worker; - private queueOptions: QueueOptions; - private workerOptions?: WorkerOptions; private handler: (job: Job) => Promise; private onError?: (error: Error) => void; private onFailed?: (job: Job, error: Error) => void; + private queueOptions: QueueOptions; + private workerOptions?: WorkerOptions; constructor(name: string, config: BullMQClientConfig) { super(name); @@ -44,10 +45,7 @@ class BullMqClient extends BaseQueueClient { return this.queue; } - async push( - data: Payload, - options?: Record, - ): Promise { + async push(data: Payload, options?: JobsOptions): Promise { try { const job = await this.queue.add(this.queueName, data, options); diff --git a/packages/worker/src/queue/clients/sqs.ts b/packages/worker/src/queue/clients/sqs.ts index 7094e8841..6268f1cf3 100644 --- a/packages/worker/src/queue/clients/sqs.ts +++ b/packages/worker/src/queue/clients/sqs.ts @@ -13,9 +13,9 @@ import BaseQueueClient from "./base"; export interface SQSQueueClientConfig { clientConfig: SQSClientConfig; handler: (data: unknown) => Promise; - receiveMessageOptions?: ReceiveMessageCommandInput; onError?: (error: Error, message?: Message) => void; queueUrl: string; + receiveMessageOptions?: ReceiveMessageCommandInput; } class SQSQueueClient extends BaseQueueClient { From bff48aa0b42383952f43f746dc25750201547ea2 Mon Sep 17 00:00:00 2001 From: sudeep Date: Fri, 20 Feb 2026 15:22:31 +0545 Subject: [PATCH 17/19] chore: pin node-cron --- packages/worker/package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/worker/package.json b/packages/worker/package.json index 287a15487..44f3dba7b 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -32,7 +32,7 @@ "dependencies": { "@aws-sdk/client-sqs": "3.991.0", "bullmq": "5.69.3", - "node-cron": "^4.2.1", + "node-cron": "4.2.1", "zod": "3.25.76" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8221b45f4..a128911c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -605,7 +605,7 @@ importers: specifier: 5.69.3 version: 5.69.3 node-cron: - specifier: ^4.2.1 + specifier: 4.2.1 version: 4.2.1 zod: specifier: 3.25.76 From a9a90562fc96ad43b5f7dd904a6e20ff7dedc6e5 Mon Sep 17 00:00:00 2001 From: Sudeep Bashistha <32100152+BashisthaSudeep@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:38:05 +0545 Subject: [PATCH 18/19] refactor: update queue implementation (#1069) --- packages/worker/README.md | 77 ++++++------ packages/worker/src/cron/index.ts | 2 +- packages/worker/src/cron/scheduler.ts | 23 ++++ packages/worker/src/cron/setup.ts | 15 --- packages/worker/src/index.ts | 2 +- packages/worker/src/lib/index.ts | 1 - packages/worker/src/lib/initialize.ts | 17 --- packages/worker/src/plugin.ts | 17 ++- packages/worker/src/queue/adapterRegistry.ts | 35 ++++++ packages/worker/src/queue/adapters/base.ts | 17 +++ packages/worker/src/queue/adapters/bullmq.ts | 83 +++++++++++++ packages/worker/src/queue/adapters/index.ts | 6 + packages/worker/src/queue/adapters/sqs.ts | 124 +++++++++++++++++++ packages/worker/src/queue/clients/base.ts | 21 ---- packages/worker/src/queue/clients/bull.ts | 89 ------------- packages/worker/src/queue/clients/index.ts | 3 - packages/worker/src/queue/clients/sqs.ts | 118 ------------------ packages/worker/src/queue/factory.ts | 33 +++++ packages/worker/src/queue/index.ts | 7 +- packages/worker/src/queue/processor.ts | 56 --------- packages/worker/src/queue/registry.ts | 30 ----- packages/worker/src/queue/setup.ts | 17 --- packages/worker/src/types/queue.ts | 8 +- packages/worker/src/worker.ts | 38 ++++++ 24 files changed, 421 insertions(+), 418 deletions(-) create mode 100644 packages/worker/src/cron/scheduler.ts delete mode 100644 packages/worker/src/cron/setup.ts delete mode 100644 packages/worker/src/lib/index.ts delete mode 100644 packages/worker/src/lib/initialize.ts create mode 100644 packages/worker/src/queue/adapterRegistry.ts create mode 100644 packages/worker/src/queue/adapters/base.ts create mode 100644 packages/worker/src/queue/adapters/bullmq.ts create mode 100644 packages/worker/src/queue/adapters/index.ts create mode 100644 packages/worker/src/queue/adapters/sqs.ts delete mode 100644 packages/worker/src/queue/clients/base.ts delete mode 100644 packages/worker/src/queue/clients/bull.ts delete mode 100644 packages/worker/src/queue/clients/index.ts delete mode 100644 packages/worker/src/queue/clients/sqs.ts create mode 100644 packages/worker/src/queue/factory.ts delete mode 100644 packages/worker/src/queue/processor.ts delete mode 100644 packages/worker/src/queue/registry.ts delete mode 100644 packages/worker/src/queue/setup.ts create mode 100644 packages/worker/src/worker.ts diff --git a/packages/worker/README.md b/packages/worker/README.md index 70c19e983..618384998 100644 --- a/packages/worker/README.md +++ b/packages/worker/README.md @@ -5,37 +5,30 @@ A [Fastify](https://github.com/fastify/fastify) plugin for managing queue proces ## Features - **Cron Jobs**: Schedule recurring tasks using standard cron expressions -- **Queue System**: Basic queue management with support for BullMQ and AWS SQS +- **Queue System**: Queue management with support for BullMQ and AWS SQS - **BullMQ Integration**: Redis-based message queues for high-performance background processing - **AWS SQS Integration**: Support for Amazon Simple Queue Service ## Requirements - - [@prefabs.tech/fastify-config](https://www.npmjs.com/package/@prefabs.tech/fastify-config) ## Usage -### Register Plugin +### Fastify Plugin Register the worker plugin with your Fastify instance: ```typescript import workerPlugin from "@prefabs.tech/fastify-worker"; -import configPlugin from "@prefabs.tech/fastify-config"; import Fastify from "fastify"; import config from "./config"; const start = async () => { - // Create fastify instance const fastify = Fastify({ logger: config.logger, }); - // Register fastify-config plugin - await fastify.register(configPlugin, { config }); - - // Register worker plugin await fastify.register(workerPlugin); await fastify.listen({ @@ -47,6 +40,44 @@ const start = async () => { start(); ``` +### Pushing to the queue + +The `AdapterRegistry` is a singleton. Once the plugin initializes the worker, any service can access the same registry directly — no instance passing required: + +```typescript +await fastify.register(workerPlugin); +``` + +```typescript +import { Worker } from "@prefabs.tech/fastify-worker"; + +const queue = Worker.adapters.get("queue-name") + +if (queue) { + queue.push({ message: 'Hello world!' }) +} +``` + +The plugin creates the `Worker` instance, which populates `Worker.adapters` on `start()`. Services import `Worker` and access the static registry directly. On fastify close, `worker.shutdown()` drains all adapters. + +### Standalone + +Use the `Worker` class directly without Fastify: + +```typescript +import { Worker } from "@prefabs.tech/fastify-worker"; + +const worker = new Worker({ + cronJobs: [...], + queues: [...], +}); + +await worker.start(); + +// later... +await worker.shutdown(); +``` + ## Configuration Add worker configuration to your config: @@ -60,7 +91,7 @@ const config: ApiConfig = { worker: { cronJobs: [ { - expression: "0 0 * * *", // Run daily at midnight + expression: "0 0 * * *", task: async () => { console.log("Running daily cleanup..."); }, @@ -98,7 +129,7 @@ const config: ApiConfig = { endpoint: "", region: "", }, - handler: async (message: any) => { + handler: async (message) => { // }, queueUrl: "", @@ -108,27 +139,3 @@ const config: ApiConfig = { }, }; ``` - -## Adding Jobs to Queues - -To add jobs to a registered queue, use the `QueueProcessorRegistry` to access the queue client: - -```typescript -import { QueueProcessorRegistry } from "@prefabs.tech/fastify-worker"; - -// Get the processor for a specific queue -const processor = QueueProcessorRegistry.get("email-queue"); - -if (processor) { - // Add a job to the queue - await processor.getQueueClient().push({ - to: "user@example.com", - subject: "Welcome!", - body: "Hello from Fastify Worker", - }); - - console.log("Job added to email-queue"); -} else { - console.error("Queue not found"); -} -``` diff --git a/packages/worker/src/cron/index.ts b/packages/worker/src/cron/index.ts index 503f327dc..d11e20550 100644 --- a/packages/worker/src/cron/index.ts +++ b/packages/worker/src/cron/index.ts @@ -1 +1 @@ -export { default as setupCronJobs } from "./setup"; +export { default as CronScheduler } from "./scheduler"; diff --git a/packages/worker/src/cron/scheduler.ts b/packages/worker/src/cron/scheduler.ts new file mode 100644 index 000000000..9fd3d13ec --- /dev/null +++ b/packages/worker/src/cron/scheduler.ts @@ -0,0 +1,23 @@ +import cron, { ScheduledTask } from "node-cron"; + +import { CronJob } from "../types"; + +class CronScheduler { + private tasks: ScheduledTask[] = []; + + schedule(job: CronJob): void { + const task = cron.schedule(job.expression, job.task, job.options); + + this.tasks.push(task); + } + + stopAll(): void { + for (const task of this.tasks) { + task.stop(); + } + + this.tasks = []; + } +} + +export default CronScheduler; diff --git a/packages/worker/src/cron/setup.ts b/packages/worker/src/cron/setup.ts deleted file mode 100644 index e1199497f..000000000 --- a/packages/worker/src/cron/setup.ts +++ /dev/null @@ -1,15 +0,0 @@ -import cron from "node-cron"; - -import { CronJob } from "src/types"; - -const setupCronJobs = (cronJobs: CronJob[]) => { - if (cronJobs.length === 0) { - return; - } - - for (const job of cronJobs) { - cron.schedule(job.expression, job.task, job.options); - } -}; - -export default setupCronJobs; diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index d287ce467..eda4a09f4 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -12,8 +12,8 @@ export { SQSClient } from "@aws-sdk/client-sqs"; export { Job, Queue } from "bullmq"; export { default } from "./plugin"; +export { default as Worker } from "./worker"; export * from "./enum"; -export * from "./lib"; export * from "./queue"; export * from "./types"; diff --git a/packages/worker/src/lib/index.ts b/packages/worker/src/lib/index.ts deleted file mode 100644 index 048cfe5bb..000000000 --- a/packages/worker/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./initialize"; diff --git a/packages/worker/src/lib/initialize.ts b/packages/worker/src/lib/initialize.ts deleted file mode 100644 index 36ade4bd8..000000000 --- a/packages/worker/src/lib/initialize.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { setupCronJobs } from "../cron"; -import { setupQueueProcessors } from "../queue"; -import { CronJob, QueueConfig } from "../types"; - -const initializeCronJobs = async (cronConfigs?: CronJob[]) => { - if (!cronConfigs) return; - - setupCronJobs(cronConfigs); -}; - -const initializeQueueProcessors = async (queueConfigs?: QueueConfig[]) => { - if (!queueConfigs) return; - - setupQueueProcessors(queueConfigs); -}; - -export { initializeCronJobs, initializeQueueProcessors }; diff --git a/packages/worker/src/plugin.ts b/packages/worker/src/plugin.ts index 8e20d7333..b6cd2b059 100644 --- a/packages/worker/src/plugin.ts +++ b/packages/worker/src/plugin.ts @@ -1,10 +1,7 @@ import { FastifyInstance } from "fastify"; import FastifyPlugin from "fastify-plugin"; -import { - initializeCronJobs, - initializeQueueProcessors, -} from "./lib/initialize"; +import Worker from "./worker"; const plugin = async (fastify: FastifyInstance) => { const { config, log } = fastify; @@ -17,8 +14,16 @@ const plugin = async (fastify: FastifyInstance) => { log.info("Registering worker plugin"); - initializeCronJobs(config.worker.cronJobs); - initializeQueueProcessors(config.worker.queues); + const worker = new Worker(config.worker); + + await worker.start(); + + fastify.decorate("worker", worker); + + fastify.addHook("onClose", async () => { + log.info("Shutting down worker"); + await worker.shutdown(); + }); }; export default FastifyPlugin(plugin); diff --git a/packages/worker/src/queue/adapterRegistry.ts b/packages/worker/src/queue/adapterRegistry.ts new file mode 100644 index 000000000..5ab83412e --- /dev/null +++ b/packages/worker/src/queue/adapterRegistry.ts @@ -0,0 +1,35 @@ +import QueueAdapter from "./adapters/base"; + +class AdapterRegistry { + private adapters = new Map(); + + add(adapter: QueueAdapter): void { + this.adapters.set(adapter.queueName, adapter); + } + + get(name: string): QueueAdapter | undefined { + return this.adapters.get(name); + } + + getAll(): QueueAdapter[] { + return [...this.adapters.values()]; + } + + has(name: string): boolean { + return this.adapters.has(name); + } + + remove(name: string): void { + this.adapters.delete(name); + } + + async shutdownAll(): Promise { + for (const adapter of this.adapters.values()) { + await adapter.shutdown(); + } + + this.adapters.clear(); + } +} + +export default AdapterRegistry; diff --git a/packages/worker/src/queue/adapters/base.ts b/packages/worker/src/queue/adapters/base.ts new file mode 100644 index 000000000..845e7d9cd --- /dev/null +++ b/packages/worker/src/queue/adapters/base.ts @@ -0,0 +1,17 @@ +abstract class QueueAdapter { + public queueName: string; + + constructor(name: string) { + this.queueName = name; + } + + abstract start(): Promise; + abstract shutdown(): Promise; + abstract getClient(): unknown; + abstract push( + data: Payload, + options?: Record, + ): Promise; +} + +export default QueueAdapter; diff --git a/packages/worker/src/queue/adapters/bullmq.ts b/packages/worker/src/queue/adapters/bullmq.ts new file mode 100644 index 000000000..6dd3a3192 --- /dev/null +++ b/packages/worker/src/queue/adapters/bullmq.ts @@ -0,0 +1,83 @@ +import { + Queue as BullQueue, + Worker, + Job, + QueueOptions, + WorkerOptions, + JobsOptions, +} from "bullmq"; + +import QueueAdapter from "./base"; + +export interface BullMQAdapterConfig { + queueOptions: QueueOptions; + workerOptions?: WorkerOptions; + handler: (job: Job) => Promise; + onError?: (error: Error) => void; + onFailed?: (job: Job, error: Error) => void; +} + +class BullMQAdapter extends QueueAdapter { + public queue?: BullQueue; + public worker?: Worker; + private config: BullMQAdapterConfig; + private queueOptions: QueueOptions; + private workerOptions: WorkerOptions; + + constructor(name: string, config: BullMQAdapterConfig) { + super(name); + + this.config = config; + this.queueOptions = config.queueOptions; + this.workerOptions = { + connection: config.queueOptions.connection, + ...config.workerOptions, + }; + } + + async start(): Promise { + this.queue = new BullQueue(this.queueName, this.queueOptions); + this.worker = new Worker( + this.queueName, + async (job: Job) => { + await this.config.handler(job); + }, + this.workerOptions, + ); + + this.worker.on("error", (error) => { + if (this.config.onError) { + this.config.onError(error); + } + }); + + this.worker.on("failed", (job, error) => { + if (this.config.onFailed) { + this.config.onFailed(job as Job, error); + } + }); + } + + async shutdown(): Promise { + await this.worker?.close(); + await this.queue?.close(); + } + + getClient(): BullQueue { + return this.queue!; + } + + async push(data: Payload, options?: JobsOptions): Promise { + try { + const job = await this.queue!.add(this.queueName, data, options); + + return job.id!; + } catch (error) { + throw new Error( + `Failed to push job to BullMQ queue: ${this.queueName}. Error: ${(error as Error).message}`, + ); + } + } +} + +export default BullMQAdapter; diff --git a/packages/worker/src/queue/adapters/index.ts b/packages/worker/src/queue/adapters/index.ts new file mode 100644 index 000000000..266871156 --- /dev/null +++ b/packages/worker/src/queue/adapters/index.ts @@ -0,0 +1,6 @@ +export { default as QueueAdapter } from "./base"; +export { default as BullMQAdapter } from "./bullmq"; +export { default as SQSAdapter } from "./sqs"; + +export type { BullMQAdapterConfig } from "./bullmq"; +export type { SQSAdapterConfig } from "./sqs"; diff --git a/packages/worker/src/queue/adapters/sqs.ts b/packages/worker/src/queue/adapters/sqs.ts new file mode 100644 index 000000000..4a58a5e06 --- /dev/null +++ b/packages/worker/src/queue/adapters/sqs.ts @@ -0,0 +1,124 @@ +import { + DeleteMessageCommand, + Message, + ReceiveMessageCommand, + ReceiveMessageCommandInput, + SendMessageCommand, + SQSClient, + SQSClientConfig, +} from "@aws-sdk/client-sqs"; + +import QueueAdapter from "./base"; + +export interface SQSAdapterConfig { + clientConfig: SQSClientConfig; + handler: (data: unknown) => Promise; + onError?: (error: Error, message?: Message) => void; + queueUrl: string; + receiveMessageOptions?: ReceiveMessageCommandInput; +} + +class SQSAdapter extends QueueAdapter { + private config: SQSAdapterConfig; + public client?: SQSClient; + private queueUrl: string; + private isPolling: boolean = false; + + constructor(name: string, config: SQSAdapterConfig) { + super(name); + + this.config = config; + this.queueUrl = config.queueUrl; + } + + async start(): Promise { + this.client = new SQSClient(this.config.clientConfig); + this.startPolling(); + } + + async shutdown(): Promise { + this.isPolling = false; + this.client?.destroy(); + } + + getClient(): SQSClient { + return this.client!; + } + + private startPolling(): void { + if (this.isPolling) { + return; + } + + this.isPolling = true; + this.poll(); + } + + private async poll(): Promise { + while (this.isPolling) { + try { + const command = new ReceiveMessageCommand({ + QueueUrl: this.queueUrl, + ...this.config.receiveMessageOptions, + }); + + const response = await this.client!.send(command); + + if (response.Messages && response.Messages.length > 0) { + await Promise.all( + response.Messages.map(async (message: Message) => { + try { + const data = JSON.parse(message.Body ?? "{}") as Payload; + + await this.config.handler(data); + + await this.client!.send( + new DeleteMessageCommand({ + QueueUrl: this.queueUrl, + ReceiptHandle: message.ReceiptHandle, + }), + ); + } catch (error) { + if (this.config.onError) { + this.config.onError( + error instanceof Error ? error : new Error(String(error)), + message, + ); + } + } + }), + ); + } + } catch (error) { + if (this.config.onError) { + this.config.onError( + error instanceof Error ? error : new Error(String(error)), + ); + } + } + } + } + + async push( + data: Payload, + options?: Record, + ): Promise { + try { + const command = new SendMessageCommand({ + QueueUrl: this.queueUrl, + MessageBody: JSON.stringify(data), + ...options, + }); + + const response = await this.client!.send(command); + + return response.MessageId!; + } catch (error) { + throw new Error( + `Failed to push job to SQS queue: ${this.queueName}. Error: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } +} + +export default SQSAdapter; diff --git a/packages/worker/src/queue/clients/base.ts b/packages/worker/src/queue/clients/base.ts deleted file mode 100644 index aa725d966..000000000 --- a/packages/worker/src/queue/clients/base.ts +++ /dev/null @@ -1,21 +0,0 @@ -abstract class BaseQueueClient { - public queueName: string; - - constructor(name: string) { - this.queueName = name; - } - - abstract getClient(): Payload; - - abstract process( - handler: (data: Payload) => Promise, - concurrency?: number, - ): void; - - abstract push( - data: Payload, - options?: Record, - ): Promise; -} - -export default BaseQueueClient; diff --git a/packages/worker/src/queue/clients/bull.ts b/packages/worker/src/queue/clients/bull.ts deleted file mode 100644 index a62c4290d..000000000 --- a/packages/worker/src/queue/clients/bull.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { - Queue as BullQueue, - Worker, - Job, - QueueOptions, - WorkerOptions, - JobsOptions, -} from "bullmq"; - -import BaseQueueClient from "./base"; - -export interface BullMQClientConfig { - queueOptions: QueueOptions; - workerOptions?: WorkerOptions; - handler: (job: Job) => Promise; - onError?: (error: Error) => void; - onFailed?: (job: Job, error: Error) => void; -} - -class BullMqClient extends BaseQueueClient { - public queue: BullQueue; - public worker?: Worker; - private handler: (job: Job) => Promise; - private onError?: (error: Error) => void; - private onFailed?: (job: Job, error: Error) => void; - private queueOptions: QueueOptions; - private workerOptions?: WorkerOptions; - - constructor(name: string, config: BullMQClientConfig) { - super(name); - - this.queueOptions = config.queueOptions; - this.workerOptions = { - connection: config.queueOptions.connection, - ...config.workerOptions, - }; - this.handler = config.handler; - this.onError = config.onError; - this.onFailed = config.onFailed; - this.queue = new BullQueue(this.queueName, this.queueOptions); - this.process(); - } - - getClient(): BullQueue { - return this.queue; - } - - async push(data: Payload, options?: JobsOptions): Promise { - try { - const job = await this.queue.add(this.queueName, data, options); - - return job.id!; - } catch (error) { - throw new Error( - `Failed to push job to BullMQ queue: ${this.queueName}. Error: ${(error as Error).message}`, - ); - } - } - - process(): void { - try { - this.worker = new Worker( - this.queueName, - async (job: Job) => { - await this.handler(job); - }, - this.workerOptions, - ); - - this.worker.on("error", (error) => { - if (this.onError) { - this.onError(error); - } - }); - - this.worker.on("failed", (job, error) => { - if (this.onFailed) { - this.onFailed(job as Job, error); - } - }); - } catch (error) { - throw new Error( - `Failed to process jobs from BullMQ queue: ${this.queueName}. Error: ${(error as Error).message}`, - ); - } - } -} - -export default BullMqClient; diff --git a/packages/worker/src/queue/clients/index.ts b/packages/worker/src/queue/clients/index.ts deleted file mode 100644 index 7ccf0cd53..000000000 --- a/packages/worker/src/queue/clients/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as BaseQueueClient } from "./base"; -export { default as BullMQQueueClient } from "./bull"; -export { default as SQSQueueClient } from "./sqs"; diff --git a/packages/worker/src/queue/clients/sqs.ts b/packages/worker/src/queue/clients/sqs.ts deleted file mode 100644 index 6268f1cf3..000000000 --- a/packages/worker/src/queue/clients/sqs.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { - DeleteMessageCommand, - Message, - ReceiveMessageCommand, - ReceiveMessageCommandInput, - SendMessageCommand, - SQSClient, - SQSClientConfig, -} from "@aws-sdk/client-sqs"; - -import BaseQueueClient from "./base"; - -export interface SQSQueueClientConfig { - clientConfig: SQSClientConfig; - handler: (data: unknown) => Promise; - onError?: (error: Error, message?: Message) => void; - queueUrl: string; - receiveMessageOptions?: ReceiveMessageCommandInput; -} - -class SQSQueueClient extends BaseQueueClient { - private config: SQSQueueClientConfig; - public client: SQSClient; - private queueUrl: string; - private isPooling: boolean = false; - - constructor(name: string, config: SQSQueueClientConfig) { - super(name); - - this.config = config; - this.client = new SQSClient(config.clientConfig); - this.queueUrl = config.queueUrl; - - this.process(config.handler); - } - - getClient(): SQSClient { - return this.client; - } - - async process(handler: (data: Payload) => Promise): Promise { - if (this.isPooling) { - return; - } - - this.isPooling = true; - - const pool = async () => { - while (this.isPooling) { - try { - const command = new ReceiveMessageCommand({ - QueueUrl: this.queueUrl, - ...this.config.receiveMessageOptions, - }); - - const response = await this.client.send(command); - - if (response.Messages && response.Messages.length > 0) { - await Promise.all( - response.Messages.map(async (message: Message) => { - try { - const data = JSON.parse(message.Body ?? "{}") as Payload; - - await handler(data); - - await this.client.send( - new DeleteMessageCommand({ - QueueUrl: this.queueUrl, - ReceiptHandle: message.ReceiptHandle, - }), - ); - } catch (error) { - if (this.config.onError) { - this.config.onError( - error instanceof Error ? error : new Error(String(error)), - message, - ); - } - } - }), - ); - } - } catch (error) { - if (this.config.onError) { - this.config.onError( - error instanceof Error ? error : new Error(String(error)), - ); - } - } - } - }; - - pool(); - } - - async push( - data: Payload, - options?: Record, - ): Promise { - try { - const command = new SendMessageCommand({ - QueueUrl: this.queueUrl, - MessageBody: JSON.stringify(data), - ...options, - }); - - const response = await this.client.send(command); - - return response.MessageId!; - } catch (error) { - throw new Error( - `Failed to push job to SQS queue: ${this.queueName}. Error: ${error instanceof Error ? error.message : String(error)}`, - ); - } - } -} - -export default SQSQueueClient; diff --git a/packages/worker/src/queue/factory.ts b/packages/worker/src/queue/factory.ts new file mode 100644 index 000000000..517d017c0 --- /dev/null +++ b/packages/worker/src/queue/factory.ts @@ -0,0 +1,33 @@ +import { QueueProvider } from "../enum"; +import { QueueConfig } from "../types"; +import { QueueAdapter, BullMQAdapter, SQSAdapter } from "./adapters"; + +const createQueueAdapter = (config: QueueConfig): QueueAdapter => { + switch (config.provider) { + case QueueProvider.BULLMQ: { + if (!config.bullmqConfig) { + throw new Error( + `BullMQ configuration is required for queue: ${config.name}`, + ); + } + + return new BullMQAdapter(config.name, config.bullmqConfig); + } + + case QueueProvider.SQS: { + if (!config.sqsConfig) { + throw new Error( + `SQS configuration is required for queue: ${config.name}`, + ); + } + + return new SQSAdapter(config.name, config.sqsConfig); + } + + default: { + throw new Error(`Unsupported queue provider: ${config.provider}`); + } + } +}; + +export default createQueueAdapter; diff --git a/packages/worker/src/queue/index.ts b/packages/worker/src/queue/index.ts index 4b887b5e2..241050086 100644 --- a/packages/worker/src/queue/index.ts +++ b/packages/worker/src/queue/index.ts @@ -1,5 +1,4 @@ -export * from "./clients"; +export * from "./adapters"; -export { default as setupQueueProcessors } from "./setup"; -export { default as QueueProcessor } from "./processor"; -export { default as QueueProcessorRegistry } from "./registry"; +export { default as AdapterRegistry } from "./adapterRegistry"; +export { default as createQueueAdapter } from "./factory"; diff --git a/packages/worker/src/queue/processor.ts b/packages/worker/src/queue/processor.ts deleted file mode 100644 index 0da9efb16..000000000 --- a/packages/worker/src/queue/processor.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { QueueProvider } from "../enum"; -import { BaseQueueClient, BullMQQueueClient, SQSQueueClient } from "./clients"; -import { QueueConfig } from "../types/queue"; - -class QueueProcessor { - private queueClient: BaseQueueClient; - - constructor(config: QueueConfig) { - this.queueClient = this.initializeQueueClient(config); - } - - protected initializeQueueClient(config: QueueConfig) { - let queueClient: BaseQueueClient; - - switch (config.provider) { - case QueueProvider.BULLMQ: { - if (!config.bullmqConfig) { - throw new Error( - `BullMQ configuration is required for queue: ${config.name}`, - ); - } - - queueClient = new BullMQQueueClient(config.name, config.bullmqConfig); - - break; - } - - case QueueProvider.SQS: { - if (!config.sqsConfig) { - throw new Error( - `SQS configuration is required for queue: ${config.name}`, - ); - } - - queueClient = new SQSQueueClient(config.name, config.sqsConfig); - - break; - } - default: { - throw new Error(`Unsupported queue provider: ${config.provider}`); - } - } - - return queueClient; - } - - public getQueueClient() { - return this.queueClient; - } - - public getName() { - return this.queueClient.queueName; - } -} - -export default QueueProcessor; diff --git a/packages/worker/src/queue/registry.ts b/packages/worker/src/queue/registry.ts deleted file mode 100644 index acc150bf2..000000000 --- a/packages/worker/src/queue/registry.ts +++ /dev/null @@ -1,30 +0,0 @@ -import QueueProcessor from "./processor"; - -class QueueProcessorRegistry { - public static queueProcessors: Map = new Map(); - - public static add(queueProcessor: QueueProcessor) { - QueueProcessorRegistry.queueProcessors.set( - queueProcessor.getName(), - queueProcessor, - ); - } - - public static get(queueName: string): QueueProcessor | undefined { - return QueueProcessorRegistry.queueProcessors.get(queueName); - } - - public static getAll(): QueueProcessor[] { - return [...QueueProcessorRegistry.queueProcessors.values()]; - } - - public static has(queueName: string): boolean { - return QueueProcessorRegistry.queueProcessors.has(queueName); - } - - public static remove(queueName: string): void { - QueueProcessorRegistry.queueProcessors.delete(queueName); - } -} - -export default QueueProcessorRegistry; diff --git a/packages/worker/src/queue/setup.ts b/packages/worker/src/queue/setup.ts deleted file mode 100644 index ae7cdabb0..000000000 --- a/packages/worker/src/queue/setup.ts +++ /dev/null @@ -1,17 +0,0 @@ -import QueueProcessor from "./processor"; -import QueueProcessorRegistry from "./registry"; -import { QueueConfig } from "../types"; - -const setupQueueProcessors = (queueConfigs: QueueConfig[]) => { - if (queueConfigs.length === 0) { - return; - } - - for (const queueConfig of queueConfigs) { - const queueProcessor = new QueueProcessor(queueConfig); - - QueueProcessorRegistry.add(queueProcessor); - } -}; - -export default setupQueueProcessors; diff --git a/packages/worker/src/types/queue.ts b/packages/worker/src/types/queue.ts index 623bf27e8..fc3e1e0dd 100644 --- a/packages/worker/src/types/queue.ts +++ b/packages/worker/src/types/queue.ts @@ -1,10 +1,10 @@ import { QueueProvider } from "../enum"; -import { BullMQClientConfig } from "../queue/clients/bull"; -import { SQSQueueClientConfig } from "../queue/clients/sqs"; +import { BullMQAdapterConfig } from "../queue/adapters/bullmq"; +import { SQSAdapterConfig } from "../queue/adapters/sqs"; export interface QueueConfig { - bullmqConfig?: BullMQClientConfig; + bullmqConfig?: BullMQAdapterConfig; name: string; provider: QueueProvider; - sqsConfig?: SQSQueueClientConfig; + sqsConfig?: SQSAdapterConfig; } diff --git a/packages/worker/src/worker.ts b/packages/worker/src/worker.ts new file mode 100644 index 000000000..207a57edf --- /dev/null +++ b/packages/worker/src/worker.ts @@ -0,0 +1,38 @@ +import { CronScheduler } from "./cron"; +import { AdapterRegistry, createQueueAdapter } from "./queue"; +import { WorkerConfig } from "./types"; + +class Worker { + public static readonly adapters = new AdapterRegistry(); + public readonly cron: CronScheduler; + private config: WorkerConfig; + + constructor(config: WorkerConfig) { + this.config = config; + this.cron = new CronScheduler(); + } + + async start(): Promise { + if (this.config.cronJobs) { + for (const job of this.config.cronJobs) { + this.cron.schedule(job); + } + } + + if (this.config.queues) { + for (const queueConfig of this.config.queues) { + const adapter = createQueueAdapter(queueConfig); + + await adapter.start(); + Worker.adapters.add(adapter); + } + } + } + + async shutdown(): Promise { + this.cron.stopAll(); + await Worker.adapters.shutdownAll(); + } +} + +export default Worker; From 4c331cab998f035dd48311ce8e95be9f307a1ee4 Mon Sep 17 00:00:00 2001 From: sudeep Date: Mon, 23 Feb 2026 15:04:58 +0545 Subject: [PATCH 19/19] chore: rename workers to JobOrchestrator --- packages/worker/README.md | 16 ++++++++-------- packages/worker/src/index.ts | 2 +- .../worker/src/{worker.ts => jobOrchestrator.ts} | 8 ++++---- packages/worker/src/plugin.ts | 10 +++++----- 4 files changed, 18 insertions(+), 18 deletions(-) rename packages/worker/src/{worker.ts => jobOrchestrator.ts} (83%) diff --git a/packages/worker/README.md b/packages/worker/README.md index 618384998..6e5e6ffb6 100644 --- a/packages/worker/README.md +++ b/packages/worker/README.md @@ -49,33 +49,33 @@ await fastify.register(workerPlugin); ``` ```typescript -import { Worker } from "@prefabs.tech/fastify-worker"; +import { JobOrchestrator } from "@prefabs.tech/fastify-worker"; -const queue = Worker.adapters.get("queue-name") +const queue = JobOrchestrator.adapters.get("queue-name") if (queue) { queue.push({ message: 'Hello world!' }) } ``` -The plugin creates the `Worker` instance, which populates `Worker.adapters` on `start()`. Services import `Worker` and access the static registry directly. On fastify close, `worker.shutdown()` drains all adapters. +The plugin creates the `JobOrchestrator` instance, which populates `JobOrchestrator.adapters` on `start()`. Services import `JobOrchestrator` and access the static registry directly. On fastify close, `jobOrchestrator.shutdown()` drains all adapters. ### Standalone -Use the `Worker` class directly without Fastify: +Use the `JobOrchestrator` class directly without Fastify: ```typescript -import { Worker } from "@prefabs.tech/fastify-worker"; +import { JobOrchestrator } from "@prefabs.tech/fastify-worker"; -const worker = new Worker({ +const jobOrchestrator = new JobOrchestrator({ cronJobs: [...], queues: [...], }); -await worker.start(); +await jobOrchestrator.start(); // later... -await worker.shutdown(); +await jobOrchestrator.shutdown(); ``` ## Configuration diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index eda4a09f4..264c4af2f 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -12,7 +12,7 @@ export { SQSClient } from "@aws-sdk/client-sqs"; export { Job, Queue } from "bullmq"; export { default } from "./plugin"; -export { default as Worker } from "./worker"; +export { default as JobOrchestrator } from "./jobOrchestrator"; export * from "./enum"; export * from "./queue"; diff --git a/packages/worker/src/worker.ts b/packages/worker/src/jobOrchestrator.ts similarity index 83% rename from packages/worker/src/worker.ts rename to packages/worker/src/jobOrchestrator.ts index 207a57edf..cfd35aef9 100644 --- a/packages/worker/src/worker.ts +++ b/packages/worker/src/jobOrchestrator.ts @@ -2,7 +2,7 @@ import { CronScheduler } from "./cron"; import { AdapterRegistry, createQueueAdapter } from "./queue"; import { WorkerConfig } from "./types"; -class Worker { +class JobOrchestrator { public static readonly adapters = new AdapterRegistry(); public readonly cron: CronScheduler; private config: WorkerConfig; @@ -24,15 +24,15 @@ class Worker { const adapter = createQueueAdapter(queueConfig); await adapter.start(); - Worker.adapters.add(adapter); + JobOrchestrator.adapters.add(adapter); } } } async shutdown(): Promise { this.cron.stopAll(); - await Worker.adapters.shutdownAll(); + await JobOrchestrator.adapters.shutdownAll(); } } -export default Worker; +export default JobOrchestrator; diff --git a/packages/worker/src/plugin.ts b/packages/worker/src/plugin.ts index b6cd2b059..24e7c0307 100644 --- a/packages/worker/src/plugin.ts +++ b/packages/worker/src/plugin.ts @@ -1,7 +1,7 @@ import { FastifyInstance } from "fastify"; import FastifyPlugin from "fastify-plugin"; -import Worker from "./worker"; +import JobOrchestrator from "./jobOrchestrator"; const plugin = async (fastify: FastifyInstance) => { const { config, log } = fastify; @@ -14,15 +14,15 @@ const plugin = async (fastify: FastifyInstance) => { log.info("Registering worker plugin"); - const worker = new Worker(config.worker); + const jobOrchestrator = new JobOrchestrator(config.worker); - await worker.start(); + await jobOrchestrator.start(); - fastify.decorate("worker", worker); + fastify.decorate("worker", jobOrchestrator); fastify.addHook("onClose", async () => { log.info("Shutting down worker"); - await worker.shutdown(); + await jobOrchestrator.shutdown(); }); };