@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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +224 -0
  3. package/lib/bin/fnd.d.ts +3 -0
  4. package/lib/bin/fnd.d.ts.map +1 -0
  5. package/lib/bin/fnd.js +9 -0
  6. package/lib/bin/fnd.js.map +1 -0
  7. package/lib/commands/add.d.ts +28 -0
  8. package/lib/commands/add.d.ts.map +1 -0
  9. package/lib/commands/add.js +547 -0
  10. package/lib/commands/add.js.map +1 -0
  11. package/lib/commands/build.d.ts +62 -0
  12. package/lib/commands/build.d.ts.map +1 -0
  13. package/lib/commands/build.js +155 -0
  14. package/lib/commands/build.js.map +1 -0
  15. package/lib/commands/deploy.d.ts +67 -0
  16. package/lib/commands/deploy.d.ts.map +1 -0
  17. package/lib/commands/deploy.js +160 -0
  18. package/lib/commands/deploy.js.map +1 -0
  19. package/lib/commands/index.d.ts +6 -0
  20. package/lib/commands/index.d.ts.map +1 -0
  21. package/lib/commands/index.js +14 -0
  22. package/lib/commands/index.js.map +1 -0
  23. package/lib/commands/new.d.ts +47 -0
  24. package/lib/commands/new.d.ts.map +1 -0
  25. package/lib/commands/new.js +199 -0
  26. package/lib/commands/new.js.map +1 -0
  27. package/lib/commands/synth.d.ts +39 -0
  28. package/lib/commands/synth.d.ts.map +1 -0
  29. package/lib/commands/synth.js +72 -0
  30. package/lib/commands/synth.js.map +1 -0
  31. package/lib/index.d.ts +15 -0
  32. package/lib/index.d.ts.map +1 -0
  33. package/lib/index.js +43 -0
  34. package/lib/index.js.map +1 -0
  35. package/lib/lib/infra-generator.d.ts +24 -0
  36. package/lib/lib/infra-generator.d.ts.map +1 -0
  37. package/lib/lib/infra-generator.js +193 -0
  38. package/lib/lib/infra-generator.js.map +1 -0
  39. package/lib/lib/logger.d.ts +50 -0
  40. package/lib/lib/logger.d.ts.map +1 -0
  41. package/lib/lib/logger.js +102 -0
  42. package/lib/lib/logger.js.map +1 -0
  43. package/lib/lib/nx-stats.d.ts +69 -0
  44. package/lib/lib/nx-stats.d.ts.map +1 -0
  45. package/lib/lib/nx-stats.js +117 -0
  46. package/lib/lib/nx-stats.js.map +1 -0
  47. package/lib/lib/project.d.ts +17 -0
  48. package/lib/lib/project.d.ts.map +1 -0
  49. package/lib/lib/project.js +49 -0
  50. package/lib/lib/project.js.map +1 -0
  51. package/lib/lib/templates.d.ts +16 -0
  52. package/lib/lib/templates.d.ts.map +1 -0
  53. package/lib/lib/templates.js +42 -0
  54. package/lib/lib/templates.js.map +1 -0
  55. package/lib/lib/timer.d.ts +120 -0
  56. package/lib/lib/timer.d.ts.map +1 -0
  57. package/lib/lib/timer.js +127 -0
  58. package/lib/lib/timer.js.map +1 -0
  59. 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,6 @@
1
+ export { newCommand } from './new.js';
2
+ export { synthCommand } from './synth.js';
3
+ export { buildCommand } from './build.js';
4
+ export { addCommand } from './add.js';
5
+ export { deployCommand } from './deploy.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -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