nuxt-processor 0.0.3 → 0.0.4
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 +29 -1
- package/bin/nuxt-processor.mjs +6 -0
- package/dist/cli.cjs +152 -0
- package/dist/cli.d.cts +5 -0
- package/dist/cli.d.mts +5 -0
- package/dist/cli.mjs +150 -0
- package/dist/module.cjs +229 -0
- package/dist/module.d.cts +16 -0
- package/dist/module.json +2 -2
- package/dist/module.mjs +1 -7
- package/dist/shared/nuxt-processor.BDPWtq8T.mjs +9 -0
- package/dist/shared/nuxt-processor.BqsFQtIQ.cjs +15 -0
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Background job processing for Nuxt using BullMQ with a dedicated workers process
|
|
|
12
12
|
Note: This package is under very active development! Please consider creating issues if you run into anything!
|
|
13
13
|
|
|
14
14
|
- [✨ Release Notes](/CHANGELOG.md)
|
|
15
|
-
|
|
15
|
+
- [📖 Documentation](https://aidanhibbard.github.io/nuxt-processor/)
|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
@@ -26,6 +26,7 @@ Note: This package is under very active development! Please consider creating is
|
|
|
26
26
|
- [Define a queue and enqueue from your app](#define-a-queue-and-enqueue-from-your-app)
|
|
27
27
|
- [Define a worker](#define-a-worker)
|
|
28
28
|
- [Running](#running)
|
|
29
|
+
- [CLI](#cli)
|
|
29
30
|
- [Bull Board](#bull-board)
|
|
30
31
|
- [Contribution](#contribution)
|
|
31
32
|
|
|
@@ -92,6 +93,33 @@ nuxi dev
|
|
|
92
93
|
node .nuxt/dev/workers/index.mjs
|
|
93
94
|
```
|
|
94
95
|
|
|
96
|
+
### CLI
|
|
97
|
+
|
|
98
|
+
A simple CLI is provided to run workers in development.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# from your project root
|
|
102
|
+
npx nuxt-processor dev
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Notes:
|
|
106
|
+
- If `.nuxt/dev/workers/index.mjs` does not exist yet, the CLI will ask you to start your Nuxt dev server first to generate the entry point for your workers.
|
|
107
|
+
- If your `package.json` does not have a `processor:dev` script, the CLI will offer to add:
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"scripts": {
|
|
112
|
+
"processor:dev": "nuxt-processor dev"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Then you can run:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm run processor:dev
|
|
121
|
+
```
|
|
122
|
+
|
|
95
123
|
- After building for production, run workers from `.output/server/workers/index.mjs`:
|
|
96
124
|
|
|
97
125
|
```bash
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const node_child_process = require('node:child_process');
|
|
4
|
+
const node_fs = require('node:fs');
|
|
5
|
+
const promises = require('node:readline/promises');
|
|
6
|
+
const node_process = require('node:process');
|
|
7
|
+
const pathe = require('pathe');
|
|
8
|
+
const consola = require('consola');
|
|
9
|
+
const citty = require('citty');
|
|
10
|
+
const kit = require('@nuxt/kit');
|
|
11
|
+
const _package = require('./shared/nuxt-processor.BqsFQtIQ.cjs');
|
|
12
|
+
|
|
13
|
+
const ensureNuxtProject = async (args) => {
|
|
14
|
+
const dir = pathe.resolve(args.dir);
|
|
15
|
+
const nuxtConfig = await kit.loadNuxtConfig({ cwd: dir });
|
|
16
|
+
if (!nuxtConfig || !nuxtConfig._layers[0]?.configFile) {
|
|
17
|
+
consola.consola.error("You are not in a Nuxt project.");
|
|
18
|
+
process.exit();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const main = citty.createMain({
|
|
23
|
+
meta: {
|
|
24
|
+
name: _package.name,
|
|
25
|
+
description: _package.description,
|
|
26
|
+
version: _package.version
|
|
27
|
+
},
|
|
28
|
+
subCommands: {
|
|
29
|
+
dev: citty.defineCommand({
|
|
30
|
+
meta: {
|
|
31
|
+
name: "dev",
|
|
32
|
+
description: "Run workers with HMR from .nuxt/dev/workers/index.mjs"
|
|
33
|
+
},
|
|
34
|
+
args: {
|
|
35
|
+
dir: {
|
|
36
|
+
type: "positional",
|
|
37
|
+
default: "."
|
|
38
|
+
},
|
|
39
|
+
nodeArgs: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "Extra Node args (e.g. --inspect)"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
async run({ args }) {
|
|
45
|
+
const dirArg = typeof args.dir === "string" ? args.dir : ".";
|
|
46
|
+
await ensureNuxtProject({ dir: dirArg });
|
|
47
|
+
const projectRoot = pathe.resolve(dirArg);
|
|
48
|
+
const indexFile = pathe.resolve(projectRoot, ".nuxt/dev/workers/index.mjs");
|
|
49
|
+
const watchDir = pathe.resolve(projectRoot, ".nuxt/dev/workers");
|
|
50
|
+
if (node_fs.existsSync(indexFile)) {
|
|
51
|
+
const pkgPath = pathe.resolve(projectRoot, "package.json");
|
|
52
|
+
if (node_fs.existsSync(pkgPath)) {
|
|
53
|
+
try {
|
|
54
|
+
const pkgRaw = JSON.parse(node_fs.readFileSync(pkgPath, "utf8"));
|
|
55
|
+
const pkg = pkgRaw;
|
|
56
|
+
const hasProcessorDev = Boolean(pkg && pkg.scripts && pkg.scripts["processor:dev"]);
|
|
57
|
+
if (!hasProcessorDev) {
|
|
58
|
+
consola.consola.warn('No "processor:dev" script found in package.json.');
|
|
59
|
+
const rl = promises.createInterface({ input: node_process.stdin, output: node_process.stdout });
|
|
60
|
+
const answer = await rl.question("Add script to package.json? (y/N) ");
|
|
61
|
+
rl.close();
|
|
62
|
+
const isYes = typeof answer === "string" && /^y(?:es)?$/i.test(answer.trim());
|
|
63
|
+
if (isYes) {
|
|
64
|
+
const updated = {
|
|
65
|
+
...pkg,
|
|
66
|
+
scripts: {
|
|
67
|
+
...pkg.scripts || {},
|
|
68
|
+
"processor:dev": "nuxt-processor dev"
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
node_fs.writeFileSync(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
73
|
+
consola.consola.success('Added "processor:dev" script to package.json');
|
|
74
|
+
} catch {
|
|
75
|
+
consola.consola.error("Failed to write to package.json");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!node_fs.existsSync(indexFile)) {
|
|
84
|
+
const pkgPath = pathe.resolve(projectRoot, "package.json");
|
|
85
|
+
let hasProcessorDev = false;
|
|
86
|
+
if (node_fs.existsSync(pkgPath)) {
|
|
87
|
+
try {
|
|
88
|
+
const pkgRaw = JSON.parse(node_fs.readFileSync(pkgPath, "utf8"));
|
|
89
|
+
const pkg = pkgRaw;
|
|
90
|
+
hasProcessorDev = Boolean(pkg && pkg.scripts && pkg.scripts["processor:dev"]);
|
|
91
|
+
if (!hasProcessorDev) {
|
|
92
|
+
consola.consola.warn('No "processor:dev" script found in package.json.');
|
|
93
|
+
const rl = promises.createInterface({ input: node_process.stdin, output: node_process.stdout });
|
|
94
|
+
const answer = await rl.question("Add script to package.json? (y/N) ");
|
|
95
|
+
rl.close();
|
|
96
|
+
const isYes = typeof answer === "string" && /^y(?:es)?$/i.test(answer.trim());
|
|
97
|
+
if (isYes) {
|
|
98
|
+
const updated = {
|
|
99
|
+
...pkg,
|
|
100
|
+
scripts: {
|
|
101
|
+
...pkg.scripts || {},
|
|
102
|
+
"processor:dev": "nuxt-processor dev"
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
try {
|
|
106
|
+
node_fs.writeFileSync(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
107
|
+
consola.consola.success('Added "processor:dev" script to package.json');
|
|
108
|
+
} catch {
|
|
109
|
+
consola.consola.error("Failed to write to package.json");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
consola.consola.error("No entry file found at .nuxt/dev/workers/index.mjs");
|
|
117
|
+
consola.consola.info("Please start your Nuxt dev server (e.g. `npm run dev`).");
|
|
118
|
+
consola.consola.info("After it starts, run `npx nuxt-processor dev` again to start the processor.");
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
const nodeBin = process.execPath;
|
|
122
|
+
const nodeArgsInput = Array.isArray(args.nodeArgs) ? args.nodeArgs : typeof args.nodeArgs === "string" ? args.nodeArgs.split(" ") : [];
|
|
123
|
+
const extraArgs = nodeArgsInput.filter(Boolean);
|
|
124
|
+
const nodeArgs = [
|
|
125
|
+
...extraArgs,
|
|
126
|
+
"--watch",
|
|
127
|
+
"--watch-path",
|
|
128
|
+
watchDir,
|
|
129
|
+
indexFile
|
|
130
|
+
];
|
|
131
|
+
consola.consola.info(`Running watcher for processor`);
|
|
132
|
+
const child = node_child_process.spawn(nodeBin, nodeArgs, {
|
|
133
|
+
stdio: "inherit",
|
|
134
|
+
cwd: projectRoot,
|
|
135
|
+
env: process.env
|
|
136
|
+
});
|
|
137
|
+
const onSignal = (signal) => {
|
|
138
|
+
if (!child.killed) {
|
|
139
|
+
child.kill(signal);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
process.on("SIGINT", onSignal);
|
|
143
|
+
process.on("SIGTERM", onSignal);
|
|
144
|
+
child.on("exit", (code) => {
|
|
145
|
+
process.exit(code ?? 0);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
exports.main = main;
|
package/dist/cli.d.cts
ADDED
package/dist/cli.d.mts
ADDED
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { createInterface } from 'node:readline/promises';
|
|
4
|
+
import { stdout, stdin } from 'node:process';
|
|
5
|
+
import { resolve } from 'pathe';
|
|
6
|
+
import { consola } from 'consola';
|
|
7
|
+
import { createMain, defineCommand } from 'citty';
|
|
8
|
+
import { loadNuxtConfig } from '@nuxt/kit';
|
|
9
|
+
import { v as version, d as description, n as name } from './shared/nuxt-processor.BDPWtq8T.mjs';
|
|
10
|
+
|
|
11
|
+
const ensureNuxtProject = async (args) => {
|
|
12
|
+
const dir = resolve(args.dir);
|
|
13
|
+
const nuxtConfig = await loadNuxtConfig({ cwd: dir });
|
|
14
|
+
if (!nuxtConfig || !nuxtConfig._layers[0]?.configFile) {
|
|
15
|
+
consola.error("You are not in a Nuxt project.");
|
|
16
|
+
process.exit();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const main = createMain({
|
|
21
|
+
meta: {
|
|
22
|
+
name,
|
|
23
|
+
description,
|
|
24
|
+
version
|
|
25
|
+
},
|
|
26
|
+
subCommands: {
|
|
27
|
+
dev: defineCommand({
|
|
28
|
+
meta: {
|
|
29
|
+
name: "dev",
|
|
30
|
+
description: "Run workers with HMR from .nuxt/dev/workers/index.mjs"
|
|
31
|
+
},
|
|
32
|
+
args: {
|
|
33
|
+
dir: {
|
|
34
|
+
type: "positional",
|
|
35
|
+
default: "."
|
|
36
|
+
},
|
|
37
|
+
nodeArgs: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "Extra Node args (e.g. --inspect)"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
async run({ args }) {
|
|
43
|
+
const dirArg = typeof args.dir === "string" ? args.dir : ".";
|
|
44
|
+
await ensureNuxtProject({ dir: dirArg });
|
|
45
|
+
const projectRoot = resolve(dirArg);
|
|
46
|
+
const indexFile = resolve(projectRoot, ".nuxt/dev/workers/index.mjs");
|
|
47
|
+
const watchDir = resolve(projectRoot, ".nuxt/dev/workers");
|
|
48
|
+
if (existsSync(indexFile)) {
|
|
49
|
+
const pkgPath = resolve(projectRoot, "package.json");
|
|
50
|
+
if (existsSync(pkgPath)) {
|
|
51
|
+
try {
|
|
52
|
+
const pkgRaw = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
53
|
+
const pkg = pkgRaw;
|
|
54
|
+
const hasProcessorDev = Boolean(pkg && pkg.scripts && pkg.scripts["processor:dev"]);
|
|
55
|
+
if (!hasProcessorDev) {
|
|
56
|
+
consola.warn('No "processor:dev" script found in package.json.');
|
|
57
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
58
|
+
const answer = await rl.question("Add script to package.json? (y/N) ");
|
|
59
|
+
rl.close();
|
|
60
|
+
const isYes = typeof answer === "string" && /^y(?:es)?$/i.test(answer.trim());
|
|
61
|
+
if (isYes) {
|
|
62
|
+
const updated = {
|
|
63
|
+
...pkg,
|
|
64
|
+
scripts: {
|
|
65
|
+
...pkg.scripts || {},
|
|
66
|
+
"processor:dev": "nuxt-processor dev"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
try {
|
|
70
|
+
writeFileSync(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
71
|
+
consola.success('Added "processor:dev" script to package.json');
|
|
72
|
+
} catch {
|
|
73
|
+
consola.error("Failed to write to package.json");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!existsSync(indexFile)) {
|
|
82
|
+
const pkgPath = resolve(projectRoot, "package.json");
|
|
83
|
+
let hasProcessorDev = false;
|
|
84
|
+
if (existsSync(pkgPath)) {
|
|
85
|
+
try {
|
|
86
|
+
const pkgRaw = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
87
|
+
const pkg = pkgRaw;
|
|
88
|
+
hasProcessorDev = Boolean(pkg && pkg.scripts && pkg.scripts["processor:dev"]);
|
|
89
|
+
if (!hasProcessorDev) {
|
|
90
|
+
consola.warn('No "processor:dev" script found in package.json.');
|
|
91
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
92
|
+
const answer = await rl.question("Add script to package.json? (y/N) ");
|
|
93
|
+
rl.close();
|
|
94
|
+
const isYes = typeof answer === "string" && /^y(?:es)?$/i.test(answer.trim());
|
|
95
|
+
if (isYes) {
|
|
96
|
+
const updated = {
|
|
97
|
+
...pkg,
|
|
98
|
+
scripts: {
|
|
99
|
+
...pkg.scripts || {},
|
|
100
|
+
"processor:dev": "nuxt-processor dev"
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
try {
|
|
104
|
+
writeFileSync(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
105
|
+
consola.success('Added "processor:dev" script to package.json');
|
|
106
|
+
} catch {
|
|
107
|
+
consola.error("Failed to write to package.json");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
consola.error("No entry file found at .nuxt/dev/workers/index.mjs");
|
|
115
|
+
consola.info("Please start your Nuxt dev server (e.g. `npm run dev`).");
|
|
116
|
+
consola.info("After it starts, run `npx nuxt-processor dev` again to start the processor.");
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const nodeBin = process.execPath;
|
|
120
|
+
const nodeArgsInput = Array.isArray(args.nodeArgs) ? args.nodeArgs : typeof args.nodeArgs === "string" ? args.nodeArgs.split(" ") : [];
|
|
121
|
+
const extraArgs = nodeArgsInput.filter(Boolean);
|
|
122
|
+
const nodeArgs = [
|
|
123
|
+
...extraArgs,
|
|
124
|
+
"--watch",
|
|
125
|
+
"--watch-path",
|
|
126
|
+
watchDir,
|
|
127
|
+
indexFile
|
|
128
|
+
];
|
|
129
|
+
consola.info(`Running watcher for processor`);
|
|
130
|
+
const child = spawn(nodeBin, nodeArgs, {
|
|
131
|
+
stdio: "inherit",
|
|
132
|
+
cwd: projectRoot,
|
|
133
|
+
env: process.env
|
|
134
|
+
});
|
|
135
|
+
const onSignal = (signal) => {
|
|
136
|
+
if (!child.killed) {
|
|
137
|
+
child.kill(signal);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
process.on("SIGINT", onSignal);
|
|
141
|
+
process.on("SIGTERM", onSignal);
|
|
142
|
+
child.on("exit", (code) => {
|
|
143
|
+
process.exit(code ?? 0);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export { main };
|
package/dist/module.cjs
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const kit = require('@nuxt/kit');
|
|
4
|
+
const _package = require('./shared/nuxt-processor.BqsFQtIQ.cjs');
|
|
5
|
+
const node_path = require('node:path');
|
|
6
|
+
const fg = require('fast-glob');
|
|
7
|
+
|
|
8
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
10
|
+
|
|
11
|
+
const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
|
|
12
|
+
|
|
13
|
+
const scanFolder = async (path) => {
|
|
14
|
+
const nuxt = kit.useNuxt();
|
|
15
|
+
const { resolve } = kit.createResolver((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href)));
|
|
16
|
+
const resolvedPath = resolve(nuxt.options.rootDir, path);
|
|
17
|
+
const files = [];
|
|
18
|
+
const updatedFiles = await fg__default("**/*.{ts,js,mjs}", {
|
|
19
|
+
cwd: resolvedPath,
|
|
20
|
+
absolute: true,
|
|
21
|
+
onlyFiles: true
|
|
22
|
+
});
|
|
23
|
+
files.push(...new Set(updatedFiles));
|
|
24
|
+
return files;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const module$1 = kit.defineNuxtModule({
|
|
28
|
+
meta: {
|
|
29
|
+
name: _package.name,
|
|
30
|
+
version: _package.version,
|
|
31
|
+
compatibility: _package.compatibility,
|
|
32
|
+
configKey: _package.configKey
|
|
33
|
+
},
|
|
34
|
+
// Default configuration options of the Nuxt module
|
|
35
|
+
defaults: {
|
|
36
|
+
redis: {
|
|
37
|
+
host: process.env.NUXT_REDIS_HOST ?? "127.0.0.1",
|
|
38
|
+
port: Number(process.env.NUXT_REDIS_PORT ?? 6379),
|
|
39
|
+
password: process.env.NUXT_REDIS_PASSWORD ?? ""
|
|
40
|
+
},
|
|
41
|
+
workers: "server/workers"
|
|
42
|
+
},
|
|
43
|
+
async setup(_options, _nuxt) {
|
|
44
|
+
const { resolve } = kit.createResolver((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href)));
|
|
45
|
+
const buildDir = _nuxt.options.buildDir;
|
|
46
|
+
function generateWorkersEntryContent(workerFiles) {
|
|
47
|
+
const redisInline = JSON.stringify(_options.redis ?? {});
|
|
48
|
+
const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
|
|
49
|
+
return `
|
|
50
|
+
import { fileURLToPath } from 'node:url'
|
|
51
|
+
import { resolve as resolvePath } from 'node:path'
|
|
52
|
+
import { consola } from 'consola'
|
|
53
|
+
import { $workers } from '#processor-utils'
|
|
54
|
+
|
|
55
|
+
// Initialize connection as early as possible so any imports that register
|
|
56
|
+
// workers/queues have a valid connection available.
|
|
57
|
+
const api = $workers()
|
|
58
|
+
api.setConnection(${redisInline})
|
|
59
|
+
|
|
60
|
+
export async function createWorkersApp() {
|
|
61
|
+
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
|
|
62
|
+
const handleStreamError = (err) => {
|
|
63
|
+
try {
|
|
64
|
+
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
|
|
65
|
+
if (code === 'EPIPE') return
|
|
66
|
+
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
|
|
67
|
+
throw err
|
|
68
|
+
}
|
|
69
|
+
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
|
|
70
|
+
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
|
|
71
|
+
const modules = [
|
|
72
|
+
${toImportArray}
|
|
73
|
+
]
|
|
74
|
+
for (const loader of modules) {
|
|
75
|
+
await loader()
|
|
76
|
+
}
|
|
77
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
78
|
+
try {
|
|
79
|
+
const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
|
|
80
|
+
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
|
|
81
|
+
for (const w of api.workers) {
|
|
82
|
+
w.on('error', (err) => logger.error('worker error', err))
|
|
83
|
+
}
|
|
84
|
+
// Explicitly start workers since autorun is disabled
|
|
85
|
+
for (const w of api.workers) {
|
|
86
|
+
try {
|
|
87
|
+
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
|
|
88
|
+
// eslint-disable-next-line promise/catch-or-return
|
|
89
|
+
w.run().catch((err) => logger.error('worker run error', err))
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
logger.error('failed to start worker', err)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
logger.success('workers started')
|
|
96
|
+
} catch (err) {
|
|
97
|
+
logger.error('failed to initialize workers', err)
|
|
98
|
+
}
|
|
99
|
+
return { stop: api.stopAll, workers: api.workers }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const isMain = (() => {
|
|
103
|
+
try {
|
|
104
|
+
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
|
|
105
|
+
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
|
|
106
|
+
const filePath = fileURLToPath(import.meta.url)
|
|
107
|
+
return filePath === argvPath
|
|
108
|
+
} catch {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
})()
|
|
112
|
+
if (isMain) {
|
|
113
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
114
|
+
const appPromise = createWorkersApp().catch((err) => {
|
|
115
|
+
logger.error('failed to start workers', err)
|
|
116
|
+
process.exit(1)
|
|
117
|
+
})
|
|
118
|
+
const shutdown = async () => {
|
|
119
|
+
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
|
|
120
|
+
try {
|
|
121
|
+
const app = await appPromise
|
|
122
|
+
try {
|
|
123
|
+
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
|
|
124
|
+
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
|
|
125
|
+
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
|
|
126
|
+
await app.stop()
|
|
127
|
+
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
|
|
128
|
+
}
|
|
129
|
+
finally { process.exit(0) }
|
|
130
|
+
}
|
|
131
|
+
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
|
|
132
|
+
process.on('beforeExit', shutdown)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export default { createWorkersApp }
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
_nuxt.options.alias = _nuxt.options.alias ?? {};
|
|
139
|
+
_nuxt.options.alias["nuxt-processor"] = resolve("./runtime/server/handlers");
|
|
140
|
+
_nuxt.options.alias["#processor"] = resolve("./runtime/server/handlers");
|
|
141
|
+
_nuxt.options.alias["#processor-utils"] = resolve("./runtime/server/utils/workers");
|
|
142
|
+
if (!_nuxt.options.alias["#bullmq"]) {
|
|
143
|
+
_nuxt.options.alias["#bullmq"] = "bullmq";
|
|
144
|
+
}
|
|
145
|
+
const typesDtsPath = kit.addTemplate({
|
|
146
|
+
filename: "types/nuxt-processor.d.ts",
|
|
147
|
+
write: true,
|
|
148
|
+
getContents: () => `
|
|
149
|
+
declare module 'nuxt-processor' {
|
|
150
|
+
export { defineQueue } from '${resolve("./runtime/server/handlers/defineQueue")}'
|
|
151
|
+
export { defineWorker } from '${resolve("./runtime/server/handlers/defineWorker")}'
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
declare module '#processor' {
|
|
155
|
+
export { defineQueue } from '${resolve("./runtime/server/handlers/defineQueue")}'
|
|
156
|
+
export { defineWorker } from '${resolve("./runtime/server/handlers/defineWorker")}'
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
declare module '#processor-utils' {
|
|
160
|
+
export { $workers } from '${resolve("./runtime/server/utils/workers")}'
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
declare module '#bullmq' {
|
|
164
|
+
export * from 'bullmq'
|
|
165
|
+
}
|
|
166
|
+
`
|
|
167
|
+
}).dst;
|
|
168
|
+
_nuxt.hooks.hook("prepare:types", (opts) => {
|
|
169
|
+
if (!opts.tsConfig.include) opts.tsConfig.include = [];
|
|
170
|
+
opts.tsConfig.include.push(resolve(buildDir, typesDtsPath));
|
|
171
|
+
});
|
|
172
|
+
function createWorkersRollupPlugin() {
|
|
173
|
+
const VIRTUAL_ID = "\0nuxt-processor-entry";
|
|
174
|
+
let virtualCode = "";
|
|
175
|
+
let entryRefId = null;
|
|
176
|
+
return {
|
|
177
|
+
name: "nuxt-processor-emit",
|
|
178
|
+
async buildStart() {
|
|
179
|
+
const workerFiles = await scanFolder(_options.workers);
|
|
180
|
+
if (workerFiles.length === 0) {
|
|
181
|
+
virtualCode = "";
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
virtualCode = generateWorkersEntryContent(workerFiles);
|
|
185
|
+
for (const id of workerFiles) {
|
|
186
|
+
this.addWatchFile(id);
|
|
187
|
+
}
|
|
188
|
+
entryRefId = this.emitFile({ type: "chunk", id: VIRTUAL_ID, fileName: "workers/_entry.mjs" });
|
|
189
|
+
},
|
|
190
|
+
resolveId(id) {
|
|
191
|
+
if (id === VIRTUAL_ID) return VIRTUAL_ID;
|
|
192
|
+
},
|
|
193
|
+
load(id) {
|
|
194
|
+
if (id === VIRTUAL_ID) return virtualCode || "export {}\n";
|
|
195
|
+
},
|
|
196
|
+
generateBundle() {
|
|
197
|
+
if (!virtualCode || !entryRefId) return;
|
|
198
|
+
const entryFile = this.getFileName(entryRefId);
|
|
199
|
+
const fromDir = "workers";
|
|
200
|
+
const rel = "./" + node_path.relative(fromDir, entryFile).split("\\").join("/");
|
|
201
|
+
const wrapper = `import { createWorkersApp } from '${rel}'
|
|
202
|
+
import { consola } from 'consola'
|
|
203
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
204
|
+
const appPromise = createWorkersApp().catch((err) => { logger.error('failed to start workers', err); process.exit(1) })
|
|
205
|
+
let shuttingDown = false
|
|
206
|
+
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) } }
|
|
207
|
+
[ 'SIGINT','SIGTERM','SIGQUIT' ].forEach(sig => process.on(sig, () => shutdown(sig)))
|
|
208
|
+
process.on('beforeExit', () => shutdown('beforeExit'))
|
|
209
|
+
`;
|
|
210
|
+
this.emitFile({ type: "asset", fileName: "workers/index.mjs", source: wrapper });
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
_nuxt.hooks.hook("nitro:config", (nitroConfig) => {
|
|
215
|
+
nitroConfig.rollupConfig = nitroConfig.rollupConfig ?? {};
|
|
216
|
+
const plugin = createWorkersRollupPlugin();
|
|
217
|
+
const current = nitroConfig.rollupConfig.plugins;
|
|
218
|
+
if (Array.isArray(current)) {
|
|
219
|
+
nitroConfig.rollupConfig.plugins = [...current, plugin];
|
|
220
|
+
} else if (current) {
|
|
221
|
+
nitroConfig.rollupConfig.plugins = [current, plugin];
|
|
222
|
+
} else {
|
|
223
|
+
nitroConfig.rollupConfig.plugins = [plugin];
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
module.exports = module$1;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { RedisOptions } from 'bullmq';
|
|
3
|
+
|
|
4
|
+
interface ModuleOptions {
|
|
5
|
+
redis: RedisOptions;
|
|
6
|
+
/**
|
|
7
|
+
* The folder containing the worker files
|
|
8
|
+
* Scans for {ts,js,mjs}
|
|
9
|
+
* @default 'server/workers'
|
|
10
|
+
*/
|
|
11
|
+
workers: string;
|
|
12
|
+
}
|
|
13
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
14
|
+
|
|
15
|
+
export = _default;
|
|
16
|
+
export type { ModuleOptions };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { useNuxt, createResolver, defineNuxtModule, addTemplate } from '@nuxt/kit';
|
|
2
|
+
import { c as configKey, a as compatibility, v as version, n as name } from './shared/nuxt-processor.BDPWtq8T.mjs';
|
|
2
3
|
import { relative } from 'node:path';
|
|
3
4
|
import fg from 'fast-glob';
|
|
4
5
|
|
|
5
|
-
const name = "nuxt-processor";
|
|
6
|
-
const version = "0.0.3";
|
|
7
|
-
const configKey = "processor";
|
|
8
|
-
const compatibility = {
|
|
9
|
-
nuxt: "^4.0.0"
|
|
10
|
-
};
|
|
11
|
-
|
|
12
6
|
const scanFolder = async (path) => {
|
|
13
7
|
const nuxt = useNuxt();
|
|
14
8
|
const { resolve } = createResolver(import.meta.url);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const name = "nuxt-processor";
|
|
2
|
+
const version = "0.0.4";
|
|
3
|
+
const description = "Nuxt Processor";
|
|
4
|
+
const configKey = "processor";
|
|
5
|
+
const compatibility = {
|
|
6
|
+
nuxt: "^4.0.0 || ^3.0.0"
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export { compatibility as a, configKey as c, description as d, name as n, version as v };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const name = "nuxt-processor";
|
|
4
|
+
const version = "0.0.4";
|
|
5
|
+
const description = "Nuxt Processor";
|
|
6
|
+
const configKey = "processor";
|
|
7
|
+
const compatibility = {
|
|
8
|
+
nuxt: "^4.0.0 || ^3.0.0"
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
exports.compatibility = compatibility;
|
|
12
|
+
exports.configKey = configKey;
|
|
13
|
+
exports.description = description;
|
|
14
|
+
exports.name = name;
|
|
15
|
+
exports.version = version;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-processor",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Nuxt Processor",
|
|
5
5
|
"repository": "https://github.com/aidanhibbard/nuxt-processor",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"configKey": "processor",
|
|
9
9
|
"compatibility": {
|
|
10
|
-
"nuxt": "^4.0.0"
|
|
10
|
+
"nuxt": "^4.0.0 || ^3.0.0"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
@@ -23,8 +23,12 @@
|
|
|
23
23
|
]
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"nuxt-processor": "./bin/nuxt-processor.mjs"
|
|
28
|
+
},
|
|
26
29
|
"files": [
|
|
27
|
-
"dist"
|
|
30
|
+
"dist",
|
|
31
|
+
"bin"
|
|
28
32
|
],
|
|
29
33
|
"scripts": {
|
|
30
34
|
"prepack": "nuxt-module-build build",
|
|
@@ -42,9 +46,12 @@
|
|
|
42
46
|
},
|
|
43
47
|
"dependencies": {
|
|
44
48
|
"@nuxt/kit": "^4.0.3",
|
|
49
|
+
"citty": "^0.1.6",
|
|
50
|
+
"consola": "^3.2.3",
|
|
45
51
|
"bullmq": "^5.58.2",
|
|
46
52
|
"fast-glob": "^3.3.3",
|
|
47
|
-
"ioredis": "^5.7.0"
|
|
53
|
+
"ioredis": "^5.7.0",
|
|
54
|
+
"pathe": "^1.1.2"
|
|
48
55
|
},
|
|
49
56
|
"devDependencies": {
|
|
50
57
|
"@nuxt/devtools": "^2.6.3",
|