vibefast-cli 0.1.3 → 0.2.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 (78) hide show
  1. package/AUTO-DETECT-DEPS.md +607 -0
  2. package/CHANGELOG.md +86 -0
  3. package/FINAL-PACKAGE-STRATEGY.md +583 -0
  4. package/FINAL-SIMPLE-PLAN.md +487 -0
  5. package/FLOW-DIAGRAM.md +1629 -0
  6. package/GOTCHAS-AND-RISKS.md +801 -0
  7. package/IMPLEMENTATION-COMPLETE.md +477 -0
  8. package/IMPLEMENTATION-PLAN.md +1360 -0
  9. package/PRE-PUBLISH-CHECKLIST.md +558 -0
  10. package/PRODUCTION-READINESS.md +684 -0
  11. package/PRODUCTION-TEST-RESULTS.md +465 -0
  12. package/README.md +73 -7
  13. package/READY-TO-PUBLISH.md +419 -0
  14. package/SIMPLIFIED-PLAN.md +578 -0
  15. package/TEST-SUMMARY.md +261 -0
  16. package/USER-MODIFICATIONS.md +448 -0
  17. package/cloudflare-worker/worker.js +39 -11
  18. package/dist/commands/add.d.ts.map +1 -1
  19. package/dist/commands/add.js +192 -15
  20. package/dist/commands/add.js.map +1 -1
  21. package/dist/commands/checklist.d.ts +3 -0
  22. package/dist/commands/checklist.d.ts.map +1 -0
  23. package/dist/commands/checklist.js +64 -0
  24. package/dist/commands/checklist.js.map +1 -0
  25. package/dist/commands/remove.d.ts.map +1 -1
  26. package/dist/commands/remove.js +85 -2
  27. package/dist/commands/remove.js.map +1 -1
  28. package/dist/commands/status.d.ts +3 -0
  29. package/dist/commands/status.d.ts.map +1 -0
  30. package/dist/commands/status.js +40 -0
  31. package/dist/commands/status.js.map +1 -0
  32. package/dist/core/__tests__/fsx.test.d.ts +2 -0
  33. package/dist/core/__tests__/fsx.test.d.ts.map +1 -0
  34. package/dist/core/__tests__/fsx.test.js +79 -0
  35. package/dist/core/__tests__/fsx.test.js.map +1 -0
  36. package/dist/core/__tests__/hash.test.d.ts +2 -0
  37. package/dist/core/__tests__/hash.test.d.ts.map +1 -0
  38. package/dist/core/__tests__/hash.test.js +84 -0
  39. package/dist/core/__tests__/hash.test.js.map +1 -0
  40. package/dist/core/__tests__/journal.test.js +65 -0
  41. package/dist/core/__tests__/journal.test.js.map +1 -1
  42. package/dist/core/__tests__/prompt.test.d.ts +2 -0
  43. package/dist/core/__tests__/prompt.test.d.ts.map +1 -0
  44. package/dist/core/__tests__/prompt.test.js +56 -0
  45. package/dist/core/__tests__/prompt.test.js.map +1 -0
  46. package/dist/core/fsx.d.ts +7 -1
  47. package/dist/core/fsx.d.ts.map +1 -1
  48. package/dist/core/fsx.js +18 -3
  49. package/dist/core/fsx.js.map +1 -1
  50. package/dist/core/hash.d.ts +13 -0
  51. package/dist/core/hash.d.ts.map +1 -0
  52. package/dist/core/hash.js +69 -0
  53. package/dist/core/hash.js.map +1 -0
  54. package/dist/core/journal.d.ts +10 -1
  55. package/dist/core/journal.d.ts.map +1 -1
  56. package/dist/core/journal.js +23 -1
  57. package/dist/core/journal.js.map +1 -1
  58. package/dist/core/prompt.d.ts +11 -0
  59. package/dist/core/prompt.d.ts.map +1 -0
  60. package/dist/core/prompt.js +34 -0
  61. package/dist/core/prompt.js.map +1 -0
  62. package/dist/index.js +5 -1
  63. package/dist/index.js.map +1 -1
  64. package/package.json +3 -1
  65. package/src/commands/add.ts +234 -16
  66. package/src/commands/checklist.ts +71 -0
  67. package/src/commands/remove.ts +105 -3
  68. package/src/commands/status.ts +47 -0
  69. package/src/core/__tests__/fsx.test.ts +101 -0
  70. package/src/core/__tests__/hash.test.ts +112 -0
  71. package/src/core/__tests__/journal.test.ts +76 -0
  72. package/src/core/__tests__/prompt.test.ts +72 -0
  73. package/src/core/fsx.ts +38 -5
  74. package/src/core/hash.ts +84 -0
  75. package/src/core/journal.ts +40 -2
  76. package/src/core/prompt.ts +40 -0
  77. package/src/index.ts +5 -1
  78. package/text.md +27 -0
@@ -0,0 +1,607 @@
1
+ # 🔍 Auto-Detecting Missing Dependencies
2
+
3
+ ## The Problem
4
+
5
+ When we install a feature, we copy files that import packages:
6
+ following is an example we aint using that pck name in reality:
7
+ ```typescript
8
+ // apps/native/src/features/charts/index.tsx
9
+ import { LineChart } from 'react-native-chart-kit'; // ← Package not installed!
10
+ import { Dimensions } from 'react-native';
11
+ ```
12
+
13
+ If `react-native-chart-kit` isn't installed, the app will crash or fail to build.
14
+
15
+ ## The Question
16
+
17
+ Can we **automatically detect** what packages are missing instead of manually specifying them in recipe.json?
18
+
19
+ **Answer: YES!** Multiple approaches:
20
+
21
+ ---
22
+
23
+ ## Approach 1: Run TypeScript Type Checking ✅ BEST
24
+
25
+ ### How It Works
26
+
27
+ TypeScript will error on missing packages:
28
+
29
+ ```bash
30
+ $ pnpm tsc --noEmit
31
+ # Output:
32
+ # error TS2307: Cannot find module 'react-native-chart-kit' or its corresponding type declarations.
33
+ ```
34
+
35
+ ### Implementation
36
+
37
+ **File:** `src/core/typecheck.ts` (NEW)
38
+
39
+ ```typescript
40
+ import { executeBash } from './shell.js';
41
+ import { log } from './log.js';
42
+
43
+ export interface TypeCheckResult {
44
+ success: boolean;
45
+ missingPackages: string[];
46
+ errors: string[];
47
+ }
48
+
49
+ export async function runTypeCheck(cwd: string): Promise<TypeCheckResult> {
50
+ log.info('Running type check to detect missing packages...');
51
+
52
+ // Try different type checkers in order of preference
53
+ const checkers = [
54
+ { cmd: 'pnpm tsc --noEmit', name: 'pnpm' },
55
+ { cmd: 'yarn tsc --noEmit', name: 'yarn' },
56
+ { cmd: 'npx tsc --noEmit', name: 'npm' },
57
+ ];
58
+
59
+ let result;
60
+ for (const checker of checkers) {
61
+ result = await executeBash(checker.cmd, { cwd });
62
+ if (result.exitCode !== 127) { // 127 = command not found
63
+ break;
64
+ }
65
+ }
66
+
67
+ if (!result || result.exitCode === 127) {
68
+ log.warn('TypeScript not found, skipping type check');
69
+ return { success: true, missingPackages: [], errors: [] };
70
+ }
71
+
72
+ // Parse TypeScript errors
73
+ const missingPackages = new Set<string>();
74
+ const errors: string[] = [];
75
+
76
+ const lines = result.stderr.split('\n');
77
+
78
+ for (const line of lines) {
79
+ // Match: error TS2307: Cannot find module 'package-name'
80
+ const match = line.match(/error TS2307: Cannot find module '([^']+)'/);
81
+ if (match) {
82
+ const moduleName = match[1];
83
+
84
+ // Extract package name (handle scoped packages and subpaths)
85
+ const packageName = extractPackageName(moduleName);
86
+
87
+ if (packageName && !isBuiltInModule(packageName)) {
88
+ missingPackages.add(packageName);
89
+ }
90
+ }
91
+
92
+ // Collect all errors for debugging
93
+ if (line.includes('error TS')) {
94
+ errors.push(line);
95
+ }
96
+ }
97
+
98
+ return {
99
+ success: result.exitCode === 0,
100
+ missingPackages: Array.from(missingPackages),
101
+ errors,
102
+ };
103
+ }
104
+
105
+ function extractPackageName(modulePath: string): string | null {
106
+ // Handle different import patterns:
107
+ // 'react-native-chart-kit' → 'react-native-chart-kit'
108
+ // 'react-native-chart-kit/dist/LineChart' → 'react-native-chart-kit'
109
+ // '@react-navigation/native' → '@react-navigation/native'
110
+ // '@react-navigation/native/lib/index' → '@react-navigation/native'
111
+
112
+ if (modulePath.startsWith('@')) {
113
+ // Scoped package: @scope/package
114
+ const parts = modulePath.split('/');
115
+ if (parts.length >= 2) {
116
+ return `${parts[0]}/${parts[1]}`;
117
+ }
118
+ } else {
119
+ // Regular package: package-name
120
+ const parts = modulePath.split('/');
121
+ return parts[0];
122
+ }
123
+
124
+ return null;
125
+ }
126
+
127
+ function isBuiltInModule(packageName: string): boolean {
128
+ // Node.js built-in modules
129
+ const builtIns = [
130
+ 'fs', 'path', 'crypto', 'http', 'https', 'url', 'util',
131
+ 'stream', 'events', 'buffer', 'process', 'os', 'child_process',
132
+ ];
133
+
134
+ // React Native built-ins
135
+ const rnBuiltIns = [
136
+ 'react-native',
137
+ 'react',
138
+ ];
139
+
140
+ return builtIns.includes(packageName) || rnBuiltIns.includes(packageName);
141
+ }
142
+ ```
143
+
144
+ ### Usage in add command
145
+
146
+ **File:** `src/commands/add.ts`
147
+
148
+ ```typescript
149
+ // After copying files, BEFORE adding watermarks
150
+
151
+ if (!options.dryRun && !options.skipTypeCheck) {
152
+ log.plain('');
153
+ log.info('🔍 Checking for missing dependencies...');
154
+
155
+ const typeCheckResult = await runTypeCheck(paths.cwd);
156
+
157
+ if (typeCheckResult.missingPackages.length > 0) {
158
+ log.plain('');
159
+ log.warn('⚠ Missing packages detected:');
160
+ log.plain('');
161
+
162
+ typeCheckResult.missingPackages.forEach(pkg => {
163
+ log.plain(` • ${pkg}`);
164
+ });
165
+
166
+ log.plain('');
167
+
168
+ // Try to find versions from recipe.json if available
169
+ const packagesWithVersions: Record<string, string> = {};
170
+
171
+ if (manifest.dependencies?.npm) {
172
+ typeCheckResult.missingPackages.forEach(pkg => {
173
+ if (manifest.dependencies.npm[pkg]) {
174
+ packagesWithVersions[pkg] = manifest.dependencies.npm[pkg];
175
+ } else {
176
+ // Default to latest
177
+ packagesWithVersions[pkg] = 'latest';
178
+ }
179
+ });
180
+ } else {
181
+ // No recipe dependencies, use latest for all
182
+ typeCheckResult.missingPackages.forEach(pkg => {
183
+ packagesWithVersions[pkg] = 'latest';
184
+ });
185
+ }
186
+
187
+ // Show install command
188
+ const pm = await detectPackageManager(paths.cwd);
189
+ const pkgList = Object.entries(packagesWithVersions)
190
+ .map(([name, version]) => version === 'latest' ? name : `${name}@${version}`)
191
+ .join(' ');
192
+ const installCmd = getInstallCommand(pm, pkgList.split(' '));
193
+
194
+ log.info('📦 Install with:');
195
+ log.plain(` ${installCmd}`);
196
+ log.plain('');
197
+
198
+ // Ask to install
199
+ if (!options.yes) {
200
+ const shouldInstall = promptYesNo(
201
+ 'Install missing packages now? (Y/n): ',
202
+ true
203
+ );
204
+
205
+ if (shouldInstall) {
206
+ log.info('Installing packages...');
207
+ const result = await installPackages(packagesWithVersions, paths.cwd);
208
+
209
+ if (result.success) {
210
+ log.success('✓ Packages installed successfully!');
211
+
212
+ // Run type check again to verify
213
+ log.info('Verifying installation...');
214
+ const verifyResult = await runTypeCheck(paths.cwd);
215
+
216
+ if (verifyResult.missingPackages.length > 0) {
217
+ log.warn('⚠ Some packages are still missing:');
218
+ verifyResult.missingPackages.forEach(pkg => {
219
+ log.plain(` • ${pkg}`);
220
+ });
221
+ } else {
222
+ log.success('✓ All dependencies resolved!');
223
+ }
224
+ } else {
225
+ log.error(`✗ Installation failed: ${result.error}`);
226
+ }
227
+ }
228
+ } else {
229
+ // Auto-install in --yes mode
230
+ log.info('Installing packages...');
231
+ const result = await installPackages(packagesWithVersions, paths.cwd);
232
+
233
+ if (!result.success) {
234
+ log.error(`✗ Installation failed: ${result.error}`);
235
+ process.exit(1);
236
+ }
237
+ }
238
+ } else if (typeCheckResult.success) {
239
+ log.success('✓ No missing dependencies detected');
240
+ } else {
241
+ log.warn('⚠ Type check completed with errors (but no missing packages)');
242
+ if (typeCheckResult.errors.length > 0 && process.env.DEBUG) {
243
+ log.plain('');
244
+ log.plain('Errors:');
245
+ typeCheckResult.errors.slice(0, 5).forEach(err => {
246
+ log.plain(` ${err}`);
247
+ });
248
+ }
249
+ }
250
+ }
251
+ ```
252
+
253
+ ### Add CLI flag
254
+
255
+ ```typescript
256
+ export const addCommand = new Command('add')
257
+ .description('Add a VibeFast feature to your project')
258
+ .argument('<feature>', 'Feature name to install')
259
+ .option('--target <target>', 'Target platform (native or web)', 'native')
260
+ .option('--dry-run', 'Preview changes without applying')
261
+ .option('--force', 'Overwrite existing files without asking')
262
+ .option('--yes', 'Answer yes to all prompts')
263
+ .option('--skip-install', 'Skip package installation')
264
+ .option('--skip-type-check', 'Skip type checking for missing packages') // NEW
265
+ .action(async (feature: string, options) => {
266
+ // ...
267
+ });
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Approach 2: Parse Import Statements 🟡 FALLBACK
273
+
274
+ If TypeScript isn't available, parse imports manually.
275
+
276
+ ### Implementation
277
+
278
+ **File:** `src/core/importParser.ts` (NEW)
279
+
280
+ ```typescript
281
+ import { readFile } from 'fs/promises';
282
+ import { join } from 'path';
283
+
284
+ export async function extractImports(filePath: string): Promise<string[]> {
285
+ const content = await readFile(filePath, 'utf-8');
286
+ const imports = new Set<string>();
287
+
288
+ // Match various import patterns
289
+ const patterns = [
290
+ // import X from 'package'
291
+ /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,
292
+ // import 'package'
293
+ /import\s+['"]([^'"]+)['"]/g,
294
+ // require('package')
295
+ /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
296
+ // import('package')
297
+ /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
298
+ ];
299
+
300
+ for (const pattern of patterns) {
301
+ let match;
302
+ while ((match = pattern.exec(content)) !== null) {
303
+ const importPath = match[1];
304
+
305
+ // Skip relative imports
306
+ if (importPath.startsWith('.') || importPath.startsWith('/')) {
307
+ continue;
308
+ }
309
+
310
+ imports.add(importPath);
311
+ }
312
+ }
313
+
314
+ return Array.from(imports);
315
+ }
316
+
317
+ export async function extractImportsFromFiles(
318
+ filePaths: string[]
319
+ ): Promise<string[]> {
320
+ const allImports = new Set<string>();
321
+
322
+ for (const filePath of filePaths) {
323
+ // Only parse JS/TS files
324
+ if (!/\.(js|jsx|ts|tsx)$/.test(filePath)) {
325
+ continue;
326
+ }
327
+
328
+ try {
329
+ const imports = await extractImports(filePath);
330
+ imports.forEach(imp => allImports.add(imp));
331
+ } catch (error) {
332
+ // Skip files that can't be read
333
+ continue;
334
+ }
335
+ }
336
+
337
+ return Array.from(allImports).map(extractPackageName).filter(Boolean) as string[];
338
+ }
339
+ ```
340
+
341
+ ### Check Against Installed Packages
342
+
343
+ **File:** `src/core/packageChecker.ts` (NEW)
344
+
345
+ ```typescript
346
+ import { readFile } from 'fs/promises';
347
+ import { join } from 'path';
348
+ import { exists } from './fsx.js';
349
+
350
+ export async function getInstalledPackages(cwd: string): Promise<Set<string>> {
351
+ const packageJsonPath = join(cwd, 'package.json');
352
+
353
+ if (!await exists(packageJsonPath)) {
354
+ return new Set();
355
+ }
356
+
357
+ const content = await readFile(packageJsonPath, 'utf-8');
358
+ const packageJson = JSON.parse(content);
359
+
360
+ const installed = new Set<string>();
361
+
362
+ // Add dependencies
363
+ if (packageJson.dependencies) {
364
+ Object.keys(packageJson.dependencies).forEach(pkg => installed.add(pkg));
365
+ }
366
+
367
+ // Add devDependencies
368
+ if (packageJson.devDependencies) {
369
+ Object.keys(packageJson.devDependencies).forEach(pkg => installed.add(pkg));
370
+ }
371
+
372
+ return installed;
373
+ }
374
+
375
+ export async function findMissingPackages(
376
+ requiredPackages: string[],
377
+ cwd: string
378
+ ): Promise<string[]> {
379
+ const installed = await getInstalledPackages(cwd);
380
+
381
+ return requiredPackages.filter(pkg => !installed.has(pkg));
382
+ }
383
+ ```
384
+
385
+ ### Usage
386
+
387
+ ```typescript
388
+ // After copying files
389
+
390
+ // Extract imports from copied files
391
+ const imports = await extractImportsFromFiles(copiedFiles);
392
+
393
+ // Check which are missing
394
+ const missing = await findMissingPackages(imports, paths.cwd);
395
+
396
+ if (missing.length > 0) {
397
+ log.warn('⚠ Missing packages detected:');
398
+ missing.forEach(pkg => log.plain(` • ${pkg}`));
399
+ // ... prompt to install
400
+ }
401
+ ```
402
+
403
+ ---
404
+
405
+ ## Approach 3: Run ESLint 🟢 BONUS
406
+
407
+ If the project has ESLint configured:
408
+
409
+ ```typescript
410
+ export async function runESLint(cwd: string): Promise<string[]> {
411
+ const result = await executeBash('npx eslint . --format json', { cwd });
412
+
413
+ if (result.exitCode === 0) {
414
+ return [];
415
+ }
416
+
417
+ try {
418
+ const eslintOutput = JSON.parse(result.stdout);
419
+ const missingPackages = new Set<string>();
420
+
421
+ eslintOutput.forEach((file: any) => {
422
+ file.messages.forEach((msg: any) => {
423
+ // ESLint rule: import/no-unresolved
424
+ if (msg.ruleId === 'import/no-unresolved') {
425
+ const match = msg.message.match(/Unable to resolve path to module '([^']+)'/);
426
+ if (match) {
427
+ const packageName = extractPackageName(match[1]);
428
+ if (packageName) {
429
+ missingPackages.add(packageName);
430
+ }
431
+ }
432
+ }
433
+ });
434
+ });
435
+
436
+ return Array.from(missingPackages);
437
+ } catch (error) {
438
+ return [];
439
+ }
440
+ }
441
+ ```
442
+
443
+ ---
444
+
445
+ ## Recommended Strategy: Hybrid Approach
446
+
447
+ ### Step 1: Try TypeScript (Most Accurate)
448
+ ```typescript
449
+ const typeCheckResult = await runTypeCheck(paths.cwd);
450
+ if (typeCheckResult.missingPackages.length > 0) {
451
+ return typeCheckResult.missingPackages;
452
+ }
453
+ ```
454
+
455
+ ### Step 2: Fallback to Import Parsing
456
+ ```typescript
457
+ if (!typeCheckResult.success && typeCheckResult.missingPackages.length === 0) {
458
+ // TypeScript failed or not available, try parsing
459
+ const imports = await extractImportsFromFiles(copiedFiles);
460
+ const missing = await findMissingPackages(imports, paths.cwd);
461
+ return missing;
462
+ }
463
+ ```
464
+
465
+ ### Step 3: Use Recipe as Source of Truth
466
+ ```typescript
467
+ // If detection fails, fall back to recipe.json
468
+ if (manifest.dependencies?.npm) {
469
+ return Object.keys(manifest.dependencies.npm);
470
+ }
471
+ ```
472
+
473
+ ---
474
+
475
+ ## Complete Flow
476
+
477
+ ```
478
+ ┌─────────────────────────────────────────────────────────────────┐
479
+ │ DEPENDENCY DETECTION FLOW │
480
+ └─────────────────────────────────────────────────────────────────┘
481
+
482
+ Step 1: Install Feature Files
483
+ ┌──────────────────────────────────────────────────────────────┐
484
+ │ $ vf add charts │
485
+ │ ✓ Files copied: 17 │
486
+ └──────────────────────────────────────────────────────────────┘
487
+
488
+
489
+ Step 2: Run Type Check
490
+ ┌──────────────────────────────────────────────────────────────┐
491
+ │ $ pnpm tsc --noEmit │
492
+ │ │
493
+ │ Output: │
494
+ │ error TS2307: Cannot find module 'react-native-chart-kit' │
495
+ │ error TS2307: Cannot find module 'react-native-svg' │
496
+ └──────────────────────────────────────────────────────────────┘
497
+
498
+
499
+ Step 3: Parse Errors
500
+ ┌──────────────────────────────────────────────────────────────┐
501
+ │ Detected missing packages: │
502
+ │ • react-native-chart-kit │
503
+ │ • react-native-svg │
504
+ └──────────────────────────────────────────────────────────────┘
505
+
506
+
507
+ Step 4: Check Recipe for Versions
508
+ ┌──────────────────────────────────────────────────────────────┐
509
+ │ recipe.json has: │
510
+ │ { │
511
+ │ "dependencies": { │
512
+ │ "npm": { │
513
+ │ "react-native-chart-kit": "^6.12.0", │
514
+ │ "react-native-svg": "^13.9.0" │
515
+ │ } │
516
+ │ } │
517
+ │ } │
518
+ │ │
519
+ │ Use these versions ✓ │
520
+ └──────────────────────────────────────────────────────────────┘
521
+
522
+
523
+ Step 5: Prompt User
524
+ ┌──────────────────────────────────────────────────────────────┐
525
+ │ ⚠ Missing packages detected: │
526
+ │ • react-native-chart-kit@^6.12.0 │
527
+ │ • react-native-svg@^13.9.0 │
528
+ │ │
529
+ │ 📦 Install with: │
530
+ │ pnpm add react-native-chart-kit@^6.12.0 react-native-svg@^13.9.0
531
+ │ │
532
+ │ Install missing packages now? (Y/n): _ │
533
+ └──────────────────────────────────────────────────────────────┘
534
+
535
+
536
+ Step 6: Install Packages
537
+ ┌──────────────────────────────────────────────────────────────┐
538
+ │ $ pnpm add react-native-chart-kit@^6.12.0 react-native-svg@^13.9.0
539
+ │ ✓ Packages installed │
540
+ └──────────────────────────────────────────────────────────────┘
541
+
542
+
543
+ Step 7: Verify
544
+ ┌──────────────────────────────────────────────────────────────┐
545
+ │ $ pnpm tsc --noEmit │
546
+ │ ✓ No errors │
547
+ │ ✓ All dependencies resolved! │
548
+ └──────────────────────────────────────────────────────────────┘
549
+ ```
550
+
551
+ ---
552
+
553
+ ## Advantages of This Approach
554
+
555
+ 1. **Automatic Detection** - No need to manually specify in recipe.json
556
+ 2. **Accurate** - TypeScript knows exactly what's missing
557
+ 3. **Version Aware** - Can still use recipe.json for specific versions
558
+ 4. **Fallback** - Import parsing if TypeScript not available
559
+ 5. **Verification** - Can re-run type check after install to confirm
560
+
561
+ ## Disadvantages
562
+
563
+ 1. **Slower** - Type checking takes 5-30 seconds
564
+ 2. **Requires TypeScript** - Not all projects have it
565
+ 3. **False Positives** - Might detect unrelated errors
566
+ 4. **Version Guessing** - If not in recipe.json, defaults to 'latest'
567
+
568
+ ---
569
+
570
+ ## Recommendation
571
+
572
+ **Use BOTH approaches:**
573
+
574
+ 1. **Recipe.json as primary** (fast, explicit, version-controlled)
575
+ 2. **Type checking as verification** (catch missing deps in recipe.json)
576
+
577
+ ```typescript
578
+ // After copying files
579
+
580
+ // 1. Check recipe.json first
581
+ if (manifest.dependencies?.npm) {
582
+ const recipeDeps = manifest.dependencies.npm;
583
+ // Show and install these
584
+ }
585
+
586
+ // 2. Run type check to verify
587
+ const typeCheckResult = await runTypeCheck(paths.cwd);
588
+ if (typeCheckResult.missingPackages.length > 0) {
589
+ log.warn('⚠ Additional missing packages detected:');
590
+ // Show packages not in recipe.json
591
+ const additional = typeCheckResult.missingPackages.filter(
592
+ pkg => !recipeDeps[pkg]
593
+ );
594
+
595
+ if (additional.length > 0) {
596
+ log.warn('These packages are missing from recipe.json:');
597
+ additional.forEach(pkg => log.plain(` • ${pkg}`));
598
+ log.info('Consider updating the recipe to include these.');
599
+ }
600
+ }
601
+ ```
602
+
603
+ This gives us:
604
+ - ✅ Fast installation (recipe.json)
605
+ - ✅ Verification (type check)
606
+ - ✅ Catches recipe mistakes
607
+ - ✅ Best of both worlds
package/CHANGELOG.md ADDED
@@ -0,0 +1,86 @@
1
+ # Changelog
2
+
3
+ All notable changes to VibeFast CLI will be documented in this file.
4
+
5
+ ## [0.2.0] - 2024-11-13
6
+
7
+ ### Added
8
+ - **Interactive Confirmation**: CLI now asks before overwriting existing files
9
+ - **Package Dependency Display**: Shows required packages with `npx expo install` command
10
+ - **Modification Detection**: Warns before deleting files you've modified
11
+ - **Manual Steps Display**: Shows setup instructions for services (Sentry, PostHog, etc.)
12
+ - **Status Command**: New `vf status` command to show installed features
13
+ - **Checklist Command**: New `vf checklist <feature>` command to show manual setup steps
14
+ - **File Hashing**: SHA-256 hashing for integrity checking
15
+ - **Auto-Migration**: Automatically migrates old journal format to new format
16
+ - **Automation Flags**: Added `--yes` flag for CI/CD and `--force` flag to skip prompts
17
+ - **Comprehensive Tests**: 34 unit tests covering all core functionality
18
+
19
+ ### Improved
20
+ - **Error Messages**: User-friendly error messages with clear actionable solutions
21
+ - **Support Contact**: All error messages include support@vibefast.pro
22
+ - **CI/CD Compatibility**: Detects non-interactive environments and behaves appropriately
23
+ - **Performance**: Optimized file hashing (skips binary files, processes in batches)
24
+ - **Documentation**: Comprehensive documentation and examples
25
+
26
+ ### Changed
27
+ - **Package Management**: Now uses `npx expo install` for native apps (no version management needed)
28
+ - **Journal Format**: Updated to store file hashes (auto-migrates old format)
29
+
30
+ ### Fixed
31
+ - Files being overwritten without confirmation
32
+ - No warning when deleting modified files
33
+ - Missing package installation information
34
+ - Generic error messages
35
+
36
+ ## [0.1.4] - 2024-11-11
37
+
38
+ ### Added
39
+ - Initial release
40
+ - Basic `vf add` and `vf remove` commands
41
+ - Authentication with `vf login` and `vf logout`
42
+ - Device management with `vf devices`
43
+ - Repository validation with `vf doctor`
44
+ - Feature listing with `vf list`
45
+ - Navigation injection
46
+ - Watermarking
47
+ - Journal tracking
48
+
49
+ ### Security
50
+ - Path security with directory traversal prevention
51
+ - Token storage in user home directory
52
+ - HTTPS-only communication
53
+ - Input validation
54
+
55
+ ---
56
+
57
+ ## Upgrade Guide
58
+
59
+ ### From 0.1.x to 0.2.0
60
+
61
+ No breaking changes! The CLI will automatically migrate your journal to the new format.
62
+
63
+ **New Features You Can Use:**
64
+ ```bash
65
+ # Check what's installed
66
+ vf status
67
+
68
+ # See manual setup steps
69
+ vf checklist sentry
70
+
71
+ # Use automation flags
72
+ vf add charts --yes
73
+ vf remove charts --force
74
+ ```
75
+
76
+ **Improved Error Messages:**
77
+ The CLI now provides much clearer error messages with actionable solutions.
78
+
79
+ ---
80
+
81
+ ## Support
82
+
83
+ For issues or questions:
84
+ - Email: support@vibefast.pro
85
+ - GitHub: https://github.com/vibefast/vibefast-cli/issues
86
+ - Website: https://vibefast.pro