@fnd-platform/cli 1.0.0-alpha.24 → 1.0.0-alpha.25
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/lib/bin/fnd.js +101 -4
- package/lib/bin/fnd.js.map +1 -1
- package/lib/commands/add.js +72 -75
- package/lib/commands/add.js.map +1 -1
- package/lib/commands/build.js +29 -34
- package/lib/commands/build.js.map +1 -1
- package/lib/commands/deploy.d.ts +13 -5
- package/lib/commands/deploy.d.ts.map +1 -1
- package/lib/commands/deploy.js +94 -75
- package/lib/commands/deploy.js.map +1 -1
- package/lib/commands/destroy.js +33 -38
- package/lib/commands/destroy.js.map +1 -1
- package/lib/commands/index.d.ts +1 -0
- package/lib/commands/index.d.ts.map +1 -1
- package/lib/commands/index.js +7 -15
- package/lib/commands/index.js.map +1 -1
- package/lib/commands/new.js +46 -50
- package/lib/commands/new.js.map +1 -1
- package/lib/commands/synth.d.ts +8 -1
- package/lib/commands/synth.d.ts.map +1 -1
- package/lib/commands/synth.js +82 -22
- package/lib/commands/synth.js.map +1 -1
- package/lib/commands/test.d.ts +73 -0
- package/lib/commands/test.d.ts.map +1 -0
- package/lib/commands/test.js +193 -0
- package/lib/commands/test.js.map +1 -0
- package/lib/index.d.ts +11 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +29 -18
- package/lib/index.js.map +1 -1
- package/lib/lib/deploy-utils.d.ts.map +1 -1
- package/lib/lib/deploy-utils.js +73 -72
- package/lib/lib/deploy-utils.js.map +1 -1
- package/lib/lib/infra-generator.js +55 -63
- package/lib/lib/infra-generator.js.map +1 -1
- package/lib/lib/logger.js +23 -29
- package/lib/lib/logger.js.map +1 -1
- package/lib/lib/nx-stats.js +12 -18
- package/lib/lib/nx-stats.js.map +1 -1
- package/lib/lib/project.js +7 -11
- package/lib/lib/project.js.map +1 -1
- package/lib/lib/templates.js +2 -6
- package/lib/lib/templates.js.map +1 -1
- package/lib/lib/timer.js +2 -7
- package/lib/lib/timer.js.map +1 -1
- package/lib/lib/validation.d.ts +135 -0
- package/lib/lib/validation.d.ts.map +1 -0
- package/lib/lib/validation.js +233 -0
- package/lib/lib/validation.js.map +1 -0
- package/lib/tui/App.d.ts +11 -0
- package/lib/tui/App.d.ts.map +1 -0
- package/lib/tui/App.js +98 -0
- package/lib/tui/App.js.map +1 -0
- package/lib/tui/components/branding/AsciiBanner.d.ts +21 -0
- package/lib/tui/components/branding/AsciiBanner.d.ts.map +1 -0
- package/lib/tui/components/branding/AsciiBanner.js +15 -0
- package/lib/tui/components/branding/AsciiBanner.js.map +1 -0
- package/lib/tui/components/branding/index.d.ts +5 -0
- package/lib/tui/components/branding/index.d.ts.map +1 -0
- package/lib/tui/components/branding/index.js +5 -0
- package/lib/tui/components/branding/index.js.map +1 -0
- package/lib/tui/components/feedback/Notification.d.ts +51 -0
- package/lib/tui/components/feedback/Notification.d.ts.map +1 -0
- package/lib/tui/components/feedback/Notification.js +89 -0
- package/lib/tui/components/feedback/Notification.js.map +1 -0
- package/lib/tui/components/feedback/ProgressBar.d.ts +46 -0
- package/lib/tui/components/feedback/ProgressBar.d.ts.map +1 -0
- package/lib/tui/components/feedback/ProgressBar.js +30 -0
- package/lib/tui/components/feedback/ProgressBar.js.map +1 -0
- package/lib/tui/components/feedback/ProgressSteps.d.ts +35 -0
- package/lib/tui/components/feedback/ProgressSteps.d.ts.map +1 -0
- package/lib/tui/components/feedback/ProgressSteps.js +37 -0
- package/lib/tui/components/feedback/ProgressSteps.js.map +1 -0
- package/lib/tui/components/feedback/Spinner.d.ts +18 -0
- package/lib/tui/components/feedback/Spinner.d.ts.map +1 -0
- package/lib/tui/components/feedback/Spinner.js +28 -0
- package/lib/tui/components/feedback/Spinner.js.map +1 -0
- package/lib/tui/components/feedback/index.d.ts +8 -0
- package/lib/tui/components/feedback/index.d.ts.map +1 -0
- package/lib/tui/components/feedback/index.js +8 -0
- package/lib/tui/components/feedback/index.js.map +1 -0
- package/lib/tui/components/index.d.ts +8 -0
- package/lib/tui/components/index.d.ts.map +1 -0
- package/lib/tui/components/index.js +8 -0
- package/lib/tui/components/index.js.map +1 -0
- package/lib/tui/components/input/Checkbox.d.ts +26 -0
- package/lib/tui/components/input/Checkbox.d.ts.map +1 -0
- package/lib/tui/components/input/Checkbox.js +20 -0
- package/lib/tui/components/input/Checkbox.js.map +1 -0
- package/lib/tui/components/input/SelectInput.d.ts +41 -0
- package/lib/tui/components/input/SelectInput.d.ts.map +1 -0
- package/lib/tui/components/input/SelectInput.js +53 -0
- package/lib/tui/components/input/SelectInput.js.map +1 -0
- package/lib/tui/components/input/TextInput.d.ts +30 -0
- package/lib/tui/components/input/TextInput.d.ts.map +1 -0
- package/lib/tui/components/input/TextInput.js +48 -0
- package/lib/tui/components/input/TextInput.js.map +1 -0
- package/lib/tui/components/input/index.d.ts +7 -0
- package/lib/tui/components/input/index.d.ts.map +1 -0
- package/lib/tui/components/input/index.js +7 -0
- package/lib/tui/components/input/index.js.map +1 -0
- package/lib/tui/components/layout/Breadcrumbs.d.ts +11 -0
- package/lib/tui/components/layout/Breadcrumbs.d.ts.map +1 -0
- package/lib/tui/components/layout/Breadcrumbs.js +34 -0
- package/lib/tui/components/layout/Breadcrumbs.js.map +1 -0
- package/lib/tui/components/layout/Footer.d.ts +11 -0
- package/lib/tui/components/layout/Footer.d.ts.map +1 -0
- package/lib/tui/components/layout/Footer.js +20 -0
- package/lib/tui/components/layout/Footer.js.map +1 -0
- package/lib/tui/components/layout/Header.d.ts +21 -0
- package/lib/tui/components/layout/Header.d.ts.map +1 -0
- package/lib/tui/components/layout/Header.js +21 -0
- package/lib/tui/components/layout/Header.js.map +1 -0
- package/lib/tui/components/layout/Screen.d.ts +27 -0
- package/lib/tui/components/layout/Screen.d.ts.map +1 -0
- package/lib/tui/components/layout/Screen.js +11 -0
- package/lib/tui/components/layout/Screen.js.map +1 -0
- package/lib/tui/components/layout/index.d.ts +8 -0
- package/lib/tui/components/layout/index.d.ts.map +1 -0
- package/lib/tui/components/layout/index.js +8 -0
- package/lib/tui/components/layout/index.js.map +1 -0
- package/lib/tui/hooks/index.d.ts +20 -0
- package/lib/tui/hooks/index.d.ts.map +1 -0
- package/lib/tui/hooks/index.js +18 -0
- package/lib/tui/hooks/index.js.map +1 -0
- package/lib/tui/hooks/useAddPackage.d.ts +120 -0
- package/lib/tui/hooks/useAddPackage.d.ts.map +1 -0
- package/lib/tui/hooks/useAddPackage.js +347 -0
- package/lib/tui/hooks/useAddPackage.js.map +1 -0
- package/lib/tui/hooks/useCreateProject.d.ts +66 -0
- package/lib/tui/hooks/useCreateProject.d.ts.map +1 -0
- package/lib/tui/hooks/useCreateProject.js +156 -0
- package/lib/tui/hooks/useCreateProject.js.map +1 -0
- package/lib/tui/hooks/useDeploy.d.ts +93 -0
- package/lib/tui/hooks/useDeploy.d.ts.map +1 -0
- package/lib/tui/hooks/useDeploy.js +252 -0
- package/lib/tui/hooks/useDeploy.js.map +1 -0
- package/lib/tui/hooks/useKeyboard.d.ts +66 -0
- package/lib/tui/hooks/useKeyboard.d.ts.map +1 -0
- package/lib/tui/hooks/useKeyboard.js +101 -0
- package/lib/tui/hooks/useKeyboard.js.map +1 -0
- package/lib/tui/hooks/useNavigation.d.ts +33 -0
- package/lib/tui/hooks/useNavigation.d.ts.map +1 -0
- package/lib/tui/hooks/useNavigation.js +27 -0
- package/lib/tui/hooks/useNavigation.js.map +1 -0
- package/lib/tui/hooks/useProject.d.ts +36 -0
- package/lib/tui/hooks/useProject.d.ts.map +1 -0
- package/lib/tui/hooks/useProject.js +47 -0
- package/lib/tui/hooks/useProject.js.map +1 -0
- package/lib/tui/index.d.ts +15 -0
- package/lib/tui/index.d.ts.map +1 -0
- package/lib/tui/index.js +16 -0
- package/lib/tui/index.js.map +1 -0
- package/lib/tui/lib/add-package-tui.d.ts +127 -0
- package/lib/tui/lib/add-package-tui.d.ts.map +1 -0
- package/lib/tui/lib/add-package-tui.js +467 -0
- package/lib/tui/lib/add-package-tui.js.map +1 -0
- package/lib/tui/lib/create-project-tui.d.ts +84 -0
- package/lib/tui/lib/create-project-tui.d.ts.map +1 -0
- package/lib/tui/lib/create-project-tui.js +141 -0
- package/lib/tui/lib/create-project-tui.js.map +1 -0
- package/lib/tui/lib/deploy-tui.d.ts +131 -0
- package/lib/tui/lib/deploy-tui.d.ts.map +1 -0
- package/lib/tui/lib/deploy-tui.js +347 -0
- package/lib/tui/lib/deploy-tui.js.map +1 -0
- package/lib/tui/screens/AddPackageScreen.d.ts +12 -0
- package/lib/tui/screens/AddPackageScreen.d.ts.map +1 -0
- package/lib/tui/screens/AddPackageScreen.js +436 -0
- package/lib/tui/screens/AddPackageScreen.js.map +1 -0
- package/lib/tui/screens/CreateProjectScreen.d.ts +12 -0
- package/lib/tui/screens/CreateProjectScreen.d.ts.map +1 -0
- package/lib/tui/screens/CreateProjectScreen.js +252 -0
- package/lib/tui/screens/CreateProjectScreen.js.map +1 -0
- package/lib/tui/screens/DeployScreen.d.ts +11 -0
- package/lib/tui/screens/DeployScreen.d.ts.map +1 -0
- package/lib/tui/screens/DeployScreen.js +224 -0
- package/lib/tui/screens/DeployScreen.js.map +1 -0
- package/lib/tui/screens/ProjectDashboard.d.ts +11 -0
- package/lib/tui/screens/ProjectDashboard.d.ts.map +1 -0
- package/lib/tui/screens/ProjectDashboard.js +42 -0
- package/lib/tui/screens/ProjectDashboard.js.map +1 -0
- package/lib/tui/screens/WelcomeScreen.d.ts +11 -0
- package/lib/tui/screens/WelcomeScreen.d.ts.map +1 -0
- package/lib/tui/screens/WelcomeScreen.js +26 -0
- package/lib/tui/screens/WelcomeScreen.js.map +1 -0
- package/lib/tui/screens/index.d.ts +9 -0
- package/lib/tui/screens/index.d.ts.map +1 -0
- package/lib/tui/screens/index.js +9 -0
- package/lib/tui/screens/index.js.map +1 -0
- package/lib/tui/services/ConfigService.d.ts +133 -0
- package/lib/tui/services/ConfigService.d.ts.map +1 -0
- package/lib/tui/services/ConfigService.js +221 -0
- package/lib/tui/services/ConfigService.js.map +1 -0
- package/lib/tui/services/ProjectService.d.ts +55 -0
- package/lib/tui/services/ProjectService.d.ts.map +1 -0
- package/lib/tui/services/ProjectService.js +179 -0
- package/lib/tui/services/ProjectService.js.map +1 -0
- package/lib/tui/services/index.d.ts +6 -0
- package/lib/tui/services/index.d.ts.map +1 -0
- package/lib/tui/services/index.js +6 -0
- package/lib/tui/services/index.js.map +1 -0
- package/lib/tui/state/AppContext.d.ts +58 -0
- package/lib/tui/state/AppContext.d.ts.map +1 -0
- package/lib/tui/state/AppContext.js +75 -0
- package/lib/tui/state/AppContext.js.map +1 -0
- package/lib/tui/state/index.d.ts +7 -0
- package/lib/tui/state/index.d.ts.map +1 -0
- package/lib/tui/state/index.js +7 -0
- package/lib/tui/state/index.js.map +1 -0
- package/lib/tui/state/reducer.d.ts +13 -0
- package/lib/tui/state/reducer.d.ts.map +1 -0
- package/lib/tui/state/reducer.js +136 -0
- package/lib/tui/state/reducer.js.map +1 -0
- package/lib/tui/state/types.d.ts +132 -0
- package/lib/tui/state/types.d.ts.map +1 -0
- package/lib/tui/state/types.js +38 -0
- package/lib/tui/state/types.js.map +1 -0
- package/lib/tui/utils/ascii.d.ts +42 -0
- package/lib/tui/utils/ascii.d.ts.map +1 -0
- package/lib/tui/utils/ascii.js +63 -0
- package/lib/tui/utils/ascii.js.map +1 -0
- package/lib/tui/utils/colors.d.ts +65 -0
- package/lib/tui/utils/colors.d.ts.map +1 -0
- package/lib/tui/utils/colors.js +65 -0
- package/lib/tui/utils/colors.js.map +1 -0
- package/lib/tui/utils/index.d.ts +6 -0
- package/lib/tui/utils/index.d.ts.map +1 -0
- package/lib/tui/utils/index.js +6 -0
- package/lib/tui/utils/index.js.map +1 -0
- package/package.json +12 -3
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { requireProjectRoot } from '../lib/project.js';
|
|
4
|
+
import { logger } from '../lib/logger.js';
|
|
5
|
+
import { PerformanceTimer } from '../lib/timer.js';
|
|
6
|
+
import { parseNxOutput } from '../lib/nx-stats.js';
|
|
7
|
+
/**
|
|
8
|
+
* Creates the `fnd test` command.
|
|
9
|
+
*
|
|
10
|
+
* @returns Commander command instance
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { testCommand } from '@fnd-platform/cli';
|
|
15
|
+
*
|
|
16
|
+
* const program = new Command();
|
|
17
|
+
* program.addCommand(testCommand());
|
|
18
|
+
* program.parse(['node', 'fnd', 'test']);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function testCommand() {
|
|
22
|
+
return new Command('test')
|
|
23
|
+
.description('Run tests across all packages using NX')
|
|
24
|
+
.option('--package <name>', 'Test specific package only')
|
|
25
|
+
.option('--coverage', 'Generate coverage report')
|
|
26
|
+
.option('--watch', 'Watch mode')
|
|
27
|
+
.option('--update', 'Update snapshots')
|
|
28
|
+
.option('--ci', 'CI mode (no watch, fail on threshold)')
|
|
29
|
+
.option('--skip-cache', 'Skip NX cache')
|
|
30
|
+
.option('--parallel <n>', 'Number of parallel tasks')
|
|
31
|
+
.action(async (options) => {
|
|
32
|
+
await runTest(options);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Runs the NX test.
|
|
37
|
+
*
|
|
38
|
+
* @param options - Command options
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* // Run all tests
|
|
43
|
+
* await runTest({});
|
|
44
|
+
*
|
|
45
|
+
* // Test a specific package with coverage
|
|
46
|
+
* await runTest({ package: 'api', coverage: true });
|
|
47
|
+
*
|
|
48
|
+
* // Run tests in watch mode
|
|
49
|
+
* await runTest({ watch: true });
|
|
50
|
+
*
|
|
51
|
+
* // Run tests in CI mode
|
|
52
|
+
* await runTest({ ci: true });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export async function runTest(options) {
|
|
56
|
+
// Initialize profiling if enabled
|
|
57
|
+
const timer = PerformanceTimer.isEnabled() ? new PerformanceTimer('fnd test') : null;
|
|
58
|
+
let projectRoot;
|
|
59
|
+
timer?.start('project-detection');
|
|
60
|
+
try {
|
|
61
|
+
projectRoot = requireProjectRoot();
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (timer) {
|
|
65
|
+
timer.end('project-detection');
|
|
66
|
+
logger.report(timer.getReport(false));
|
|
67
|
+
}
|
|
68
|
+
logger.error(error.message);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const detectResult = timer?.end('project-detection');
|
|
72
|
+
if (detectResult) {
|
|
73
|
+
logger.timing('project-detection', detectResult.durationMs);
|
|
74
|
+
}
|
|
75
|
+
logger.info('Running tests...');
|
|
76
|
+
logger.debug(`Project root: ${projectRoot}`);
|
|
77
|
+
// Build the NX command arguments
|
|
78
|
+
const args = buildNxTestArgs(options);
|
|
79
|
+
const command = args.join(' ');
|
|
80
|
+
logger.debug(`Running: ${command}`);
|
|
81
|
+
timer?.start('nx-test');
|
|
82
|
+
try {
|
|
83
|
+
if (timer) {
|
|
84
|
+
// Capture output for cache statistics when profiling is enabled
|
|
85
|
+
const output = execSync(command, {
|
|
86
|
+
cwd: projectRoot,
|
|
87
|
+
stdio: 'pipe',
|
|
88
|
+
encoding: 'utf-8',
|
|
89
|
+
});
|
|
90
|
+
const testResult = timer.end('nx-test');
|
|
91
|
+
logger.timing('nx-test', testResult.durationMs);
|
|
92
|
+
// Print output since we captured it
|
|
93
|
+
console.log(output);
|
|
94
|
+
// Parse and display NX cache statistics
|
|
95
|
+
const stats = parseNxOutput(output);
|
|
96
|
+
if (stats) {
|
|
97
|
+
logger.cacheStats(stats);
|
|
98
|
+
}
|
|
99
|
+
logger.success('Tests complete');
|
|
100
|
+
logger.report(timer.getReport(true));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// Normal execution without profiling
|
|
104
|
+
execSync(command, {
|
|
105
|
+
cwd: projectRoot,
|
|
106
|
+
stdio: 'inherit',
|
|
107
|
+
});
|
|
108
|
+
logger.success('Tests complete');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (timer) {
|
|
113
|
+
timer.end('nx-test');
|
|
114
|
+
logger.report(timer.getReport(false));
|
|
115
|
+
}
|
|
116
|
+
logger.error('Tests failed');
|
|
117
|
+
logger.debug(`Error: ${error.message}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Builds the NX command arguments based on options.
|
|
123
|
+
*
|
|
124
|
+
* @param options - Command options
|
|
125
|
+
* @returns Array of command arguments
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* // Run all tests
|
|
130
|
+
* buildNxTestArgs({});
|
|
131
|
+
* // Returns: ['npx', 'nx', 'run-many', '--target=test', '--all']
|
|
132
|
+
*
|
|
133
|
+
* // Test specific package with coverage
|
|
134
|
+
* buildNxTestArgs({ package: 'api', coverage: true });
|
|
135
|
+
* // Returns: ['npx', 'nx', 'run', 'api:test', '--', '--coverage']
|
|
136
|
+
*
|
|
137
|
+
* // Run all tests in CI mode
|
|
138
|
+
* buildNxTestArgs({ ci: true });
|
|
139
|
+
* // Returns: ['npx', 'nx', 'run-many', '--target=test', '--all', '--', '--ci']
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export function buildNxTestArgs(options) {
|
|
143
|
+
// If testing a specific package
|
|
144
|
+
if (options.package) {
|
|
145
|
+
const args = ['npx', 'nx', 'run', `${options.package}:test`];
|
|
146
|
+
if (options.skipCache) {
|
|
147
|
+
args.push('--skip-nx-cache');
|
|
148
|
+
}
|
|
149
|
+
// Vitest/Jest options go after --
|
|
150
|
+
const vitestArgs = buildVitestArgs(options);
|
|
151
|
+
if (vitestArgs.length > 0) {
|
|
152
|
+
args.push('--', ...vitestArgs);
|
|
153
|
+
}
|
|
154
|
+
return args;
|
|
155
|
+
}
|
|
156
|
+
// Testing all packages
|
|
157
|
+
const args = ['npx', 'nx', 'run-many', '--target=test', '--all'];
|
|
158
|
+
if (options.skipCache) {
|
|
159
|
+
args.push('--skip-nx-cache');
|
|
160
|
+
}
|
|
161
|
+
if (options.parallel) {
|
|
162
|
+
args.push(`--parallel=${options.parallel}`);
|
|
163
|
+
}
|
|
164
|
+
// Vitest/Jest options go after --
|
|
165
|
+
const vitestArgs = buildVitestArgs(options);
|
|
166
|
+
if (vitestArgs.length > 0) {
|
|
167
|
+
args.push('--', ...vitestArgs);
|
|
168
|
+
}
|
|
169
|
+
return args;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Builds Vitest/Jest specific arguments.
|
|
173
|
+
*
|
|
174
|
+
* @param options - Command options
|
|
175
|
+
* @returns Array of test runner arguments
|
|
176
|
+
*/
|
|
177
|
+
function buildVitestArgs(options) {
|
|
178
|
+
const args = [];
|
|
179
|
+
if (options.coverage) {
|
|
180
|
+
args.push('--coverage');
|
|
181
|
+
}
|
|
182
|
+
if (options.watch) {
|
|
183
|
+
args.push('--watch');
|
|
184
|
+
}
|
|
185
|
+
if (options.update) {
|
|
186
|
+
args.push('--update');
|
|
187
|
+
}
|
|
188
|
+
if (options.ci) {
|
|
189
|
+
args.push('--ci');
|
|
190
|
+
}
|
|
191
|
+
return args;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -6,10 +6,19 @@
|
|
|
6
6
|
* @packageDocumentation
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Gets the CLI version.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getVersion(): string;
|
|
12
|
+
/**
|
|
13
|
+
* Runs the fnd CLI in traditional Commander.js mode.
|
|
10
14
|
*
|
|
11
15
|
* @param args - Command line arguments (defaults to process.argv)
|
|
12
16
|
* @returns Promise that resolves when command completes
|
|
13
17
|
*/
|
|
14
|
-
export declare function
|
|
18
|
+
export declare function runCommander(args?: string[]): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Backward-compatible alias for runCommander.
|
|
21
|
+
* @deprecated Use runCommander instead.
|
|
22
|
+
*/
|
|
23
|
+
export declare const run: typeof runCommander;
|
|
15
24
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwBH;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B/E;AAED;;;GAGG;AACH,eAAO,MAAM,GAAG,qBAAe,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @fnd-platform/cli
|
|
4
3
|
*
|
|
@@ -6,37 +5,44 @@
|
|
|
6
5
|
*
|
|
7
6
|
* @packageDocumentation
|
|
8
7
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const index_js_1 = require("./commands/index.js");
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import { readFileSync } from 'fs';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { newCommand, synthCommand, buildCommand, testCommand, addCommand, deployCommand, destroyCommand, } from './commands/index.js';
|
|
15
13
|
/**
|
|
16
14
|
* CLI version from package.json.
|
|
17
15
|
*/
|
|
18
|
-
|
|
19
|
-
const
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
20
19
|
const VERSION = pkg.version;
|
|
21
20
|
/**
|
|
22
|
-
*
|
|
21
|
+
* Gets the CLI version.
|
|
22
|
+
*/
|
|
23
|
+
export function getVersion() {
|
|
24
|
+
return VERSION;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Runs the fnd CLI in traditional Commander.js mode.
|
|
23
28
|
*
|
|
24
29
|
* @param args - Command line arguments (defaults to process.argv)
|
|
25
30
|
* @returns Promise that resolves when command completes
|
|
26
31
|
*/
|
|
27
|
-
async function
|
|
28
|
-
const program = new
|
|
32
|
+
export async function runCommander(args = process.argv) {
|
|
33
|
+
const program = new Command();
|
|
29
34
|
program
|
|
30
35
|
.name('fnd')
|
|
31
36
|
.description('fnd-platform CLI - Scaffold AWS-native TypeScript monorepo projects')
|
|
32
37
|
.version(VERSION, '-v, --version', 'Display version number');
|
|
33
38
|
// Register commands
|
|
34
|
-
program.addCommand(
|
|
35
|
-
program.addCommand(
|
|
36
|
-
program.addCommand(
|
|
37
|
-
program.addCommand((
|
|
38
|
-
program.addCommand((
|
|
39
|
-
program.addCommand((
|
|
39
|
+
program.addCommand(newCommand());
|
|
40
|
+
program.addCommand(synthCommand());
|
|
41
|
+
program.addCommand(buildCommand());
|
|
42
|
+
program.addCommand(testCommand());
|
|
43
|
+
program.addCommand(addCommand());
|
|
44
|
+
program.addCommand(deployCommand());
|
|
45
|
+
program.addCommand(destroyCommand());
|
|
40
46
|
// Handle unknown commands
|
|
41
47
|
program.on('command:*', () => {
|
|
42
48
|
console.error(`Invalid command: ${program.args.join(' ')}\n` +
|
|
@@ -45,4 +51,9 @@ async function run(args = process.argv) {
|
|
|
45
51
|
});
|
|
46
52
|
await program.parseAsync(args);
|
|
47
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Backward-compatible alias for runCommander.
|
|
56
|
+
* @deprecated Use runCommander instead.
|
|
57
|
+
*/
|
|
58
|
+
export const run = runCommander;
|
|
48
59
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,aAAa,EACb,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACrF,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;AAE5B;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAiB,OAAO,CAAC,IAAI;IAC9D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,KAAK,CAAC;SACX,WAAW,CAAC,qEAAqE,CAAC;SAClF,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,wBAAwB,CAAC,CAAC;IAE/D,oBAAoB;IACpB,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;IACnC,OAAO,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;IACnC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IAErC,0BAA0B;IAC1B,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;QAC3B,OAAO,CAAC,KAAK,CACX,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;YAC5C,8CAA8C,CACjD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-utils.d.ts","sourceRoot":"","sources":["../../src/lib/deploy-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy-utils.d.ts","sourceRoot":"","sources":["../../src/lib/deploy-utils.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAyB1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0BlF;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CA6BhF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAG5E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwBrE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAY1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG5F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,IAAI,CAgBzF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,IAAI,CA+B3F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,IAAI,CAqBhG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAiBrC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB9E"}
|
package/lib/lib/deploy-utils.js
CHANGED
|
@@ -1,23 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.hasPackage = hasPackage;
|
|
8
|
-
exports.findBuildDirectory = findBuildDirectory;
|
|
9
|
-
exports.promptConfirmation = promptConfirmation;
|
|
10
|
-
exports.buildStackName = buildStackName;
|
|
11
|
-
exports.syncToS3 = syncToS3;
|
|
12
|
-
exports.invalidateCloudFront = invalidateCloudFront;
|
|
13
|
-
exports.buildPackage = buildPackage;
|
|
14
|
-
exports.validateAwsCli = validateAwsCli;
|
|
15
|
-
exports.listProjectStacks = listProjectStacks;
|
|
16
|
-
const child_process_1 = require("child_process");
|
|
17
|
-
const fs_1 = require("fs");
|
|
18
|
-
const path_1 = require("path");
|
|
19
|
-
const readline_1 = require("readline");
|
|
20
|
-
const logger_js_1 = require("./logger.js");
|
|
1
|
+
import { execSync, execFileSync } from 'child_process';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { createInterface } from 'readline';
|
|
5
|
+
import { logger } from './logger.js';
|
|
6
|
+
import { validateStackName, validateStackOutputKey, validateBucketName, validateDistributionId, validateLocalPath, } from './validation.js';
|
|
21
7
|
/**
|
|
22
8
|
* Converts a string to PascalCase.
|
|
23
9
|
*
|
|
@@ -30,7 +16,7 @@ const logger_js_1 = require("./logger.js");
|
|
|
30
16
|
* toPascalCase('hello_world'); // 'HelloWorld'
|
|
31
17
|
* ```
|
|
32
18
|
*/
|
|
33
|
-
function toPascalCase(str) {
|
|
19
|
+
export function toPascalCase(str) {
|
|
34
20
|
return str
|
|
35
21
|
.split(/[-_\s]+/)
|
|
36
22
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
@@ -49,21 +35,21 @@ function toPascalCase(str) {
|
|
|
49
35
|
* // Returns 'my-app'
|
|
50
36
|
* ```
|
|
51
37
|
*/
|
|
52
|
-
function getProjectName(projectRoot) {
|
|
53
|
-
const projenrcPath =
|
|
54
|
-
if (!
|
|
38
|
+
export function getProjectName(projectRoot) {
|
|
39
|
+
const projenrcPath = join(projectRoot, '.projenrc.ts');
|
|
40
|
+
if (!existsSync(projenrcPath)) {
|
|
55
41
|
throw new Error(`.projenrc.ts not found at ${projenrcPath}`);
|
|
56
42
|
}
|
|
57
|
-
const content =
|
|
43
|
+
const content = readFileSync(projenrcPath, 'utf-8');
|
|
58
44
|
// Try to match: name: 'project-name' or name: "project-name"
|
|
59
45
|
const nameMatch = content.match(/name:\s*['"]([^'"]+)['"]/);
|
|
60
46
|
if (nameMatch) {
|
|
61
47
|
return nameMatch[1];
|
|
62
48
|
}
|
|
63
49
|
// Fallback: try to get from package.json
|
|
64
|
-
const packageJsonPath =
|
|
65
|
-
if (
|
|
66
|
-
const packageJson = JSON.parse(
|
|
50
|
+
const packageJsonPath = join(projectRoot, 'package.json');
|
|
51
|
+
if (existsSync(packageJsonPath)) {
|
|
52
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
67
53
|
if (packageJson.name) {
|
|
68
54
|
return packageJson.name;
|
|
69
55
|
}
|
|
@@ -83,13 +69,25 @@ function getProjectName(projectRoot) {
|
|
|
83
69
|
* // Returns 'https://abc123.execute-api.us-east-1.amazonaws.com/dev'
|
|
84
70
|
* ```
|
|
85
71
|
*/
|
|
86
|
-
function getStackOutput(stackName, outputKey) {
|
|
72
|
+
export function getStackOutput(stackName, outputKey) {
|
|
87
73
|
try {
|
|
88
|
-
|
|
74
|
+
// Validate inputs to prevent command injection
|
|
75
|
+
validateStackName(stackName);
|
|
76
|
+
validateStackOutputKey(outputKey);
|
|
77
|
+
const result = execFileSync('aws', [
|
|
78
|
+
'cloudformation',
|
|
79
|
+
'describe-stacks',
|
|
80
|
+
'--stack-name',
|
|
81
|
+
stackName,
|
|
82
|
+
'--query',
|
|
83
|
+
`Stacks[0].Outputs[?OutputKey=='${outputKey}'].OutputValue`,
|
|
84
|
+
'--output',
|
|
85
|
+
'text',
|
|
86
|
+
], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
89
87
|
return result && result !== 'None' ? result : null;
|
|
90
88
|
}
|
|
91
89
|
catch {
|
|
92
|
-
|
|
90
|
+
logger.debug(`Failed to get output ${outputKey} from stack ${stackName}`);
|
|
93
91
|
return null;
|
|
94
92
|
}
|
|
95
93
|
}
|
|
@@ -106,7 +104,7 @@ function getStackOutput(stackName, outputKey) {
|
|
|
106
104
|
* console.log(outputs.apiUrl);
|
|
107
105
|
* ```
|
|
108
106
|
*/
|
|
109
|
-
function getStackOutputs(projectRoot, stage) {
|
|
107
|
+
export function getStackOutputs(projectRoot, stage) {
|
|
110
108
|
const projectName = getProjectName(projectRoot);
|
|
111
109
|
const pascalName = toPascalCase(projectName);
|
|
112
110
|
const outputs = {};
|
|
@@ -144,9 +142,9 @@ function getStackOutputs(projectRoot, stage) {
|
|
|
144
142
|
* }
|
|
145
143
|
* ```
|
|
146
144
|
*/
|
|
147
|
-
function hasPackage(projectRoot, packageName) {
|
|
148
|
-
const packagePath =
|
|
149
|
-
return
|
|
145
|
+
export function hasPackage(projectRoot, packageName) {
|
|
146
|
+
const packagePath = join(projectRoot, 'packages', packageName);
|
|
147
|
+
return existsSync(packagePath);
|
|
150
148
|
}
|
|
151
149
|
/**
|
|
152
150
|
* Finds the build output directory for a package.
|
|
@@ -161,24 +159,24 @@ function hasPackage(projectRoot, packageName) {
|
|
|
161
159
|
* // Returns '/path/to/project/packages/frontend/build/client'
|
|
162
160
|
* ```
|
|
163
161
|
*/
|
|
164
|
-
function findBuildDirectory(packagePath) {
|
|
162
|
+
export function findBuildDirectory(packagePath) {
|
|
165
163
|
// Check for Remix/Vite SPA build output (build/client)
|
|
166
|
-
const buildClientDir =
|
|
167
|
-
if (
|
|
164
|
+
const buildClientDir = join(packagePath, 'build', 'client');
|
|
165
|
+
if (existsSync(buildClientDir)) {
|
|
168
166
|
return buildClientDir;
|
|
169
167
|
}
|
|
170
168
|
// Check for standard build directory
|
|
171
|
-
const buildDir =
|
|
172
|
-
if (
|
|
169
|
+
const buildDir = join(packagePath, 'build');
|
|
170
|
+
if (existsSync(buildDir)) {
|
|
173
171
|
// If build exists but we need client assets, look for index.html
|
|
174
|
-
const hasIndex =
|
|
172
|
+
const hasIndex = existsSync(join(buildDir, 'index.html'));
|
|
175
173
|
if (hasIndex) {
|
|
176
174
|
return buildDir;
|
|
177
175
|
}
|
|
178
176
|
}
|
|
179
177
|
// Check for dist directory (some build tools use this)
|
|
180
|
-
const distDir =
|
|
181
|
-
if (
|
|
178
|
+
const distDir = join(packagePath, 'dist');
|
|
179
|
+
if (existsSync(distDir)) {
|
|
182
180
|
return distDir;
|
|
183
181
|
}
|
|
184
182
|
return null;
|
|
@@ -197,8 +195,8 @@ function findBuildDirectory(packagePath) {
|
|
|
197
195
|
* }
|
|
198
196
|
* ```
|
|
199
197
|
*/
|
|
200
|
-
async function promptConfirmation(message) {
|
|
201
|
-
const rl =
|
|
198
|
+
export async function promptConfirmation(message) {
|
|
199
|
+
const rl = createInterface({
|
|
202
200
|
input: process.stdin,
|
|
203
201
|
output: process.stdout,
|
|
204
202
|
});
|
|
@@ -223,7 +221,7 @@ async function promptConfirmation(message) {
|
|
|
223
221
|
* // Returns 'MyAppFrontendStack-dev'
|
|
224
222
|
* ```
|
|
225
223
|
*/
|
|
226
|
-
function buildStackName(projectName, stackType, stage) {
|
|
224
|
+
export function buildStackName(projectName, stackType, stage) {
|
|
227
225
|
const pascalName = toPascalCase(projectName);
|
|
228
226
|
return `${pascalName}${stackType}Stack-${stage}`;
|
|
229
227
|
}
|
|
@@ -239,15 +237,17 @@ function buildStackName(projectName, stackType, stage) {
|
|
|
239
237
|
* syncToS3('/path/to/build', 'my-app-frontend-dev-123456789', true);
|
|
240
238
|
* ```
|
|
241
239
|
*/
|
|
242
|
-
function syncToS3(localDir, bucket, verbose = false) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
240
|
+
export function syncToS3(localDir, bucket, verbose = false) {
|
|
241
|
+
// Validate inputs to prevent command injection
|
|
242
|
+
validateLocalPath(localDir);
|
|
243
|
+
validateBucketName(bucket);
|
|
244
|
+
logger.info(`Syncing ${localDir} to s3://${bucket}/`);
|
|
245
|
+
logger.debug(`Running: aws s3 sync ${localDir} s3://${bucket}/ --delete`);
|
|
246
246
|
try {
|
|
247
|
-
(
|
|
247
|
+
execFileSync('aws', ['s3', 'sync', localDir, `s3://${bucket}/`, '--delete'], {
|
|
248
248
|
stdio: verbose ? 'inherit' : ['pipe', 'pipe', 'pipe'],
|
|
249
249
|
});
|
|
250
|
-
|
|
250
|
+
logger.success(`Synced assets to s3://${bucket}/`);
|
|
251
251
|
}
|
|
252
252
|
catch (error) {
|
|
253
253
|
throw new Error(`Failed to sync to S3: ${error.message}`);
|
|
@@ -264,23 +264,24 @@ function syncToS3(localDir, bucket, verbose = false) {
|
|
|
264
264
|
* invalidateCloudFront('E1234567890ABC', true);
|
|
265
265
|
* ```
|
|
266
266
|
*/
|
|
267
|
-
function invalidateCloudFront(distributionId, verbose = false) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
267
|
+
export function invalidateCloudFront(distributionId, verbose = false) {
|
|
268
|
+
// Validate input to prevent command injection
|
|
269
|
+
validateDistributionId(distributionId);
|
|
270
|
+
logger.info(`Invalidating CloudFront distribution ${distributionId}`);
|
|
271
|
+
logger.debug(`Running: aws cloudfront create-invalidation --distribution-id ${distributionId} --paths "/*"`);
|
|
271
272
|
try {
|
|
272
|
-
const result = (
|
|
273
|
+
const result = execFileSync('aws', ['cloudfront', 'create-invalidation', '--distribution-id', distributionId, '--paths', '/*'], {
|
|
273
274
|
encoding: 'utf-8',
|
|
274
275
|
stdio: verbose ? 'inherit' : ['pipe', 'pipe', 'pipe'],
|
|
275
276
|
});
|
|
276
|
-
if (!verbose) {
|
|
277
|
+
if (!verbose && typeof result === 'string') {
|
|
277
278
|
// Extract invalidation ID from response
|
|
278
279
|
const invalidationMatch = result.match(/"Id":\s*"([^"]+)"/);
|
|
279
280
|
if (invalidationMatch) {
|
|
280
|
-
|
|
281
|
+
logger.info(`CloudFront invalidation created: ${invalidationMatch[1]}`);
|
|
281
282
|
}
|
|
282
283
|
}
|
|
283
|
-
|
|
284
|
+
logger.success('CloudFront invalidation initiated (runs asynchronously)');
|
|
284
285
|
}
|
|
285
286
|
catch (error) {
|
|
286
287
|
throw new Error(`Failed to invalidate CloudFront: ${error.message}`);
|
|
@@ -298,13 +299,13 @@ function invalidateCloudFront(distributionId, verbose = false) {
|
|
|
298
299
|
* buildPackage('/path/to/frontend', 'https://api.example.com', true);
|
|
299
300
|
* ```
|
|
300
301
|
*/
|
|
301
|
-
function buildPackage(packagePath, apiUrl, verbose = false) {
|
|
302
|
+
export function buildPackage(packagePath, apiUrl, verbose = false) {
|
|
302
303
|
const packageName = packagePath.split('/').pop();
|
|
303
|
-
|
|
304
|
+
logger.info(`Building ${packageName} with API URL: ${apiUrl}`);
|
|
304
305
|
const command = 'pnpm build';
|
|
305
|
-
|
|
306
|
+
logger.debug(`Running: ${command} in ${packagePath}`);
|
|
306
307
|
try {
|
|
307
|
-
|
|
308
|
+
execSync(command, {
|
|
308
309
|
cwd: packagePath,
|
|
309
310
|
stdio: verbose ? 'inherit' : ['pipe', 'pipe', 'pipe'],
|
|
310
311
|
env: {
|
|
@@ -313,7 +314,7 @@ function buildPackage(packagePath, apiUrl, verbose = false) {
|
|
|
313
314
|
API_URL: apiUrl,
|
|
314
315
|
},
|
|
315
316
|
});
|
|
316
|
-
|
|
317
|
+
logger.success(`Built ${packageName}`);
|
|
317
318
|
}
|
|
318
319
|
catch (error) {
|
|
319
320
|
throw new Error(`Failed to build ${packageName}: ${error.message}`);
|
|
@@ -324,16 +325,16 @@ function buildPackage(packagePath, apiUrl, verbose = false) {
|
|
|
324
325
|
*
|
|
325
326
|
* @throws Error if AWS CLI is not available or not configured
|
|
326
327
|
*/
|
|
327
|
-
function validateAwsCli() {
|
|
328
|
+
export function validateAwsCli() {
|
|
328
329
|
try {
|
|
329
|
-
|
|
330
|
+
execSync('aws --version', { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
330
331
|
}
|
|
331
332
|
catch {
|
|
332
333
|
throw new Error('AWS CLI is not installed or not in PATH. ' +
|
|
333
334
|
'Install it from https://aws.amazon.com/cli/ and run `aws configure`.');
|
|
334
335
|
}
|
|
335
336
|
try {
|
|
336
|
-
|
|
337
|
+
execSync('aws sts get-caller-identity', { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
337
338
|
}
|
|
338
339
|
catch {
|
|
339
340
|
throw new Error('AWS credentials not configured. Run `aws configure` or set AWS environment variables.');
|
|
@@ -346,14 +347,14 @@ function validateAwsCli() {
|
|
|
346
347
|
* @param stage - Deployment stage
|
|
347
348
|
* @returns Array of stack names
|
|
348
349
|
*/
|
|
349
|
-
function listProjectStacks(projectRoot, stage) {
|
|
350
|
+
export function listProjectStacks(projectRoot, stage) {
|
|
350
351
|
const projectName = getProjectName(projectRoot);
|
|
351
352
|
const pascalName = toPascalCase(projectName);
|
|
352
353
|
const stacks = [];
|
|
353
354
|
// Check for infrastructure stacks directory
|
|
354
|
-
const stacksDir =
|
|
355
|
-
if (
|
|
356
|
-
const files =
|
|
355
|
+
const stacksDir = join(projectRoot, 'packages', 'infra', 'src', 'stacks');
|
|
356
|
+
if (existsSync(stacksDir)) {
|
|
357
|
+
const files = readdirSync(stacksDir);
|
|
357
358
|
for (const file of files) {
|
|
358
359
|
if (file.endsWith('-stack.ts')) {
|
|
359
360
|
// Extract stack name from file (e.g., 'api-stack.ts' -> 'Api')
|