appshot-cli 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +244 -5
  2. package/dist/cli.js +23 -4
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/device.d.ts +3 -0
  5. package/dist/commands/device.d.ts.map +1 -0
  6. package/dist/commands/device.js +414 -0
  7. package/dist/commands/device.js.map +1 -0
  8. package/dist/commands/frame.d.ts +3 -0
  9. package/dist/commands/frame.d.ts.map +1 -0
  10. package/dist/commands/frame.js +251 -0
  11. package/dist/commands/frame.js.map +1 -0
  12. package/dist/commands/unwatch.d.ts +3 -0
  13. package/dist/commands/unwatch.d.ts.map +1 -0
  14. package/dist/commands/unwatch.js +53 -0
  15. package/dist/commands/unwatch.js.map +1 -0
  16. package/dist/commands/watch-status.d.ts +3 -0
  17. package/dist/commands/watch-status.d.ts.map +1 -0
  18. package/dist/commands/watch-status.js +116 -0
  19. package/dist/commands/watch-status.js.map +1 -0
  20. package/dist/commands/watch.d.ts +3 -0
  21. package/dist/commands/watch.d.ts.map +1 -0
  22. package/dist/commands/watch.js +322 -0
  23. package/dist/commands/watch.js.map +1 -0
  24. package/dist/core/compose.d.ts +25 -0
  25. package/dist/core/compose.d.ts.map +1 -1
  26. package/dist/core/compose.js +82 -0
  27. package/dist/core/compose.js.map +1 -1
  28. package/dist/core/devices.d.ts +5 -0
  29. package/dist/core/devices.d.ts.map +1 -1
  30. package/dist/core/devices.js +43 -1
  31. package/dist/core/devices.js.map +1 -1
  32. package/dist/services/compose-bridge.d.ts +47 -0
  33. package/dist/services/compose-bridge.d.ts.map +1 -0
  34. package/dist/services/compose-bridge.js +222 -0
  35. package/dist/services/compose-bridge.js.map +1 -0
  36. package/dist/services/device-manager.d.ts +14 -0
  37. package/dist/services/device-manager.d.ts.map +1 -0
  38. package/dist/services/device-manager.js +244 -0
  39. package/dist/services/device-manager.js.map +1 -0
  40. package/dist/services/doctor.d.ts +1 -0
  41. package/dist/services/doctor.d.ts.map +1 -1
  42. package/dist/services/doctor.js +94 -2
  43. package/dist/services/doctor.js.map +1 -1
  44. package/dist/services/processing-queue.d.ts +32 -0
  45. package/dist/services/processing-queue.d.ts.map +1 -0
  46. package/dist/services/processing-queue.js +150 -0
  47. package/dist/services/processing-queue.js.map +1 -0
  48. package/dist/services/screenshot-router.d.ts +31 -0
  49. package/dist/services/screenshot-router.d.ts.map +1 -0
  50. package/dist/services/screenshot-router.js +227 -0
  51. package/dist/services/screenshot-router.js.map +1 -0
  52. package/dist/services/system-requirements.d.ts +26 -0
  53. package/dist/services/system-requirements.d.ts.map +1 -0
  54. package/dist/services/system-requirements.js +189 -0
  55. package/dist/services/system-requirements.js.map +1 -0
  56. package/dist/services/watch-service.d.ts +39 -0
  57. package/dist/services/watch-service.d.ts.map +1 -0
  58. package/dist/services/watch-service.js +293 -0
  59. package/dist/services/watch-service.js.map +1 -0
  60. package/dist/types/device.d.ts +52 -0
  61. package/dist/types/device.d.ts.map +1 -0
  62. package/dist/types/device.js +2 -0
  63. package/dist/types/device.js.map +1 -0
  64. package/dist/types.d.ts +9 -0
  65. package/dist/types.d.ts.map +1 -1
  66. package/dist/utils/pid-manager.d.ts +11 -0
  67. package/dist/utils/pid-manager.d.ts.map +1 -0
  68. package/dist/utils/pid-manager.js +76 -0
  69. package/dist/utils/pid-manager.js.map +1 -0
  70. package/package.json +3 -3
@@ -0,0 +1,251 @@
1
+ import { Command } from 'commander';
2
+ import { promises as fs } from 'fs';
3
+ import path from 'path';
4
+ import pc from 'picocolors';
5
+ import sharp from 'sharp';
6
+ import { initializeFrameRegistry, getImageDimensions, autoSelectFrame, detectDeviceTypeFromDimensions } from '../core/devices.js';
7
+ import { composeFrameOnly } from '../core/compose.js';
8
+ function isImage(file) {
9
+ return /\.(png|jpg|jpeg)$/i.test(file);
10
+ }
11
+ async function ensureDir(dir) {
12
+ await fs.mkdir(dir, { recursive: true });
13
+ }
14
+ async function listImagesRecursively(root) {
15
+ const entries = await fs.readdir(root, { withFileTypes: true });
16
+ const files = [];
17
+ for (const entry of entries) {
18
+ const full = path.join(root, entry.name);
19
+ if (entry.isDirectory()) {
20
+ const nested = await listImagesRecursively(full);
21
+ files.push(...nested);
22
+ }
23
+ else if (entry.isFile() && isImage(entry.name)) {
24
+ files.push(full);
25
+ }
26
+ }
27
+ return files;
28
+ }
29
+ async function processSingleFile(inputPath, framesDir, options) {
30
+ const { width, height, orientation } = await getImageDimensions(inputPath);
31
+ // Validate minimum dimensions
32
+ if (width < 100 || height < 100) {
33
+ console.error(pc.red(' āœ—'), path.basename(inputPath), pc.dim(`Image too small (${width}x${height}). Minimum 100x100 required.`));
34
+ return { processed: 0, errors: 1 };
35
+ }
36
+ // Warn on extreme aspect ratios
37
+ const aspect = Math.max(width, height) / Math.min(width, height);
38
+ if (aspect > 3) {
39
+ console.warn(pc.yellow(' ⚠'), path.basename(inputPath), pc.dim(`Extreme aspect ratio (${aspect.toFixed(2)}:1) may not match any device frame.`));
40
+ }
41
+ let device = options.device || detectDeviceTypeFromDimensions(width, height);
42
+ if (!device) {
43
+ console.error(pc.red(' āœ—'), path.basename(inputPath), pc.dim(`Unable to detect device type (${width}x${height}). Use --device to specify.`));
44
+ return { processed: 0, errors: 1 };
45
+ }
46
+ // Choose frame
47
+ const { frame, metadata } = await autoSelectFrame(inputPath, framesDir, device, undefined, Boolean(options.dryRun));
48
+ if (!metadata) {
49
+ console.error(pc.red(' āœ—'), path.basename(inputPath), pc.dim('No matching frame found'));
50
+ return { processed: 0, errors: 1 };
51
+ }
52
+ if (options.dryRun) {
53
+ console.log(pc.cyan(` ${path.basename(inputPath)}`) + pc.dim(` → ${device} (${orientation})`));
54
+ console.log(pc.dim(` Source: ${width}x${height}`));
55
+ console.log(pc.dim(` Frame: ${metadata.displayName} (${metadata.frameWidth}x${metadata.frameHeight})`));
56
+ return { processed: 1, errors: 0 };
57
+ }
58
+ if (!frame) {
59
+ console.error(pc.red(' āœ—'), path.basename(inputPath), pc.dim('Frame image failed to load'));
60
+ return { processed: 0, errors: 1 };
61
+ }
62
+ // Load screenshot buffer
63
+ let screenshotBuffer;
64
+ try {
65
+ await fs.access(inputPath, fs.constants.R_OK);
66
+ screenshotBuffer = await sharp(inputPath).toBuffer();
67
+ }
68
+ catch (err) {
69
+ console.error(pc.red(' āœ—'), path.basename(inputPath), pc.dim(`Failed to read image: ${err instanceof Error ? err.message : String(err)}`));
70
+ return { processed: 0, errors: 1 };
71
+ }
72
+ // Compose framed image with transparent background
73
+ let outBuffer;
74
+ try {
75
+ outBuffer = await composeFrameOnly({
76
+ screenshot: screenshotBuffer,
77
+ frame,
78
+ frameMetadata: {
79
+ frameWidth: metadata.frameWidth,
80
+ frameHeight: metadata.frameHeight,
81
+ screenRect: metadata.screenRect,
82
+ maskPath: metadata.maskPath,
83
+ deviceType: metadata.deviceType,
84
+ displayName: metadata.displayName,
85
+ name: metadata.name
86
+ },
87
+ outputFormat: options.format || 'png',
88
+ jpegQuality: 92,
89
+ verbose: options.verbose
90
+ });
91
+ }
92
+ catch (err) {
93
+ console.error(pc.red(' āœ—'), path.basename(inputPath), pc.dim(`Compose failed: ${err instanceof Error ? err.message : String(err)}`));
94
+ return { processed: 0, errors: 1 };
95
+ }
96
+ // Determine output path
97
+ const format = options.format || 'png';
98
+ const ext = format === 'png' ? '.png' : '.jpg';
99
+ const baseName = path.basename(inputPath, path.extname(inputPath));
100
+ const outputDir = options.output ? path.resolve(options.output) : path.dirname(inputPath);
101
+ await ensureDir(outputDir);
102
+ let suffix = options.suffix ?? '-framed';
103
+ let outName = options.overwrite ? `${baseName}${ext}` : `${baseName}${suffix}${ext}`;
104
+ let outPath = path.join(outputDir, outName);
105
+ if (!options.overwrite) {
106
+ try {
107
+ await fs.access(outPath);
108
+ // File exists; if suffix is empty, fall back to default '-framed'
109
+ if (!suffix) {
110
+ suffix = '-framed';
111
+ outName = `${baseName}${suffix}${ext}`;
112
+ outPath = path.join(outputDir, outName);
113
+ }
114
+ }
115
+ catch {
116
+ // ok, does not exist
117
+ }
118
+ }
119
+ try {
120
+ await fs.writeFile(outPath, outBuffer);
121
+ console.log(pc.green(' āœ“'), path.basename(outPath), pc.dim(`[${device}, ${orientation}, transparent]`));
122
+ return { processed: 1, errors: 0 };
123
+ }
124
+ catch (err) {
125
+ console.error(pc.red(' āœ—'), path.basename(inputPath), pc.dim(`Write failed: ${err instanceof Error ? err.message : String(err)}`));
126
+ return { processed: 0, errors: 1 };
127
+ }
128
+ }
129
+ export default function frameCmd() {
130
+ const cmd = new Command('frame')
131
+ .description('Apply device frames to screenshots with a transparent background (no gradients or captions)')
132
+ .argument('<input>', 'input image file or directory')
133
+ .option('-o, --output <dir>', 'output directory (default: same as input)')
134
+ .option('-d, --device <type>', 'force device type (iphone|ipad|mac|watch)')
135
+ .option('-r, --recursive', 'process directories recursively')
136
+ .option('-f, --format <type>', 'output format (png|jpeg)', 'png')
137
+ .option('--suffix <text>', 'filename suffix when not overwriting', '-framed')
138
+ .option('--overwrite', 'overwrite original file name')
139
+ .option('--dry-run', 'preview files without processing')
140
+ .option('--verbose', 'show detailed information')
141
+ .addHelpText('after', `
142
+ ${pc.bold('Examples:')}
143
+ ${pc.dim('# Single file (auto-detect device)')}
144
+ $ appshot frame screenshot.png
145
+
146
+ ${pc.dim('# Specify output directory')}
147
+ $ appshot frame screenshot.png -o framed/
148
+
149
+ ${pc.dim('# Force device type')}
150
+ $ appshot frame screenshot.png --device iphone
151
+
152
+ ${pc.dim('# Batch process a directory')}
153
+ $ appshot frame ./screenshots -o ./framed --recursive
154
+
155
+ ${pc.dim('# Dry run with verbose logs')}
156
+ $ appshot frame ./screenshots --dry-run --verbose`)
157
+ .action(async (input, opts) => {
158
+ const options = {
159
+ output: opts.output,
160
+ device: opts.device,
161
+ recursive: Boolean(opts.recursive),
162
+ format: (opts.format === 'jpeg' ? 'jpeg' : 'png'),
163
+ suffix: opts.suffix,
164
+ overwrite: Boolean(opts.overwrite),
165
+ verbose: Boolean(opts.verbose),
166
+ dryRun: Boolean(opts.dryRun)
167
+ };
168
+ // Validate device option if provided
169
+ if (options.device && !['iphone', 'ipad', 'mac', 'watch'].includes(options.device)) {
170
+ console.error(pc.red('Error:'), `Invalid --device value: ${options.device}`);
171
+ process.exit(1);
172
+ }
173
+ try {
174
+ // Initialize frames registry (use project frames dir by default)
175
+ const framesDir = path.resolve('frames');
176
+ await initializeFrameRegistry(framesDir);
177
+ const inputPath = path.resolve(input);
178
+ const stat = await fs.stat(inputPath);
179
+ let totalProcessed = 0;
180
+ let totalErrors = 0;
181
+ if (stat.isFile()) {
182
+ // Ensure output directory exists if specified
183
+ if (options.output) {
184
+ await ensureDir(path.resolve(options.output));
185
+ }
186
+ const res = await processSingleFile(inputPath, framesDir, options);
187
+ totalProcessed += res.processed;
188
+ totalErrors += res.errors;
189
+ }
190
+ else if (stat.isDirectory()) {
191
+ // List images
192
+ const files = options.recursive
193
+ ? await listImagesRecursively(inputPath)
194
+ : (await fs.readdir(inputPath))
195
+ .filter(isImage)
196
+ .map(f => path.join(inputPath, f));
197
+ if (files.length === 0) {
198
+ console.log(pc.yellow('⚠'), 'No images found');
199
+ return;
200
+ }
201
+ console.log(pc.cyan(`\n${path.basename(inputPath)}:`), `${options.dryRun ? 'Would frame' : 'Framing'} ${files.length} images`);
202
+ let currentIndex = 0;
203
+ for (const file of files) {
204
+ currentIndex++;
205
+ if (!options.dryRun && files.length > 5) {
206
+ process.stdout.write(pc.dim(`\r[${currentIndex}/${files.length}] Processing...`));
207
+ }
208
+ // Compute output for recursive structure
209
+ if (options.output && options.recursive) {
210
+ const rel = path.relative(inputPath, path.dirname(file));
211
+ const outDir = path.join(path.resolve(options.output), rel);
212
+ const res = await processSingleFile(file, framesDir, { ...options, output: outDir });
213
+ totalProcessed += res.processed;
214
+ totalErrors += res.errors;
215
+ }
216
+ else {
217
+ const res = await processSingleFile(file, framesDir, options);
218
+ totalProcessed += res.processed;
219
+ totalErrors += res.errors;
220
+ }
221
+ }
222
+ // Clear progress line
223
+ if (!options.dryRun && files.length > 5) {
224
+ process.stdout.write('\r' + ' '.repeat(30) + '\r');
225
+ }
226
+ }
227
+ else {
228
+ console.error(pc.red('Error:'), 'Input must be a file or directory');
229
+ process.exit(1);
230
+ }
231
+ // Summary
232
+ if (options.dryRun) {
233
+ console.log('\n' + pc.bold('Dry run complete!'));
234
+ console.log(pc.cyan(`→ ${totalProcessed} images would be framed`));
235
+ }
236
+ else {
237
+ console.log('\n' + pc.bold('Framing complete!'));
238
+ console.log(pc.green(`āœ“ ${totalProcessed} images processed`));
239
+ if (totalErrors > 0) {
240
+ console.log(pc.red(`āœ— ${totalErrors} errors`));
241
+ }
242
+ }
243
+ }
244
+ catch (error) {
245
+ console.error(pc.red('Error:'), error instanceof Error ? error.message : String(error));
246
+ process.exit(1);
247
+ }
248
+ });
249
+ return cmd;
250
+ }
251
+ //# sourceMappingURL=frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/commands/frame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export default function unwatchCommand(): Command;
3
+ //# sourceMappingURL=unwatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unwatch.d.ts","sourceRoot":"","sources":["../../src/commands/unwatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,CAAC,OAAO,UAAU,cAAc,IAAI,OAAO,CAoDhD"}
@@ -0,0 +1,53 @@
1
+ import { Command } from 'commander';
2
+ import pc from 'picocolors';
3
+ import { PIDManager } from '../utils/pid-manager.js';
4
+ export default function unwatchCommand() {
5
+ return new Command('unwatch')
6
+ .description('Stop watching directories (alias for "watch stop")')
7
+ .action(async () => {
8
+ try {
9
+ const pidManager = new PIDManager('.appshot/watch.pid');
10
+ const pid = await pidManager.readPID();
11
+ if (!pid) {
12
+ console.log(pc.yellow('āš ļø Watch service is not running'));
13
+ return;
14
+ }
15
+ if (!(await pidManager.isProcessRunning(pid))) {
16
+ console.log(pc.yellow('āš ļø Watch service PID file exists but process is not running'));
17
+ await pidManager.cleanup();
18
+ return;
19
+ }
20
+ console.log(pc.cyan(`šŸ›‘ Stopping watch service (PID: ${pid})...`));
21
+ try {
22
+ process.kill(pid, 'SIGTERM');
23
+ // Wait for process to stop
24
+ let attempts = 0;
25
+ while (attempts < 10 && await pidManager.isProcessRunning(pid)) {
26
+ await new Promise(resolve => setTimeout(resolve, 500));
27
+ attempts++;
28
+ }
29
+ if (await pidManager.isProcessRunning(pid)) {
30
+ // Force kill if still running
31
+ console.log(pc.yellow('āš ļø Process did not stop gracefully, forcing...'));
32
+ process.kill(pid, 'SIGKILL');
33
+ }
34
+ await pidManager.cleanup();
35
+ console.log(pc.green('āœ… Watch service stopped'));
36
+ }
37
+ catch (error) {
38
+ if (error.code === 'ESRCH') {
39
+ console.log(pc.yellow('āš ļø Process already stopped'));
40
+ await pidManager.cleanup();
41
+ }
42
+ else {
43
+ throw error;
44
+ }
45
+ }
46
+ }
47
+ catch (error) {
48
+ console.error(pc.red('āŒ Error stopping watch service:'), error);
49
+ process.exit(1);
50
+ }
51
+ });
52
+ }
53
+ //# sourceMappingURL=unwatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unwatch.js","sourceRoot":"","sources":["../../src/commands/unwatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,CAAC,OAAO,UAAU,cAAc;IACpC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;SAC1B,WAAW,CAAC,oDAAoD,CAAC;SACjE,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,oBAAoB,CAAC,CAAC;YACxD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;YAEvC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,kCAAkC,CAAC,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,8DAA8D,CAAC,CAAC,CAAC;gBACvF,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,mCAAmC,GAAG,MAAM,CAAC,CAAC,CAAC;YAEnE,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAE7B,2BAA2B;gBAC3B,IAAI,QAAQ,GAAG,CAAC,CAAC;gBACjB,OAAO,QAAQ,GAAG,EAAE,IAAI,MAAM,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC/D,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;oBACvD,QAAQ,EAAE,CAAC;gBACb,CAAC;gBAED,IAAI,MAAM,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3C,8BAA8B;oBAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,iDAAiD,CAAC,CAAC,CAAC;oBAC1E,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAC/B,CAAC;gBAED,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC;oBACtD,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;gBAC7B,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,iCAAiC,CAAC,EAAE,KAAK,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export default function watchStatusCommand(): Command;
3
+ //# sourceMappingURL=watch-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-status.d.ts","sourceRoot":"","sources":["../../src/commands/watch-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,MAAM,CAAC,OAAO,UAAU,kBAAkB,IAAI,OAAO,CAsHpD"}
@@ -0,0 +1,116 @@
1
+ import { Command } from 'commander';
2
+ import pc from 'picocolors';
3
+ import fs from 'fs/promises';
4
+ import { PIDManager } from '../utils/pid-manager.js';
5
+ export default function watchStatusCommand() {
6
+ return new Command('watch-status')
7
+ .description('Check the status of the watch service')
8
+ .option('--json', 'Output as JSON')
9
+ .option('--verbose', 'Show detailed information')
10
+ .action(async (options) => {
11
+ try {
12
+ const pidManager = new PIDManager('.appshot/watch.pid');
13
+ const pid = await pidManager.readPID();
14
+ // Basic status
15
+ const status = {
16
+ running: false,
17
+ pid: null,
18
+ pidFile: '.appshot/watch.pid',
19
+ processedCache: false,
20
+ cachedHashes: 0
21
+ };
22
+ if (pid) {
23
+ status.pid = pid;
24
+ status.running = await pidManager.isProcessRunning(pid);
25
+ }
26
+ // Check for processed cache
27
+ try {
28
+ const hashCacheFile = '.appshot/processed/hashes.json';
29
+ const content = await fs.readFile(hashCacheFile, 'utf8');
30
+ const hashes = JSON.parse(content);
31
+ status.processedCache = true;
32
+ status.cachedHashes = hashes.length;
33
+ }
34
+ catch {
35
+ // Cache doesn't exist or is invalid
36
+ }
37
+ if (options.json) {
38
+ console.log(JSON.stringify(status, null, 2));
39
+ return;
40
+ }
41
+ // Human-readable output
42
+ console.log(pc.bold('\nšŸ“Š Watch Service Status\n'));
43
+ if (status.running) {
44
+ console.log(pc.green('āœ… Service is running'));
45
+ console.log(pc.dim(` PID: ${status.pid}`));
46
+ console.log(pc.dim(` PID file: ${status.pidFile}`));
47
+ }
48
+ else if (status.pid) {
49
+ console.log(pc.yellow('āš ļø Service is not running'));
50
+ console.log(pc.dim(` Stale PID: ${status.pid}`));
51
+ console.log(pc.dim(' Run "appshot watch stop" to clean up'));
52
+ }
53
+ else {
54
+ console.log(pc.gray('⚪ Service is not running'));
55
+ console.log(pc.dim(' Use "appshot watch start" to begin watching'));
56
+ }
57
+ if (options.verbose) {
58
+ console.log(pc.bold('\nšŸ“ Cache Information\n'));
59
+ if (status.processedCache) {
60
+ console.log(pc.dim(` Processed hashes: ${status.cachedHashes}`));
61
+ console.log(pc.dim(' Cache file: .appshot/processed/hashes.json'));
62
+ }
63
+ else {
64
+ console.log(pc.dim(' No processing cache found'));
65
+ }
66
+ // Check for watch directories in config
67
+ try {
68
+ const configPath = '.appshot/config.json';
69
+ const configContent = await fs.readFile(configPath, 'utf8');
70
+ const config = JSON.parse(configContent);
71
+ if (config.watch) {
72
+ console.log(pc.bold('\nāš™ļø Watch Configuration\n'));
73
+ if (config.watch.directories) {
74
+ console.log(pc.dim(' Configured directories:'));
75
+ for (const dir of config.watch.directories) {
76
+ const exists = await fs.stat(dir).then(() => true).catch(() => false);
77
+ const indicator = exists ? pc.green('āœ“') : pc.red('āœ—');
78
+ console.log(` ${indicator} ${dir}`);
79
+ }
80
+ }
81
+ if (config.watch.devices) {
82
+ console.log(pc.dim('\n Configured devices:'));
83
+ for (const device of config.watch.devices) {
84
+ console.log(` • ${device}`);
85
+ }
86
+ }
87
+ if (config.watch.process !== undefined) {
88
+ console.log(pc.dim(`\n Auto-process: ${config.watch.process ? 'Yes' : 'No'}`));
89
+ if (config.watch.frameOnly) {
90
+ console.log(pc.dim(' Mode: Frame only'));
91
+ }
92
+ }
93
+ }
94
+ }
95
+ catch {
96
+ // No config or invalid config
97
+ }
98
+ }
99
+ // Quick actions
100
+ console.log(pc.bold('\nšŸŽÆ Quick Actions\n'));
101
+ if (status.running) {
102
+ console.log(pc.dim(' appshot watch stop - Stop the service'));
103
+ console.log(pc.dim(' appshot watch status -v - Show detailed info'));
104
+ }
105
+ else {
106
+ console.log(pc.dim(' appshot watch start - Start watching'));
107
+ console.log(pc.dim(' appshot watch setup - Interactive setup'));
108
+ }
109
+ }
110
+ catch (error) {
111
+ console.error(pc.red('āŒ Error checking status:'), error);
112
+ process.exit(1);
113
+ }
114
+ });
115
+ }
116
+ //# sourceMappingURL=watch-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-status.js","sourceRoot":"","sources":["../../src/commands/watch-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export default function watchCommand(): Command;
3
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,MAAM,CAAC,OAAO,UAAU,YAAY,IAAI,OAAO,CAuV9C"}