bunqueue 2.8.38 → 2.8.40
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/dist/application/backgroundTasks.js +9 -0
- package/dist/application/cleanupTasks.js +31 -11
- package/dist/application/contextFactory.d.ts +3 -0
- package/dist/application/contextFactory.js +6 -0
- package/dist/application/dependencyResultTracker.d.ts +17 -0
- package/dist/application/dependencyResultTracker.js +71 -0
- package/dist/application/operations/ack.d.ts +2 -0
- package/dist/application/operations/ack.js +6 -0
- package/dist/application/operations/ackHelpers.d.ts +2 -1
- package/dist/application/operations/ackHelpers.js +6 -0
- package/dist/application/operations/jobManagement.d.ts +2 -0
- package/dist/application/operations/jobManagement.js +10 -4
- package/dist/application/operations/jobStateTransitions.js +1 -0
- package/dist/application/operations/pull.d.ts +2 -2
- package/dist/application/operations/pull.js +43 -10
- package/dist/application/operations/push.d.ts +2 -0
- package/dist/application/operations/pushInsert.d.ts +4 -0
- package/dist/application/operations/pushInsert.js +6 -0
- package/dist/application/operations/queryOperations.d.ts +2 -0
- package/dist/application/operations/queryOperations.js +5 -1
- package/dist/application/operations/queueControl.d.ts +2 -0
- package/dist/application/operations/queueControl.js +4 -0
- package/dist/application/queueManager.d.ts +5 -4
- package/dist/application/queueManager.js +37 -11
- package/dist/application/types.d.ts +2 -0
- package/dist/cli/client.js +6 -47
- package/dist/cli/commandRegistry.d.ts +27 -0
- package/dist/cli/commandRegistry.js +40 -0
- package/dist/cli/commandRouter.d.ts +3 -0
- package/dist/cli/commandRouter.js +44 -0
- package/dist/cli/commands/backup.js +1 -1
- package/dist/cli/commands/core.js +54 -2
- package/dist/cli/commands/doctor.d.ts +50 -5
- package/dist/cli/commands/doctor.js +125 -108
- package/dist/cli/commands/types.js +5 -1
- package/dist/cli/globalOptions.d.ts +16 -0
- package/dist/cli/globalOptions.js +192 -0
- package/dist/cli/help.d.ts +9 -0
- package/dist/cli/help.js +42 -21
- package/dist/cli/index.d.ts +1 -25
- package/dist/cli/index.js +84 -348
- package/dist/cli/localOutput.d.ts +22 -0
- package/dist/cli/localOutput.js +45 -0
- package/dist/client/queue/dlqOps.js +1 -3
- package/dist/client/tcp/client.js +10 -8
- package/dist/domain/queue/shard.d.ts +2 -2
- package/dist/domain/queue/shard.js +3 -3
- package/dist/domain/queue/waiterManager.d.ts +2 -2
- package/dist/domain/queue/waiterManager.js +26 -5
- package/dist/infrastructure/cloud/wsSender.js +4 -4
- package/dist/infrastructure/persistence/schema.d.ts +2 -2
- package/dist/infrastructure/persistence/schema.js +7 -2
- package/dist/infrastructure/persistence/sqlite.d.ts +5 -1
- package/dist/infrastructure/persistence/sqlite.js +10 -2
- package/dist/infrastructure/persistence/sqliteSerializer.js +1 -1
- package/dist/infrastructure/persistence/statements.d.ts +2 -1
- package/dist/infrastructure/persistence/statements.js +3 -2
- package/dist/infrastructure/server/handlers/core.js +4 -4
- package/dist/infrastructure/server/tcp.d.ts +1 -0
- package/dist/infrastructure/server/tcp.js +23 -12
- package/dist/infrastructure/server/types.d.ts +2 -0
- package/dist/shared/msgpack.d.ts +3 -0
- package/dist/shared/msgpack.js +70 -0
- package/package.json +1 -1
|
@@ -1,128 +1,145 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* bunqueue doctor - Diagnostic command
|
|
3
|
-
* Checks client/server version, connectivity, health, and queue state
|
|
4
|
-
*/
|
|
5
1
|
import { VERSION } from '../../shared/version';
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
const style = {
|
|
3
|
+
green: '\x1b[32m',
|
|
4
|
+
red: '\x1b[31m',
|
|
5
|
+
yellow: '\x1b[33m',
|
|
6
|
+
dim: '\x1b[2m',
|
|
7
|
+
bold: '\x1b[1m',
|
|
8
|
+
reset: '\x1b[0m',
|
|
9
|
+
};
|
|
10
|
+
export async function fetchDoctorHealth(host, httpPort) {
|
|
11
|
+
const endpoint = `${host}:${httpPort}`;
|
|
12
|
+
try {
|
|
13
|
+
const response = await fetch(`http://${endpoint}/health`, {
|
|
14
|
+
signal: AbortSignal.timeout(5000),
|
|
15
|
+
});
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
return { kind: 'http-error', endpoint, status: response.status };
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
kind: 'ok',
|
|
21
|
+
endpoint,
|
|
22
|
+
health: (await response.json()),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return {
|
|
27
|
+
kind: 'network-error',
|
|
28
|
+
endpoint,
|
|
29
|
+
message: error instanceof Error ? error.message : String(error),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
14
32
|
}
|
|
15
|
-
|
|
16
|
-
|
|
33
|
+
/** Evaluate diagnostics without performing I/O or reading clocks. */
|
|
34
|
+
export function evaluateDoctor(input) {
|
|
35
|
+
if (input.kind !== 'ok') {
|
|
36
|
+
const error = input.kind === 'http-error' ? `HTTP ${input.status} from ${input.endpoint}` : input.message;
|
|
37
|
+
return {
|
|
38
|
+
clientVersion: VERSION,
|
|
39
|
+
endpoint: input.endpoint,
|
|
40
|
+
reachable: false,
|
|
41
|
+
error,
|
|
42
|
+
issues: 1,
|
|
43
|
+
fatal: true,
|
|
44
|
+
exitCode: 1,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const health = input.health;
|
|
48
|
+
let issues = 0;
|
|
49
|
+
if (health.version && health.version !== VERSION)
|
|
50
|
+
issues++;
|
|
51
|
+
if (health.status !== 'healthy')
|
|
52
|
+
issues++;
|
|
53
|
+
if ((health.queues?.dlq ?? 0) > 0)
|
|
54
|
+
issues++;
|
|
55
|
+
if ((health.memory?.rss ?? 0) > 512)
|
|
56
|
+
issues++;
|
|
57
|
+
return {
|
|
58
|
+
clientVersion: VERSION,
|
|
59
|
+
endpoint: input.endpoint,
|
|
60
|
+
reachable: true,
|
|
61
|
+
health,
|
|
62
|
+
issues,
|
|
63
|
+
fatal: false,
|
|
64
|
+
exitCode: issues > 0 ? 1 : 0,
|
|
65
|
+
};
|
|
17
66
|
}
|
|
18
|
-
function
|
|
19
|
-
|
|
67
|
+
function mark(kind, message) {
|
|
68
|
+
const decoration = kind === 'pass' ? `${style.green}✓` : kind === 'fail' ? `${style.red}✗` : `${style.yellow}!`;
|
|
69
|
+
return ` ${decoration}${style.reset} ${message}`;
|
|
20
70
|
}
|
|
21
|
-
function
|
|
22
|
-
|
|
71
|
+
function formatUptime(uptime) {
|
|
72
|
+
const hours = Math.floor(uptime / 3600);
|
|
73
|
+
const minutes = Math.floor((uptime % 3600) / 60);
|
|
74
|
+
const seconds = uptime % 60;
|
|
75
|
+
const parts = [];
|
|
76
|
+
if (hours > 0)
|
|
77
|
+
parts.push(`${hours}h`);
|
|
78
|
+
if (minutes > 0)
|
|
79
|
+
parts.push(`${minutes}m`);
|
|
80
|
+
parts.push(`${seconds}s`);
|
|
81
|
+
return parts.join(' ');
|
|
23
82
|
}
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
health = (await resp.json());
|
|
38
|
-
pass(`Reachable at ${host}:${httpPort}`);
|
|
39
|
-
}
|
|
83
|
+
export function formatDoctorText(report) {
|
|
84
|
+
const lines = [
|
|
85
|
+
'',
|
|
86
|
+
`${style.bold}bunqueue doctor${style.reset}`,
|
|
87
|
+
'',
|
|
88
|
+
`${style.bold}Client${style.reset}`,
|
|
89
|
+
mark('pass', `Version: ${report.clientVersion}`),
|
|
90
|
+
'',
|
|
91
|
+
`${style.bold}Server${style.reset}`,
|
|
92
|
+
];
|
|
93
|
+
if (!report.reachable) {
|
|
94
|
+
if (report.error?.startsWith('HTTP '))
|
|
95
|
+
lines.push(mark('fail', report.error));
|
|
40
96
|
else {
|
|
41
|
-
fail
|
|
42
|
-
|
|
97
|
+
lines.push(mark('fail', `Not reachable at ${report.endpoint}`));
|
|
98
|
+
if (report.error)
|
|
99
|
+
lines.push(` ${style.dim}${report.error}${style.reset}`);
|
|
43
100
|
}
|
|
101
|
+
lines.push('', `${style.red}${style.bold}Cannot continue without server connection.${style.reset}`, `${style.dim}Start the server or use --port to specify the TCP port.${style.reset}`, '');
|
|
102
|
+
return lines.join('\n');
|
|
44
103
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
info(err instanceof Error ? err.message : String(err));
|
|
48
|
-
issues++;
|
|
49
|
-
}
|
|
50
|
-
if (!health) {
|
|
51
|
-
console.log(`\n${red}${bold}Cannot continue without server connection.${reset}`);
|
|
52
|
-
console.log(`${dim}Start the server or use --port to specify the TCP port.${reset}\n`);
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
// 3. Server version + mismatch check
|
|
104
|
+
const health = report.health ?? {};
|
|
105
|
+
lines.push(mark('pass', `Reachable at ${report.endpoint}`));
|
|
56
106
|
if (health.version) {
|
|
57
|
-
pass
|
|
107
|
+
lines.push(mark('pass', `Version: ${health.version}`));
|
|
58
108
|
if (health.version !== VERSION) {
|
|
59
|
-
warn
|
|
60
|
-
|
|
61
|
-
issues++;
|
|
109
|
+
lines.push(mark('warn', `Version mismatch! Client=${VERSION}, Server=${health.version}`));
|
|
110
|
+
lines.push(` ${style.dim}Update both client and server to the same version${style.reset}`);
|
|
62
111
|
}
|
|
63
112
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
fail(`Status: ${health.status ?? 'unknown'}`);
|
|
70
|
-
issues++;
|
|
71
|
-
}
|
|
72
|
-
// 5. Uptime
|
|
113
|
+
lines.push(health.status === 'healthy'
|
|
114
|
+
? mark('pass', 'Status: healthy')
|
|
115
|
+
: mark('fail', `Status: ${health.status ?? 'unknown'}`));
|
|
73
116
|
if (health.uptime !== undefined) {
|
|
74
|
-
|
|
75
|
-
const mins = Math.floor((health.uptime % 3600) / 60);
|
|
76
|
-
const secs = health.uptime % 60;
|
|
77
|
-
const parts = [];
|
|
78
|
-
if (hrs > 0)
|
|
79
|
-
parts.push(`${hrs}h`);
|
|
80
|
-
if (mins > 0)
|
|
81
|
-
parts.push(`${mins}m`);
|
|
82
|
-
parts.push(`${secs}s`);
|
|
83
|
-
pass(`Uptime: ${parts.join(' ')}`);
|
|
117
|
+
lines.push(mark('pass', `Uptime: ${formatUptime(health.uptime)}`));
|
|
84
118
|
}
|
|
85
|
-
// 6. Connections
|
|
86
119
|
if (health.connections) {
|
|
87
|
-
const
|
|
88
|
-
pass
|
|
120
|
+
const connections = health.connections;
|
|
121
|
+
lines.push(mark('pass', `Connections: TCP=${connections.tcp ?? 0}, WS=${connections.ws ?? 0}, SSE=${connections.sse ?? 0}`));
|
|
89
122
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
pass(`Delayed: ${q.delayed ?? 0}`);
|
|
97
|
-
pass(`Completed: ${q.completed ?? 0}`);
|
|
98
|
-
if ((q.dlq ?? 0) > 0) {
|
|
99
|
-
warn(`DLQ: ${q.dlq} (dead-letter jobs need attention)`);
|
|
100
|
-
issues++;
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
pass(`DLQ: 0`);
|
|
104
|
-
}
|
|
123
|
+
lines.push('', `${style.bold}Queues${style.reset}`);
|
|
124
|
+
if (health.queues) {
|
|
125
|
+
const queues = health.queues;
|
|
126
|
+
lines.push(mark('pass', `Waiting: ${queues.waiting ?? 0}`), mark('pass', `Active: ${queues.active ?? 0}`), mark('pass', `Delayed: ${queues.delayed ?? 0}`), mark('pass', `Completed: ${queues.completed ?? 0}`), (queues.dlq ?? 0) > 0
|
|
127
|
+
? mark('warn', `DLQ: ${queues.dlq} (dead-letter jobs need attention)`)
|
|
128
|
+
: mark('pass', 'DLQ: 0'));
|
|
105
129
|
}
|
|
106
|
-
|
|
107
|
-
console.log(`\n${bold}Memory${reset}`);
|
|
130
|
+
lines.push('', `${style.bold}Memory${style.reset}`);
|
|
108
131
|
if (health.memory) {
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (rss > 512) {
|
|
115
|
-
warn(`High memory usage (${rss}MB RSS)`);
|
|
116
|
-
issues++;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// Summary
|
|
120
|
-
console.log('');
|
|
121
|
-
if (issues === 0) {
|
|
122
|
-
console.log(`${green}${bold}All checks passed.${reset}\n`);
|
|
132
|
+
const heapUsed = health.memory.heapUsed ?? 0;
|
|
133
|
+
const rss = health.memory.rss ?? 0;
|
|
134
|
+
lines.push(mark('pass', `Heap: ${heapUsed}MB`), mark('pass', `RSS: ${rss}MB`));
|
|
135
|
+
if (rss > 512)
|
|
136
|
+
lines.push(mark('warn', `High memory usage (${rss}MB RSS)`));
|
|
123
137
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
lines.push('', report.issues === 0
|
|
139
|
+
? `${style.green}${style.bold}All checks passed.${style.reset}`
|
|
140
|
+
: `${style.yellow}${style.bold}${report.issues} issue${report.issues > 1 ? 's' : ''} found.${style.reset}`, '');
|
|
141
|
+
return lines.join('\n');
|
|
142
|
+
}
|
|
143
|
+
export async function runDoctor(host, httpPort) {
|
|
144
|
+
return evaluateDoctor(await fetchDoctorHealth(host, httpPort));
|
|
128
145
|
}
|
|
@@ -33,7 +33,11 @@ export function parseNumberArg(value, name) {
|
|
|
33
33
|
if (!/^-?\d+$/.test(value)) {
|
|
34
34
|
throw new CommandError(`Invalid number for ${name}: ${value}`);
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
const parsed = Number(value);
|
|
37
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
38
|
+
throw new CommandError(`Invalid number for ${name}: ${value}`);
|
|
39
|
+
}
|
|
40
|
+
return parsed === 0 ? 0 : parsed;
|
|
37
41
|
}
|
|
38
42
|
/** Parse job ID argument (UUIDs, numeric IDs, or custom IDs) */
|
|
39
43
|
export function parseBigIntArg(value, name) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface GlobalOptions {
|
|
2
|
+
host: string;
|
|
3
|
+
port: number;
|
|
4
|
+
token?: string;
|
|
5
|
+
tls?: boolean | {
|
|
6
|
+
rejectUnauthorized?: boolean;
|
|
7
|
+
caFile?: string;
|
|
8
|
+
};
|
|
9
|
+
json: boolean;
|
|
10
|
+
help: boolean;
|
|
11
|
+
version: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function parseGlobalOptions(allArgs?: string[]): {
|
|
14
|
+
options: GlobalOptions;
|
|
15
|
+
commandArgs: string[];
|
|
16
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { resolveToken } from '../client/resolveToken';
|
|
2
|
+
function resolveEnvPort(currentPort) {
|
|
3
|
+
const envPort = Bun.env.TCP_PORT ?? Bun.env.BUNQUEUE_TCP_PORT ?? Bun.env.BQ_TCP_PORT;
|
|
4
|
+
if (!envPort)
|
|
5
|
+
return currentPort;
|
|
6
|
+
const parsed = parseInt(envPort, 10);
|
|
7
|
+
if (Number.isNaN(parsed) || parsed < 1 || parsed > 65535) {
|
|
8
|
+
console.warn(`Warning: Invalid env port "${envPort}". Using ${currentPort}.`);
|
|
9
|
+
return currentPort;
|
|
10
|
+
}
|
|
11
|
+
return parsed;
|
|
12
|
+
}
|
|
13
|
+
function resolveEnvHost(currentHost) {
|
|
14
|
+
return Bun.env.HOST ?? Bun.env.BUNQUEUE_HOST ?? Bun.env.BQ_HOST ?? currentHost;
|
|
15
|
+
}
|
|
16
|
+
function applyTlsFlag(arg, allArgs, index, state, commandArgs) {
|
|
17
|
+
if (arg === '--tls') {
|
|
18
|
+
state.enabled = true;
|
|
19
|
+
return index;
|
|
20
|
+
}
|
|
21
|
+
if (arg === '--tls-no-verify') {
|
|
22
|
+
state.noVerify = true;
|
|
23
|
+
return index;
|
|
24
|
+
}
|
|
25
|
+
if (arg === '--tls-ca') {
|
|
26
|
+
const value = allArgs[index + 1];
|
|
27
|
+
if (value === undefined || value.startsWith('-')) {
|
|
28
|
+
console.warn('Warning: --tls-ca requires a file path. Option ignored.');
|
|
29
|
+
return index;
|
|
30
|
+
}
|
|
31
|
+
state.caFile = value;
|
|
32
|
+
return index + 1;
|
|
33
|
+
}
|
|
34
|
+
if (arg.startsWith('--tls-ca=')) {
|
|
35
|
+
const value = arg.slice(9);
|
|
36
|
+
if (value)
|
|
37
|
+
state.caFile = value;
|
|
38
|
+
else
|
|
39
|
+
console.warn('Warning: --tls-ca= requires a file path. Option ignored.');
|
|
40
|
+
return index;
|
|
41
|
+
}
|
|
42
|
+
commandArgs.push(arg);
|
|
43
|
+
return index;
|
|
44
|
+
}
|
|
45
|
+
function buildTlsOption(state) {
|
|
46
|
+
if (state.noVerify || state.caFile !== undefined) {
|
|
47
|
+
return {
|
|
48
|
+
...(state.noVerify && { rejectUnauthorized: false }),
|
|
49
|
+
...(state.caFile !== undefined && { caFile: state.caFile }),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return state.enabled ? true : undefined;
|
|
53
|
+
}
|
|
54
|
+
function commandOwnsShortT(commandArgs) {
|
|
55
|
+
return commandArgs[0] === 'pull' || (commandArgs[0] === 'job' && commandArgs[1] === 'wait');
|
|
56
|
+
}
|
|
57
|
+
function applyTokenFlag(arg, allArgs, index, state, commandArgs) {
|
|
58
|
+
if (arg === '-t' && commandOwnsShortT(commandArgs)) {
|
|
59
|
+
commandArgs.push(arg);
|
|
60
|
+
return index;
|
|
61
|
+
}
|
|
62
|
+
const value = allArgs[index + 1];
|
|
63
|
+
if (value === undefined || value.startsWith('-')) {
|
|
64
|
+
console.warn('Warning: --token requires a value. Token not set.');
|
|
65
|
+
return index;
|
|
66
|
+
}
|
|
67
|
+
state.token = value;
|
|
68
|
+
return index + 1;
|
|
69
|
+
}
|
|
70
|
+
function applyHostFlag(allArgs, index, state) {
|
|
71
|
+
const value = allArgs[index + 1];
|
|
72
|
+
if (value === undefined || value.startsWith('-')) {
|
|
73
|
+
console.warn('Warning: --host requires a value. Using localhost.');
|
|
74
|
+
return index;
|
|
75
|
+
}
|
|
76
|
+
state.host = value;
|
|
77
|
+
state.hostExplicit = true;
|
|
78
|
+
return index + 1;
|
|
79
|
+
}
|
|
80
|
+
function applyPortFlag(allArgs, index, state) {
|
|
81
|
+
const value = allArgs[index + 1];
|
|
82
|
+
if (value === undefined || value.startsWith('-')) {
|
|
83
|
+
console.warn('Warning: --port requires a value. Using default port 6789.');
|
|
84
|
+
return index;
|
|
85
|
+
}
|
|
86
|
+
const parsed = parseInt(value, 10);
|
|
87
|
+
if (Number.isNaN(parsed) || parsed < 1 || parsed > 65535) {
|
|
88
|
+
console.warn(`Warning: Invalid port "${value}". Using default port 6789.`);
|
|
89
|
+
state.port = 6789;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
state.port = parsed;
|
|
93
|
+
state.portExplicit = true;
|
|
94
|
+
}
|
|
95
|
+
return index + 1;
|
|
96
|
+
}
|
|
97
|
+
function warnAmbiguousAttachedShort(arg, commandArgs) {
|
|
98
|
+
if (!/^-[Hpthv][^-\s]/.test(arg))
|
|
99
|
+
return;
|
|
100
|
+
if (arg.startsWith('-t') && commandOwnsShortT(commandArgs))
|
|
101
|
+
return;
|
|
102
|
+
console.warn(`Warning: "${arg}" looks like a short flag with an attached value; ` +
|
|
103
|
+
`use the separated form ("${arg.slice(0, 2)} ${arg.slice(2)}") or the long form.`);
|
|
104
|
+
}
|
|
105
|
+
export function parseGlobalOptions(allArgs = process.argv.slice(2)) {
|
|
106
|
+
const hp = {
|
|
107
|
+
host: 'localhost',
|
|
108
|
+
port: 6789,
|
|
109
|
+
hostExplicit: false,
|
|
110
|
+
portExplicit: false,
|
|
111
|
+
};
|
|
112
|
+
const tokenState = {};
|
|
113
|
+
const tlsState = { enabled: false, noVerify: false };
|
|
114
|
+
const commandArgs = [];
|
|
115
|
+
let json = false;
|
|
116
|
+
let help = false;
|
|
117
|
+
let version = false;
|
|
118
|
+
for (let index = 0; index < allArgs.length; index++) {
|
|
119
|
+
const arg = allArgs[index];
|
|
120
|
+
if (arg === '--') {
|
|
121
|
+
commandArgs.push(...allArgs.slice(index + 1));
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
if (arg === '--host' || arg === '-H') {
|
|
125
|
+
index = applyHostFlag(allArgs, index, hp);
|
|
126
|
+
}
|
|
127
|
+
else if (arg === '--port' || arg === '-p') {
|
|
128
|
+
index = applyPortFlag(allArgs, index, hp);
|
|
129
|
+
}
|
|
130
|
+
else if (arg === '--token' || arg === '-t') {
|
|
131
|
+
index = applyTokenFlag(arg, allArgs, index, tokenState, commandArgs);
|
|
132
|
+
}
|
|
133
|
+
else if (arg.startsWith('--tls')) {
|
|
134
|
+
index = applyTlsFlag(arg, allArgs, index, tlsState, commandArgs);
|
|
135
|
+
}
|
|
136
|
+
else if (arg === '--json') {
|
|
137
|
+
json = true;
|
|
138
|
+
}
|
|
139
|
+
else if (arg === '--help' || (arg === '-h' && commandArgs.length === 0)) {
|
|
140
|
+
help = true;
|
|
141
|
+
}
|
|
142
|
+
else if (arg === '--version' || (arg === '-v' && commandArgs.length === 0)) {
|
|
143
|
+
version = true;
|
|
144
|
+
}
|
|
145
|
+
else if (arg.startsWith('--host=')) {
|
|
146
|
+
hp.host = arg.slice(7);
|
|
147
|
+
hp.hostExplicit = true;
|
|
148
|
+
}
|
|
149
|
+
else if (arg.startsWith('--port=')) {
|
|
150
|
+
const raw = arg.slice(7);
|
|
151
|
+
const parsed = parseInt(raw, 10);
|
|
152
|
+
if (Number.isNaN(parsed) || parsed < 1 || parsed > 65535) {
|
|
153
|
+
console.warn(`Warning: Invalid port "${raw}". Using default port 6789.`);
|
|
154
|
+
hp.port = 6789;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
hp.port = parsed;
|
|
158
|
+
hp.portExplicit = true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (arg.startsWith('--token=')) {
|
|
162
|
+
const value = arg.slice(8);
|
|
163
|
+
if (value)
|
|
164
|
+
tokenState.token = value;
|
|
165
|
+
else
|
|
166
|
+
console.warn('Warning: --token= requires a value. Token not set.');
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
warnAmbiguousAttachedShort(arg, commandArgs);
|
|
170
|
+
commandArgs.push(arg);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const serverMode = commandArgs[0] === 'start' || commandArgs.length === 0 || commandArgs[0]?.startsWith('-');
|
|
174
|
+
if (serverMode) {
|
|
175
|
+
if (hp.hostExplicit)
|
|
176
|
+
commandArgs.push('--host', hp.host);
|
|
177
|
+
if (hp.portExplicit)
|
|
178
|
+
commandArgs.push('--tcp-port', String(hp.port));
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
options: {
|
|
182
|
+
host: hp.hostExplicit ? hp.host : resolveEnvHost(hp.host),
|
|
183
|
+
port: hp.portExplicit ? hp.port : resolveEnvPort(hp.port),
|
|
184
|
+
token: resolveToken(tokenState.token),
|
|
185
|
+
tls: buildTlsOption(tlsState),
|
|
186
|
+
json,
|
|
187
|
+
help,
|
|
188
|
+
version,
|
|
189
|
+
},
|
|
190
|
+
commandArgs,
|
|
191
|
+
};
|
|
192
|
+
}
|
package/dist/cli/help.d.ts
CHANGED
|
@@ -3,11 +3,20 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/** Print version information */
|
|
5
5
|
export declare function printVersion(version: string): void;
|
|
6
|
+
export declare function renderVersion(version: string): string;
|
|
7
|
+
/** Render main help, optionally without terminal escapes for JSON output. */
|
|
8
|
+
export declare function renderHelp(color?: boolean): string;
|
|
6
9
|
/** Print main help */
|
|
7
10
|
export declare function printHelp(): void;
|
|
11
|
+
/** Render server help. */
|
|
12
|
+
export declare function renderServerHelp(): string;
|
|
8
13
|
/** Print server help */
|
|
9
14
|
export declare function printServerHelp(): void;
|
|
15
|
+
/** Render push command help. */
|
|
16
|
+
export declare function renderPushHelp(): string;
|
|
10
17
|
/** Print push command help */
|
|
11
18
|
export declare function printPushHelp(): void;
|
|
19
|
+
/** Render cron add help. */
|
|
20
|
+
export declare function renderCronAddHelp(): string;
|
|
12
21
|
/** Print cron add help */
|
|
13
22
|
export declare function printCronAddHelp(): void;
|
package/dist/cli/help.js
CHANGED
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/** Print version information */
|
|
5
5
|
export function printVersion(version) {
|
|
6
|
-
console.log(
|
|
6
|
+
console.log(renderVersion(version));
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
8
|
+
export function renderVersion(version) {
|
|
9
|
+
return `bunqueue v${version}`;
|
|
10
|
+
}
|
|
11
|
+
/** Render main help, optionally without terminal escapes for JSON output. */
|
|
12
|
+
export function renderHelp(color = true) {
|
|
13
|
+
const magenta = color ? '\x1b[35m' : '';
|
|
14
|
+
const reset = color ? '\x1b[0m' : '';
|
|
15
|
+
const dim = color ? '\x1b[2m' : '';
|
|
16
|
+
const bold = color ? '\x1b[1m' : '';
|
|
17
|
+
return `
|
|
15
18
|
${magenta} (\\(\\ ${reset}
|
|
16
19
|
${magenta} ( -.-) ${bold}bunqueue${reset} ${dim}- High-performance job queue for Bun${reset}
|
|
17
20
|
${magenta} o_(")(") ${reset}
|
|
@@ -85,11 +88,13 @@ MONITORING:
|
|
|
85
88
|
stats Show server statistics
|
|
86
89
|
metrics Show Prometheus metrics
|
|
87
90
|
health Health check
|
|
91
|
+
ping Check TCP connectivity
|
|
88
92
|
version Show client and server version
|
|
89
93
|
doctor Run diagnostics (version, health, queues)
|
|
90
94
|
|
|
91
95
|
BACKUP (S3):
|
|
92
96
|
backup now Create backup immediately
|
|
97
|
+
backup create Alias for backup now
|
|
93
98
|
backup list List available backups
|
|
94
99
|
backup restore <key> [-f] Restore from backup
|
|
95
100
|
backup status Show backup configuration
|
|
@@ -115,11 +120,15 @@ EXAMPLES:
|
|
|
115
120
|
bunqueue job get 12345
|
|
116
121
|
bunqueue queue list
|
|
117
122
|
bunqueue stats --json
|
|
118
|
-
|
|
123
|
+
`;
|
|
119
124
|
}
|
|
120
|
-
/** Print
|
|
121
|
-
export function
|
|
122
|
-
console.log(
|
|
125
|
+
/** Print main help */
|
|
126
|
+
export function printHelp() {
|
|
127
|
+
console.log(renderHelp());
|
|
128
|
+
}
|
|
129
|
+
/** Render server help. */
|
|
130
|
+
export function renderServerHelp() {
|
|
131
|
+
return `
|
|
123
132
|
Usage: bunqueue start [options]
|
|
124
133
|
|
|
125
134
|
Start the bunQ server.
|
|
@@ -138,11 +147,15 @@ Examples:
|
|
|
138
147
|
bunqueue start
|
|
139
148
|
bunqueue start --tcp-port 7000 --http-port 7001
|
|
140
149
|
bunqueue start --data-path ./data/queue.db
|
|
141
|
-
|
|
150
|
+
`;
|
|
142
151
|
}
|
|
143
|
-
/** Print
|
|
144
|
-
export function
|
|
145
|
-
console.log(
|
|
152
|
+
/** Print server help */
|
|
153
|
+
export function printServerHelp() {
|
|
154
|
+
console.log(renderServerHelp());
|
|
155
|
+
}
|
|
156
|
+
/** Render push command help. */
|
|
157
|
+
export function renderPushHelp() {
|
|
158
|
+
return `
|
|
146
159
|
Usage: bunqueue push <queue> <data> [options]
|
|
147
160
|
|
|
148
161
|
Push a job to a queue.
|
|
@@ -171,11 +184,15 @@ Examples:
|
|
|
171
184
|
bunqueue push emails '{"to":"user@test.com"}'
|
|
172
185
|
bunqueue push tasks '{"action":"sync"}' --priority 10
|
|
173
186
|
bunqueue push jobs '{"id":1}' --delay 60000 --max-attempts 5
|
|
174
|
-
|
|
187
|
+
`;
|
|
175
188
|
}
|
|
176
|
-
/** Print
|
|
177
|
-
export function
|
|
178
|
-
console.log(
|
|
189
|
+
/** Print push command help */
|
|
190
|
+
export function printPushHelp() {
|
|
191
|
+
console.log(renderPushHelp());
|
|
192
|
+
}
|
|
193
|
+
/** Render cron add help. */
|
|
194
|
+
export function renderCronAddHelp() {
|
|
195
|
+
return `
|
|
179
196
|
Usage: bunqueue cron add <name> [options]
|
|
180
197
|
|
|
181
198
|
Add a cron job.
|
|
@@ -194,5 +211,9 @@ Options:
|
|
|
194
211
|
Examples:
|
|
195
212
|
bunqueue cron add hourly-cleanup -q maintenance -d '{"task":"cleanup"}' -s "0 * * * *"
|
|
196
213
|
bunqueue cron add health-check -q monitoring -d '{}' -e 60000
|
|
197
|
-
|
|
214
|
+
`;
|
|
215
|
+
}
|
|
216
|
+
/** Print cron add help */
|
|
217
|
+
export function printCronAddHelp() {
|
|
218
|
+
console.log(renderCronAddHelp());
|
|
198
219
|
}
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,27 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
* bunqueue CLI Entry Point
|
|
4
|
-
* Routes to server or client mode based on arguments
|
|
5
|
-
*/
|
|
6
|
-
/** Global CLI options */
|
|
7
|
-
interface GlobalOptions {
|
|
8
|
-
host: string;
|
|
9
|
-
port: number;
|
|
10
|
-
token?: string;
|
|
11
|
-
/** TLS to the server: true = verify with system CAs, object = custom CA / no-verify */
|
|
12
|
-
tls?: boolean | {
|
|
13
|
-
rejectUnauthorized?: boolean;
|
|
14
|
-
caFile?: string;
|
|
15
|
-
};
|
|
16
|
-
json: boolean;
|
|
17
|
-
help: boolean;
|
|
18
|
-
version: boolean;
|
|
19
|
-
}
|
|
20
|
-
/** Parse global options from process.argv */
|
|
21
|
-
export declare function parseGlobalOptions(): {
|
|
22
|
-
options: GlobalOptions;
|
|
23
|
-
commandArgs: string[];
|
|
24
|
-
};
|
|
25
|
-
/** Main CLI entry */
|
|
2
|
+
export { parseGlobalOptions } from './globalOptions';
|
|
26
3
|
export declare function main(): Promise<void>;
|
|
27
|
-
export {};
|