nuxt-processor 0.0.12 → 0.0.15

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 CHANGED
@@ -20,6 +20,14 @@ Note: This package is under very active development! Please consider creating is
20
20
  - **Scalability**: Run multiple worker processes and instances across machines.
21
21
  - **Simple DX**: Define queues/workers using first-class helpers.
22
22
 
23
+ ## Used by
24
+
25
+ <div>
26
+ <a href="https://getminds.ai/" target="_blank" rel="noreferrer">
27
+ <img src="https://media.licdn.com/dms/image/v2/D4D0BAQFsL_KsNSWwow/company-logo_200_200/B4DZvtmrYRJQAI-/0/1769217898466/mindsaicompany_logo?e=1771459200&v=beta&t=FRLR2608GdLLgD9dIPqIs8wtdk-_ZAG_bWahup1kTr4" alt="Minds AI" height="72" />
28
+ </a>
29
+ </div>
30
+
23
31
  ## Sections
24
32
 
25
33
  - [Install](#install)
@@ -33,7 +41,7 @@ Note: This package is under very active development! Please consider creating is
33
41
  ## Install
34
42
 
35
43
  ```bash
36
- npx nuxi@latest module add nuxt-processor
44
+ npx nuxi@latest module add nuxt-processor@latest
37
45
  ```
38
46
 
39
47
  Add the module in `nuxt.config.ts` and set your Redis connection.
@@ -113,13 +121,22 @@ nuxi dev
113
121
  node .nuxt/dev/workers/index.mjs
114
122
  ```
115
123
 
124
+ By default all workers run. To run only specific workers, use the `--workers=` flag with a comma-separated list of worker names:
125
+
126
+ ```bash
127
+ node .nuxt/dev/workers/index.mjs --workers=basic,hello
128
+ ```
129
+
116
130
  ### CLI
117
131
 
118
- A simple CLI is provided to run workers in development.
132
+ A simple CLI is provided to run workers in development (with file watching and restarts).
119
133
 
120
134
  ```bash
121
- # from your project root
135
+ # from your project root – runs all workers
122
136
  npx nuxt-processor dev
137
+
138
+ # run only specific workers
139
+ npx nuxt-processor dev --workers=basic,hello
123
140
  ```
124
141
 
125
142
  Notes:
@@ -147,6 +164,12 @@ nuxi build
147
164
  node .output/server/workers/index.mjs
148
165
  ```
149
166
 
167
+ To run only specific workers in production:
168
+
169
+ ```bash
170
+ node .output/server/workers/index.mjs --workers=basic,hello
171
+ ```
172
+
150
173
  ## Bull Board
151
174
 
152
175
  [Bull Board](https://github.com/felixmosh/bull-board) is an excellent UI for watching your queues, you can follow the setup in the playground to use it.
package/dist/cli.cjs CHANGED
@@ -2,28 +2,76 @@
2
2
 
3
3
  const node_child_process = require('node:child_process');
4
4
  const node_fs = require('node:fs');
5
- const promises = require('node:readline/promises');
6
- const node_process = require('node:process');
7
5
  const pathe = require('pathe');
8
- const consola = require('consola');
9
6
  const citty = require('citty');
10
7
  const kit = require('@nuxt/kit');
11
- const _package = require('./shared/nuxt-processor.XeX-J1zD.cjs');
8
+ const logger = require('./shared/nuxt-processor.anOQG_7p.cjs');
9
+ const promises = require('node:readline/promises');
10
+ const node_process = require('node:process');
11
+ require('consola');
12
12
 
13
13
  const ensureNuxtProject = async (args) => {
14
14
  const dir = pathe.resolve(args.dir);
15
15
  const nuxtConfig = await kit.loadNuxtConfig({ cwd: dir });
16
16
  if (!nuxtConfig || !nuxtConfig._layers[0]?.configFile) {
17
- consola.consola.error("You are not in a Nuxt project.");
18
- process.exit();
17
+ logger.logger.error("You are not in a Nuxt project.");
18
+ process.exit(1);
19
19
  }
20
20
  };
21
21
 
22
+ const PROCESSOR_DEV_SCRIPT = "nuxt-processor dev";
23
+ async function ensureProcessorDevScript(projectRoot, options) {
24
+ const pkgPath = pathe.resolve(projectRoot, "package.json");
25
+ if (!node_fs.existsSync(pkgPath)) {
26
+ return false;
27
+ }
28
+ let pkg;
29
+ try {
30
+ const pkgRaw = JSON.parse(node_fs.readFileSync(pkgPath, "utf8"));
31
+ pkg = pkgRaw;
32
+ } catch (error) {
33
+ logger.logger.error("Failed to parse", error);
34
+ return false;
35
+ }
36
+ if (pkg?.scripts?.["processor:dev"]) {
37
+ return true;
38
+ }
39
+ logger.logger.warn('No "processor:dev" script found in package.json.');
40
+ let answer;
41
+ {
42
+ const rl = promises.createInterface({ input: node_process.stdin, output: node_process.stdout });
43
+ try {
44
+ answer = await rl.question("Add script to package.json? (y/N) ");
45
+ } finally {
46
+ rl.close();
47
+ }
48
+ }
49
+ const isYes = typeof answer === "string" && /^y(?:es)?$/i.test(answer.trim());
50
+ if (!isYes) {
51
+ return false;
52
+ }
53
+ const updated = {
54
+ ...pkg,
55
+ scripts: {
56
+ ...pkg.scripts ?? {},
57
+ "processor:dev": PROCESSOR_DEV_SCRIPT
58
+ }
59
+ };
60
+ try {
61
+ node_fs.writeFileSync(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
62
+ logger.logger.success('Added "processor:dev" script to package.json');
63
+ return true;
64
+ } catch {
65
+ logger.logger.error("Failed to write to package.json");
66
+ return false;
67
+ }
68
+ }
69
+
22
70
  const main = citty.createMain({
23
71
  meta: {
24
- name: _package.name,
25
- description: _package.description,
26
- version: _package.version
72
+ name: logger.name,
73
+ description: logger.description,
74
+ version: logger.version
27
75
  },
28
76
  subCommands: {
29
77
  dev: citty.defineCommand({
@@ -39,6 +87,10 @@ const main = citty.createMain({
39
87
  nodeArgs: {
40
88
  type: "string",
41
89
  description: "Extra Node args (e.g. --inspect)"
90
+ },
91
+ workers: {
92
+ type: "string",
93
+ description: "Workers to run, comma-separated; use --workers=name1,name2 (default: all)"
42
94
  }
43
95
  },
44
96
  async run({ args }) {
@@ -47,88 +99,31 @@ const main = citty.createMain({
47
99
  const projectRoot = pathe.resolve(dirArg);
48
100
  const indexFile = pathe.resolve(projectRoot, ".nuxt/dev/workers/index.mjs");
49
101
  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
- }
102
+ const scriptEnsured = await ensureProcessorDevScript(projectRoot);
83
103
  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.");
104
+ logger.logger.error("No entry file found at .nuxt/dev/workers/index.mjs");
105
+ logger.logger.info("Please start your Nuxt dev server (e.g. `npm run dev`).");
106
+ logger.logger.info("After it starts, run `npx nuxt-processor dev` again to start the processor.");
107
+ process.exit(1);
108
+ }
109
+ if (!scriptEnsured) {
110
+ logger.logger.error("Could not ensure processor:dev script in package.json.");
119
111
  process.exit(1);
120
112
  }
121
113
  const nodeBin = process.execPath;
122
114
  const nodeArgsInput = Array.isArray(args.nodeArgs) ? args.nodeArgs : typeof args.nodeArgs === "string" ? args.nodeArgs.split(" ") : [];
123
115
  const extraArgs = nodeArgsInput.filter(Boolean);
116
+ const workersValue = typeof args.workers === "string" ? args.workers.trim() : "";
117
+ const workersFlag = workersValue ? `--workers=${workersValue}` : null;
124
118
  const nodeArgs = [
125
119
  ...extraArgs,
126
120
  "--watch",
127
121
  "--watch-path",
128
122
  watchDir,
129
- indexFile
123
+ indexFile,
124
+ ...workersFlag ? [workersFlag] : []
130
125
  ];
131
- consola.consola.info(`Running watcher for processor`);
126
+ logger.logger.info(`Running watcher for processor`);
132
127
  const child = node_child_process.spawn(nodeBin, nodeArgs, {
133
128
  stdio: "inherit",
134
129
  cwd: projectRoot,
package/dist/cli.mjs CHANGED
@@ -1,22 +1,70 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
- import { createInterface } from 'node:readline/promises';
4
- import { stdout, stdin } from 'node:process';
5
3
  import { resolve } from 'pathe';
6
- import { consola } from 'consola';
7
4
  import { createMain, defineCommand } from 'citty';
8
5
  import { loadNuxtConfig } from '@nuxt/kit';
9
- import { v as version, d as description, n as name } from './shared/nuxt-processor.Bp92mFhC.mjs';
6
+ import { l as logger, v as version, d as description, n as name } from './shared/nuxt-processor.Ff27cxgy.mjs';
7
+ import { createInterface } from 'node:readline/promises';
8
+ import { stdout, stdin } from 'node:process';
9
+ import 'consola';
10
10
 
11
11
  const ensureNuxtProject = async (args) => {
12
12
  const dir = resolve(args.dir);
13
13
  const nuxtConfig = await loadNuxtConfig({ cwd: dir });
14
14
  if (!nuxtConfig || !nuxtConfig._layers[0]?.configFile) {
15
- consola.error("You are not in a Nuxt project.");
16
- process.exit();
15
+ logger.error("You are not in a Nuxt project.");
16
+ process.exit(1);
17
17
  }
18
18
  };
19
19
 
20
+ const PROCESSOR_DEV_SCRIPT = "nuxt-processor dev";
21
+ async function ensureProcessorDevScript(projectRoot, options) {
22
+ const pkgPath = resolve(projectRoot, "package.json");
23
+ if (!existsSync(pkgPath)) {
24
+ return false;
25
+ }
26
+ let pkg;
27
+ try {
28
+ const pkgRaw = JSON.parse(readFileSync(pkgPath, "utf8"));
29
+ pkg = pkgRaw;
30
+ } catch (error) {
31
+ logger.error("Failed to parse", error);
32
+ return false;
33
+ }
34
+ if (pkg?.scripts?.["processor:dev"]) {
35
+ return true;
36
+ }
37
+ logger.warn('No "processor:dev" script found in package.json.');
38
+ let answer;
39
+ {
40
+ const rl = createInterface({ input: stdin, output: stdout });
41
+ try {
42
+ answer = await rl.question("Add script to package.json? (y/N) ");
43
+ } finally {
44
+ rl.close();
45
+ }
46
+ }
47
+ const isYes = typeof answer === "string" && /^y(?:es)?$/i.test(answer.trim());
48
+ if (!isYes) {
49
+ return false;
50
+ }
51
+ const updated = {
52
+ ...pkg,
53
+ scripts: {
54
+ ...pkg.scripts ?? {},
55
+ "processor:dev": PROCESSOR_DEV_SCRIPT
56
+ }
57
+ };
58
+ try {
59
+ writeFileSync(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
60
+ logger.success('Added "processor:dev" script to package.json');
61
+ return true;
62
+ } catch {
63
+ logger.error("Failed to write to package.json");
64
+ return false;
65
+ }
66
+ }
67
+
20
68
  const main = createMain({
21
69
  meta: {
22
70
  name,
@@ -37,6 +85,10 @@ const main = createMain({
37
85
  nodeArgs: {
38
86
  type: "string",
39
87
  description: "Extra Node args (e.g. --inspect)"
88
+ },
89
+ workers: {
90
+ type: "string",
91
+ description: "Workers to run, comma-separated; use --workers=name1,name2 (default: all)"
40
92
  }
41
93
  },
42
94
  async run({ args }) {
@@ -45,88 +97,31 @@ const main = createMain({
45
97
  const projectRoot = resolve(dirArg);
46
98
  const indexFile = resolve(projectRoot, ".nuxt/dev/workers/index.mjs");
47
99
  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
- }
100
+ const scriptEnsured = await ensureProcessorDevScript(projectRoot);
81
101
  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.");
102
+ logger.error("No entry file found at .nuxt/dev/workers/index.mjs");
103
+ logger.info("Please start your Nuxt dev server (e.g. `npm run dev`).");
104
+ logger.info("After it starts, run `npx nuxt-processor dev` again to start the processor.");
105
+ process.exit(1);
106
+ }
107
+ if (!scriptEnsured) {
108
+ logger.error("Could not ensure processor:dev script in package.json.");
117
109
  process.exit(1);
118
110
  }
119
111
  const nodeBin = process.execPath;
120
112
  const nodeArgsInput = Array.isArray(args.nodeArgs) ? args.nodeArgs : typeof args.nodeArgs === "string" ? args.nodeArgs.split(" ") : [];
121
113
  const extraArgs = nodeArgsInput.filter(Boolean);
114
+ const workersValue = typeof args.workers === "string" ? args.workers.trim() : "";
115
+ const workersFlag = workersValue ? `--workers=${workersValue}` : null;
122
116
  const nodeArgs = [
123
117
  ...extraArgs,
124
118
  "--watch",
125
119
  "--watch-path",
126
120
  watchDir,
127
- indexFile
121
+ indexFile,
122
+ ...workersFlag ? [workersFlag] : []
128
123
  ];
129
- consola.info(`Running watcher for processor`);
124
+ logger.info(`Running watcher for processor`);
130
125
  const child = spawn(nodeBin, nodeArgs, {
131
126
  stdio: "inherit",
132
127
  cwd: projectRoot,
package/dist/module.cjs CHANGED
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  const kit = require('@nuxt/kit');
4
- const _package = require('./shared/nuxt-processor.XeX-J1zD.cjs');
4
+ const logger = require('./shared/nuxt-processor.anOQG_7p.cjs');
5
5
  const node_path = require('node:path');
6
6
  const fg = require('fast-glob');
7
+ require('consola');
7
8
 
8
9
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
9
10
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
@@ -21,15 +22,126 @@ const scanFolder = async (path) => {
21
22
  onlyFiles: true
22
23
  });
23
24
  files.push(...new Set(updatedFiles));
25
+ if (files.length === 0) {
26
+ logger.logger.warn("No worker files found in project");
27
+ }
24
28
  return files;
25
29
  };
26
30
 
31
+ function generateWorkersEntryContent(workerFiles, redisInline) {
32
+ const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
33
+ return `
34
+ import { fileURLToPath } from 'node:url'
35
+ import { resolve as resolvePath } from 'node:path'
36
+ import { consola } from 'consola'
37
+ import { $workers } from '#processor-utils'
38
+
39
+ // Initialize connection as early as possible so any imports that register
40
+ // workers/queues have a valid connection available.
41
+ const api = $workers()
42
+ api.setConnection(${redisInline})
43
+
44
+ export async function createWorkersApp() {
45
+ // Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
46
+ const handleStreamError = (err) => {
47
+ try {
48
+ const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
49
+ if (code === 'EPIPE') return
50
+ } catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
51
+ throw err
52
+ }
53
+ try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
54
+ try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
55
+ const modules = [
56
+ ${toImportArray}
57
+ ]
58
+ for (const loader of modules) {
59
+ await loader()
60
+ }
61
+ // Parse --workers flag (e.g. --workers=basic,hello)
62
+ const workersArg = process.argv.find(a => typeof a === 'string' && a.startsWith('--workers='))
63
+ const selectedWorkers = workersArg
64
+ ? workersArg.split('=')[1].split(',').map(s => s.trim()).filter(Boolean)
65
+ : null
66
+ const workersToRun = selectedWorkers
67
+ ? (Array.isArray(api.workers) ? api.workers.filter(w => w && selectedWorkers.includes(w.name)) : [])
68
+ : (Array.isArray(api.workers) ? api.workers : [])
69
+ const logger = consola.create({}).withTag('nuxt-processor')
70
+ if (selectedWorkers && workersToRun.length === 0) {
71
+ const available = (Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : [])
72
+ logger.warn('No workers matched --workers=' + selectedWorkers.join(',') + (available.length ? '. Available: ' + available.join(', ') : '.'))
73
+ process.exit(1)
74
+ }
75
+ try {
76
+ const workerNames = workersToRun.map(w => w && w.name).filter(Boolean)
77
+ logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
78
+ for (const w of workersToRun) {
79
+ w.on('error', (err) => logger.error('worker error', err))
80
+ }
81
+ // Explicitly start workers since autorun is disabled
82
+ for (const w of workersToRun) {
83
+ try {
84
+ // run() returns a promise that resolves when the worker stops; do not await to avoid blocking
85
+ // eslint-disable-next-line promise/catch-or-return
86
+ w.run().catch((err) => logger.error('worker run error', err))
87
+ }
88
+ catch (err) {
89
+ logger.error('failed to start worker', err)
90
+ }
91
+ }
92
+ logger.success('workers started')
93
+ } catch (err) {
94
+ logger.error('failed to initialize workers', err)
95
+ }
96
+ const closeRunningWorkers = async () => {
97
+ await Promise.allSettled(workersToRun.map(w => w.close()))
98
+ }
99
+ return { stop: closeRunningWorkers, workers: workersToRun }
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
+
27
139
  const module$1 = kit.defineNuxtModule({
28
140
  meta: {
29
- name: _package.name,
30
- version: _package.version,
31
- compatibility: _package.compatibility,
32
- configKey: _package.configKey
141
+ name: logger.name,
142
+ version: logger.version,
143
+ compatibility: logger.compatibility,
144
+ configKey: logger.configKey
33
145
  },
34
146
  // Default configuration options of the Nuxt module
35
147
  defaults: {
@@ -64,97 +176,6 @@ const module$1 = kit.defineNuxtModule({
64
176
  getContents: () => nitroPlugin
65
177
  });
66
178
  kit.addServerPlugin(tpl.dst);
67
- function generateWorkersEntryContent(workerFiles) {
68
- const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
69
- return `
70
- import { fileURLToPath } from 'node:url'
71
- import { resolve as resolvePath } from 'node:path'
72
- import { consola } from 'consola'
73
- import { $workers } from '#processor-utils'
74
-
75
- // Initialize connection as early as possible so any imports that register
76
- // workers/queues have a valid connection available.
77
- const api = $workers()
78
- api.setConnection(${redisInline})
79
-
80
- export async function createWorkersApp() {
81
- // Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
82
- const handleStreamError = (err) => {
83
- try {
84
- const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
85
- if (code === 'EPIPE') return
86
- } catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
87
- throw err
88
- }
89
- try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
90
- try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
91
- const modules = [
92
- ${toImportArray}
93
- ]
94
- for (const loader of modules) {
95
- await loader()
96
- }
97
- const logger = consola.create({}).withTag('nuxt-processor')
98
- try {
99
- const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
100
- logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
101
- for (const w of api.workers) {
102
- w.on('error', (err) => logger.error('worker error', err))
103
- }
104
- // Explicitly start workers since autorun is disabled
105
- for (const w of api.workers) {
106
- try {
107
- // run() returns a promise that resolves when the worker stops; do not await to avoid blocking
108
- // eslint-disable-next-line promise/catch-or-return
109
- w.run().catch((err) => logger.error('worker run error', err))
110
- }
111
- catch (err) {
112
- logger.error('failed to start worker', err)
113
- }
114
- }
115
- logger.success('workers started')
116
- } catch (err) {
117
- logger.error('failed to initialize workers', err)
118
- }
119
- return { stop: api.stopAll, workers: api.workers }
120
- }
121
-
122
- const isMain = (() => {
123
- try {
124
- if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
125
- const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
126
- const filePath = fileURLToPath(import.meta.url)
127
- return filePath === argvPath
128
- } catch {
129
- return false
130
- }
131
- })()
132
- if (isMain) {
133
- const logger = consola.create({}).withTag('nuxt-processor')
134
- const appPromise = createWorkersApp().catch((err) => {
135
- logger.error('failed to start workers', err)
136
- process.exit(1)
137
- })
138
- const shutdown = async () => {
139
- try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
140
- try {
141
- const app = await appPromise
142
- try {
143
- const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
144
- logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
145
- } catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
146
- await app.stop()
147
- try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
148
- }
149
- finally { process.exit(0) }
150
- }
151
- ;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
152
- process.on('beforeExit', shutdown)
153
- }
154
-
155
- export default { createWorkersApp }
156
- `;
157
- }
158
179
  nuxt.options.alias = nuxt.options.alias ?? {};
159
180
  nuxt.options.alias["nuxt-processor"] = resolve("./runtime/server/handlers");
160
181
  nuxt.options.alias["#processor"] = resolve("./runtime/server/handlers");
@@ -196,7 +217,7 @@ declare module '#bullmq' {
196
217
  virtualCode = "";
197
218
  return;
198
219
  }
199
- virtualCode = generateWorkersEntryContent(workerFiles);
220
+ virtualCode = generateWorkersEntryContent(workerFiles, redisInline);
200
221
  for (const id of workerFiles) {
201
222
  this.addWatchFile(id);
202
223
  }
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-processor",
3
- "version": "0.0.12",
3
+ "version": "0.0.15",
4
4
  "compatibility": {
5
5
  "nuxt": "^4.0.0 || ^3.0.0"
6
6
  },
package/dist/module.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { useNuxt, createResolver, defineNuxtModule, addTemplate, addServerPlugin, addTypeTemplate } from '@nuxt/kit';
2
- import { c as configKey, a as compatibility, v as version, n as name } from './shared/nuxt-processor.Bp92mFhC.mjs';
2
+ import { l as logger, c as configKey, a as compatibility, v as version, n as name } from './shared/nuxt-processor.Ff27cxgy.mjs';
3
3
  import { relative } from 'node:path';
4
4
  import fg from 'fast-glob';
5
+ import 'consola';
5
6
 
6
7
  const scanFolder = async (path) => {
7
8
  const nuxt = useNuxt();
@@ -14,10 +15,121 @@ const scanFolder = async (path) => {
14
15
  onlyFiles: true
15
16
  });
16
17
  files.push(...new Set(updatedFiles));
18
+ if (files.length === 0) {
19
+ logger.warn("No worker files found in project");
20
+ }
17
21
  return files;
18
22
  };
19
23
 
20
- const module = defineNuxtModule({
24
+ function generateWorkersEntryContent(workerFiles, redisInline) {
25
+ const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
26
+ return `
27
+ import { fileURLToPath } from 'node:url'
28
+ import { resolve as resolvePath } from 'node:path'
29
+ import { consola } from 'consola'
30
+ import { $workers } from '#processor-utils'
31
+
32
+ // Initialize connection as early as possible so any imports that register
33
+ // workers/queues have a valid connection available.
34
+ const api = $workers()
35
+ api.setConnection(${redisInline})
36
+
37
+ export async function createWorkersApp() {
38
+ // Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
39
+ const handleStreamError = (err) => {
40
+ try {
41
+ const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
42
+ if (code === 'EPIPE') return
43
+ } catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
44
+ throw err
45
+ }
46
+ try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
47
+ try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
48
+ const modules = [
49
+ ${toImportArray}
50
+ ]
51
+ for (const loader of modules) {
52
+ await loader()
53
+ }
54
+ // Parse --workers flag (e.g. --workers=basic,hello)
55
+ const workersArg = process.argv.find(a => typeof a === 'string' && a.startsWith('--workers='))
56
+ const selectedWorkers = workersArg
57
+ ? workersArg.split('=')[1].split(',').map(s => s.trim()).filter(Boolean)
58
+ : null
59
+ const workersToRun = selectedWorkers
60
+ ? (Array.isArray(api.workers) ? api.workers.filter(w => w && selectedWorkers.includes(w.name)) : [])
61
+ : (Array.isArray(api.workers) ? api.workers : [])
62
+ const logger = consola.create({}).withTag('nuxt-processor')
63
+ if (selectedWorkers && workersToRun.length === 0) {
64
+ const available = (Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : [])
65
+ logger.warn('No workers matched --workers=' + selectedWorkers.join(',') + (available.length ? '. Available: ' + available.join(', ') : '.'))
66
+ process.exit(1)
67
+ }
68
+ try {
69
+ const workerNames = workersToRun.map(w => w && w.name).filter(Boolean)
70
+ logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
71
+ for (const w of workersToRun) {
72
+ w.on('error', (err) => logger.error('worker error', err))
73
+ }
74
+ // Explicitly start workers since autorun is disabled
75
+ for (const w of workersToRun) {
76
+ try {
77
+ // run() returns a promise that resolves when the worker stops; do not await to avoid blocking
78
+ // eslint-disable-next-line promise/catch-or-return
79
+ w.run().catch((err) => logger.error('worker run error', err))
80
+ }
81
+ catch (err) {
82
+ logger.error('failed to start worker', err)
83
+ }
84
+ }
85
+ logger.success('workers started')
86
+ } catch (err) {
87
+ logger.error('failed to initialize workers', err)
88
+ }
89
+ const closeRunningWorkers = async () => {
90
+ await Promise.allSettled(workersToRun.map(w => w.close()))
91
+ }
92
+ return { stop: closeRunningWorkers, workers: workersToRun }
93
+ }
94
+
95
+ const isMain = (() => {
96
+ try {
97
+ if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
98
+ const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
99
+ const filePath = fileURLToPath(import.meta.url)
100
+ return filePath === argvPath
101
+ } catch {
102
+ return false
103
+ }
104
+ })()
105
+ if (isMain) {
106
+ const logger = consola.create({}).withTag('nuxt-processor')
107
+ const appPromise = createWorkersApp().catch((err) => {
108
+ logger.error('failed to start workers', err)
109
+ process.exit(1)
110
+ })
111
+ const shutdown = async () => {
112
+ try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
113
+ try {
114
+ const app = await appPromise
115
+ try {
116
+ const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
117
+ logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
118
+ } catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
119
+ await app.stop()
120
+ try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
121
+ }
122
+ finally { process.exit(0) }
123
+ }
124
+ ;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
125
+ process.on('beforeExit', shutdown)
126
+ }
127
+
128
+ export default { createWorkersApp }
129
+ `;
130
+ }
131
+
132
+ const module$1 = defineNuxtModule({
21
133
  meta: {
22
134
  name,
23
135
  version,
@@ -57,97 +169,6 @@ const module = defineNuxtModule({
57
169
  getContents: () => nitroPlugin
58
170
  });
59
171
  addServerPlugin(tpl.dst);
60
- function generateWorkersEntryContent(workerFiles) {
61
- const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
62
- return `
63
- import { fileURLToPath } from 'node:url'
64
- import { resolve as resolvePath } from 'node:path'
65
- import { consola } from 'consola'
66
- import { $workers } from '#processor-utils'
67
-
68
- // Initialize connection as early as possible so any imports that register
69
- // workers/queues have a valid connection available.
70
- const api = $workers()
71
- api.setConnection(${redisInline})
72
-
73
- export async function createWorkersApp() {
74
- // Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
75
- const handleStreamError = (err) => {
76
- try {
77
- const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
78
- if (code === 'EPIPE') return
79
- } catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
80
- throw err
81
- }
82
- try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
83
- try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
84
- const modules = [
85
- ${toImportArray}
86
- ]
87
- for (const loader of modules) {
88
- await loader()
89
- }
90
- const logger = consola.create({}).withTag('nuxt-processor')
91
- try {
92
- const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
93
- logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
94
- for (const w of api.workers) {
95
- w.on('error', (err) => logger.error('worker error', err))
96
- }
97
- // Explicitly start workers since autorun is disabled
98
- for (const w of api.workers) {
99
- try {
100
- // run() returns a promise that resolves when the worker stops; do not await to avoid blocking
101
- // eslint-disable-next-line promise/catch-or-return
102
- w.run().catch((err) => logger.error('worker run error', err))
103
- }
104
- catch (err) {
105
- logger.error('failed to start worker', err)
106
- }
107
- }
108
- logger.success('workers started')
109
- } catch (err) {
110
- logger.error('failed to initialize workers', err)
111
- }
112
- return { stop: api.stopAll, workers: api.workers }
113
- }
114
-
115
- const isMain = (() => {
116
- try {
117
- if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
118
- const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
119
- const filePath = fileURLToPath(import.meta.url)
120
- return filePath === argvPath
121
- } catch {
122
- return false
123
- }
124
- })()
125
- if (isMain) {
126
- const logger = consola.create({}).withTag('nuxt-processor')
127
- const appPromise = createWorkersApp().catch((err) => {
128
- logger.error('failed to start workers', err)
129
- process.exit(1)
130
- })
131
- const shutdown = async () => {
132
- try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
133
- try {
134
- const app = await appPromise
135
- try {
136
- const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
137
- logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
138
- } catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
139
- await app.stop()
140
- try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
141
- }
142
- finally { process.exit(0) }
143
- }
144
- ;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
145
- process.on('beforeExit', shutdown)
146
- }
147
-
148
- export default { createWorkersApp }
149
- `;
150
- }
151
172
  nuxt.options.alias = nuxt.options.alias ?? {};
152
173
  nuxt.options.alias["nuxt-processor"] = resolve("./runtime/server/handlers");
153
174
  nuxt.options.alias["#processor"] = resolve("./runtime/server/handlers");
@@ -189,7 +210,7 @@ declare module '#bullmq' {
189
210
  virtualCode = "";
190
211
  return;
191
212
  }
192
- virtualCode = generateWorkersEntryContent(workerFiles);
213
+ virtualCode = generateWorkersEntryContent(workerFiles, redisInline);
193
214
  for (const id of workerFiles) {
194
215
  this.addWatchFile(id);
195
216
  }
@@ -234,4 +255,4 @@ process.on('beforeExit', () => shutdown('beforeExit'))
234
255
  }
235
256
  });
236
257
 
237
- export { module as default };
258
+ export { module$1 as default };
@@ -9,7 +9,7 @@ export declare function $workers(): {
9
9
  path: string;
10
10
  }> & {
11
11
  disconnectTimeout?: number;
12
- tls?: import("tls").ConnectionOptions;
12
+ tls?: import("node:tls").ConnectionOptions;
13
13
  } & {
14
14
  url?: string;
15
15
  })) => void;
@@ -0,0 +1,13 @@
1
+ import { createConsola } from 'consola';
2
+
3
+ const name = "nuxt-processor";
4
+ const version = "0.0.15";
5
+ const description = "Nuxt Processor";
6
+ const configKey = "processor";
7
+ const compatibility = {
8
+ nuxt: "^4.0.0 || ^3.0.0"
9
+ };
10
+
11
+ const logger = createConsola({}).withTag(name);
12
+
13
+ export { compatibility as a, configKey as c, description as d, logger as l, name as n, version as v };
@@ -1,15 +1,20 @@
1
1
  'use strict';
2
2
 
3
+ const consola = require('consola');
4
+
3
5
  const name = "nuxt-processor";
4
- const version = "0.0.12";
6
+ const version = "0.0.15";
5
7
  const description = "Nuxt Processor";
6
8
  const configKey = "processor";
7
9
  const compatibility = {
8
10
  nuxt: "^4.0.0 || ^3.0.0"
9
11
  };
10
12
 
13
+ const logger = consola.createConsola({}).withTag(name);
14
+
11
15
  exports.compatibility = compatibility;
12
16
  exports.configKey = configKey;
13
17
  exports.description = description;
18
+ exports.logger = logger;
14
19
  exports.name = name;
15
20
  exports.version = version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-processor",
3
- "version": "0.0.12",
3
+ "version": "0.0.15",
4
4
  "description": "Nuxt Processor",
5
5
  "repository": "https://github.com/aidanhibbard/nuxt-processor",
6
6
  "license": "MIT",
@@ -35,9 +35,9 @@
35
35
  "dev": "npm run dev:prepare && nuxi dev playground",
36
36
  "dev:build": "nuxi build playground",
37
37
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
38
- "ci:dev:build": "npm run dev:prepare && cd playground && npm i && cd ../ && npm run dev:build",
39
38
  "release": "npm run lint && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
40
39
  "lint": "eslint .",
40
+ "lint:fix": "eslint . --fix",
41
41
  "test": "vitest run",
42
42
  "test:coverage": "vitest run --coverage",
43
43
  "test:watch": "vitest watch",
@@ -47,13 +47,13 @@
47
47
  "vp:preview": "vitepress preview docs"
48
48
  },
49
49
  "dependencies": {
50
- "@nuxt/kit": "^4.0.3",
51
- "bullmq": "^5.58.2",
52
- "citty": "^0.1.6",
53
- "consola": "^3.2.3",
50
+ "@nuxt/kit": "^4.3.0",
51
+ "bullmq": "^5.67.2",
52
+ "citty": "^0.2.0",
53
+ "consola": "^3.4.2",
54
54
  "fast-glob": "^3.3.3",
55
- "ioredis": "^5.7.0",
56
- "pathe": "^1.1.2"
55
+ "ioredis": "^5.9.2",
56
+ "pathe": "^2.0.3"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@nuxt/devtools": "^2.6.3",
@@ -66,7 +66,7 @@
66
66
  "@vitest/coverage-v8": "^3.2.4",
67
67
  "changelogen": "^0.6.2",
68
68
  "eslint": "^9.34.0",
69
- "happy-dom": "^18.0.1",
69
+ "happy-dom": "^20.0.11",
70
70
  "nuxt": "^4.0.3",
71
71
  "typescript": "~5.9.2",
72
72
  "vitepress": "^2.0.0-alpha.12",
@@ -1,9 +0,0 @@
1
- const name = "nuxt-processor";
2
- const version = "0.0.12";
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 };