nuxt-processor 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -0
- package/dist/module.d.mts +12 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +244 -0
- package/dist/runtime/server/handlers/defineQueue.d.ts +9 -0
- package/dist/runtime/server/handlers/defineQueue.js +6 -0
- package/dist/runtime/server/handlers/defineWorker.d.ts +8 -0
- package/dist/runtime/server/handlers/defineWorker.js +7 -0
- package/dist/runtime/server/handlers/index.d.ts +2 -0
- package/dist/runtime/server/handlers/index.js +2 -0
- package/dist/runtime/server/utils/workers.d.ts +13 -0
- package/dist/runtime/server/utils/workers.js +44 -0
- package/dist/types.d.mts +3 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Nuxt Processor
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
[![License][license-src]][license-href]
|
|
6
|
+
[![Nuxt][nuxt-src]][nuxt-href]
|
|
7
|
+
|
|
8
|
+
Background job processing for Nuxt using BullMQ with a dedicated workers process.
|
|
9
|
+
|
|
10
|
+
- [✨ Release Notes](/CHANGELOG.md)
|
|
11
|
+
<!-- - [📖 Documentation](https://example.com) -->
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Dedicated processing**: Workers run in a separate Node process – no coupling to your web server.
|
|
16
|
+
- **Scalability**: Run multiple worker processes and instances across machines; backed by Redis.
|
|
17
|
+
- **Simple DX**: Define queues/workers in `server/queues` and `server/workers` using first-class helpers.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm i -D nuxt-processor
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Add the module in `nuxt.config.ts` and set your Redis connection.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// nuxt.config.ts
|
|
29
|
+
export default defineNuxtConfig({
|
|
30
|
+
modules: ['nuxt-processor'],
|
|
31
|
+
workers: {
|
|
32
|
+
redis: {
|
|
33
|
+
host: process.env.NUXT_REDIS_HOST ?? '127.0.0.1', // defaults '127.0.0.1'
|
|
34
|
+
port: Number(process.env.NUXT_REDIS_PORT ?? 6379), // defaults 6379
|
|
35
|
+
password: process.env.NUXT_REDIS_PASSWORD ?? '', // defaults ''
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Define a queue and enqueue from your app
|
|
42
|
+
|
|
43
|
+
Create `server/queues/index.ts`:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { defineQueue } from '#workers'
|
|
47
|
+
|
|
48
|
+
export default defineQueue({
|
|
49
|
+
name: 'hello',
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Define a worker
|
|
54
|
+
|
|
55
|
+
Create `server/workers/index.ts`:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { defineWorker } from '#workers'
|
|
59
|
+
import type { Job } from '#bullmq'
|
|
60
|
+
|
|
61
|
+
export default defineWorker({
|
|
62
|
+
name: 'hello',
|
|
63
|
+
async processor(job: Job) {
|
|
64
|
+
// do work
|
|
65
|
+
console.log('processed', job.name, job.data)
|
|
66
|
+
return job.data
|
|
67
|
+
},
|
|
68
|
+
options: {},
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Running
|
|
73
|
+
|
|
74
|
+
- Start your Nuxt app normally (dev or build). This module generates a dedicated workers entry.
|
|
75
|
+
- Start workers explicitly in a separate terminal:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# after a build
|
|
79
|
+
nuxi build
|
|
80
|
+
node .output/server/workers/index.mjs
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Shutdown
|
|
84
|
+
|
|
85
|
+
The workers process handles graceful shutdown on `SIGINT/SIGTERM` and logs worker start/stop.
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
## Contribution
|
|
89
|
+
|
|
90
|
+
<details>
|
|
91
|
+
<summary>Local development</summary>
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Install dependencies
|
|
95
|
+
npm install
|
|
96
|
+
|
|
97
|
+
# Generate type stubs
|
|
98
|
+
npm run dev:prepare
|
|
99
|
+
|
|
100
|
+
# Develop with the playground
|
|
101
|
+
npm run dev
|
|
102
|
+
|
|
103
|
+
# Build the playground
|
|
104
|
+
npm run dev:build
|
|
105
|
+
|
|
106
|
+
# Run ESLint
|
|
107
|
+
npm run lint
|
|
108
|
+
|
|
109
|
+
# Run Vitest
|
|
110
|
+
npm run test
|
|
111
|
+
npm run test:watch
|
|
112
|
+
|
|
113
|
+
# Release new version
|
|
114
|
+
npm run release
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
</details>
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
<!-- Badges -->
|
|
121
|
+
[npm-version-src]: https://img.shields.io/npm/v/my-module/latest.svg?style=flat&colorA=020420&colorB=00DC82
|
|
122
|
+
[npm-version-href]: https://npmjs.com/package/my-module
|
|
123
|
+
|
|
124
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/my-module.svg?style=flat&colorA=020420&colorB=00DC82
|
|
125
|
+
[npm-downloads-href]: https://npm.chart.dev/my-module
|
|
126
|
+
|
|
127
|
+
[license-src]: https://img.shields.io/npm/l/my-module.svg?style=flat&colorA=020420&colorB=00DC82
|
|
128
|
+
[license-href]: https://npmjs.com/package/my-module
|
|
129
|
+
|
|
130
|
+
[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
|
|
131
|
+
[nuxt-href]: https://nuxt.com
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { RedisOptions } from 'bullmq';
|
|
3
|
+
|
|
4
|
+
interface ModuleOptions {
|
|
5
|
+
redis: RedisOptions;
|
|
6
|
+
queues: string[];
|
|
7
|
+
workers: string[];
|
|
8
|
+
}
|
|
9
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
10
|
+
|
|
11
|
+
export { _default as default };
|
|
12
|
+
export type { ModuleOptions };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addTemplate, logger } from '@nuxt/kit';
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { relative } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const name = "nuxt-processor";
|
|
6
|
+
const version = "0.0.1";
|
|
7
|
+
const configKey = "processor";
|
|
8
|
+
const compatibility = {
|
|
9
|
+
nuxt: "^4.0.0"
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const module = defineNuxtModule({
|
|
13
|
+
meta: {
|
|
14
|
+
name,
|
|
15
|
+
version,
|
|
16
|
+
compatibility,
|
|
17
|
+
configKey
|
|
18
|
+
},
|
|
19
|
+
// Default configuration options of the Nuxt module
|
|
20
|
+
defaults: {
|
|
21
|
+
redis: {
|
|
22
|
+
host: process.env.NUXT_REDIS_HOST ?? "127.0.0.1",
|
|
23
|
+
port: Number(process.env.NUXT_REDIS_PORT ?? 6379),
|
|
24
|
+
password: process.env.NUXT_REDIS_PASSWORD ?? ""
|
|
25
|
+
},
|
|
26
|
+
queues: [],
|
|
27
|
+
workers: []
|
|
28
|
+
},
|
|
29
|
+
setup(_options, _nuxt) {
|
|
30
|
+
const { resolve } = createResolver(import.meta.url);
|
|
31
|
+
const buildDir = _nuxt.options.buildDir;
|
|
32
|
+
const srcDir = _nuxt.options.srcDir;
|
|
33
|
+
const allowedExtensions = /* @__PURE__ */ new Set([".ts", ".js", ".mjs", ".mts", ".cjs", ".cts"]);
|
|
34
|
+
async function collectFiles(fromDir) {
|
|
35
|
+
const results = [];
|
|
36
|
+
async function walk(dir) {
|
|
37
|
+
let entries = [];
|
|
38
|
+
try {
|
|
39
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
40
|
+
} catch (err) {
|
|
41
|
+
logger.withTag("nuxt-processor").warn("failed to read directory", dir, err);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
await Promise.all(entries.map(async (entry) => {
|
|
45
|
+
const fullPath = resolve(dir, entry.name);
|
|
46
|
+
if (entry.isDirectory()) {
|
|
47
|
+
await walk(fullPath);
|
|
48
|
+
} else {
|
|
49
|
+
const dotIndex = fullPath.lastIndexOf(".");
|
|
50
|
+
const ext = dotIndex >= 0 ? fullPath.slice(dotIndex) : "";
|
|
51
|
+
if (allowedExtensions.has(ext)) {
|
|
52
|
+
results.push(fullPath);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
await walk(fromDir);
|
|
58
|
+
return results;
|
|
59
|
+
}
|
|
60
|
+
function generateWorkersEntryContent(workerFiles) {
|
|
61
|
+
const redisInline = JSON.stringify(_options.redis ?? {});
|
|
62
|
+
const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
|
|
63
|
+
return `
|
|
64
|
+
import { fileURLToPath } from 'node:url'
|
|
65
|
+
import { resolve as resolvePath } from 'node:path'
|
|
66
|
+
import { consola } from 'consola'
|
|
67
|
+
import { $workers } from '#workers-utils'
|
|
68
|
+
|
|
69
|
+
// Initialize connection as early as possible so any imports that register
|
|
70
|
+
// workers/queues have a valid connection available.
|
|
71
|
+
const api = $workers()
|
|
72
|
+
api.setConnection(${redisInline})
|
|
73
|
+
|
|
74
|
+
export async function createWorkersApp() {
|
|
75
|
+
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
|
|
76
|
+
const handleStreamError = (err) => {
|
|
77
|
+
try {
|
|
78
|
+
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
|
|
79
|
+
if (code === 'EPIPE') return
|
|
80
|
+
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
|
|
81
|
+
throw err
|
|
82
|
+
}
|
|
83
|
+
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
|
|
84
|
+
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
|
|
85
|
+
const modules = [
|
|
86
|
+
${toImportArray}
|
|
87
|
+
]
|
|
88
|
+
for (const loader of modules) {
|
|
89
|
+
await loader()
|
|
90
|
+
}
|
|
91
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
92
|
+
try {
|
|
93
|
+
const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
|
|
94
|
+
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
|
|
95
|
+
for (const w of api.workers) {
|
|
96
|
+
w.on('error', (err) => logger.error('worker error', err))
|
|
97
|
+
}
|
|
98
|
+
// Explicitly start workers since autorun is disabled
|
|
99
|
+
for (const w of api.workers) {
|
|
100
|
+
try {
|
|
101
|
+
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
|
|
102
|
+
// eslint-disable-next-line promise/catch-or-return
|
|
103
|
+
w.run().catch((err) => logger.error('worker run error', err))
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
logger.error('failed to start worker', err)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
logger.success('workers started')
|
|
110
|
+
} catch (err) {
|
|
111
|
+
logger.error('failed to initialize workers', err)
|
|
112
|
+
}
|
|
113
|
+
return { stop: api.stopAll, workers: api.workers }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const isMain = (() => {
|
|
117
|
+
try {
|
|
118
|
+
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
|
|
119
|
+
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
|
|
120
|
+
const filePath = fileURLToPath(import.meta.url)
|
|
121
|
+
return filePath === argvPath
|
|
122
|
+
} catch {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
})()
|
|
126
|
+
if (isMain) {
|
|
127
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
128
|
+
const appPromise = createWorkersApp().catch((err) => {
|
|
129
|
+
logger.error('failed to start workers', err)
|
|
130
|
+
process.exit(1)
|
|
131
|
+
})
|
|
132
|
+
const shutdown = async () => {
|
|
133
|
+
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
|
|
134
|
+
try {
|
|
135
|
+
const app = await appPromise
|
|
136
|
+
try {
|
|
137
|
+
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
|
|
138
|
+
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
|
|
139
|
+
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
|
|
140
|
+
await app.stop()
|
|
141
|
+
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
|
|
142
|
+
}
|
|
143
|
+
finally { process.exit(0) }
|
|
144
|
+
}
|
|
145
|
+
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
|
|
146
|
+
process.on('beforeExit', shutdown)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export default { createWorkersApp }
|
|
150
|
+
`;
|
|
151
|
+
}
|
|
152
|
+
const { resolve: r } = createResolver(import.meta.url);
|
|
153
|
+
_nuxt.options.alias = _nuxt.options.alias || {};
|
|
154
|
+
_nuxt.options.alias["nuxt-processor"] = r("./runtime/server/handlers");
|
|
155
|
+
_nuxt.options.alias["#workers"] = r("./runtime/server/handlers");
|
|
156
|
+
_nuxt.options.alias["#workers-utils"] = r("./runtime/server/utils/workers");
|
|
157
|
+
if (!_nuxt.options.alias["#bullmq"]) {
|
|
158
|
+
_nuxt.options.alias["#bullmq"] = "bullmq";
|
|
159
|
+
}
|
|
160
|
+
const typesDtsPath = addTemplate({
|
|
161
|
+
filename: "types/nuxt-processor.d.ts",
|
|
162
|
+
write: true,
|
|
163
|
+
getContents: () => `
|
|
164
|
+
declare module 'nuxt-processor' {
|
|
165
|
+
export { defineQueue } from '${r("./runtime/server/handlers/defineQueue")}'
|
|
166
|
+
export { defineWorker } from '${r("./runtime/server/handlers/defineWorker")}'
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
declare module '#workers' {
|
|
170
|
+
export { defineQueue } from '${r("./runtime/server/handlers/defineQueue")}'
|
|
171
|
+
export { defineWorker } from '${r("./runtime/server/handlers/defineWorker")}'
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
declare module '#workers-utils' {
|
|
175
|
+
export { $workers } from '${r("./runtime/server/utils/workers")}'
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
declare module '#bullmq' {
|
|
179
|
+
export * from 'bullmq'
|
|
180
|
+
}
|
|
181
|
+
`
|
|
182
|
+
}).dst;
|
|
183
|
+
_nuxt.hooks.hook("prepare:types", (opts) => {
|
|
184
|
+
if (!opts.tsConfig.include) opts.tsConfig.include = [];
|
|
185
|
+
opts.tsConfig.include.push(resolve(buildDir, typesDtsPath));
|
|
186
|
+
});
|
|
187
|
+
function createWorkersRollupPlugin() {
|
|
188
|
+
const VIRTUAL_ID = "\0nuxt-processor-entry";
|
|
189
|
+
let virtualCode = "";
|
|
190
|
+
let entryRefId = null;
|
|
191
|
+
return {
|
|
192
|
+
name: "nuxt-processor-emit",
|
|
193
|
+
async buildStart() {
|
|
194
|
+
const workerFiles = await collectFiles(resolve(srcDir, "server/workers"));
|
|
195
|
+
if (workerFiles.length === 0) {
|
|
196
|
+
virtualCode = "";
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
virtualCode = generateWorkersEntryContent(workerFiles);
|
|
200
|
+
for (const id of workerFiles) {
|
|
201
|
+
this.addWatchFile(id);
|
|
202
|
+
}
|
|
203
|
+
entryRefId = this.emitFile({ type: "chunk", id: VIRTUAL_ID, fileName: "workers/_entry.mjs" });
|
|
204
|
+
},
|
|
205
|
+
resolveId(id) {
|
|
206
|
+
if (id === VIRTUAL_ID) return VIRTUAL_ID;
|
|
207
|
+
},
|
|
208
|
+
load(id) {
|
|
209
|
+
if (id === VIRTUAL_ID) return virtualCode || "export {}\n";
|
|
210
|
+
},
|
|
211
|
+
generateBundle() {
|
|
212
|
+
if (!virtualCode || !entryRefId) return;
|
|
213
|
+
const entryFile = this.getFileName(entryRefId);
|
|
214
|
+
const fromDir = "workers";
|
|
215
|
+
const rel = "./" + relative(fromDir, entryFile).split("\\").join("/");
|
|
216
|
+
const wrapper = `import { createWorkersApp } from '${rel}'
|
|
217
|
+
import { consola } from 'consola'
|
|
218
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
219
|
+
const appPromise = createWorkersApp().catch((err) => { logger.error('failed to start workers', err); process.exit(1) })
|
|
220
|
+
let shuttingDown = false
|
|
221
|
+
const shutdown = async (signal) => { if (shuttingDown) return; shuttingDown = true; try { logger.info('closing workers' + (signal ? ' ('+signal+')' : '') + '...') } catch (e) { console.warn('nuxt-processor: failed to log shutdown start', e) } ; try { const app = await appPromise; try { const names = (app?.workers || []).map(w => w && w.name).filter(Boolean); logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n')) } catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) } await app.stop(); try { logger.success('workers closed') } catch (e2) { console.warn('nuxt-processor: failed to log shutdown complete', e2) } } catch (err) { try { logger.error('shutdown error', err) } catch (e3) { console.warn('nuxt-processor: failed to log shutdown error', e3) } } finally { setTimeout(() => process.exit(0), 0) } }
|
|
222
|
+
[ 'SIGINT','SIGTERM','SIGQUIT' ].forEach(sig => process.on(sig, () => shutdown(sig)))
|
|
223
|
+
process.on('beforeExit', () => shutdown('beforeExit'))
|
|
224
|
+
`;
|
|
225
|
+
this.emitFile({ type: "asset", fileName: "workers/index.mjs", source: wrapper });
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
_nuxt.hooks.hook("nitro:config", (nitroConfig) => {
|
|
230
|
+
nitroConfig.rollupConfig = nitroConfig.rollupConfig ?? {};
|
|
231
|
+
const plugin = createWorkersRollupPlugin();
|
|
232
|
+
const current = nitroConfig.rollupConfig.plugins;
|
|
233
|
+
if (Array.isArray(current)) {
|
|
234
|
+
nitroConfig.rollupConfig.plugins = [...current, plugin];
|
|
235
|
+
} else if (current) {
|
|
236
|
+
nitroConfig.rollupConfig.plugins = [current, plugin];
|
|
237
|
+
} else {
|
|
238
|
+
nitroConfig.rollupConfig.plugins = [plugin];
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
export { module as default };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Queue, QueueOptions, JobsOptions } from '../utils/workers.js';
|
|
2
|
+
type DefineQueueArgs = {
|
|
3
|
+
name: Queue['name'];
|
|
4
|
+
options?: Omit<QueueOptions, 'connection'> & {
|
|
5
|
+
defaultJobOptions?: JobsOptions;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
export declare function defineQueue({ name, options }: DefineQueueArgs): Queue;
|
|
9
|
+
export default defineQueue;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Worker, WorkerOptions, Processor } from 'bullmq';
|
|
2
|
+
type DefineWorkerArgs = {
|
|
3
|
+
name: Worker['name'];
|
|
4
|
+
processor: Processor;
|
|
5
|
+
options?: Omit<WorkerOptions, 'connection'>;
|
|
6
|
+
};
|
|
7
|
+
export declare function defineWorker(args: DefineWorkerArgs): Worker;
|
|
8
|
+
export default defineWorker;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Job, JobsOptions, QueueOptions, WorkerOptions, Processor } from 'bullmq';
|
|
2
|
+
import { Queue, Worker } from 'bullmq';
|
|
3
|
+
export declare function $workers(): {
|
|
4
|
+
setConnection: (connection: QueueOptions["connection"]) => void;
|
|
5
|
+
createQueue: (name: string, options?: Omit<QueueOptions, "connection"> & {
|
|
6
|
+
defaultJobOptions?: JobsOptions;
|
|
7
|
+
}) => Queue<any, any, string, any, any, string>;
|
|
8
|
+
createWorker: (name: string, processor: Processor, options?: Omit<WorkerOptions, "connection">) => Worker<any, any, string>;
|
|
9
|
+
stopAll: () => Promise<void>;
|
|
10
|
+
readonly queues: Queue<any, any, string, any, any, string>[];
|
|
11
|
+
readonly workers: Worker<any, any, string>[];
|
|
12
|
+
};
|
|
13
|
+
export type { Queue, Worker, Processor, QueueOptions, WorkerOptions, JobsOptions, Job };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Queue, Worker } from "bullmq";
|
|
2
|
+
const registry = {
|
|
3
|
+
connection: void 0,
|
|
4
|
+
queues: [],
|
|
5
|
+
workers: []
|
|
6
|
+
};
|
|
7
|
+
export function $workers() {
|
|
8
|
+
function setConnection(connection) {
|
|
9
|
+
registry.connection = connection;
|
|
10
|
+
}
|
|
11
|
+
function createQueue(name, options) {
|
|
12
|
+
const queue = new Queue(name, {
|
|
13
|
+
connection: registry.connection,
|
|
14
|
+
...options
|
|
15
|
+
});
|
|
16
|
+
registry.queues.push(queue);
|
|
17
|
+
return queue;
|
|
18
|
+
}
|
|
19
|
+
function createWorker(name, processor, options) {
|
|
20
|
+
const worker = new Worker(name, processor, {
|
|
21
|
+
connection: registry.connection,
|
|
22
|
+
...options,
|
|
23
|
+
autorun: false
|
|
24
|
+
});
|
|
25
|
+
registry.workers.push(worker);
|
|
26
|
+
return worker;
|
|
27
|
+
}
|
|
28
|
+
async function stopAll() {
|
|
29
|
+
await Promise.allSettled(registry.workers.map((w) => w.close()));
|
|
30
|
+
await Promise.allSettled(registry.queues.map((q) => q.close()));
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
setConnection,
|
|
34
|
+
createQueue,
|
|
35
|
+
createWorker,
|
|
36
|
+
stopAll,
|
|
37
|
+
get queues() {
|
|
38
|
+
return registry.queues;
|
|
39
|
+
},
|
|
40
|
+
get workers() {
|
|
41
|
+
return registry.workers;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
package/dist/types.d.mts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nuxt-processor",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Nuxt Processor",
|
|
5
|
+
"repository": "https://github.com/aidanhibbard/nuxt-processor",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"configKey": "processor",
|
|
9
|
+
"compatibility": {
|
|
10
|
+
"nuxt": "^4.0.0"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/types.d.mts",
|
|
15
|
+
"import": "./dist/module.mjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"main": "./dist/module.mjs",
|
|
19
|
+
"typesVersions": {
|
|
20
|
+
"*": {
|
|
21
|
+
".": [
|
|
22
|
+
"./dist/types.d.mts"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"prepack": "nuxt-module-build build",
|
|
31
|
+
"dev": "npm run dev:prepare && nuxi dev playground",
|
|
32
|
+
"dev:build": "nuxi build playground",
|
|
33
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
34
|
+
"release": "npm run lint && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
35
|
+
"lint": "eslint .",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest watch",
|
|
38
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
39
|
+
"vp:dev": "vitepress dev docs",
|
|
40
|
+
"vp:build": "vitepress build docs",
|
|
41
|
+
"vp:preview": "vitepress preview docs"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@nuxt/kit": "^4.0.3",
|
|
45
|
+
"bullmq": "^5.58.2",
|
|
46
|
+
"ioredis": "^5.7.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@nuxt/devtools": "^2.6.3",
|
|
50
|
+
"@nuxt/eslint": "^1.9.0",
|
|
51
|
+
"@nuxt/eslint-config": "^1.9.0",
|
|
52
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
53
|
+
"@nuxt/schema": "^4.0.3",
|
|
54
|
+
"@nuxt/test-utils": "^3.19.2",
|
|
55
|
+
"@types/node": "latest",
|
|
56
|
+
"changelogen": "^0.6.2",
|
|
57
|
+
"eslint": "^9.34.0",
|
|
58
|
+
"nuxt": "^4.0.3",
|
|
59
|
+
"typescript": "~5.9.2",
|
|
60
|
+
"vitepress": "^2.0.0-alpha.12",
|
|
61
|
+
"vitest": "^3.2.4",
|
|
62
|
+
"vue-tsc": "^3.0.6"
|
|
63
|
+
}
|
|
64
|
+
}
|