@fnd-platform/cli 1.0.0-alpha.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.
- package/LICENSE +21 -0
- package/README.md +224 -0
- package/lib/bin/fnd.d.ts +3 -0
- package/lib/bin/fnd.d.ts.map +1 -0
- package/lib/bin/fnd.js +9 -0
- package/lib/bin/fnd.js.map +1 -0
- package/lib/commands/add.d.ts +28 -0
- package/lib/commands/add.d.ts.map +1 -0
- package/lib/commands/add.js +547 -0
- package/lib/commands/add.js.map +1 -0
- package/lib/commands/build.d.ts +62 -0
- package/lib/commands/build.d.ts.map +1 -0
- package/lib/commands/build.js +155 -0
- package/lib/commands/build.js.map +1 -0
- package/lib/commands/deploy.d.ts +67 -0
- package/lib/commands/deploy.d.ts.map +1 -0
- package/lib/commands/deploy.js +160 -0
- package/lib/commands/deploy.js.map +1 -0
- package/lib/commands/index.d.ts +6 -0
- package/lib/commands/index.d.ts.map +1 -0
- package/lib/commands/index.js +14 -0
- package/lib/commands/index.js.map +1 -0
- package/lib/commands/new.d.ts +47 -0
- package/lib/commands/new.d.ts.map +1 -0
- package/lib/commands/new.js +199 -0
- package/lib/commands/new.js.map +1 -0
- package/lib/commands/synth.d.ts +39 -0
- package/lib/commands/synth.d.ts.map +1 -0
- package/lib/commands/synth.js +72 -0
- package/lib/commands/synth.js.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +43 -0
- package/lib/index.js.map +1 -0
- package/lib/lib/infra-generator.d.ts +24 -0
- package/lib/lib/infra-generator.d.ts.map +1 -0
- package/lib/lib/infra-generator.js +193 -0
- package/lib/lib/infra-generator.js.map +1 -0
- package/lib/lib/logger.d.ts +50 -0
- package/lib/lib/logger.d.ts.map +1 -0
- package/lib/lib/logger.js +102 -0
- package/lib/lib/logger.js.map +1 -0
- package/lib/lib/nx-stats.d.ts +69 -0
- package/lib/lib/nx-stats.d.ts.map +1 -0
- package/lib/lib/nx-stats.js +117 -0
- package/lib/lib/nx-stats.js.map +1 -0
- package/lib/lib/project.d.ts +17 -0
- package/lib/lib/project.d.ts.map +1 -0
- package/lib/lib/project.js +49 -0
- package/lib/lib/project.js.map +1 -0
- package/lib/lib/templates.d.ts +16 -0
- package/lib/lib/templates.d.ts.map +1 -0
- package/lib/lib/templates.js +42 -0
- package/lib/lib/templates.js.map +1 -0
- package/lib/lib/timer.d.ts +120 -0
- package/lib/lib/timer.d.ts.map +1 -0
- package/lib/lib/timer.js +127 -0
- package/lib/lib/timer.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildCommand = buildCommand;
|
|
4
|
+
exports.runBuild = runBuild;
|
|
5
|
+
exports.buildNxArgs = buildNxArgs;
|
|
6
|
+
const commander_1 = require("commander");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const project_js_1 = require("../lib/project.js");
|
|
9
|
+
const logger_js_1 = require("../lib/logger.js");
|
|
10
|
+
const timer_js_1 = require("../lib/timer.js");
|
|
11
|
+
const nx_stats_js_1 = require("../lib/nx-stats.js");
|
|
12
|
+
/**
|
|
13
|
+
* Creates the `fnd build` command.
|
|
14
|
+
*
|
|
15
|
+
* @returns Commander command instance
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { buildCommand } from '@fnd-platform/cli';
|
|
20
|
+
*
|
|
21
|
+
* const program = new Command();
|
|
22
|
+
* program.addCommand(buildCommand());
|
|
23
|
+
* program.parse(['node', 'fnd', 'build']);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
function buildCommand() {
|
|
27
|
+
return new commander_1.Command('build')
|
|
28
|
+
.description('Build all packages using NX')
|
|
29
|
+
.option('--skip-cache', 'Skip NX cache')
|
|
30
|
+
.option('--parallel <n>', 'Number of parallel tasks')
|
|
31
|
+
.option('--package <name>', 'Build specific package only')
|
|
32
|
+
.action(async (options) => {
|
|
33
|
+
await runBuild(options);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Runs the NX build.
|
|
38
|
+
*
|
|
39
|
+
* @param options - Command options
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* // Build all packages
|
|
44
|
+
* await runBuild({});
|
|
45
|
+
*
|
|
46
|
+
* // Build a specific package with no cache
|
|
47
|
+
* await runBuild({ package: 'api', skipCache: true });
|
|
48
|
+
*
|
|
49
|
+
* // Build with parallel tasks
|
|
50
|
+
* await runBuild({ parallel: '4' });
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
async function runBuild(options) {
|
|
54
|
+
// Initialize profiling if enabled
|
|
55
|
+
const timer = timer_js_1.PerformanceTimer.isEnabled() ? new timer_js_1.PerformanceTimer('fnd build') : null;
|
|
56
|
+
let projectRoot;
|
|
57
|
+
timer?.start('project-detection');
|
|
58
|
+
try {
|
|
59
|
+
projectRoot = (0, project_js_1.requireProjectRoot)();
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (timer) {
|
|
63
|
+
timer.end('project-detection');
|
|
64
|
+
logger_js_1.logger.report(timer.getReport(false));
|
|
65
|
+
}
|
|
66
|
+
logger_js_1.logger.error(error.message);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const detectResult = timer?.end('project-detection');
|
|
70
|
+
if (detectResult) {
|
|
71
|
+
logger_js_1.logger.timing('project-detection', detectResult.durationMs);
|
|
72
|
+
}
|
|
73
|
+
logger_js_1.logger.info('Building packages...');
|
|
74
|
+
logger_js_1.logger.debug(`Project root: ${projectRoot}`);
|
|
75
|
+
// Build the NX command arguments
|
|
76
|
+
const args = buildNxArgs(options);
|
|
77
|
+
const command = args.join(' ');
|
|
78
|
+
logger_js_1.logger.debug(`Running: ${command}`);
|
|
79
|
+
timer?.start('nx-build');
|
|
80
|
+
try {
|
|
81
|
+
if (timer) {
|
|
82
|
+
// Capture output for cache statistics when profiling is enabled
|
|
83
|
+
const output = (0, child_process_1.execSync)(command, {
|
|
84
|
+
cwd: projectRoot,
|
|
85
|
+
stdio: 'pipe',
|
|
86
|
+
encoding: 'utf-8',
|
|
87
|
+
});
|
|
88
|
+
const buildResult = timer.end('nx-build');
|
|
89
|
+
logger_js_1.logger.timing('nx-build', buildResult.durationMs);
|
|
90
|
+
// Print output since we captured it
|
|
91
|
+
console.log(output);
|
|
92
|
+
// Parse and display NX cache statistics
|
|
93
|
+
const stats = (0, nx_stats_js_1.parseNxOutput)(output);
|
|
94
|
+
if (stats) {
|
|
95
|
+
logger_js_1.logger.cacheStats(stats);
|
|
96
|
+
}
|
|
97
|
+
logger_js_1.logger.success('Build complete');
|
|
98
|
+
logger_js_1.logger.report(timer.getReport(true));
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Normal execution without profiling
|
|
102
|
+
(0, child_process_1.execSync)(command, {
|
|
103
|
+
cwd: projectRoot,
|
|
104
|
+
stdio: 'inherit',
|
|
105
|
+
});
|
|
106
|
+
logger_js_1.logger.success('Build complete');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (timer) {
|
|
111
|
+
timer.end('nx-build');
|
|
112
|
+
logger_js_1.logger.report(timer.getReport(false));
|
|
113
|
+
}
|
|
114
|
+
logger_js_1.logger.error('Build failed');
|
|
115
|
+
logger_js_1.logger.debug(`Error: ${error.message}`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Builds the NX command arguments based on options.
|
|
121
|
+
*
|
|
122
|
+
* @param options - Command options
|
|
123
|
+
* @returns Array of command arguments
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* // Build all packages
|
|
128
|
+
* buildNxArgs({});
|
|
129
|
+
* // Returns: ['npx', 'nx', 'run-many', '--target=build', '--all']
|
|
130
|
+
*
|
|
131
|
+
* // Build specific package with skip cache
|
|
132
|
+
* buildNxArgs({ package: 'api', skipCache: true });
|
|
133
|
+
* // Returns: ['npx', 'nx', 'run', 'api:build', '--skip-nx-cache']
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
function buildNxArgs(options) {
|
|
137
|
+
// If building a specific package
|
|
138
|
+
if (options.package) {
|
|
139
|
+
const args = ['npx', 'nx', 'run', `${options.package}:build`];
|
|
140
|
+
if (options.skipCache) {
|
|
141
|
+
args.push('--skip-nx-cache');
|
|
142
|
+
}
|
|
143
|
+
return args;
|
|
144
|
+
}
|
|
145
|
+
// Building all packages
|
|
146
|
+
const args = ['npx', 'nx', 'run-many', '--target=build', '--all'];
|
|
147
|
+
if (options.skipCache) {
|
|
148
|
+
args.push('--skip-nx-cache');
|
|
149
|
+
}
|
|
150
|
+
if (options.parallel) {
|
|
151
|
+
args.push(`--parallel=${options.parallel}`);
|
|
152
|
+
}
|
|
153
|
+
return args;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Options for the deploy command.
|
|
4
|
+
*/
|
|
5
|
+
interface DeployCommandOptions {
|
|
6
|
+
stage: string;
|
|
7
|
+
dryRun?: boolean;
|
|
8
|
+
requireApproval?: 'never' | 'any-change' | 'broadening';
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates the `fnd deploy` command.
|
|
12
|
+
*
|
|
13
|
+
* @returns Commander command instance
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { deployCommand } from '@fnd-platform/cli';
|
|
18
|
+
*
|
|
19
|
+
* const program = new Command();
|
|
20
|
+
* program.addCommand(deployCommand());
|
|
21
|
+
*
|
|
22
|
+
* // Deploy to dev
|
|
23
|
+
* program.parse(['node', 'fnd', 'deploy', '--stage=dev']);
|
|
24
|
+
*
|
|
25
|
+
* // Dry run (synth only)
|
|
26
|
+
* program.parse(['node', 'fnd', 'deploy', '--stage=dev', '--dry-run']);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function deployCommand(): Command;
|
|
30
|
+
/**
|
|
31
|
+
* Runs the CDK deployment.
|
|
32
|
+
*
|
|
33
|
+
* @param options - Command options
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* // Deploy to dev environment
|
|
38
|
+
* await runDeploy({ stage: 'dev' });
|
|
39
|
+
*
|
|
40
|
+
* // Dry run (CDK synth only)
|
|
41
|
+
* await runDeploy({ stage: 'dev', dryRun: true });
|
|
42
|
+
*
|
|
43
|
+
* // Deploy with approval mode
|
|
44
|
+
* await runDeploy({
|
|
45
|
+
* stage: 'prod',
|
|
46
|
+
* requireApproval: 'any-change',
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function runDeploy(options: DeployCommandOptions): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Builds the CDK synth command.
|
|
53
|
+
*
|
|
54
|
+
* @param stage - Deployment stage
|
|
55
|
+
* @returns Command string
|
|
56
|
+
*/
|
|
57
|
+
export declare function buildCdkSynthCommand(stage: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Builds the CDK deploy command.
|
|
60
|
+
*
|
|
61
|
+
* @param stage - Deployment stage
|
|
62
|
+
* @param requireApproval - Approval mode
|
|
63
|
+
* @returns Command string
|
|
64
|
+
*/
|
|
65
|
+
export declare function buildCdkDeployCommand(stage: string, requireApproval?: 'never' | 'any-change' | 'broadening'): string;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=deploy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC;;GAEG;AACH,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,CAAC;CACzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAavC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B5E;AA0DD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,eAAe,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,GACtD,MAAM,CAQR"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deployCommand = deployCommand;
|
|
4
|
+
exports.runDeploy = runDeploy;
|
|
5
|
+
exports.buildCdkSynthCommand = buildCdkSynthCommand;
|
|
6
|
+
exports.buildCdkDeployCommand = buildCdkDeployCommand;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const path_1 = require("path");
|
|
11
|
+
const project_js_1 = require("../lib/project.js");
|
|
12
|
+
const logger_js_1 = require("../lib/logger.js");
|
|
13
|
+
/**
|
|
14
|
+
* Creates the `fnd deploy` command.
|
|
15
|
+
*
|
|
16
|
+
* @returns Commander command instance
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { deployCommand } from '@fnd-platform/cli';
|
|
21
|
+
*
|
|
22
|
+
* const program = new Command();
|
|
23
|
+
* program.addCommand(deployCommand());
|
|
24
|
+
*
|
|
25
|
+
* // Deploy to dev
|
|
26
|
+
* program.parse(['node', 'fnd', 'deploy', '--stage=dev']);
|
|
27
|
+
*
|
|
28
|
+
* // Dry run (synth only)
|
|
29
|
+
* program.parse(['node', 'fnd', 'deploy', '--stage=dev', '--dry-run']);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function deployCommand() {
|
|
33
|
+
return new commander_1.Command('deploy')
|
|
34
|
+
.description('Deploy infrastructure using CDK')
|
|
35
|
+
.requiredOption('--stage <stage>', 'Deployment stage (e.g., dev, staging, prod)')
|
|
36
|
+
.option('--dry-run', 'Run CDK synth only without deploying')
|
|
37
|
+
.option('--require-approval <mode>', 'CDK approval mode (never, any-change, broadening)', 'broadening')
|
|
38
|
+
.action(async (options) => {
|
|
39
|
+
await runDeploy(options);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Runs the CDK deployment.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Command options
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // Deploy to dev environment
|
|
50
|
+
* await runDeploy({ stage: 'dev' });
|
|
51
|
+
*
|
|
52
|
+
* // Dry run (CDK synth only)
|
|
53
|
+
* await runDeploy({ stage: 'dev', dryRun: true });
|
|
54
|
+
*
|
|
55
|
+
* // Deploy with approval mode
|
|
56
|
+
* await runDeploy({
|
|
57
|
+
* stage: 'prod',
|
|
58
|
+
* requireApproval: 'any-change',
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
async function runDeploy(options) {
|
|
63
|
+
let projectRoot;
|
|
64
|
+
try {
|
|
65
|
+
projectRoot = (0, project_js_1.requireProjectRoot)();
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
logger_js_1.logger.error(error.message);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
// Validate infra package exists
|
|
72
|
+
const infraDir = (0, path_1.join)(projectRoot, 'packages', 'infra');
|
|
73
|
+
if (!(0, fs_1.existsSync)(infraDir)) {
|
|
74
|
+
logger_js_1.logger.error('Infrastructure package not found at packages/infra. ' +
|
|
75
|
+
'Make sure you have added an API package with `fnd add api`, ' +
|
|
76
|
+
'which generates the infrastructure package.');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
const stage = options.stage;
|
|
80
|
+
if (options.dryRun) {
|
|
81
|
+
logger_js_1.logger.info(`Synthesizing CloudFormation templates for stage: ${stage}`);
|
|
82
|
+
await runCdkSynth(infraDir, stage);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
logger_js_1.logger.info(`Deploying to stage: ${stage}`);
|
|
86
|
+
await runCdkDeploy(infraDir, stage, options.requireApproval);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Runs CDK synth (dry-run mode).
|
|
91
|
+
*
|
|
92
|
+
* @param infraDir - Path to the infrastructure package
|
|
93
|
+
* @param stage - Deployment stage
|
|
94
|
+
*/
|
|
95
|
+
async function runCdkSynth(infraDir, stage) {
|
|
96
|
+
logger_js_1.logger.debug(`Running CDK synth in: ${infraDir}`);
|
|
97
|
+
const command = buildCdkSynthCommand(stage);
|
|
98
|
+
logger_js_1.logger.debug(`Command: ${command}`);
|
|
99
|
+
try {
|
|
100
|
+
(0, child_process_1.execSync)(command, {
|
|
101
|
+
cwd: infraDir,
|
|
102
|
+
stdio: 'inherit',
|
|
103
|
+
});
|
|
104
|
+
logger_js_1.logger.success('CDK synthesis complete');
|
|
105
|
+
logger_js_1.logger.info(`CloudFormation templates generated in ${(0, path_1.join)(infraDir, 'cdk.out')}`);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
logger_js_1.logger.error('CDK synthesis failed');
|
|
109
|
+
logger_js_1.logger.debug(`Error: ${error.message}`);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Runs CDK deploy.
|
|
115
|
+
*
|
|
116
|
+
* @param infraDir - Path to the infrastructure package
|
|
117
|
+
* @param stage - Deployment stage
|
|
118
|
+
* @param requireApproval - Approval mode for CDK
|
|
119
|
+
*/
|
|
120
|
+
async function runCdkDeploy(infraDir, stage, requireApproval) {
|
|
121
|
+
logger_js_1.logger.debug(`Running CDK deploy in: ${infraDir}`);
|
|
122
|
+
const command = buildCdkDeployCommand(stage, requireApproval);
|
|
123
|
+
logger_js_1.logger.debug(`Command: ${command}`);
|
|
124
|
+
try {
|
|
125
|
+
(0, child_process_1.execSync)(command, {
|
|
126
|
+
cwd: infraDir,
|
|
127
|
+
stdio: 'inherit',
|
|
128
|
+
});
|
|
129
|
+
logger_js_1.logger.success(`Deployment to ${stage} complete`);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
logger_js_1.logger.error('CDK deployment failed');
|
|
133
|
+
logger_js_1.logger.debug(`Error: ${error.message}`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Builds the CDK synth command.
|
|
139
|
+
*
|
|
140
|
+
* @param stage - Deployment stage
|
|
141
|
+
* @returns Command string
|
|
142
|
+
*/
|
|
143
|
+
function buildCdkSynthCommand(stage) {
|
|
144
|
+
return `pnpm exec cdk synth --all -c stage=${stage}`;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Builds the CDK deploy command.
|
|
148
|
+
*
|
|
149
|
+
* @param stage - Deployment stage
|
|
150
|
+
* @param requireApproval - Approval mode
|
|
151
|
+
* @returns Command string
|
|
152
|
+
*/
|
|
153
|
+
function buildCdkDeployCommand(stage, requireApproval) {
|
|
154
|
+
const args = ['pnpm', 'exec', 'cdk', 'deploy', '--all', `-c stage=${stage}`];
|
|
155
|
+
if (requireApproval) {
|
|
156
|
+
args.push(`--require-approval=${requireApproval}`);
|
|
157
|
+
}
|
|
158
|
+
return args.join(' ');
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=deploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deployCommand = exports.addCommand = exports.buildCommand = exports.synthCommand = exports.newCommand = void 0;
|
|
4
|
+
var new_js_1 = require("./new.js");
|
|
5
|
+
Object.defineProperty(exports, "newCommand", { enumerable: true, get: function () { return new_js_1.newCommand; } });
|
|
6
|
+
var synth_js_1 = require("./synth.js");
|
|
7
|
+
Object.defineProperty(exports, "synthCommand", { enumerable: true, get: function () { return synth_js_1.synthCommand; } });
|
|
8
|
+
var build_js_1 = require("./build.js");
|
|
9
|
+
Object.defineProperty(exports, "buildCommand", { enumerable: true, get: function () { return build_js_1.buildCommand; } });
|
|
10
|
+
var add_js_1 = require("./add.js");
|
|
11
|
+
Object.defineProperty(exports, "addCommand", { enumerable: true, get: function () { return add_js_1.addCommand; } });
|
|
12
|
+
var deploy_js_1 = require("./deploy.js");
|
|
13
|
+
Object.defineProperty(exports, "deployCommand", { enumerable: true, get: function () { return deploy_js_1.deployCommand; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":";;;AAAA,mCAAsC;AAA7B,oGAAA,UAAU,OAAA;AACnB,uCAA0C;AAAjC,wGAAA,YAAY,OAAA;AACrB,uCAA0C;AAAjC,wGAAA,YAAY,OAAA;AACrB,mCAAsC;AAA7B,oGAAA,UAAU,OAAA;AACnB,yCAA4C;AAAnC,0GAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Valid project name pattern: lowercase alphanumeric with hyphens.
|
|
4
|
+
* Must start with a letter.
|
|
5
|
+
*/
|
|
6
|
+
declare const PROJECT_NAME_PATTERN: RegExp;
|
|
7
|
+
/**
|
|
8
|
+
* Options for the new command.
|
|
9
|
+
*/
|
|
10
|
+
interface NewCommandOptions {
|
|
11
|
+
packageManager: 'pnpm' | 'yarn';
|
|
12
|
+
git: boolean;
|
|
13
|
+
install: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Creates the `fnd new` command.
|
|
17
|
+
*
|
|
18
|
+
* @returns Commander command instance
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { newCommand } from '@fnd-platform/cli';
|
|
23
|
+
*
|
|
24
|
+
* const program = new Command();
|
|
25
|
+
* program.addCommand(newCommand());
|
|
26
|
+
* program.parse(['node', 'fnd', 'new', 'my-app']);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function newCommand(): Command;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new fnd-platform project.
|
|
32
|
+
*
|
|
33
|
+
* @param name - Project name
|
|
34
|
+
* @param options - Command options
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* await createProject('my-app', {
|
|
39
|
+
* packageManager: 'pnpm',
|
|
40
|
+
* git: true,
|
|
41
|
+
* install: true,
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function createProject(name: string, options: NewCommandOptions): Promise<void>;
|
|
46
|
+
export { PROJECT_NAME_PATTERN };
|
|
47
|
+
//# sourceMappingURL=new.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC;;;GAGG;AACH,QAAA,MAAM,oBAAoB,QAAsB,CAAC;AAEjD;;GAEG;AACH,UAAU,iBAAiB;IACzB,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAUpC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoG3F;AAgED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROJECT_NAME_PATTERN = void 0;
|
|
4
|
+
exports.newCommand = newCommand;
|
|
5
|
+
exports.createProject = createProject;
|
|
6
|
+
const commander_1 = require("commander");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const logger_js_1 = require("../lib/logger.js");
|
|
11
|
+
const templates_js_1 = require("../lib/templates.js");
|
|
12
|
+
const timer_js_1 = require("../lib/timer.js");
|
|
13
|
+
/**
|
|
14
|
+
* Valid project name pattern: lowercase alphanumeric with hyphens.
|
|
15
|
+
* Must start with a letter.
|
|
16
|
+
*/
|
|
17
|
+
const PROJECT_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
18
|
+
exports.PROJECT_NAME_PATTERN = PROJECT_NAME_PATTERN;
|
|
19
|
+
/**
|
|
20
|
+
* Creates the `fnd new` command.
|
|
21
|
+
*
|
|
22
|
+
* @returns Commander command instance
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { newCommand } from '@fnd-platform/cli';
|
|
27
|
+
*
|
|
28
|
+
* const program = new Command();
|
|
29
|
+
* program.addCommand(newCommand());
|
|
30
|
+
* program.parse(['node', 'fnd', 'new', 'my-app']);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
function newCommand() {
|
|
34
|
+
return new commander_1.Command('new')
|
|
35
|
+
.description('Create a new fnd-platform monorepo project')
|
|
36
|
+
.argument('<name>', 'Project name (lowercase alphanumeric with hyphens)')
|
|
37
|
+
.option('--package-manager <pm>', 'Package manager to use (pnpm or yarn)', 'pnpm')
|
|
38
|
+
.option('--no-git', 'Skip git repository initialization')
|
|
39
|
+
.option('--no-install', 'Skip dependency installation')
|
|
40
|
+
.action(async (name, options) => {
|
|
41
|
+
await createProject(name, options);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new fnd-platform project.
|
|
46
|
+
*
|
|
47
|
+
* @param name - Project name
|
|
48
|
+
* @param options - Command options
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* await createProject('my-app', {
|
|
53
|
+
* packageManager: 'pnpm',
|
|
54
|
+
* git: true,
|
|
55
|
+
* install: true,
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
async function createProject(name, options) {
|
|
60
|
+
// Initialize profiling if enabled
|
|
61
|
+
const timer = timer_js_1.PerformanceTimer.isEnabled() ? new timer_js_1.PerformanceTimer('fnd new') : null;
|
|
62
|
+
// Validate project name
|
|
63
|
+
if (!PROJECT_NAME_PATTERN.test(name)) {
|
|
64
|
+
logger_js_1.logger.error(`Invalid project name: '${name}'. ` +
|
|
65
|
+
'Project name must start with a letter and contain only lowercase letters, numbers, and hyphens.');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const projectDir = (0, path_1.resolve)(process.cwd(), name);
|
|
69
|
+
// Check if directory already exists
|
|
70
|
+
if ((0, fs_1.existsSync)(projectDir)) {
|
|
71
|
+
logger_js_1.logger.error(`Directory '${name}' already exists. ` +
|
|
72
|
+
'Please choose a different name or remove the existing directory.');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
logger_js_1.logger.info(`Creating new fnd-platform project: ${name}`);
|
|
76
|
+
try {
|
|
77
|
+
// Step 1: Create project directory and write files
|
|
78
|
+
timer?.start('file-generation');
|
|
79
|
+
logger_js_1.logger.debug(`Creating directory: ${projectDir}`);
|
|
80
|
+
(0, fs_1.mkdirSync)(projectDir, { recursive: true });
|
|
81
|
+
// Step 2: Write .projenrc.ts
|
|
82
|
+
logger_js_1.logger.debug('Writing .projenrc.ts');
|
|
83
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(projectDir, '.projenrc.ts'), (0, templates_js_1.getProjenrcTemplate)(name));
|
|
84
|
+
// Step 3: Write initial package.json
|
|
85
|
+
logger_js_1.logger.debug('Writing initial package.json');
|
|
86
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(projectDir, 'package.json'), JSON.stringify((0, templates_js_1.getInitialPackageJson)(name, options.packageManager), null, 2));
|
|
87
|
+
const fileGenResult = timer?.end('file-generation');
|
|
88
|
+
if (fileGenResult) {
|
|
89
|
+
logger_js_1.logger.timing('file-generation', fileGenResult.durationMs);
|
|
90
|
+
}
|
|
91
|
+
// Step 4: Initialize git repository (unless --no-git)
|
|
92
|
+
if (options.git) {
|
|
93
|
+
timer?.start('git-init');
|
|
94
|
+
logger_js_1.logger.debug('Initializing git repository');
|
|
95
|
+
initializeGit(projectDir);
|
|
96
|
+
const gitResult = timer?.end('git-init');
|
|
97
|
+
if (gitResult) {
|
|
98
|
+
logger_js_1.logger.timing('git-init', gitResult.durationMs);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Step 5: Install dependencies and run Projen (unless --no-install)
|
|
102
|
+
if (options.install) {
|
|
103
|
+
timer?.start('install-dependencies');
|
|
104
|
+
logger_js_1.logger.info('Installing dependencies...');
|
|
105
|
+
installDependencies(projectDir, options.packageManager);
|
|
106
|
+
const installResult = timer?.end('install-dependencies');
|
|
107
|
+
if (installResult) {
|
|
108
|
+
logger_js_1.logger.timing('install-dependencies', installResult.durationMs);
|
|
109
|
+
}
|
|
110
|
+
timer?.start('projen-synth');
|
|
111
|
+
logger_js_1.logger.info('Running Projen synthesis...');
|
|
112
|
+
runProjen(projectDir);
|
|
113
|
+
const synthResult = timer?.end('projen-synth');
|
|
114
|
+
if (synthResult) {
|
|
115
|
+
logger_js_1.logger.timing('projen-synth', synthResult.durationMs);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
logger_js_1.logger.success(`Project '${name}' created successfully!`);
|
|
119
|
+
printNextSteps(name, options);
|
|
120
|
+
// Output profile report if enabled
|
|
121
|
+
if (timer) {
|
|
122
|
+
const report = timer.getReport(true);
|
|
123
|
+
logger_js_1.logger.report(report);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
// Output profile report even on failure
|
|
128
|
+
if (timer) {
|
|
129
|
+
const report = timer.getReport(false);
|
|
130
|
+
logger_js_1.logger.report(report);
|
|
131
|
+
}
|
|
132
|
+
logger_js_1.logger.error(`Failed to create project: ${error.message}`);
|
|
133
|
+
// Clean up partial project on failure
|
|
134
|
+
if ((0, fs_1.existsSync)(projectDir)) {
|
|
135
|
+
logger_js_1.logger.debug('Cleaning up partial project directory');
|
|
136
|
+
(0, fs_1.rmSync)(projectDir, { recursive: true, force: true });
|
|
137
|
+
}
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Initialize git repository in project directory.
|
|
143
|
+
*/
|
|
144
|
+
function initializeGit(projectDir) {
|
|
145
|
+
try {
|
|
146
|
+
(0, child_process_1.execSync)('git init', {
|
|
147
|
+
cwd: projectDir,
|
|
148
|
+
stdio: 'pipe',
|
|
149
|
+
});
|
|
150
|
+
(0, child_process_1.execSync)('git add -A', {
|
|
151
|
+
cwd: projectDir,
|
|
152
|
+
stdio: 'pipe',
|
|
153
|
+
});
|
|
154
|
+
(0, child_process_1.execSync)('git commit -m "Initial commit from fnd-platform"', {
|
|
155
|
+
cwd: projectDir,
|
|
156
|
+
stdio: 'pipe',
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
logger_js_1.logger.warn('Git initialization failed (git may not be configured)');
|
|
161
|
+
logger_js_1.logger.debug(`Git error: ${error.message}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Install project dependencies.
|
|
166
|
+
*/
|
|
167
|
+
function installDependencies(projectDir, packageManager) {
|
|
168
|
+
const installCmd = packageManager === 'pnpm' ? 'pnpm install' : 'yarn install';
|
|
169
|
+
(0, child_process_1.execSync)(installCmd, {
|
|
170
|
+
cwd: projectDir,
|
|
171
|
+
stdio: 'inherit',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Run Projen synthesis.
|
|
176
|
+
*/
|
|
177
|
+
function runProjen(projectDir) {
|
|
178
|
+
(0, child_process_1.execSync)('npx projen', {
|
|
179
|
+
cwd: projectDir,
|
|
180
|
+
stdio: 'inherit',
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Print next steps for the user.
|
|
185
|
+
*/
|
|
186
|
+
function printNextSteps(name, options) {
|
|
187
|
+
console.log('');
|
|
188
|
+
logger_js_1.logger.info('Next steps:');
|
|
189
|
+
console.log(` cd ${name}`);
|
|
190
|
+
if (!options.install) {
|
|
191
|
+
const pm = options.packageManager;
|
|
192
|
+
console.log(` ${pm} install`);
|
|
193
|
+
console.log(' npx projen');
|
|
194
|
+
}
|
|
195
|
+
console.log(' fnd add api --name=api');
|
|
196
|
+
console.log(' fnd add frontend --name=frontend --api=api');
|
|
197
|
+
console.log('');
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=new.js.map
|