@tonk/cli 0.3.3 → 0.4.0

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.
Files changed (129) hide show
  1. package/README.md +15 -202
  2. package/bin/tonk.js +36 -1
  3. package/package.json +23 -89
  4. package/dist/commands/auth.d.ts +0 -3
  5. package/dist/commands/auth.d.ts.map +0 -1
  6. package/dist/commands/auth.js +0 -184
  7. package/dist/commands/auth.js.map +0 -1
  8. package/dist/commands/create.d.ts +0 -3
  9. package/dist/commands/create.d.ts.map +0 -1
  10. package/dist/commands/create.js +0 -55
  11. package/dist/commands/create.js.map +0 -1
  12. package/dist/commands/delete.d.ts +0 -3
  13. package/dist/commands/delete.d.ts.map +0 -1
  14. package/dist/commands/delete.js +0 -67
  15. package/dist/commands/delete.js.map +0 -1
  16. package/dist/commands/deploy.d.ts +0 -3
  17. package/dist/commands/deploy.d.ts.map +0 -1
  18. package/dist/commands/deploy.js +0 -336
  19. package/dist/commands/deploy.js.map +0 -1
  20. package/dist/commands/hello/index.d.ts +0 -3
  21. package/dist/commands/hello/index.d.ts.map +0 -1
  22. package/dist/commands/hello/index.js +0 -296
  23. package/dist/commands/hello/index.js.map +0 -1
  24. package/dist/commands/hello.d.ts +0 -3
  25. package/dist/commands/hello.d.ts.map +0 -1
  26. package/dist/commands/hello.js +0 -83
  27. package/dist/commands/hello.js.map +0 -1
  28. package/dist/commands/init.d.ts +0 -3
  29. package/dist/commands/init.d.ts.map +0 -1
  30. package/dist/commands/init.js +0 -137
  31. package/dist/commands/init.js.map +0 -1
  32. package/dist/commands/kill.d.ts +0 -3
  33. package/dist/commands/kill.d.ts.map +0 -1
  34. package/dist/commands/kill.js +0 -66
  35. package/dist/commands/kill.js.map +0 -1
  36. package/dist/commands/ls.d.ts +0 -3
  37. package/dist/commands/ls.d.ts.map +0 -1
  38. package/dist/commands/ls.js +0 -52
  39. package/dist/commands/ls.js.map +0 -1
  40. package/dist/commands/proxy.d.ts +0 -3
  41. package/dist/commands/proxy.d.ts.map +0 -1
  42. package/dist/commands/proxy.js +0 -86
  43. package/dist/commands/proxy.js.map +0 -1
  44. package/dist/commands/ps.d.ts +0 -3
  45. package/dist/commands/ps.d.ts.map +0 -1
  46. package/dist/commands/ps.js +0 -56
  47. package/dist/commands/ps.js.map +0 -1
  48. package/dist/commands/push.d.ts +0 -3
  49. package/dist/commands/push.d.ts.map +0 -1
  50. package/dist/commands/push.js +0 -238
  51. package/dist/commands/push.js.map +0 -1
  52. package/dist/commands/server.d.ts +0 -3
  53. package/dist/commands/server.d.ts.map +0 -1
  54. package/dist/commands/server.js +0 -676
  55. package/dist/commands/server.js.map +0 -1
  56. package/dist/commands/start.d.ts +0 -3
  57. package/dist/commands/start.d.ts.map +0 -1
  58. package/dist/commands/start.js +0 -82
  59. package/dist/commands/start.js.map +0 -1
  60. package/dist/commands/worker/commands.d.ts +0 -42
  61. package/dist/commands/worker/commands.d.ts.map +0 -1
  62. package/dist/commands/worker/commands.js +0 -968
  63. package/dist/commands/worker/commands.js.map +0 -1
  64. package/dist/commands/worker/index.d.ts +0 -7
  65. package/dist/commands/worker/index.d.ts.map +0 -1
  66. package/dist/commands/worker/index.js +0 -30
  67. package/dist/commands/worker/index.js.map +0 -1
  68. package/dist/commands/worker/utils/config.d.ts +0 -26
  69. package/dist/commands/worker/utils/config.d.ts.map +0 -1
  70. package/dist/commands/worker/utils/config.js +0 -197
  71. package/dist/commands/worker/utils/config.js.map +0 -1
  72. package/dist/commands/worker/utils/display.d.ts +0 -6
  73. package/dist/commands/worker/utils/display.d.ts.map +0 -1
  74. package/dist/commands/worker/utils/display.js +0 -32
  75. package/dist/commands/worker/utils/display.js.map +0 -1
  76. package/dist/commands/worker/utils/finder.d.ts +0 -12
  77. package/dist/commands/worker/utils/finder.d.ts.map +0 -1
  78. package/dist/commands/worker/utils/finder.js +0 -60
  79. package/dist/commands/worker/utils/finder.js.map +0 -1
  80. package/dist/config/environment.d.ts +0 -52
  81. package/dist/config/environment.d.ts.map +0 -1
  82. package/dist/config/environment.js +0 -83
  83. package/dist/config/environment.js.map +0 -1
  84. package/dist/index.d.ts +0 -1
  85. package/dist/index.d.ts.map +0 -1
  86. package/dist/index.js +0 -3
  87. package/dist/index.js.map +0 -1
  88. package/dist/lib/tonkAuth.d.ts +0 -21
  89. package/dist/lib/tonkAuth.d.ts.map +0 -1
  90. package/dist/lib/tonkAuth.js +0 -140
  91. package/dist/lib/tonkAuth.js.map +0 -1
  92. package/dist/lib/workerManager.d.ts +0 -60
  93. package/dist/lib/workerManager.d.ts.map +0 -1
  94. package/dist/lib/workerManager.js +0 -417
  95. package/dist/lib/workerManager.js.map +0 -1
  96. package/dist/scripts/aws/create-key.sh +0 -20
  97. package/dist/scripts/aws/ec2-dns.sh +0 -20
  98. package/dist/scripts/aws/provision.sh +0 -93
  99. package/dist/tonk.d.ts +0 -2
  100. package/dist/tonk.d.ts.map +0 -1
  101. package/dist/tonk.js +0 -106
  102. package/dist/tonk.js.map +0 -1
  103. package/dist/types/worker.d.ts +0 -161
  104. package/dist/types/worker.d.ts.map +0 -1
  105. package/dist/types/worker.js +0 -7
  106. package/dist/types/worker.js.map +0 -1
  107. package/dist/types/workerConfig.d.ts +0 -164
  108. package/dist/types/workerConfig.d.ts.map +0 -1
  109. package/dist/types/workerConfig.js +0 -80
  110. package/dist/types/workerConfig.js.map +0 -1
  111. package/dist/utils/analytics.d.ts +0 -26
  112. package/dist/utils/analytics.d.ts.map +0 -1
  113. package/dist/utils/analytics.js +0 -218
  114. package/dist/utils/analytics.js.map +0 -1
  115. package/dist/utils/messages.d.ts +0 -6
  116. package/dist/utils/messages.d.ts.map +0 -1
  117. package/dist/utils/messages.js +0 -18
  118. package/dist/utils/messages.js.map +0 -1
  119. package/dist/utils/serverUtils.d.ts +0 -5
  120. package/dist/utils/serverUtils.d.ts.map +0 -1
  121. package/dist/utils/serverUtils.js +0 -34
  122. package/dist/utils/serverUtils.js.map +0 -1
  123. package/dist/utils/version.d.ts +0 -2
  124. package/dist/utils/version.d.ts.map +0 -1
  125. package/dist/utils/version.js +0 -3
  126. package/dist/utils/version.js.map +0 -1
  127. package/scripts/aws/create-key.sh +0 -20
  128. package/scripts/aws/ec2-dns.sh +0 -20
  129. package/scripts/aws/provision.sh +0 -93
@@ -1,968 +0,0 @@
1
- import chalk from 'chalk';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import Table from 'cli-table3';
5
- import { promisify } from 'node:util';
6
- import { exec } from 'node:child_process';
7
- import { TonkWorkerManager } from '../../lib/workerManager.js';
8
- import { displayWorkerDetails } from './utils/display.js';
9
- import { findWorkerRoot, findAvailablePort } from './utils/finder.js';
10
- import { trackCommand, trackCommandError, trackCommandSuccess, shutdownAnalytics, } from '../../utils/analytics.js';
11
- import { readPackageJson, readWorkerConfigJs, updateWorkerConfig, promptForMissingOptions, generatePackageJsonContent, generateWorkerConfigJsContent, } from './utils/config.js';
12
- /**
13
- * Register the inspect command
14
- */
15
- export function registerInspectCommand(workerCommand) {
16
- workerCommand
17
- .command('inspect <nameOrId>')
18
- .description('Inspect a specific worker')
19
- .option('-s, --start', 'Start the worker')
20
- .option('-S, --stop', 'Stop the worker')
21
- .option('-c, --config <path>', 'Path to worker configuration file')
22
- .option('-p, --ping', 'Ping the worker to check its status')
23
- .action(async (nameOrId, options) => {
24
- const startTime = Date.now();
25
- try {
26
- trackCommand('worker-inspect', {
27
- nameOrId,
28
- start: options.start,
29
- stop: options.stop,
30
- config: !!options.config,
31
- ping: options.ping,
32
- });
33
- // Create worker manager
34
- const workerManager = new TonkWorkerManager();
35
- // Get worker
36
- const worker = await workerManager.findByNameOrId(nameOrId);
37
- if (!worker) {
38
- console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
39
- const duration = Date.now() - startTime;
40
- trackCommandError('worker-inspect', new Error('Worker not found'), duration, {
41
- nameOrId,
42
- });
43
- await shutdownAnalytics();
44
- process.exit(1);
45
- }
46
- // If no options provided, show worker details
47
- if (!options.start &&
48
- !options.stop &&
49
- !options.config &&
50
- !options.ping) {
51
- displayWorkerDetails(worker);
52
- const duration = Date.now() - startTime;
53
- trackCommandSuccess('worker-inspect', duration, {
54
- workerId: worker.id,
55
- workerName: worker.name,
56
- action: 'display',
57
- });
58
- await shutdownAnalytics();
59
- process.exit(0);
60
- }
61
- // Handle ping option
62
- if (options.ping) {
63
- console.log(chalk.blue(`Pinging worker '${worker.name}' at ${worker.endpoint}...`));
64
- // Check worker health
65
- const isHealthy = await workerManager.checkHealth(worker.id);
66
- if (isHealthy) {
67
- console.log(chalk.green(`Worker '${worker.name}' is active!`));
68
- }
69
- else {
70
- console.log(chalk.red(`Worker '${worker.name}' is not responding.`));
71
- }
72
- const duration = Date.now() - startTime;
73
- trackCommandSuccess('worker-inspect', duration, {
74
- workerId: worker.id,
75
- workerName: worker.name,
76
- action: 'ping',
77
- isHealthy,
78
- });
79
- await shutdownAnalytics();
80
- process.exit(0);
81
- }
82
- // Handle start option
83
- if (options.start) {
84
- console.log(chalk.blue(`Starting worker '${worker.name}'...`));
85
- await workerManager.start(worker.id);
86
- console.log(chalk.green(`Worker '${worker.name}' started successfully!`));
87
- const duration = Date.now() - startTime;
88
- trackCommandSuccess('worker-inspect', duration, {
89
- workerId: worker.id,
90
- workerName: worker.name,
91
- action: 'start',
92
- });
93
- await shutdownAnalytics();
94
- process.exit(0);
95
- }
96
- // Handle stop option
97
- if (options.stop) {
98
- console.log(chalk.blue(`Stopping worker '${worker.name}'...`));
99
- await workerManager.stop(worker.id);
100
- console.log(chalk.green(`Worker '${worker.name}' stopped successfully!`));
101
- const duration = Date.now() - startTime;
102
- trackCommandSuccess('worker-inspect', duration, {
103
- workerId: worker.id,
104
- workerName: worker.name,
105
- action: 'stop',
106
- });
107
- await shutdownAnalytics();
108
- process.exit(0);
109
- }
110
- // Handle config option
111
- if (options.config) {
112
- await updateWorkerConfig(workerManager, worker.id, options.config);
113
- const duration = Date.now() - startTime;
114
- trackCommandSuccess('worker-inspect', duration, {
115
- workerId: worker.id,
116
- workerName: worker.name,
117
- action: 'config',
118
- configPath: options.config,
119
- });
120
- await shutdownAnalytics();
121
- process.exit(0);
122
- }
123
- }
124
- catch (error) {
125
- const duration = Date.now() - startTime;
126
- trackCommandError('worker-inspect', error, duration, {
127
- nameOrId,
128
- options,
129
- });
130
- console.error(chalk.red('Failed to manage worker:'), error);
131
- await shutdownAnalytics();
132
- process.exit(1);
133
- }
134
- });
135
- }
136
- /**
137
- * Register the list command
138
- */
139
- export function registerListCommand(workerCommand) {
140
- workerCommand
141
- .command('ls')
142
- .description('List all registered workers')
143
- .action(async () => {
144
- const startTime = Date.now();
145
- try {
146
- trackCommand('worker-ls', {});
147
- // Create worker manager
148
- const workerManager = new TonkWorkerManager();
149
- // Get all workers
150
- const workers = await workerManager.list();
151
- if (workers.length === 0) {
152
- console.log(chalk.yellow('No workers registered yet.'));
153
- console.log(chalk.blue(`Use '${chalk.bold('tonk worker register')}' to register a worker.`));
154
- const duration = Date.now() - startTime;
155
- trackCommandSuccess('worker-ls', duration, {
156
- workerCount: 0,
157
- });
158
- await shutdownAnalytics();
159
- process.exit(0);
160
- }
161
- // Create a table for display
162
- const table = new Table({
163
- head: [
164
- chalk.cyan('ID'),
165
- chalk.cyan('Name'),
166
- chalk.cyan('Endpoint'),
167
- chalk.cyan('Protocol'),
168
- chalk.cyan('Status'),
169
- chalk.cyan('Last Seen'),
170
- ],
171
- colWidths: [24, 20, 30, 10, 10, 20],
172
- });
173
- // Add workers to table
174
- workers.forEach(worker => {
175
- const lastSeen = worker.status.lastSeen
176
- ? new Date(worker.status.lastSeen).toLocaleString()
177
- : 'Never';
178
- table.push([
179
- worker.id,
180
- worker.name,
181
- worker.endpoint,
182
- worker.protocol,
183
- worker.status.active
184
- ? chalk.green('Active')
185
- : chalk.yellow('Inactive'),
186
- lastSeen,
187
- ]);
188
- });
189
- console.log(chalk.bold(`Registered Workers (${workers.length}):`));
190
- console.log(table.toString());
191
- console.log(chalk.blue(`\nUse '${chalk.bold('tonk worker inspect <name or id>')}' to view details of a specific worker.`));
192
- const duration = Date.now() - startTime;
193
- trackCommandSuccess('worker-ls', duration, {
194
- workerCount: workers.length,
195
- activeWorkers: workers.filter(w => w.status.active).length,
196
- });
197
- await shutdownAnalytics();
198
- process.exit(0);
199
- }
200
- catch (error) {
201
- const duration = Date.now() - startTime;
202
- trackCommandError('worker-ls', error, duration);
203
- console.error(chalk.red('Failed to list workers:'), error);
204
- await shutdownAnalytics();
205
- process.exit(1);
206
- }
207
- });
208
- }
209
- /**
210
- * Register the remove command
211
- */
212
- export function registerRemoveCommand(workerCommand) {
213
- workerCommand
214
- .command('rm <nameOrId>')
215
- .description('Remove a registered worker')
216
- .action(async (nameOrId) => {
217
- const startTime = Date.now();
218
- try {
219
- trackCommand('worker-rm', {
220
- nameOrId,
221
- });
222
- // Create worker manager
223
- const workerManager = new TonkWorkerManager();
224
- // Get worker
225
- const worker = await workerManager.findByNameOrId(nameOrId);
226
- if (!worker) {
227
- console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
228
- const duration = Date.now() - startTime;
229
- trackCommandError('worker-rm', new Error('Worker not found'), duration, {
230
- nameOrId,
231
- });
232
- await shutdownAnalytics();
233
- process.exit(1);
234
- }
235
- // Remove worker
236
- await workerManager.remove(worker.id);
237
- console.log(chalk.green(`Worker '${worker.name}' (${worker.id}) removed successfully.`));
238
- const duration = Date.now() - startTime;
239
- trackCommandSuccess('worker-rm', duration, {
240
- workerId: worker.id,
241
- workerName: worker.name,
242
- });
243
- await shutdownAnalytics();
244
- process.exit(0);
245
- }
246
- catch (error) {
247
- const duration = Date.now() - startTime;
248
- trackCommandError('worker-rm', error, duration, {
249
- nameOrId,
250
- });
251
- console.error(chalk.red('Failed to remove worker:'), error);
252
- await shutdownAnalytics();
253
- process.exit(1);
254
- }
255
- });
256
- }
257
- /**
258
- * Register the ping command
259
- */
260
- export function registerPingCommand(workerCommand) {
261
- workerCommand
262
- .command('ping <nameOrId>')
263
- .description('Ping a worker to check its status')
264
- .action(async (nameOrId) => {
265
- const startTime = Date.now();
266
- try {
267
- trackCommand('worker-ping', {
268
- nameOrId,
269
- });
270
- // Create worker manager
271
- const workerManager = new TonkWorkerManager();
272
- // Get worker
273
- const worker = await workerManager.findByNameOrId(nameOrId);
274
- if (!worker) {
275
- console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
276
- const duration = Date.now() - startTime;
277
- trackCommandError('worker-ping', new Error('Worker not found'), duration, {
278
- nameOrId,
279
- });
280
- await shutdownAnalytics();
281
- process.exit(1);
282
- }
283
- console.log(chalk.blue(`Pinging worker '${worker.name}' at ${worker.endpoint}...`));
284
- // Check worker health
285
- const isHealthy = await workerManager.checkHealth(worker.id);
286
- if (isHealthy) {
287
- console.log(chalk.green(`Worker '${worker.name}' is active!`));
288
- }
289
- else {
290
- console.log(chalk.red(`Worker '${worker.name}' is not responding.`));
291
- }
292
- const duration = Date.now() - startTime;
293
- trackCommandSuccess('worker-ping', duration, {
294
- workerId: worker.id,
295
- workerName: worker.name,
296
- isHealthy,
297
- });
298
- await shutdownAnalytics();
299
- process.exit(0);
300
- }
301
- catch (error) {
302
- const duration = Date.now() - startTime;
303
- trackCommandError('worker-ping', error, duration, {
304
- nameOrId,
305
- });
306
- console.error(chalk.red('Failed to ping worker:'), error);
307
- await shutdownAnalytics();
308
- process.exit(1);
309
- }
310
- });
311
- }
312
- /**
313
- * Register the start command
314
- */
315
- export function registerStartCommand(workerCommand) {
316
- workerCommand
317
- .command('start <nameOrId>')
318
- .description('Start a worker')
319
- .action(async (nameOrId) => {
320
- const startTime = Date.now();
321
- try {
322
- trackCommand('worker-start', {
323
- nameOrId,
324
- });
325
- // Create worker manager
326
- const workerManager = new TonkWorkerManager();
327
- // Get worker
328
- const worker = await workerManager.findByNameOrId(nameOrId);
329
- if (!worker) {
330
- console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
331
- const duration = Date.now() - startTime;
332
- trackCommandError('worker-start', new Error('Worker not found'), duration, {
333
- nameOrId,
334
- });
335
- await shutdownAnalytics();
336
- process.exit(1);
337
- }
338
- console.log(chalk.blue(`Starting worker '${worker.name}'...`));
339
- await workerManager.start(worker.id);
340
- console.log(chalk.green(`Worker '${worker.name}' started successfully!`));
341
- const duration = Date.now() - startTime;
342
- trackCommandSuccess('worker-start', duration, {
343
- workerId: worker.id,
344
- workerName: worker.name,
345
- });
346
- await shutdownAnalytics();
347
- process.exit(0);
348
- }
349
- catch (error) {
350
- const duration = Date.now() - startTime;
351
- trackCommandError('worker-start', error, duration, {
352
- nameOrId,
353
- });
354
- console.error(chalk.red('Failed to start worker:'), error);
355
- await shutdownAnalytics();
356
- process.exit(1);
357
- }
358
- });
359
- }
360
- /**
361
- * Register the stop command
362
- */
363
- export function registerStopCommand(workerCommand) {
364
- workerCommand
365
- .command('stop <nameOrId>')
366
- .description('Stop a worker')
367
- .action(async (nameOrId) => {
368
- const startTime = Date.now();
369
- try {
370
- trackCommand('worker-stop', {
371
- nameOrId,
372
- });
373
- // Create worker manager
374
- const workerManager = new TonkWorkerManager();
375
- // Get worker
376
- const worker = await workerManager.findByNameOrId(nameOrId);
377
- if (!worker) {
378
- console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
379
- const duration = Date.now() - startTime;
380
- trackCommandError('worker-stop', new Error('Worker not found'), duration, {
381
- nameOrId,
382
- });
383
- await shutdownAnalytics();
384
- process.exit(1);
385
- }
386
- console.log(chalk.blue(`Stopping worker '${worker.name}'...`));
387
- await workerManager.stop(worker.id);
388
- console.log(chalk.green(`Worker '${worker.name}' stopped successfully!`));
389
- const duration = Date.now() - startTime;
390
- trackCommandSuccess('worker-stop', duration, {
391
- workerId: worker.id,
392
- workerName: worker.name,
393
- });
394
- await shutdownAnalytics();
395
- process.exit(0);
396
- }
397
- catch (error) {
398
- const duration = Date.now() - startTime;
399
- trackCommandError('worker-stop', error, duration, {
400
- nameOrId,
401
- });
402
- console.error(chalk.red('Failed to stop worker:'), error);
403
- await shutdownAnalytics();
404
- process.exit(1);
405
- }
406
- });
407
- }
408
- /**
409
- * Register the logs command
410
- */
411
- export function registerLogsCommand(workerCommand) {
412
- workerCommand
413
- .command('logs <nameOrId>')
414
- .description('View logs for a worker')
415
- .option('-f, --follow', 'Follow log output')
416
- .option('-l, --lines <n>', 'Number of lines to show', '100')
417
- .option('-e, --error', 'Show only error logs')
418
- .option('-o, --out', 'Show only standard output logs')
419
- .action(async (nameOrId, options) => {
420
- const startTime = Date.now();
421
- try {
422
- trackCommand('worker-logs', {
423
- nameOrId,
424
- follow: options.follow,
425
- lines: options.lines,
426
- error: options.error,
427
- out: options.out,
428
- });
429
- // Create worker manager
430
- const workerManager = new TonkWorkerManager();
431
- // Get worker
432
- const worker = await workerManager.findByNameOrId(nameOrId);
433
- if (!worker) {
434
- console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
435
- const duration = Date.now() - startTime;
436
- trackCommandError('worker-logs', new Error('Worker not found'), duration, {
437
- nameOrId,
438
- });
439
- await shutdownAnalytics();
440
- process.exit(1);
441
- }
442
- console.log(chalk.blue(`Fetching logs for worker '${worker.name}'...`));
443
- const { spawn } = await import('node:child_process');
444
- try {
445
- // Build the PM2 logs command arguments
446
- const args = ['logs', worker.id];
447
- // Add options
448
- if (options.lines) {
449
- args.push('--lines', options.lines);
450
- }
451
- if (options.error) {
452
- args.push('--err');
453
- }
454
- else if (options.out) {
455
- args.push('--out');
456
- }
457
- // Always use --raw to get cleaner output
458
- args.push('--raw');
459
- // For non-follow mode, we'll use --lines and then kill the process after a short delay
460
- if (!options.follow) {
461
- console.log(chalk.blue(`Showing last ${options.lines || '100'} lines of logs...`));
462
- const child = spawn('pm2', args, {
463
- stdio: 'inherit',
464
- });
465
- // Kill the process after a short delay to get just the initial output
466
- setTimeout(() => {
467
- child.kill('SIGINT');
468
- }, 1000);
469
- // Wait for the child process to exit
470
- await new Promise(resolve => {
471
- child.on('exit', resolve);
472
- });
473
- console.log(chalk.blue('\nUse -f or --follow to stream logs in real-time'));
474
- }
475
- else {
476
- // For follow mode
477
- console.log(chalk.blue('Streaming logs in real-time. Press Ctrl+C to exit.'));
478
- const child = spawn('pm2', args, {
479
- stdio: 'inherit',
480
- });
481
- // Handle process exit
482
- process.on('SIGINT', async () => {
483
- child.kill();
484
- await shutdownAnalytics();
485
- process.exit(0);
486
- });
487
- // Wait for the child process to exit
488
- await new Promise(resolve => {
489
- child.on('exit', resolve);
490
- });
491
- }
492
- const duration = Date.now() - startTime;
493
- trackCommandSuccess('worker-logs', duration, {
494
- workerId: worker.id,
495
- workerName: worker.name,
496
- follow: options.follow,
497
- lines: options.lines,
498
- logType: options.error ? 'error' : options.out ? 'out' : 'all',
499
- });
500
- await shutdownAnalytics();
501
- process.exit(0);
502
- }
503
- catch (error) {
504
- const duration = Date.now() - startTime;
505
- trackCommandError('worker-logs', error, duration, {
506
- workerId: worker.id,
507
- workerName: worker.name,
508
- options,
509
- });
510
- console.error(chalk.red('Failed to fetch logs:'), error);
511
- await shutdownAnalytics();
512
- process.exit(1);
513
- }
514
- }
515
- catch (error) {
516
- const duration = Date.now() - startTime;
517
- trackCommandError('worker-logs', error, duration, {
518
- nameOrId,
519
- options,
520
- });
521
- console.error(chalk.red('Failed to fetch worker logs:'), error);
522
- await shutdownAnalytics();
523
- process.exit(1);
524
- }
525
- });
526
- }
527
- /**
528
- * Register the register command
529
- */
530
- export function registerRegisterCommand(workerCommand) {
531
- workerCommand
532
- .command('register')
533
- .description('Register a worker with Tonk')
534
- .argument('[dir]', 'Path to worker directory (defaults to current directory)')
535
- .option('-n, --name <n>', 'Name of the worker')
536
- .option('-e, --endpoint <endpoint>', 'Endpoint URL of the worker')
537
- .option('-p, --port <port>', 'Port number for the worker')
538
- .option('-d, --description <description>', 'Description of the worker')
539
- .action(async (dir = '.', options) => {
540
- const startTime = Date.now();
541
- try {
542
- trackCommand('worker-register', {
543
- hasDir: !!dir && dir !== '.',
544
- hasName: !!options.name,
545
- hasEndpoint: !!options.endpoint,
546
- hasPort: !!options.port,
547
- hasDescription: !!options.description,
548
- });
549
- // Create worker manager
550
- const workerManager = new TonkWorkerManager();
551
- // If options are provided, use them directly
552
- if (options.name && options.endpoint) {
553
- // Register worker using provided options
554
- const worker = await workerManager.register({
555
- name: options.name,
556
- description: options.description || `Worker at ${options.endpoint}`,
557
- endpoint: options.endpoint,
558
- protocol: 'http',
559
- env: options.port ? [`WORKER_PORT=${options.port}`] : [],
560
- });
561
- console.log(chalk.green(`Worker '${worker.name}' registered successfully!`));
562
- console.log(chalk.cyan('Worker ID:'), chalk.bold(worker.id));
563
- console.log(chalk.cyan('Endpoint:'), chalk.bold(worker.endpoint));
564
- console.log(chalk.cyan('Protocol:'), chalk.bold(worker.protocol));
565
- console.log(chalk.cyan('Status:'), worker.status.active
566
- ? chalk.green('Active')
567
- : chalk.yellow('Inactive'));
568
- if (Object.keys(worker.env).length > 0) {
569
- console.log(chalk.cyan('Environment Variables:'));
570
- Object.entries(worker.env).forEach(([key, value]) => {
571
- console.log(` ${key}=${value}`);
572
- });
573
- }
574
- const duration = Date.now() - startTime;
575
- trackCommandSuccess('worker-register', duration, {
576
- workerId: worker.id,
577
- workerName: worker.name,
578
- registrationType: 'direct',
579
- hasCustomPort: !!options.port,
580
- });
581
- await shutdownAnalytics();
582
- process.exit(0);
583
- }
584
- // Look for package.json and worker.config.js files
585
- const workerDir = await findWorkerRoot(dir);
586
- if (!workerDir) {
587
- console.error(chalk.red(`No package.json or worker.config.js found in ${path.resolve(dir)} or its parent directories.`));
588
- console.log(chalk.yellow('Make sure you are in a valid worker directory or specify the path to one, or provide --name and --endpoint options.'));
589
- const duration = Date.now() - startTime;
590
- trackCommandError('worker-register', new Error('Worker directory not found'), duration, {
591
- dir: path.resolve(dir),
592
- });
593
- await shutdownAnalytics();
594
- process.exit(1);
595
- }
596
- console.log(chalk.blue(`Found worker directory at: ${workerDir}`));
597
- // Read package.json for worker metadata
598
- const packageJsonPath = path.join(workerDir, 'package.json');
599
- const packageJson = await readPackageJson(packageJsonPath);
600
- if (!packageJson) {
601
- console.error(chalk.red(`Failed to parse package.json file at ${packageJsonPath}`));
602
- const duration = Date.now() - startTime;
603
- trackCommandError('worker-register', new Error('Failed to parse package.json'), duration, {
604
- packageJsonPath,
605
- });
606
- await shutdownAnalytics();
607
- process.exit(1);
608
- }
609
- // Read worker.config.js for configuration
610
- const workerConfigPath = path.join(workerDir, 'worker.config.js');
611
- const workerConfig = await readWorkerConfigJs(workerConfigPath);
612
- if (!workerConfig) {
613
- console.error(chalk.red(`Failed to parse worker.config.js file at ${workerConfigPath}`));
614
- const duration = Date.now() - startTime;
615
- trackCommandError('worker-register', new Error('Failed to parse worker.config.js'), duration, {
616
- workerConfigPath,
617
- });
618
- await shutdownAnalytics();
619
- process.exit(1);
620
- }
621
- // Determine port from config or use default
622
- const port = options.port || workerConfig.runtime?.port || 5555;
623
- // Create worker registration options
624
- const registrationOptions = {
625
- name: packageJson.name,
626
- description: packageJson.description || 'Tonk worker',
627
- endpoint: options.endpoint || `http://localhost:${port}/tonk`,
628
- protocol: 'http',
629
- env: [`WORKER_PORT=${port}`],
630
- config: {
631
- ...workerConfig,
632
- version: packageJson.version,
633
- },
634
- };
635
- // Register worker
636
- const worker = await workerManager.register(registrationOptions);
637
- console.log(chalk.green(`Worker '${worker.name}' registered successfully!`));
638
- console.log(chalk.cyan('Worker ID:'), chalk.bold(worker.id));
639
- console.log(chalk.cyan('Endpoint:'), chalk.bold(worker.endpoint));
640
- console.log(chalk.cyan('Protocol:'), chalk.bold(worker.protocol));
641
- console.log(chalk.cyan('Status:'), worker.status.active
642
- ? chalk.green('Active')
643
- : chalk.yellow('Inactive'));
644
- if (Object.keys(worker.env).length > 0) {
645
- console.log(chalk.cyan('Environment Variables:'));
646
- Object.entries(worker.env).forEach(([key, value]) => {
647
- console.log(` ${key}=${value}`);
648
- });
649
- }
650
- const duration = Date.now() - startTime;
651
- trackCommandSuccess('worker-register', duration, {
652
- workerId: worker.id,
653
- workerName: worker.name,
654
- registrationType: 'config-based',
655
- workerDir,
656
- port,
657
- hasCustomEndpoint: !!options.endpoint,
658
- });
659
- await shutdownAnalytics();
660
- process.exit(0);
661
- }
662
- catch (error) {
663
- const duration = Date.now() - startTime;
664
- trackCommandError('worker-register', error, duration, {
665
- dir,
666
- options,
667
- });
668
- console.error(chalk.red('Failed to register worker:'), error);
669
- await shutdownAnalytics();
670
- process.exit(1);
671
- }
672
- });
673
- }
674
- /**
675
- * Register the install command
676
- */
677
- export function registerInstallCommand(workerCommand) {
678
- workerCommand
679
- .command('install <package>')
680
- .description('Install and start a worker from npm')
681
- .option('-p, --port <port>', 'Specify a port for the worker (default: auto-detect)')
682
- .option('-n, --name <n>', 'Custom name for the worker (default: npm package name)')
683
- .action(async (packageName, options) => {
684
- const startTime = Date.now();
685
- try {
686
- trackCommand('worker-install', {
687
- packageName,
688
- hasCustomPort: !!options.port,
689
- hasCustomName: !!options.name,
690
- });
691
- console.log(chalk.blue(`Installing worker from npm package: ${packageName}...`));
692
- // Create worker manager
693
- const workerManager = new TonkWorkerManager();
694
- // Execute npm install
695
- const execAsync = promisify(exec);
696
- try {
697
- console.log(chalk.blue('Installing package...'));
698
- await execAsync(`npm install -g ${packageName}`);
699
- console.log(chalk.green('Package installed successfully!'));
700
- }
701
- catch (error) {
702
- console.error(chalk.red('Failed to install package:'), error);
703
- const duration = Date.now() - startTime;
704
- trackCommandError('worker-install', error, duration, {
705
- packageName,
706
- stage: 'npm-install',
707
- });
708
- await shutdownAnalytics();
709
- process.exit(1);
710
- }
711
- // Find an available port starting from 5555
712
- let port = options.port;
713
- if (!port) {
714
- port = await findAvailablePort(5555);
715
- console.log(chalk.blue(`Found available port: ${port}`));
716
- }
717
- // Get package info to determine the worker name and entry point
718
- let packageInfo;
719
- try {
720
- const { stdout } = await execAsync(`npm view ${packageName} --json`);
721
- packageInfo = JSON.parse(stdout);
722
- }
723
- catch (error) {
724
- console.error(chalk.red('Failed to get package info:'), error);
725
- const duration = Date.now() - startTime;
726
- trackCommandError('worker-install', error, duration, {
727
- packageName,
728
- stage: 'package-info',
729
- });
730
- await shutdownAnalytics();
731
- process.exit(1);
732
- }
733
- // Strip scope from package name for display purposes (e.g., @tonk/worker -> worker)
734
- const commandName = options.name || packageName.replace(/^@[^/]+\//, '');
735
- // Verify the package can be executed directly
736
- let setupCompleted = false;
737
- try {
738
- // Check if the command exists by running a simple help command
739
- await execAsync(`${commandName} --help`);
740
- console.log(chalk.green(`Verified that '${packageName}' is executable.`));
741
- // Try running the setup command if it exists
742
- try {
743
- console.log(chalk.blue(`Running setup for '${packageName}'...`));
744
- // Use spawn to allow user interaction during setup
745
- const { spawn } = await import('node:child_process');
746
- const setupProcess = spawn(commandName, ['setup'], {
747
- stdio: 'inherit',
748
- shell: true,
749
- });
750
- // Wait for the setup process to complete
751
- setupCompleted = await new Promise((resolve, reject) => {
752
- setupProcess.on('close', code => {
753
- if (code === 0) {
754
- console.log(chalk.green(`Setup completed successfully for '${packageName}'`));
755
- resolve(true);
756
- }
757
- else {
758
- console.warn(chalk.yellow(`Setup command exited with code ${code}`));
759
- resolve(false);
760
- }
761
- });
762
- setupProcess.on('error', err => {
763
- reject(err);
764
- });
765
- });
766
- }
767
- catch (setupError) {
768
- console.log(chalk.yellow(`Setup command not available for '${packageName}', continuing with installation...`));
769
- }
770
- }
771
- catch (error) {
772
- const errorMessage = error instanceof Error ? error.message : String(error);
773
- console.warn(chalk.yellow(`Warning: Could not verify that '${packageName}' is executable. It may not be properly installed or may not provide a CLI.`));
774
- console.warn(chalk.yellow(`Error: ${errorMessage}`));
775
- }
776
- // Register the worker with the npm package name
777
- const worker = await workerManager.register({
778
- name: packageName, // Use the actual package name for npm resolution
779
- description: packageInfo.description || `Worker from npm package ${packageName}`,
780
- endpoint: `http://localhost:${port}/tonk`,
781
- protocol: 'http',
782
- env: [`WORKER_PORT=${port}`],
783
- type: 'npm',
784
- });
785
- console.log(chalk.green(`Worker '${packageName}' registered successfully!`));
786
- // Start the worker
787
- console.log(chalk.blue(`Starting worker '${packageName}'...`));
788
- const success = await workerManager.start(worker.id);
789
- if (success) {
790
- console.log(chalk.green(`Worker '${packageName}' started successfully!`));
791
- console.log(chalk.cyan('Worker ID:'), chalk.bold(worker.id));
792
- console.log(chalk.cyan('Endpoint:'), chalk.bold(worker.endpoint));
793
- const duration = Date.now() - startTime;
794
- trackCommandSuccess('worker-install', duration, {
795
- workerId: worker.id,
796
- workerName: worker.name,
797
- packageName,
798
- port,
799
- setupCompleted,
800
- startedSuccessfully: true,
801
- });
802
- await shutdownAnalytics();
803
- process.exit(0);
804
- }
805
- else {
806
- console.error(chalk.red(`Failed to start worker '${packageName}'.`));
807
- const duration = Date.now() - startTime;
808
- trackCommandError('worker-install', new Error('Failed to start worker'), duration, {
809
- workerId: worker.id,
810
- packageName,
811
- stage: 'worker-start',
812
- });
813
- await shutdownAnalytics();
814
- process.exit(1);
815
- }
816
- }
817
- catch (error) {
818
- const duration = Date.now() - startTime;
819
- trackCommandError('worker-install', error, duration, {
820
- packageName,
821
- options,
822
- });
823
- console.error(chalk.red('Failed to install worker:'), error);
824
- await shutdownAnalytics();
825
- process.exit(1);
826
- }
827
- });
828
- }
829
- /**
830
- * Register the init command
831
- */
832
- export function registerInitCommand(workerCommand) {
833
- workerCommand
834
- .command('init')
835
- .description('Initialise a new worker configuration file')
836
- .option('-d, --dir <directory>', 'Directory to create the configuration file in', '.')
837
- .option('-n, --name <n>', 'Name of the worker')
838
- .option('-p, --port <port>', 'Port number for the worker', '5555')
839
- .option('-D, --description <description>', 'Description of the worker')
840
- .action(async (options) => {
841
- const startTime = Date.now();
842
- try {
843
- trackCommand('worker-init', {
844
- hasCustomDir: options.dir !== '.',
845
- hasName: !!options.name,
846
- hasCustomPort: options.port !== '5555',
847
- hasDescription: !!options.description,
848
- });
849
- // Prompt for missing options
850
- const answers = await promptForMissingOptions(options);
851
- const mergedOptions = { ...options, ...answers };
852
- // Create the directory if it doesn't exist
853
- const targetDir = path.resolve(mergedOptions.dir);
854
- let directoryCreated = false;
855
- if (!fs.existsSync(targetDir)) {
856
- fs.mkdirSync(targetDir, { recursive: true });
857
- console.log(chalk.blue(`Created directory: ${targetDir}`));
858
- directoryCreated = true;
859
- }
860
- // Generate the package.json content if it doesn't exist
861
- const packageJsonPath = path.join(targetDir, 'package.json');
862
- let packageJsonCreated = false;
863
- if (!fs.existsSync(packageJsonPath)) {
864
- const packageJsonContent = generatePackageJsonContent(mergedOptions);
865
- fs.writeFileSync(packageJsonPath, packageJsonContent);
866
- console.log(chalk.green(`Created package.json at: ${packageJsonPath}`));
867
- packageJsonCreated = true;
868
- }
869
- // Generate the worker.config.js content
870
- const workerConfigContent = generateWorkerConfigJsContent();
871
- const workerConfigPath = path.join(targetDir, 'worker.config.js');
872
- fs.writeFileSync(workerConfigPath, workerConfigContent);
873
- // Create src directory if it doesn't exist
874
- const srcDir = path.join(targetDir, 'src');
875
- let srcDirCreated = false;
876
- if (!fs.existsSync(srcDir)) {
877
- fs.mkdirSync(srcDir, { recursive: true });
878
- console.log(chalk.blue(`Created src directory: ${srcDir}`));
879
- srcDirCreated = true;
880
- }
881
- // Copy CLI template file
882
- const cliTemplatePath = path.join(__dirname, 'templates', 'cli.ts.template');
883
- const cliDestPath = path.join(srcDir, 'cli.ts');
884
- let cliFileCreated = false;
885
- if (fs.existsSync(cliTemplatePath)) {
886
- let cliContent = fs.readFileSync(cliTemplatePath, 'utf-8');
887
- // Replace template variables
888
- cliContent = cliContent
889
- .replace(/{{name}}/g, mergedOptions.name)
890
- .replace(/{{description}}/g, mergedOptions.description || 'A Tonk worker')
891
- .replace(/{{version}}/g, '1.0.0');
892
- fs.writeFileSync(cliDestPath, cliContent);
893
- console.log(chalk.green(`Created CLI file at: ${cliDestPath}`));
894
- cliFileCreated = true;
895
- }
896
- else {
897
- console.warn(chalk.yellow(`CLI template not found at: ${cliTemplatePath}`));
898
- }
899
- // Copy index.ts template file
900
- const indexTemplatePath = path.join(__dirname, 'templates', 'index.ts.template');
901
- const indexDestPath = path.join(srcDir, 'index.ts');
902
- let indexFileCreated = false;
903
- if (!fs.existsSync(indexDestPath) && fs.existsSync(indexTemplatePath)) {
904
- let indexContent = fs.readFileSync(indexTemplatePath, 'utf-8');
905
- // Replace template variables
906
- indexContent = indexContent
907
- .replace(/{{name}}/g, mergedOptions.name)
908
- .replace(/{{description}}/g, mergedOptions.description || 'A Tonk worker')
909
- .replace(/{{port}}/g, mergedOptions.port);
910
- fs.writeFileSync(indexDestPath, indexContent);
911
- console.log(chalk.green(`Created index.ts file at: ${indexDestPath}`));
912
- indexFileCreated = true;
913
- }
914
- else if (!fs.existsSync(indexTemplatePath)) {
915
- console.warn(chalk.yellow(`Index template not found at: ${indexTemplatePath}`));
916
- }
917
- // Copy tsconfig.json template file
918
- const tsconfigTemplatePath = path.join(__dirname, 'templates', 'tsconfig.json.template');
919
- const tsconfigDestPath = path.join(targetDir, 'tsconfig.json');
920
- let tsconfigFileCreated = false;
921
- if (!fs.existsSync(tsconfigDestPath) &&
922
- fs.existsSync(tsconfigTemplatePath)) {
923
- const tsconfigContent = fs.readFileSync(tsconfigTemplatePath, 'utf-8');
924
- fs.writeFileSync(tsconfigDestPath, tsconfigContent);
925
- console.log(chalk.green(`Created tsconfig.json file at: ${tsconfigDestPath}`));
926
- tsconfigFileCreated = true;
927
- }
928
- else if (!fs.existsSync(tsconfigTemplatePath)) {
929
- console.warn(chalk.yellow(`tsconfig.json template not found at: ${tsconfigTemplatePath}`));
930
- }
931
- console.log(chalk.green(`Worker configuration file created at: ${workerConfigPath}`));
932
- console.log(chalk.blue(`\nYou can now register this worker with:`));
933
- console.log(chalk.cyan(` tonk worker register ${targetDir}`));
934
- const duration = Date.now() - startTime;
935
- trackCommandSuccess('worker-init', duration, {
936
- workerName: mergedOptions.name,
937
- targetDir,
938
- port: mergedOptions.port,
939
- directoryCreated,
940
- packageJsonCreated,
941
- srcDirCreated,
942
- cliFileCreated,
943
- indexFileCreated,
944
- tsconfigFileCreated,
945
- filesCreated: [
946
- packageJsonCreated && 'package.json',
947
- 'worker.config.js',
948
- srcDirCreated && 'src/',
949
- cliFileCreated && 'cli.ts',
950
- indexFileCreated && 'index.ts',
951
- tsconfigFileCreated && 'tsconfig.json',
952
- ].filter(Boolean).length,
953
- });
954
- await shutdownAnalytics();
955
- process.exit(0);
956
- }
957
- catch (error) {
958
- const duration = Date.now() - startTime;
959
- trackCommandError('worker-init', error, duration, {
960
- options,
961
- });
962
- console.error(chalk.red('Failed to initialise worker configuration:'), error);
963
- await shutdownAnalytics();
964
- process.exit(1);
965
- }
966
- });
967
- }
968
- //# sourceMappingURL=commands.js.map