@codefast/cli 0.2.46-canary.6

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 (77) hide show
  1. package/.turbo/turbo-build.log +12 -0
  2. package/CHANGELOG.md +15 -0
  3. package/LICENSE +21 -0
  4. package/README.md +125 -0
  5. package/dist/cjs/commands/update-exports/analyze-imports.cjs +92 -0
  6. package/dist/cjs/commands/update-exports/analyze-imports.cjs.map +1 -0
  7. package/dist/cjs/commands/update-exports/command.cjs +58 -0
  8. package/dist/cjs/commands/update-exports/command.cjs.map +1 -0
  9. package/dist/cjs/commands/update-exports/config.cjs +113 -0
  10. package/dist/cjs/commands/update-exports/config.cjs.map +1 -0
  11. package/dist/cjs/commands/update-exports/file-utils.cjs +144 -0
  12. package/dist/cjs/commands/update-exports/file-utils.cjs.map +1 -0
  13. package/dist/cjs/commands/update-exports/generate-exports.cjs +76 -0
  14. package/dist/cjs/commands/update-exports/generate-exports.cjs.map +1 -0
  15. package/dist/cjs/commands/update-exports/index.cjs +36 -0
  16. package/dist/cjs/commands/update-exports/process-package.cjs +143 -0
  17. package/dist/cjs/commands/update-exports/process-package.cjs.map +1 -0
  18. package/dist/cjs/commands/update-exports/types.cjs +55 -0
  19. package/dist/cjs/commands/update-exports/types.cjs.map +1 -0
  20. package/dist/cjs/index.cjs +46 -0
  21. package/dist/cjs/index.cjs.map +1 -0
  22. package/dist/cjs/lib/logger.cjs +72 -0
  23. package/dist/cjs/lib/logger.cjs.map +1 -0
  24. package/dist/esm/commands/update-exports/analyze-imports.js +58 -0
  25. package/dist/esm/commands/update-exports/analyze-imports.js.map +1 -0
  26. package/dist/esm/commands/update-exports/command.js +24 -0
  27. package/dist/esm/commands/update-exports/command.js.map +1 -0
  28. package/dist/esm/commands/update-exports/config.js +62 -0
  29. package/dist/esm/commands/update-exports/config.js.map +1 -0
  30. package/dist/esm/commands/update-exports/file-utils.js +81 -0
  31. package/dist/esm/commands/update-exports/file-utils.js.map +1 -0
  32. package/dist/esm/commands/update-exports/generate-exports.js +42 -0
  33. package/dist/esm/commands/update-exports/generate-exports.js.map +1 -0
  34. package/dist/esm/commands/update-exports/index.js +3 -0
  35. package/dist/esm/commands/update-exports/process-package.js +93 -0
  36. package/dist/esm/commands/update-exports/process-package.js.map +1 -0
  37. package/dist/esm/commands/update-exports/types.js +18 -0
  38. package/dist/esm/commands/update-exports/types.js.map +1 -0
  39. package/dist/esm/index.js +18 -0
  40. package/dist/esm/index.js.map +1 -0
  41. package/dist/esm/lib/logger.js +28 -0
  42. package/dist/esm/lib/logger.js.map +1 -0
  43. package/dist/types/src/commands/update-exports/analyze-imports.d.ts +9 -0
  44. package/dist/types/src/commands/update-exports/analyze-imports.d.ts.map +1 -0
  45. package/dist/types/src/commands/update-exports/command.d.ts +7 -0
  46. package/dist/types/src/commands/update-exports/command.d.ts.map +1 -0
  47. package/dist/types/src/commands/update-exports/config.d.ts +16 -0
  48. package/dist/types/src/commands/update-exports/config.d.ts.map +1 -0
  49. package/dist/types/src/commands/update-exports/file-utils.d.ts +47 -0
  50. package/dist/types/src/commands/update-exports/file-utils.d.ts.map +1 -0
  51. package/dist/types/src/commands/update-exports/generate-exports.d.ts +11 -0
  52. package/dist/types/src/commands/update-exports/generate-exports.d.ts.map +1 -0
  53. package/dist/types/src/commands/update-exports/index.d.ts +2 -0
  54. package/dist/types/src/commands/update-exports/index.d.ts.map +1 -0
  55. package/dist/types/src/commands/update-exports/process-package.d.ts +23 -0
  56. package/dist/types/src/commands/update-exports/process-package.d.ts.map +1 -0
  57. package/dist/types/src/commands/update-exports/types.d.ts +83 -0
  58. package/dist/types/src/commands/update-exports/types.d.ts.map +1 -0
  59. package/dist/types/src/index.d.ts +3 -0
  60. package/dist/types/src/index.d.ts.map +1 -0
  61. package/dist/types/src/lib/logger.d.ts +15 -0
  62. package/dist/types/src/lib/logger.d.ts.map +1 -0
  63. package/eslint.config.js +18 -0
  64. package/package.json +49 -0
  65. package/rslib.config.ts +40 -0
  66. package/src/commands/update-exports/analyze-imports.ts +112 -0
  67. package/src/commands/update-exports/command.ts +38 -0
  68. package/src/commands/update-exports/config.ts +99 -0
  69. package/src/commands/update-exports/file-utils.ts +178 -0
  70. package/src/commands/update-exports/generate-exports.ts +74 -0
  71. package/src/commands/update-exports/index.ts +1 -0
  72. package/src/commands/update-exports/process-package.ts +164 -0
  73. package/src/commands/update-exports/types.ts +94 -0
  74. package/src/index.ts +28 -0
  75. package/src/lib/logger.ts +39 -0
  76. package/tsconfig.build.json +5 -0
  77. package/tsconfig.json +14 -0
@@ -0,0 +1,74 @@
1
+ import type { ImportPath, PackageExports, ScriptConfig } from "@/commands/update-exports/types";
2
+
3
+ import { getPackageConfig } from "@/commands/update-exports/config";
4
+
5
+ /**
6
+ * Formats an output path based on a pattern, directory, and name
7
+ * @param pattern - Output pattern
8
+ * @param directory - Directory path
9
+ * @param name - Module name
10
+ * @returns Formatted output path
11
+ */
12
+ function formatOutputPath(pattern: string, directory: string, name: string): string {
13
+ const dirPart = directory === "." ? "" : `${directory}/`;
14
+
15
+ return pattern.replace("{dir}/", dirPart).replace("{dir}", directory).replace("{name}", name);
16
+ }
17
+
18
+ /**
19
+ * Generates export structure for package.json
20
+ * @param packageName - Name of the package
21
+ * @param imports - Analyzed import paths
22
+ * @param existingExports - Current exports to preserve
23
+ * @param config - Optional ScriptConfig
24
+ * @returns Updated PackageExports
25
+ */
26
+ export function generateExports(
27
+ packageName: string,
28
+ imports: ImportPath[],
29
+ existingExports: PackageExports = {},
30
+ config?: ScriptConfig,
31
+ ): PackageExports {
32
+ const packageConfig = getPackageConfig(packageName, config);
33
+
34
+ const exports: PackageExports = {
35
+ ".": existingExports["."] ?? {
36
+ import: {
37
+ types: "./dist/types/index.d.ts",
38
+ default: "./dist/esm/index.js",
39
+ },
40
+ require: {
41
+ types: "./dist/types/index.d.cts",
42
+ default: "./dist/cjs/index.cjs",
43
+ },
44
+ },
45
+ };
46
+
47
+ // Preserve existing CSS exports
48
+ if (existingExports["./styles.css"]) {
49
+ exports["./styles.css"] = existingExports["./styles.css"];
50
+ }
51
+
52
+ // Generate exports for each import path
53
+ for (const importPath of imports) {
54
+ const { directory, name, exportPath } = importPath;
55
+
56
+ const esmOutput = formatOutputPath(packageConfig.esmOutputPattern, directory, name);
57
+ const cjsOutput = formatOutputPath(packageConfig.cjsOutputPattern, directory, name);
58
+ const typesOutput = formatOutputPath(packageConfig.typesOutputPattern, directory, name);
59
+ const typesCjsOutput = formatOutputPath(packageConfig.typesOutputCjsPattern, directory, name);
60
+
61
+ exports[exportPath] = {
62
+ import: {
63
+ types: typesOutput,
64
+ default: esmOutput,
65
+ },
66
+ require: {
67
+ types: typesCjsOutput,
68
+ default: cjsOutput,
69
+ },
70
+ };
71
+ }
72
+
73
+ return exports;
74
+ }
@@ -0,0 +1 @@
1
+ export { createUpdateExportsCommand } from "@/commands/update-exports/command";
@@ -0,0 +1,164 @@
1
+ import { glob } from "glob";
2
+ import path from "node:path";
3
+
4
+ import type { ProcessOptions, ScriptConfig } from "@/commands/update-exports/types";
5
+ import type { Logger } from "@/lib/logger";
6
+
7
+ import { analyzeImports } from "@/commands/update-exports/analyze-imports";
8
+ import { getConfig, getPackageConfig } from "@/commands/update-exports/config";
9
+ import {
10
+ backupPackageJson,
11
+ fileExists,
12
+ readPackageJson,
13
+ saveExportsAnalysis,
14
+ saveExportsPreview,
15
+ savePackageJson,
16
+ } from "@/commands/update-exports/file-utils";
17
+ import { generateExports } from "@/commands/update-exports/generate-exports";
18
+
19
+ const DEFAULT_IGNORE_PATTERN = ["**/node_modules/**"];
20
+
21
+ /**
22
+ * Finds all package.json files in the workspace
23
+ * @param config - Optional ScriptConfig
24
+ * @returns Array of package.json paths
25
+ */
26
+ export async function findAllPackages(config?: ScriptConfig): Promise<string[]> {
27
+ const configObj = config ?? getConfig();
28
+
29
+ return await glob(configObj.packagesGlob, {
30
+ ignore: DEFAULT_IGNORE_PATTERN,
31
+ });
32
+ }
33
+
34
+ /**
35
+ * Processes a single package
36
+ * @param packageJsonPath - Path to package.json
37
+ * @param options - Processing options
38
+ * @param logger - Logger instance
39
+ * @returns True if processing was successful
40
+ */
41
+ export function processPackage(packageJsonPath: string, options: ProcessOptions, logger: Logger): boolean {
42
+ const packageDir = path.dirname(packageJsonPath);
43
+ const packageJson = readPackageJson(packageJsonPath);
44
+
45
+ if (!packageJson) {
46
+ logger.error(`Failed to read ${packageJsonPath}`);
47
+
48
+ return false;
49
+ }
50
+
51
+ const packageName = packageJson.name;
52
+
53
+ // Skip if package doesn't match filter
54
+ if (options.packageFilter && packageName !== options.packageFilter) {
55
+ logger.debug(`Skipping ${packageName} (does not match filter)`);
56
+
57
+ return false;
58
+ }
59
+
60
+ logger.info(`\n📦 Processing package: ${packageName}`);
61
+
62
+ const config = getConfig(options.configPath);
63
+ const packageConfig = getPackageConfig(packageName, config);
64
+ const srcIndexPath = path.join(packageDir, packageConfig.srcIndexPath);
65
+
66
+ if (!fileExists(srcIndexPath)) {
67
+ logger.error(`Source file not found at ${srcIndexPath}`);
68
+
69
+ return false;
70
+ }
71
+
72
+ // Analyze imports
73
+ logger.info(`🔍 Analyzing imports from ${srcIndexPath}...`);
74
+ const { imports } = analyzeImports(srcIndexPath, packageConfig);
75
+
76
+ if (imports.length === 0) {
77
+ logger.warn(`No imports found to analyze in ${packageName}`);
78
+
79
+ return false;
80
+ }
81
+
82
+ logger.success(`Analysis complete. Found ${imports.length} subpath exports.`);
83
+
84
+ // Save analysis results
85
+ saveExportsAnalysis(packageDir, { imports });
86
+
87
+ // Generate new exports
88
+ const newExports = generateExports(packageName, imports, packageJson.exports, config);
89
+
90
+ // Compare export counts
91
+ const currentExportsCount = packageJson.exports ? Object.keys(packageJson.exports).length : 0;
92
+ const newExportsCount = Object.keys(newExports).length;
93
+
94
+ logger.info(`📊 Exports: ${currentExportsCount} -> ${newExportsCount}`);
95
+
96
+ if (options.dryRun) {
97
+ saveExportsPreview(packageDir, newExports);
98
+ logger.warn(`🧪 📄 Saved exports preview to .exports-analysis`);
99
+ logger.warn(`🧪 🚫 Dry run: no changes saved for ${packageName}`);
100
+
101
+ return true;
102
+ }
103
+
104
+ // Backup package.json
105
+ if (backupPackageJson(packageJsonPath)) {
106
+ logger.success(`Backed up ${packageJsonPath}`);
107
+ }
108
+
109
+ // Update package.json
110
+ const updatedPackageJson = { ...packageJson, exports: newExports };
111
+
112
+ if (savePackageJson(packageJsonPath, updatedPackageJson)) {
113
+ logger.success(`Updated exports for ${packageName}`);
114
+
115
+ return true;
116
+ }
117
+
118
+ logger.error(`Failed to update ${packageJsonPath}`);
119
+
120
+ return false;
121
+ }
122
+
123
+ /**
124
+ * Processes all packages in the workspace
125
+ * @param options - Processing options
126
+ * @param logger - Logger instance
127
+ */
128
+ export async function processAllPackages(options: ProcessOptions, logger: Logger): Promise<void> {
129
+ try {
130
+ logger.info("🔍 Searching for packages...");
131
+ const config = getConfig(options.configPath);
132
+ const packageJsonPaths = await findAllPackages(config);
133
+
134
+ if (packageJsonPaths.length === 0) {
135
+ logger.warn("⚠️ No packages found.");
136
+
137
+ return;
138
+ }
139
+
140
+ logger.success(`✅ Found ${packageJsonPaths.length} packages.`);
141
+
142
+ let successCount = 0;
143
+ let skipCount = 0;
144
+ let errorCount = 0;
145
+
146
+ for (const packageJsonPath of packageJsonPaths) {
147
+ const result = processPackage(packageJsonPath, options, logger);
148
+
149
+ if (result) {
150
+ successCount++;
151
+ } else if (options.packageFilter) {
152
+ skipCount++;
153
+ } else {
154
+ errorCount++;
155
+ }
156
+ }
157
+
158
+ logger.success("\n✅ Completed exports update.");
159
+ logger.info(`📊 Stats: ${successCount} succeeded, ${skipCount} skipped, ${errorCount} failed`);
160
+ } catch (error) {
161
+ logger.error("❌ Error processing packages:", error);
162
+ throw error;
163
+ }
164
+ }
@@ -0,0 +1,94 @@
1
+ import { z } from "zod";
2
+
3
+ // Schema for package configuration, defining output patterns and paths
4
+ export const PackageConfigSchema = z.interface({
5
+ // Output path pattern for CommonJS (CJS) modules
6
+ // Example: "dist/cjs/*.js" specifies where CJS files are emitted
7
+ cjsOutputPattern: z.string(),
8
+ // Output path pattern for ES Modules (ESM)
9
+ // Example: "dist/esm/*.js" specifies where ESM files are emitted
10
+ esmOutputPattern: z.string(),
11
+ // Path to the package.json file
12
+ // Used to read or update package metadata (e.g., version, exports)
13
+ packageJsonPath: z.string(),
14
+ // Path to the src/index.ts file
15
+ // Main entry point for analyzing exports or building the package
16
+ srcIndexPath: z.string(),
17
+ // Output path pattern for CJS type definitions
18
+ // Example: "dist/cjs/*.d.ts" for CJS-compatible type definitions
19
+ typesOutputCjsPattern: z.string(),
20
+ // General output path pattern for type definitions
21
+ // Example: "dist/types/*.d.ts" for type definitions used by both CJS and ESM
22
+ typesOutputPattern: z.string(),
23
+ // Optional prefixes to strip from export paths
24
+ // Example: ["components"] removes "components" from export paths
25
+ "exportPathPrefixesToRemove?": z.array(z.string()),
26
+ });
27
+
28
+ // Schema for script configuration, defining package discovery and defaults
29
+ export const ScriptConfigSchema = z.interface({
30
+ // Custom configurations for specific packages
31
+ // Key is the package name, value is a partial override of defaultPackageConfig
32
+ // Example: { "my-package": { cjsOutputPattern: "dist/custom/*.js" } }
33
+ customPackageConfigs: z.record(z.string(), PackageConfigSchema.partial()),
34
+ // Default configuration applied to all packages
35
+ // Ensures consistent settings unless overridden
36
+ defaultPackageConfig: PackageConfigSchema,
37
+ // Glob pattern to locate packages in the project
38
+ // Example: "packages/*" finds all package folders under packages/
39
+ packagesGlob: z.string(),
40
+ });
41
+
42
+ // TypeScript type inferred from schemas for type safety
43
+ export type PackageConfig = z.infer<typeof PackageConfigSchema>;
44
+ export type ScriptConfig = z.infer<typeof ScriptConfigSchema>;
45
+
46
+ // Interface for import path metadata
47
+ export interface ImportPath {
48
+ // Directory containing the module (e.g., 'components')
49
+ directory: string;
50
+ // Export path for package.json (e.g., './button')
51
+ exportPath: string;
52
+ // Module name (e.g., 'Button')
53
+ name: string;
54
+ // Original import path (e.g., './components/Button')
55
+ originalPath: string;
56
+ }
57
+
58
+ // Interface for import analysis results
59
+ export interface AnalysisResult {
60
+ // List of analyzed import paths
61
+ imports: ImportPath[];
62
+ }
63
+
64
+ // Interface for module export configuration
65
+ export interface ExportConfig {
66
+ import: {
67
+ default: string; // ESM default file (e.g., "./dist/esm/index.js")
68
+ types: string; // ESM type definitions (e.g., "./dist/types/index.d.ts")
69
+ };
70
+ require: {
71
+ default: string; // CJS default file (e.g., "./dist/cjs/index.cjs")
72
+ types: string; // CJS type definitions (e.g., "./dist/types/index.d.cts")
73
+ };
74
+ }
75
+
76
+ export type ExportTarget = ExportConfig | string;
77
+ export type PackageExports = Record<string, ExportTarget>;
78
+
79
+ // Interface for package.json structure
80
+ export interface PackageJson {
81
+ [key: string]: unknown;
82
+ name: string;
83
+ version: string;
84
+
85
+ exports?: PackageExports;
86
+ }
87
+
88
+ // Options for processing packages
89
+ export interface ProcessOptions {
90
+ dryRun: boolean;
91
+ verbose: boolean;
92
+ configPath?: string;
93
+ packageFilter?: string;
94
+ }
package/src/index.ts ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+
5
+ import { createUpdateExportsCommand } from "@/commands/update-exports";
6
+
7
+ import packageJson from "../package.json";
8
+
9
+ function main(): void {
10
+ const program = new Command();
11
+
12
+ program
13
+ .name("codefast")
14
+ .description("CodeFast CLI - A development toolkit for CodeFast.")
15
+ .version(packageJson.version, "-v, --version", "display CLI version");
16
+
17
+ createUpdateExportsCommand(program);
18
+
19
+ program.action(() => {
20
+ console.log('Use "codefast update-exports" to update exports.');
21
+ console.log('Run "codefast --help" to see all available commands.');
22
+ program.help();
23
+ });
24
+
25
+ program.parse(process.argv);
26
+ }
27
+
28
+ main();
@@ -0,0 +1,39 @@
1
+ import chalk from "chalk";
2
+
3
+ interface LoggerOptions {
4
+ verbose?: boolean;
5
+ }
6
+
7
+ export class Logger {
8
+ private readonly verbose: boolean;
9
+
10
+ constructor(options: LoggerOptions = {}) {
11
+ this.verbose = options.verbose ?? false;
12
+ }
13
+
14
+ info(message: string, ...args: any[]): void {
15
+ console.log(chalk.blue(message), ...args);
16
+ }
17
+
18
+ success(message: string, ...args: any[]): void {
19
+ console.log(chalk.green(message), ...args);
20
+ }
21
+
22
+ warn(message: string, ...args: any[]): void {
23
+ console.log(chalk.yellow(message), ...args);
24
+ }
25
+
26
+ error(message: string, ...args: any[]): void {
27
+ console.error(chalk.red(message), ...args);
28
+ }
29
+
30
+ debug(message: string, ...args: any[]): void {
31
+ if (this.verbose) {
32
+ console.log(chalk.gray(message), ...args);
33
+ }
34
+ }
35
+
36
+ table(data: any[]): void {
37
+ console.table(data);
38
+ }
39
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["src/**/*"],
4
+ "exclude": ["node_modules", "dist", ".turbo", "coverage", "/**/*.test.*", "**/*.spec.*"]
5
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "@codefast/typescript-config/library.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "esModuleInterop": true,
6
+ "outDir": "dist",
7
+ "paths": {
8
+ "@/*": ["./src/*"]
9
+ },
10
+ "resolveJsonModule": true
11
+ },
12
+ "include": ["**/*.ts", "**/*.tsx"],
13
+ "exclude": ["node_modules", "dist", ".turbo", "coverage"]
14
+ }