@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,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CACHE_HIT_TARGET = void 0;
4
+ exports.parseNxOutput = parseNxOutput;
5
+ exports.getCacheDirectoryStats = getCacheDirectoryStats;
6
+ exports.formatCacheStats = formatCacheStats;
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ /**
10
+ * Target cache hit ratio (80%).
11
+ */
12
+ exports.CACHE_HIT_TARGET = 0.8;
13
+ /**
14
+ * Parses NX output to extract cache statistics.
15
+ *
16
+ * @param output - NX command output
17
+ * @returns Cache statistics or null if parsing fails
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const output = `
22
+ * > NX Successfully ran target build for 5 projects (234ms)
23
+ *
24
+ * Nx read the output from the cache instead of running the command for 4 out of 5 tasks.
25
+ * `;
26
+ * const stats = parseNxOutput(output);
27
+ * // { totalTasks: 5, cacheHits: 4, cacheMisses: 1, hitRatio: 0.8, ... }
28
+ * ```
29
+ */
30
+ function parseNxOutput(output) {
31
+ // Match patterns like "4 out of 5 tasks" or "read from cache for X tasks"
32
+ const cacheMatch = output.match(/(?:instead of running the command for |from cache for )(\d+) out of (\d+) tasks/i);
33
+ if (cacheMatch) {
34
+ const cacheHits = parseInt(cacheMatch[1], 10);
35
+ const totalTasks = parseInt(cacheMatch[2], 10);
36
+ const cacheMisses = totalTasks - cacheHits;
37
+ const hitRatio = totalTasks > 0 ? cacheHits / totalTasks : 0;
38
+ return {
39
+ totalTasks,
40
+ cacheHits,
41
+ cacheMisses,
42
+ hitRatio,
43
+ hitRatioFormatted: `${(hitRatio * 100).toFixed(1)}%`,
44
+ meetsTarget: hitRatio >= exports.CACHE_HIT_TARGET,
45
+ };
46
+ }
47
+ // Check for "Successfully ran target X for N projects"
48
+ const successMatch = output.match(/Successfully ran target \w+ for (\d+) projects?/i);
49
+ if (successMatch) {
50
+ const totalTasks = parseInt(successMatch[1], 10);
51
+ // If no cache message, all were cache misses
52
+ return {
53
+ totalTasks,
54
+ cacheHits: 0,
55
+ cacheMisses: totalTasks,
56
+ hitRatio: 0,
57
+ hitRatioFormatted: '0.0%',
58
+ meetsTarget: false,
59
+ };
60
+ }
61
+ return null;
62
+ }
63
+ /**
64
+ * Gets cache statistics from the NX cache directory.
65
+ *
66
+ * @param projectRoot - Root directory of the project
67
+ * @returns Cache statistics based on cache directory analysis
68
+ */
69
+ function getCacheDirectoryStats(projectRoot) {
70
+ const cacheDir = (0, path_1.join)(projectRoot, 'node_modules', '.cache', 'nx');
71
+ if (!(0, fs_1.existsSync)(cacheDir)) {
72
+ return null;
73
+ }
74
+ const walkDir = (dir, state) => {
75
+ const entries = (0, fs_1.readdirSync)(dir);
76
+ for (const entry of entries) {
77
+ const fullPath = (0, path_1.join)(dir, entry);
78
+ const stat = (0, fs_1.statSync)(fullPath);
79
+ if (stat.isDirectory()) {
80
+ state.entryCount++;
81
+ walkDir(fullPath, state);
82
+ }
83
+ else {
84
+ state.totalSize += stat.size;
85
+ }
86
+ }
87
+ };
88
+ try {
89
+ const state = { totalSize: 0, entryCount: 0 };
90
+ walkDir(cacheDir, state);
91
+ return {
92
+ cacheEntries: state.entryCount,
93
+ cacheSizeMB: Math.round((state.totalSize / (1024 * 1024)) * 100) / 100,
94
+ };
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ /**
101
+ * Creates a formatted report of NX cache statistics.
102
+ *
103
+ * @param stats - Cache statistics to report
104
+ * @returns Formatted string for display
105
+ */
106
+ function formatCacheStats(stats) {
107
+ const lines = [
108
+ 'NX Cache Statistics:',
109
+ ` Total tasks: ${stats.totalTasks}`,
110
+ ` Cache hits: ${stats.cacheHits}`,
111
+ ` Cache misses: ${stats.cacheMisses}`,
112
+ ` Hit ratio: ${stats.hitRatioFormatted}`,
113
+ ` Target (>80%): ${stats.meetsTarget ? 'PASS' : 'FAIL'}`,
114
+ ];
115
+ return lines.join('\n');
116
+ }
117
+ //# sourceMappingURL=nx-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nx-stats.js","sourceRoot":"","sources":["../../src/lib/nx-stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Searches upward from a starting directory to find the project root.
3
+ * The project root is identified by the presence of a .projenrc.ts file.
4
+ *
5
+ * @param startDir - Directory to start searching from (defaults to cwd)
6
+ * @returns The project root path, or null if not found
7
+ */
8
+ export declare function findProjectRoot(startDir?: string): string | null;
9
+ /**
10
+ * Finds the project root or throws an error if not in a project.
11
+ *
12
+ * @param startDir - Directory to start searching from (defaults to cwd)
13
+ * @returns The project root path
14
+ * @throws Error if not inside an fnd-platform project
15
+ */
16
+ export declare function requireProjectRoot(startDir?: string): string;
17
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/lib/project.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAoB/E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAU3E"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findProjectRoot = findProjectRoot;
4
+ exports.requireProjectRoot = requireProjectRoot;
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ /**
8
+ * Searches upward from a starting directory to find the project root.
9
+ * The project root is identified by the presence of a .projenrc.ts file.
10
+ *
11
+ * @param startDir - Directory to start searching from (defaults to cwd)
12
+ * @returns The project root path, or null if not found
13
+ */
14
+ function findProjectRoot(startDir = process.cwd()) {
15
+ let currentDir = (0, path_1.resolve)(startDir);
16
+ // Traverse up the directory tree
17
+ let reachedRoot = false;
18
+ while (!reachedRoot) {
19
+ if ((0, fs_1.existsSync)((0, path_1.join)(currentDir, '.projenrc.ts'))) {
20
+ return currentDir;
21
+ }
22
+ const parent = (0, path_1.dirname)(currentDir);
23
+ if (parent === currentDir) {
24
+ // Reached filesystem root
25
+ reachedRoot = true;
26
+ }
27
+ else {
28
+ currentDir = parent;
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ /**
34
+ * Finds the project root or throws an error if not in a project.
35
+ *
36
+ * @param startDir - Directory to start searching from (defaults to cwd)
37
+ * @returns The project root path
38
+ * @throws Error if not inside an fnd-platform project
39
+ */
40
+ function requireProjectRoot(startDir = process.cwd()) {
41
+ const root = findProjectRoot(startDir);
42
+ if (!root) {
43
+ throw new Error('Not inside an fnd-platform project. ' +
44
+ 'Run this command from a project directory containing .projenrc.ts, ' +
45
+ 'or create a new project with: fnd new <project-name>');
46
+ }
47
+ return root;
48
+ }
49
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/lib/project.ts"],"names":[],"mappings":";;AAUA,0CAoBC;AASD,gDAUC;AAjDD,2BAAgC;AAChC,+BAA8C;AAE9C;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAC9D,IAAI,UAAU,GAAG,IAAA,cAAO,EAAC,QAAQ,CAAC,CAAC;IAEnC,iCAAiC;IACjC,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,OAAO,CAAC,WAAW,EAAE,CAAC;QACpB,IAAI,IAAA,eAAU,EAAC,IAAA,WAAI,EAAC,UAAU,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YACjD,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,cAAO,EAAC,UAAU,CAAC,CAAC;QACnC,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;YAC1B,0BAA0B;YAC1B,WAAW,GAAG,IAAI,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,MAAM,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IACjE,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,sCAAsC;YACpC,qEAAqE;YACrE,sDAAsD,CACzD,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Template for .projenrc.ts file in new projects.
3
+ *
4
+ * @param projectName - The name of the project
5
+ * @returns The .projenrc.ts file content
6
+ */
7
+ export declare function getProjenrcTemplate(projectName: string): string;
8
+ /**
9
+ * Template for initial package.json before Projen runs.
10
+ *
11
+ * @param projectName - The name of the project
12
+ * @param packageManager - The package manager to use
13
+ * @returns The package.json content as an object
14
+ */
15
+ export declare function getInitialPackageJson(projectName: string, packageManager?: 'pnpm' | 'yarn'): Record<string, unknown>;
16
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAU/D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,MAAM,GAAG,MAAe,GACvC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYzB"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getProjenrcTemplate = getProjenrcTemplate;
4
+ exports.getInitialPackageJson = getInitialPackageJson;
5
+ /**
6
+ * Template for .projenrc.ts file in new projects.
7
+ *
8
+ * @param projectName - The name of the project
9
+ * @returns The .projenrc.ts file content
10
+ */
11
+ function getProjenrcTemplate(projectName) {
12
+ return `import { FndMonorepoProject } from '@fnd-platform/core';
13
+
14
+ const project = new FndMonorepoProject({
15
+ name: '${projectName}',
16
+ defaultReleaseBranch: 'main',
17
+ });
18
+
19
+ project.synth();
20
+ `;
21
+ }
22
+ /**
23
+ * Template for initial package.json before Projen runs.
24
+ *
25
+ * @param projectName - The name of the project
26
+ * @param packageManager - The package manager to use
27
+ * @returns The package.json content as an object
28
+ */
29
+ function getInitialPackageJson(projectName, packageManager = 'pnpm') {
30
+ return {
31
+ name: projectName,
32
+ version: '0.0.0',
33
+ private: true,
34
+ devDependencies: {
35
+ '@fnd-platform/core': '^0.1.0',
36
+ projen: '^0.91.0',
37
+ typescript: '^5.6.3',
38
+ },
39
+ ...(packageManager === 'pnpm' && { packageManager: 'pnpm@10.6.5' }),
40
+ };
41
+ }
42
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":";;AAMA,kDAUC;AASD,sDAeC;AAxCD;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,WAAmB;IACrD,OAAO;;;WAGE,WAAW;;;;;CAKrB,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,qBAAqB,CACnC,WAAmB,EACnB,iBAAkC,MAAM;IAExC,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,eAAe,EAAE;YACf,oBAAoB,EAAE,QAAQ;YAC9B,MAAM,EAAE,SAAS;YACjB,UAAU,EAAE,QAAQ;SACrB;QACD,GAAG,CAAC,cAAc,KAAK,MAAM,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;KACpE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Performance timing utilities for CLI profiling.
3
+ * Enable profiling with FND_PROFILE=true environment variable.
4
+ */
5
+ /**
6
+ * Result of a single timing measurement.
7
+ */
8
+ export interface TimingResult {
9
+ /**
10
+ * Name/label for this timing.
11
+ */
12
+ name: string;
13
+ /**
14
+ * Duration in milliseconds.
15
+ */
16
+ durationMs: number;
17
+ /**
18
+ * Human-readable duration string.
19
+ */
20
+ durationFormatted: string;
21
+ }
22
+ /**
23
+ * Complete profile report for a command execution.
24
+ */
25
+ export interface ProfileReport {
26
+ /**
27
+ * Command that was profiled (e.g., 'fnd new', 'fnd build').
28
+ */
29
+ command: string;
30
+ /**
31
+ * Total execution time in milliseconds.
32
+ */
33
+ totalDurationMs: number;
34
+ /**
35
+ * Total execution time formatted for display.
36
+ */
37
+ totalDurationFormatted: string;
38
+ /**
39
+ * Individual timing measurements.
40
+ */
41
+ timings: TimingResult[];
42
+ /**
43
+ * Whether the command completed successfully.
44
+ */
45
+ success: boolean;
46
+ }
47
+ /**
48
+ * Formats milliseconds into a human-readable string.
49
+ *
50
+ * @param ms - Duration in milliseconds
51
+ * @returns Formatted duration string
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * formatDuration(1234); // "1.23s"
56
+ * formatDuration(234); // "234ms"
57
+ * formatDuration(65000); // "1m 5.00s"
58
+ * ```
59
+ */
60
+ export declare function formatDuration(ms: number): string;
61
+ /**
62
+ * High-resolution performance timer for profiling CLI commands.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const timer = new PerformanceTimer('fnd new');
67
+ *
68
+ * timer.start('file-generation');
69
+ * // ... do file generation
70
+ * timer.end('file-generation');
71
+ *
72
+ * timer.start('git-init');
73
+ * // ... do git init
74
+ * timer.end('git-init');
75
+ *
76
+ * const report = timer.getReport(true);
77
+ * console.log(report.timings);
78
+ * ```
79
+ */
80
+ export declare class PerformanceTimer {
81
+ private command;
82
+ private startTime;
83
+ private activeTimers;
84
+ private timings;
85
+ /**
86
+ * Creates a new performance timer.
87
+ *
88
+ * @param command - Name of the command being profiled
89
+ */
90
+ constructor(command: string);
91
+ /**
92
+ * Starts timing a named phase.
93
+ *
94
+ * @param name - Name of the phase to time
95
+ * @throws Error if a timer with the same name is already running
96
+ */
97
+ start(name: string): void;
98
+ /**
99
+ * Ends timing a named phase and records the result.
100
+ *
101
+ * @param name - Name of the phase to stop timing
102
+ * @returns The timing result
103
+ * @throws Error if no timer with the given name is running
104
+ */
105
+ end(name: string): TimingResult;
106
+ /**
107
+ * Gets the complete profile report.
108
+ *
109
+ * @param success - Whether the command completed successfully
110
+ * @returns Complete profile report
111
+ */
112
+ getReport(success: boolean): ProfileReport;
113
+ /**
114
+ * Checks if profiling is enabled via FND_PROFILE environment variable.
115
+ *
116
+ * @returns true if profiling is enabled
117
+ */
118
+ static isEnabled(): boolean;
119
+ }
120
+ //# sourceMappingURL=timer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer.d.ts","sourceRoot":"","sources":["../../src/lib/timer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAE/B;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAC;IAExB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,OAAO,CAAsB;IAErC;;;;OAIG;gBACS,OAAO,EAAE,MAAM;IAK3B;;;;;OAKG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAOzB;;;;;;OAMG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAoB/B;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa;IAY1C;;;;OAIG;IACH,MAAM,CAAC,SAAS,IAAI,OAAO;CAG5B"}
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ /**
3
+ * Performance timing utilities for CLI profiling.
4
+ * Enable profiling with FND_PROFILE=true environment variable.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.PerformanceTimer = void 0;
8
+ exports.formatDuration = formatDuration;
9
+ /**
10
+ * Formats milliseconds into a human-readable string.
11
+ *
12
+ * @param ms - Duration in milliseconds
13
+ * @returns Formatted duration string
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * formatDuration(1234); // "1.23s"
18
+ * formatDuration(234); // "234ms"
19
+ * formatDuration(65000); // "1m 5.00s"
20
+ * ```
21
+ */
22
+ function formatDuration(ms) {
23
+ if (ms < 1000) {
24
+ return `${Math.round(ms)}ms`;
25
+ }
26
+ if (ms < 60000) {
27
+ return `${(ms / 1000).toFixed(2)}s`;
28
+ }
29
+ const minutes = Math.floor(ms / 60000);
30
+ const seconds = ((ms % 60000) / 1000).toFixed(2);
31
+ return `${minutes}m ${seconds}s`;
32
+ }
33
+ /**
34
+ * High-resolution performance timer for profiling CLI commands.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const timer = new PerformanceTimer('fnd new');
39
+ *
40
+ * timer.start('file-generation');
41
+ * // ... do file generation
42
+ * timer.end('file-generation');
43
+ *
44
+ * timer.start('git-init');
45
+ * // ... do git init
46
+ * timer.end('git-init');
47
+ *
48
+ * const report = timer.getReport(true);
49
+ * console.log(report.timings);
50
+ * ```
51
+ */
52
+ class PerformanceTimer {
53
+ command;
54
+ startTime;
55
+ activeTimers = new Map();
56
+ timings = [];
57
+ /**
58
+ * Creates a new performance timer.
59
+ *
60
+ * @param command - Name of the command being profiled
61
+ */
62
+ constructor(command) {
63
+ this.command = command;
64
+ this.startTime = performance.now();
65
+ }
66
+ /**
67
+ * Starts timing a named phase.
68
+ *
69
+ * @param name - Name of the phase to time
70
+ * @throws Error if a timer with the same name is already running
71
+ */
72
+ start(name) {
73
+ if (this.activeTimers.has(name)) {
74
+ throw new Error(`Timer '${name}' is already running`);
75
+ }
76
+ this.activeTimers.set(name, performance.now());
77
+ }
78
+ /**
79
+ * Ends timing a named phase and records the result.
80
+ *
81
+ * @param name - Name of the phase to stop timing
82
+ * @returns The timing result
83
+ * @throws Error if no timer with the given name is running
84
+ */
85
+ end(name) {
86
+ const startTime = this.activeTimers.get(name);
87
+ if (startTime === undefined) {
88
+ throw new Error(`Timer '${name}' was not started`);
89
+ }
90
+ const endTime = performance.now();
91
+ const durationMs = endTime - startTime;
92
+ this.activeTimers.delete(name);
93
+ const result = {
94
+ name,
95
+ durationMs,
96
+ durationFormatted: formatDuration(durationMs),
97
+ };
98
+ this.timings.push(result);
99
+ return result;
100
+ }
101
+ /**
102
+ * Gets the complete profile report.
103
+ *
104
+ * @param success - Whether the command completed successfully
105
+ * @returns Complete profile report
106
+ */
107
+ getReport(success) {
108
+ const totalDurationMs = performance.now() - this.startTime;
109
+ return {
110
+ command: this.command,
111
+ totalDurationMs,
112
+ totalDurationFormatted: formatDuration(totalDurationMs),
113
+ timings: [...this.timings],
114
+ success,
115
+ };
116
+ }
117
+ /**
118
+ * Checks if profiling is enabled via FND_PROFILE environment variable.
119
+ *
120
+ * @returns true if profiling is enabled
121
+ */
122
+ static isEnabled() {
123
+ return process.env.FND_PROFILE === 'true' || process.env.FND_PROFILE === '1';
124
+ }
125
+ }
126
+ exports.PerformanceTimer = PerformanceTimer;
127
+ //# sourceMappingURL=timer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer.js","sourceRoot":"","sources":["../../src/lib/timer.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAiEH,wCAUC;AAvBD;;;;;;;;;;;;GAYG;AACH,SAAgB,cAAc,CAAC,EAAU;IACvC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;QACd,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC;IAC/B,CAAC;IACD,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACtC,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD,OAAO,GAAG,OAAO,KAAK,OAAO,GAAG,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAa,gBAAgB;IACnB,OAAO,CAAS;IAChB,SAAS,CAAS;IAClB,YAAY,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC9C,OAAO,GAAmB,EAAE,CAAC;IAErC;;;;OAIG;IACH,YAAY,OAAe;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAY;QAChB,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,sBAAsB,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;OAMG;IACH,GAAG,CAAC,IAAY;QACd,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;QACvC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,MAAM,GAAiB;YAC3B,IAAI;YACJ,UAAU;YACV,iBAAiB,EAAE,cAAc,CAAC,UAAU,CAAC;SAC9C,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,OAAgB;QACxB,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QAE3D,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,eAAe;YACf,sBAAsB,EAAE,cAAc,CAAC,eAAe,CAAC;YACvD,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAC1B,OAAO;SACR,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,SAAS;QACd,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,GAAG,CAAC;IAC/E,CAAC;CACF;AAlFD,4CAkFC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@fnd-platform/cli",
3
+ "version": "1.0.0-alpha.1",
4
+ "description": "CLI tool for fnd-platform monorepo scaffolding",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "bin": {
8
+ "fnd": "./lib/bin/fnd.js"
9
+ },
10
+ "files": [
11
+ "lib/"
12
+ ],
13
+ "dependencies": {
14
+ "chalk": "^5.3.0",
15
+ "commander": "^12.0.0",
16
+ "@fnd-platform/core": "1.0.0-alpha.1"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^20.0.0",
20
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
21
+ "@typescript-eslint/parser": "^7.18.0",
22
+ "@vitest/coverage-v8": "^1.6.0",
23
+ "eslint": "^8.57.0",
24
+ "typescript": "^5.6.3",
25
+ "vitest": "^1.6.0"
26
+ },
27
+ "keywords": [
28
+ "cli",
29
+ "fnd-platform",
30
+ "monorepo",
31
+ "scaffolding",
32
+ "aws",
33
+ "typescript"
34
+ ],
35
+ "license": "MIT",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/your-org/fnd-platform",
42
+ "directory": "packages/cli"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc",
46
+ "postbuild": "chmod +x lib/bin/fnd.js",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "test:coverage": "vitest run --coverage",
50
+ "e2e": "vitest run --config vitest.config.e2e.ts",
51
+ "e2e:watch": "vitest --config vitest.config.e2e.ts",
52
+ "lint": "eslint src/ test/"
53
+ }
54
+ }