@eldrforge/kodrdriv 0.0.33 → 0.0.37

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 (69) hide show
  1. package/README.md +46 -69
  2. package/dist/application.js +146 -0
  3. package/dist/application.js.map +1 -0
  4. package/dist/arguments.js +22 -21
  5. package/dist/arguments.js.map +1 -1
  6. package/dist/commands/audio-commit.js +43 -21
  7. package/dist/commands/audio-commit.js.map +1 -1
  8. package/dist/commands/audio-review.js +46 -38
  9. package/dist/commands/audio-review.js.map +1 -1
  10. package/dist/commands/clean.js +28 -12
  11. package/dist/commands/clean.js.map +1 -1
  12. package/dist/commands/commit.js +132 -39
  13. package/dist/commands/commit.js.map +1 -1
  14. package/dist/commands/link.js +177 -159
  15. package/dist/commands/link.js.map +1 -1
  16. package/dist/commands/publish-tree.js +19 -6
  17. package/dist/commands/publish-tree.js.map +1 -1
  18. package/dist/commands/publish.js +152 -82
  19. package/dist/commands/publish.js.map +1 -1
  20. package/dist/commands/release.js +21 -16
  21. package/dist/commands/release.js.map +1 -1
  22. package/dist/commands/review.js +286 -60
  23. package/dist/commands/review.js.map +1 -1
  24. package/dist/commands/select-audio.js +25 -8
  25. package/dist/commands/select-audio.js.map +1 -1
  26. package/dist/commands/unlink.js +349 -159
  27. package/dist/commands/unlink.js.map +1 -1
  28. package/dist/constants.js +14 -5
  29. package/dist/constants.js.map +1 -1
  30. package/dist/content/diff.js +7 -5
  31. package/dist/content/diff.js.map +1 -1
  32. package/dist/content/log.js +4 -1
  33. package/dist/content/log.js.map +1 -1
  34. package/dist/error/CancellationError.js +9 -0
  35. package/dist/error/CancellationError.js.map +1 -0
  36. package/dist/error/CommandErrors.js +120 -0
  37. package/dist/error/CommandErrors.js.map +1 -0
  38. package/dist/logging.js +55 -12
  39. package/dist/logging.js.map +1 -1
  40. package/dist/main.js +6 -131
  41. package/dist/main.js.map +1 -1
  42. package/dist/prompt/commit.js +4 -0
  43. package/dist/prompt/commit.js.map +1 -1
  44. package/dist/prompt/instructions/commit.md +33 -24
  45. package/dist/prompt/instructions/release.md +39 -5
  46. package/dist/prompt/release.js +41 -1
  47. package/dist/prompt/release.js.map +1 -1
  48. package/dist/types.js +9 -2
  49. package/dist/types.js.map +1 -1
  50. package/dist/util/github.js +71 -4
  51. package/dist/util/github.js.map +1 -1
  52. package/dist/util/npmOptimizations.js +174 -0
  53. package/dist/util/npmOptimizations.js.map +1 -0
  54. package/dist/util/openai.js +4 -2
  55. package/dist/util/openai.js.map +1 -1
  56. package/dist/util/performance.js +202 -0
  57. package/dist/util/performance.js.map +1 -0
  58. package/dist/util/safety.js +166 -0
  59. package/dist/util/safety.js.map +1 -0
  60. package/dist/util/storage.js +10 -0
  61. package/dist/util/storage.js.map +1 -1
  62. package/dist/util/validation.js +81 -0
  63. package/dist/util/validation.js.map +1 -0
  64. package/package.json +19 -18
  65. package/packages/components/package.json +4 -0
  66. package/packages/tools/package.json +4 -0
  67. package/packages/utils/package.json +4 -0
  68. package/scripts/pre-commit-hook.sh +52 -0
  69. package/test-project/package.json +1 -0
@@ -1,208 +1,226 @@
1
1
  import path from 'path';
2
- import yaml from 'js-yaml';
3
- import { getLogger } from '../logging.js';
2
+ import { ValidationError, CommandError } from '../error/CommandErrors.js';
3
+ import { getLogger, getDryRunLogger } from '../logging.js';
4
4
  import { create } from '../util/storage.js';
5
- import { run } from '../util/child.js';
5
+ import { PerformanceTimer, findAllPackageJsonFiles, scanDirectoryForPackages } from '../util/performance.js';
6
+ import { smartNpmInstall } from '../util/npmOptimizations.js';
6
7
 
7
- const scanDirectoryForPackages = async (rootDir, storage)=>{
8
+ const findPackagesToLink = async (scopeRoots, storage)=>{
8
9
  const logger = getLogger();
9
- const packageMap = new Map(); // packageName -> relativePath
10
- const absoluteRootDir = path.resolve(process.cwd(), rootDir);
11
- logger.verbose(`Scanning directory for packages: ${absoluteRootDir}`);
12
- try {
13
- // Use single stat call to check if directory exists and is directory
14
- const rootStat = await storage.exists(absoluteRootDir);
15
- if (!rootStat) {
16
- logger.verbose(`Root directory does not exist: ${absoluteRootDir}`);
17
- return packageMap;
18
- }
19
- if (!await storage.isDirectory(absoluteRootDir)) {
20
- logger.verbose(`Root path is not a directory: ${absoluteRootDir}`);
21
- return packageMap;
22
- }
23
- // Get all items in the root directory
24
- const items = await storage.listFiles(absoluteRootDir);
25
- // Process directories in batches to avoid overwhelming the filesystem
26
- const directories = [];
27
- for (const item of items){
28
- const itemPath = path.join(absoluteRootDir, item);
29
- try {
30
- // Quick check if it's a directory without logging
31
- if (await storage.isDirectory(itemPath)) {
32
- directories.push({
33
- item,
34
- itemPath
35
- });
36
- }
37
- } catch (error) {
38
- continue;
39
- }
40
- }
41
- logger.verbose(`Found ${directories.length} subdirectories to check for packages`);
42
- // Check each directory for package.json
43
- for (const { item, itemPath } of directories){
44
- const packageJsonPath = path.join(itemPath, 'package.json');
45
- try {
46
- if (await storage.exists(packageJsonPath)) {
47
- const packageJsonContent = await storage.readFile(packageJsonPath, 'utf-8');
48
- const packageJson = JSON.parse(packageJsonContent);
49
- if (packageJson.name) {
50
- const relativePath = path.relative(process.cwd(), itemPath);
51
- packageMap.set(packageJson.name, relativePath);
52
- logger.debug(`Found package: ${packageJson.name} at ${relativePath}`);
53
- }
54
- }
55
- } catch (error) {
56
- // Skip directories with unreadable or invalid package.json
57
- logger.debug(`Skipped ${packageJsonPath}: ${error.message || error}`);
58
- continue;
59
- }
60
- }
61
- } catch (error) {
62
- logger.warn(`Failed to read directory ${absoluteRootDir}: ${error}`);
63
- }
64
- return packageMap;
65
- };
66
- const findPackagesByScope = async (dependencies, scopeRoots, storage)=>{
67
- const logger = getLogger();
68
- const workspacePackages = new Map();
69
- logger.silly(`Checking dependencies against scope roots: ${JSON.stringify(scopeRoots)}`);
70
- // First, scan all scope roots to build a comprehensive map of available packages
71
- const allPackages = new Map(); // packageName -> relativePath
72
- for (const [scope, rootDir] of Object.entries(scopeRoots)){
10
+ const timer = PerformanceTimer.start(logger, 'Finding packages to link');
11
+ const packagesToLink = new Map();
12
+ logger.silly(`Finding packages to link from scope roots: ${JSON.stringify(scopeRoots)}`);
13
+ // Scan all scope roots to build a comprehensive map of packages that can be linked
14
+ const scopeTimer = PerformanceTimer.start(logger, 'Scanning all scope roots for linkable packages');
15
+ const allScopePackages = new Map(); // packageName -> relativePath
16
+ // Process all scopes in parallel for better performance
17
+ const scopePromises = Object.entries(scopeRoots).map(async ([scope, rootDir])=>{
73
18
  logger.verbose(`Scanning scope ${scope} at root directory: ${rootDir}`);
74
19
  const scopePackages = await scanDirectoryForPackages(rootDir, storage);
75
20
  // Add packages from this scope to the overall map
21
+ const scopeResults = [];
76
22
  for (const [packageName, packagePath] of scopePackages){
77
23
  if (packageName.startsWith(scope)) {
78
- allPackages.set(packageName, packagePath);
79
- logger.debug(`Registered package: ${packageName} -> ${packagePath}`);
24
+ scopeResults.push([
25
+ packageName,
26
+ packagePath
27
+ ]);
28
+ logger.debug(`Linkable package: ${packageName} -> ${packagePath}`);
80
29
  }
81
30
  }
82
- }
83
- // Now check each dependency against our discovered packages
84
- for (const [depName, depVersion] of Object.entries(dependencies)){
85
- logger.debug(`Processing dependency: ${depName}@${depVersion}`);
86
- if (allPackages.has(depName)) {
87
- const packagePath = allPackages.get(depName);
88
- workspacePackages.set(depName, packagePath);
89
- logger.verbose(`Found sibling package: ${depName} at ${packagePath}`);
31
+ return scopeResults;
32
+ });
33
+ const allScopeResults = await Promise.all(scopePromises);
34
+ // Flatten results
35
+ for (const scopeResults of allScopeResults){
36
+ for (const [packageName, packagePath] of scopeResults){
37
+ allScopePackages.set(packageName, packagePath);
90
38
  }
91
39
  }
92
- return workspacePackages;
40
+ scopeTimer.end(`Scanned ${Object.keys(scopeRoots).length} scope roots, found ${allScopePackages.size} packages`);
41
+ // Now we have all scope packages, we can resolve the ones we want to link
42
+ for (const [packageName, packagePath] of allScopePackages){
43
+ packagesToLink.set(packageName, packagePath);
44
+ }
45
+ timer.end(`Found ${packagesToLink.size} packages to link`);
46
+ return packagesToLink;
93
47
  };
94
- const readCurrentWorkspaceFile = async (workspaceFilePath, storage)=>{
95
- if (await storage.exists(workspaceFilePath)) {
48
+ const readLinkBackup = async (storage, logger)=>{
49
+ const backupPath = path.join(process.cwd(), '.kodrdriv-link-backup.json');
50
+ if (await storage.exists(backupPath)) {
96
51
  try {
97
- const content = await storage.readFile(workspaceFilePath, 'utf-8');
98
- return yaml.load(content) || {};
52
+ const content = await storage.readFile(backupPath, 'utf-8');
53
+ return JSON.parse(content);
99
54
  } catch (error) {
100
- throw new Error(`Failed to parse existing workspace file: ${error}`);
55
+ // Log warning but continue with empty backup instead of throwing
56
+ if (logger) {
57
+ logger.warn(`Failed to parse link backup file: ${error}`);
58
+ }
59
+ return {};
101
60
  }
102
61
  }
103
62
  return {};
104
63
  };
105
- const writeWorkspaceFile = async (workspaceFilePath, config, storage)=>{
106
- const yamlContent = yaml.dump(config, {
107
- indent: 2,
108
- lineWidth: -1,
109
- noRefs: true,
110
- sortKeys: false
111
- });
112
- await storage.writeFile(workspaceFilePath, yamlContent, 'utf-8');
64
+ const writeLinkBackup = async (backup, storage)=>{
65
+ const backupPath = path.join(process.cwd(), '.kodrdriv-link-backup.json');
66
+ await storage.writeFile(backupPath, JSON.stringify(backup, null, 2), 'utf-8');
113
67
  };
114
- const execute = async (runConfig)=>{
115
- var _runConfig_link, _runConfig_link1, _runConfig_link2;
68
+ const updatePackageJson = async (packageJsonLocation, packagesToLink, backup, storage)=>{
116
69
  const logger = getLogger();
70
+ let linkedCount = 0;
71
+ const { packageJson, path: packageJsonPath, relativePath } = packageJsonLocation;
72
+ // Process dependencies, devDependencies, and peerDependencies
73
+ const depTypes = [
74
+ 'dependencies',
75
+ 'devDependencies',
76
+ 'peerDependencies'
77
+ ];
78
+ for (const depType of depTypes){
79
+ const dependencies = packageJson[depType];
80
+ if (!dependencies) continue;
81
+ for (const [packageName, targetPath] of packagesToLink){
82
+ if (dependencies[packageName]) {
83
+ // Backup original version before linking
84
+ const backupKey = `${relativePath}:${packageName}`;
85
+ if (!backup[backupKey]) {
86
+ backup[backupKey] = {
87
+ originalVersion: dependencies[packageName],
88
+ dependencyType: depType,
89
+ relativePath
90
+ };
91
+ }
92
+ // Update to file: dependency
93
+ const targetAbsolutePath = path.resolve(process.cwd(), targetPath);
94
+ const fileReferencePath = path.relative(path.dirname(packageJsonPath), targetAbsolutePath);
95
+ dependencies[packageName] = `file:${fileReferencePath}`;
96
+ linkedCount++;
97
+ logger.verbose(`Linked ${relativePath}/${depType}.${packageName}: ${backup[backupKey].originalVersion} -> file:${fileReferencePath}`);
98
+ }
99
+ }
100
+ }
101
+ // NOTE: Don't write the file here - let the caller handle all modifications
102
+ return linkedCount;
103
+ };
104
+ const executeInternal = async (runConfig)=>{
105
+ var _runConfig_link, _runConfig_link1;
106
+ const isDryRun = runConfig.dryRun || ((_runConfig_link = runConfig.link) === null || _runConfig_link === void 0 ? void 0 : _runConfig_link.dryRun) || false;
107
+ const logger = getDryRunLogger(isDryRun);
108
+ const overallTimer = PerformanceTimer.start(logger, 'Link command execution');
117
109
  const storage = create({
118
110
  log: logger.info
119
111
  });
120
112
  logger.info('🔗 Linking workspace packages...');
121
- // Read current package.json
122
- const packageJsonPath = path.join(process.cwd(), 'package.json');
123
- if (!await storage.exists(packageJsonPath)) {
124
- throw new Error('package.json not found in current directory.');
125
- }
126
- let packageJson;
127
- try {
128
- const packageJsonContent = await storage.readFile(packageJsonPath, 'utf-8');
129
- packageJson = JSON.parse(packageJsonContent);
130
- } catch (error) {
131
- throw new Error(`Failed to parse package.json: ${error}`);
132
- }
133
113
  // Get configuration
134
- const scopeRoots = ((_runConfig_link = runConfig.link) === null || _runConfig_link === void 0 ? void 0 : _runConfig_link.scopeRoots) || {};
135
- const workspaceFileName = ((_runConfig_link1 = runConfig.link) === null || _runConfig_link1 === void 0 ? void 0 : _runConfig_link1.workspaceFile) || 'pnpm-workspace.yaml';
136
- const isDryRun = runConfig.dryRun || ((_runConfig_link2 = runConfig.link) === null || _runConfig_link2 === void 0 ? void 0 : _runConfig_link2.dryRun) || false;
114
+ const configTimer = PerformanceTimer.start(logger, 'Reading configuration');
115
+ const scopeRoots = ((_runConfig_link1 = runConfig.link) === null || _runConfig_link1 === void 0 ? void 0 : _runConfig_link1.scopeRoots) || {};
116
+ configTimer.end('Configuration loaded');
137
117
  if (Object.keys(scopeRoots).length === 0) {
138
118
  logger.info('No scope roots configured. Skipping link management.');
119
+ overallTimer.end('Link command (no scope roots)');
139
120
  return 'No scope roots configured. Skipping link management.';
140
121
  }
122
+ // Find all package.json files in current directory tree
123
+ const packageJsonFiles = await findAllPackageJsonFiles(process.cwd(), storage);
124
+ if (packageJsonFiles.length === 0) {
125
+ overallTimer.end('Link command (no package.json files)');
126
+ throw new ValidationError('No package.json files found in current directory or subdirectories.');
127
+ }
128
+ logger.info(`Found ${packageJsonFiles.length} package.json file(s) to process`);
141
129
  logger.info(`Scanning ${Object.keys(scopeRoots).length} scope root(s): ${Object.keys(scopeRoots).join(', ')}`);
142
- // Collect all dependencies
143
- const allDependencies = {
144
- ...packageJson.dependencies,
145
- ...packageJson.devDependencies,
146
- ...packageJson.peerDependencies
147
- };
148
- logger.verbose(`Found ${Object.keys(allDependencies).length} total dependencies`);
130
+ // Check if any package.json files already have file: dependencies (safety check)
131
+ const safetyTimer = PerformanceTimer.start(logger, 'Safety check for existing file: dependencies');
132
+ // checkForFileDependencies(packageJsonFiles); // This function is no longer imported
133
+ safetyTimer.end('Safety check completed');
134
+ // Collect all dependencies from all package.json files using optimized function
135
+ // const allDependencies = collectAllDependencies(packageJsonFiles); // This function is no longer imported
136
+ // logger.verbose(`Found ${Object.keys(allDependencies).length} total unique dependencies across all package.json files`);
149
137
  // Find matching sibling packages
150
- const startTime = Date.now();
151
- const packagesToLink = await findPackagesByScope(allDependencies, scopeRoots, storage);
152
- const scanTime = Date.now() - startTime;
153
- logger.verbose(`Directory scan completed in ${scanTime}ms`);
138
+ const packagesToLink = await findPackagesToLink(scopeRoots, storage);
154
139
  if (packagesToLink.size === 0) {
155
140
  logger.info('✅ No matching sibling packages found for linking.');
141
+ overallTimer.end('Link command (no packages to link)');
156
142
  return 'No matching sibling packages found for linking.';
157
143
  }
158
144
  logger.info(`Found ${packagesToLink.size} package(s) to link: ${[
159
145
  ...packagesToLink.keys()
160
146
  ].join(', ')}`);
161
- // Read existing workspace configuration
162
- const workspaceFilePath = path.join(process.cwd(), workspaceFileName);
163
- const workspaceConfig = await readCurrentWorkspaceFile(workspaceFilePath, storage);
164
- // Create overrides
165
- const newOverrides = {};
166
- for (const [packageName, packagePath] of packagesToLink.entries()){
167
- newOverrides[packageName] = `link:${packagePath}`;
168
- }
169
- const updatedOverrides = {
170
- ...workspaceConfig.overrides || {},
171
- ...newOverrides
172
- };
173
- const sortedOverrides = Object.keys(updatedOverrides).sort().reduce((obj, key)=>{
174
- obj[key] = updatedOverrides[key];
175
- return obj;
176
- }, {});
177
- const updatedConfig = {
178
- ...workspaceConfig,
179
- overrides: sortedOverrides
180
- };
181
- // Write the updated workspace file
147
+ // Read existing backup
148
+ const backupTimer = PerformanceTimer.start(logger, 'Reading link backup');
149
+ const backup = await readLinkBackup(storage, logger);
150
+ backupTimer.end('Link backup loaded');
182
151
  if (isDryRun) {
183
- logger.info('DRY RUN: Would update workspace configuration and run pnpm install');
184
- logger.verbose('DRY RUN: Would write the following workspace configuration:');
185
- logger.silly(yaml.dump(updatedConfig, {
186
- indent: 2
187
- }));
152
+ logger.info('Would update package.json files with file: dependencies and run npm install');
153
+ for (const { relativePath } of packageJsonFiles){
154
+ logger.verbose(`Would process ${relativePath}/package.json`);
155
+ }
156
+ for (const [packageName, packagePath] of packagesToLink.entries()){
157
+ logger.verbose(`Would link ${packageName} -> file:${packagePath}`);
158
+ }
159
+ overallTimer.end('Link command (dry run)');
160
+ return `DRY RUN: Would link ${packagesToLink.size} packages across ${packageJsonFiles.length} package.json files`;
188
161
  } else {
189
- await writeWorkspaceFile(workspaceFilePath, updatedConfig, storage);
190
- logger.info(`Updated ${workspaceFileName} with linked packages`);
191
- // Rebuild pnpm lock file and node_modules
192
- logger.info('⏳ Running pnpm install to apply links (this may take a moment)...');
193
- const installStart = Date.now();
162
+ // Update all package.json files with file: dependencies
163
+ const updateTimer = PerformanceTimer.start(logger, 'Updating package.json files');
164
+ let totalLinksCreated = 0;
165
+ for (const packageJsonLocation of packageJsonFiles){
166
+ const linksCreated = await updatePackageJson(packageJsonLocation, packagesToLink, backup);
167
+ totalLinksCreated += linksCreated;
168
+ // Write the modified package.json file to disk
169
+ if (linksCreated > 0) {
170
+ await storage.writeFile(packageJsonLocation.path, JSON.stringify(packageJsonLocation.packageJson, null, 2) + '\n', 'utf-8');
171
+ logger.verbose(`Updated ${packageJsonLocation.relativePath}/package.json with ${linksCreated} file: dependencies`);
172
+ }
173
+ }
174
+ updateTimer.end(`Updated ${packageJsonFiles.length} package.json files, created ${totalLinksCreated} links`);
175
+ if (totalLinksCreated === 0) {
176
+ logger.info('✅ No dependencies were linked (packages may not be referenced).');
177
+ overallTimer.end('Link command (no links created)');
178
+ return 'No dependencies were linked.';
179
+ }
180
+ // Save backup after all changes
181
+ const saveTimer = PerformanceTimer.start(logger, 'Saving link backup');
182
+ await writeLinkBackup(backup, storage);
183
+ saveTimer.end('Link backup saved');
184
+ logger.info(`Updated ${packageJsonFiles.length} package.json file(s) with file: dependencies`);
185
+ // Run optimized npm install to create symlinks
186
+ logger.info('⏳ Installing dependencies to create symlinks...');
194
187
  try {
195
- await run('pnpm install');
196
- const installTime = Date.now() - installStart;
197
- logger.info(`✅ Links applied successfully (${installTime}ms)`);
188
+ const installResult = await smartNpmInstall({
189
+ skipIfNotNeeded: false,
190
+ preferCi: false,
191
+ verbose: false
192
+ });
193
+ if (installResult.skipped) {
194
+ logger.info(`⚡ Dependencies were up to date (${installResult.method})`);
195
+ } else {
196
+ logger.info(`✅ Links applied successfully using ${installResult.method} (${installResult.duration}ms)`);
197
+ }
198
198
  } catch (error) {
199
- logger.warn(`Failed to run pnpm install: ${error}. You may need to run 'pnpm install' manually.`);
199
+ logger.warn(`Failed to install dependencies: ${error}. You may need to run 'npm install' manually.`);
200
+ }
201
+ const summary = `Successfully linked ${totalLinksCreated} dependency reference(s) across ${packageJsonFiles.length} package.json file(s):\n${[
202
+ ...packagesToLink.entries()
203
+ ].map(([name, path])=>` - ${name}: file:${path}`).join('\n')}`;
204
+ overallTimer.end('Link command execution completed');
205
+ return summary;
206
+ }
207
+ };
208
+ const execute = async (runConfig)=>{
209
+ try {
210
+ return await executeInternal(runConfig);
211
+ } catch (error) {
212
+ const logger = getLogger();
213
+ if (error instanceof ValidationError || error instanceof CommandError) {
214
+ logger.error(`link failed: ${error.message}`);
215
+ if (error.cause) {
216
+ logger.debug(`Caused by: ${error.cause.message}`);
217
+ }
218
+ process.exit(1);
200
219
  }
220
+ // Unexpected errors
221
+ logger.error(`link encountered unexpected error: ${error.message}`);
222
+ process.exit(1);
201
223
  }
202
- const summary = `Successfully linked ${packagesToLink.size} sibling packages:\n${[
203
- ...packagesToLink.entries()
204
- ].map(([name, path])=>` - ${name}: link:${path}`).join('\n')}`;
205
- return summary;
206
224
  };
207
225
 
208
226
  export { execute };
@@ -1 +1 @@
1
- {"version":3,"file":"link.js","sources":["../../src/commands/link.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport path from 'path';\nimport yaml from 'js-yaml';\nimport { getLogger } from '../logging';\nimport { Config } from '../types';\nimport { create as createStorage } from '../util/storage';\nimport { run } from '../util/child';\n\ninterface PackageJson {\n name?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\ninterface PnpmWorkspaceFile {\n packages?: string[];\n overrides?: Record<string, string>;\n}\n\nconst scanDirectoryForPackages = async (rootDir: string, storage: any): Promise<Map<string, string>> => {\n const logger = getLogger();\n const packageMap = new Map<string, string>(); // packageName -> relativePath\n\n const absoluteRootDir = path.resolve(process.cwd(), rootDir);\n logger.verbose(`Scanning directory for packages: ${absoluteRootDir}`);\n\n try {\n // Use single stat call to check if directory exists and is directory\n const rootStat = await storage.exists(absoluteRootDir);\n if (!rootStat) {\n logger.verbose(`Root directory does not exist: ${absoluteRootDir}`);\n return packageMap;\n }\n\n if (!await storage.isDirectory(absoluteRootDir)) {\n logger.verbose(`Root path is not a directory: ${absoluteRootDir}`);\n return packageMap;\n }\n\n // Get all items in the root directory\n const items = await storage.listFiles(absoluteRootDir);\n\n // Process directories in batches to avoid overwhelming the filesystem\n const directories = [];\n for (const item of items) {\n const itemPath = path.join(absoluteRootDir, item);\n try {\n // Quick check if it's a directory without logging\n if (await storage.isDirectory(itemPath)) {\n directories.push({ item, itemPath });\n }\n } catch (error: any) {\n // Skip items that can't be stat'ed (permissions, etc)\n continue;\n }\n }\n\n logger.verbose(`Found ${directories.length} subdirectories to check for packages`);\n\n // Check each directory for package.json\n for (const { item, itemPath } of directories) {\n const packageJsonPath = path.join(itemPath, 'package.json');\n\n try {\n if (await storage.exists(packageJsonPath)) {\n const packageJsonContent = await storage.readFile(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(packageJsonContent) as PackageJson;\n\n if (packageJson.name) {\n const relativePath = path.relative(process.cwd(), itemPath);\n packageMap.set(packageJson.name, relativePath);\n logger.debug(`Found package: ${packageJson.name} at ${relativePath}`);\n }\n }\n } catch (error: any) {\n // Skip directories with unreadable or invalid package.json\n logger.debug(`Skipped ${packageJsonPath}: ${error.message || error}`);\n continue;\n }\n }\n } catch (error) {\n logger.warn(`Failed to read directory ${absoluteRootDir}: ${error}`);\n }\n\n return packageMap;\n};\n\nconst findPackagesByScope = async (dependencies: Record<string, string>, scopeRoots: Record<string, string>, storage: any): Promise<Map<string, string>> => {\n const logger = getLogger();\n const workspacePackages = new Map<string, string>();\n\n logger.silly(`Checking dependencies against scope roots: ${JSON.stringify(scopeRoots)}`);\n\n // First, scan all scope roots to build a comprehensive map of available packages\n const allPackages = new Map<string, string>(); // packageName -> relativePath\n\n for (const [scope, rootDir] of Object.entries(scopeRoots)) {\n logger.verbose(`Scanning scope ${scope} at root directory: ${rootDir}`);\n const scopePackages = await scanDirectoryForPackages(rootDir, storage);\n\n // Add packages from this scope to the overall map\n for (const [packageName, packagePath] of scopePackages) {\n if (packageName.startsWith(scope)) {\n allPackages.set(packageName, packagePath);\n logger.debug(`Registered package: ${packageName} -> ${packagePath}`);\n }\n }\n }\n\n // Now check each dependency against our discovered packages\n for (const [depName, depVersion] of Object.entries(dependencies)) {\n logger.debug(`Processing dependency: ${depName}@${depVersion}`);\n\n if (allPackages.has(depName)) {\n const packagePath = allPackages.get(depName)!;\n workspacePackages.set(depName, packagePath);\n logger.verbose(`Found sibling package: ${depName} at ${packagePath}`);\n }\n }\n\n return workspacePackages;\n};\n\nconst readCurrentWorkspaceFile = async (workspaceFilePath: string, storage: any): Promise<PnpmWorkspaceFile> => {\n if (await storage.exists(workspaceFilePath)) {\n try {\n const content = await storage.readFile(workspaceFilePath, 'utf-8');\n return (yaml.load(content) as PnpmWorkspaceFile) || {};\n } catch (error) {\n throw new Error(`Failed to parse existing workspace file: ${error}`);\n }\n }\n return {};\n};\n\nconst writeWorkspaceFile = async (workspaceFilePath: string, config: PnpmWorkspaceFile, storage: any): Promise<void> => {\n const yamlContent = yaml.dump(config, {\n indent: 2,\n lineWidth: -1,\n noRefs: true,\n sortKeys: false\n });\n await storage.writeFile(workspaceFilePath, yamlContent, 'utf-8');\n};\n\nexport const execute = async (runConfig: Config): Promise<string> => {\n const logger = getLogger();\n const storage = createStorage({ log: logger.info });\n\n logger.info('🔗 Linking workspace packages...');\n\n // Read current package.json\n const packageJsonPath = path.join(process.cwd(), 'package.json');\n if (!await storage.exists(packageJsonPath)) {\n throw new Error('package.json not found in current directory.');\n }\n\n let packageJson: PackageJson;\n try {\n const packageJsonContent = await storage.readFile(packageJsonPath, 'utf-8');\n packageJson = JSON.parse(packageJsonContent);\n } catch (error) {\n throw new Error(`Failed to parse package.json: ${error}`);\n }\n\n // Get configuration\n const scopeRoots = runConfig.link?.scopeRoots || {};\n const workspaceFileName = runConfig.link?.workspaceFile || 'pnpm-workspace.yaml';\n const isDryRun = runConfig.dryRun || runConfig.link?.dryRun || false;\n\n if (Object.keys(scopeRoots).length === 0) {\n logger.info('No scope roots configured. Skipping link management.');\n return 'No scope roots configured. Skipping link management.';\n }\n\n logger.info(`Scanning ${Object.keys(scopeRoots).length} scope root(s): ${Object.keys(scopeRoots).join(', ')}`);\n\n // Collect all dependencies\n const allDependencies = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n ...packageJson.peerDependencies\n };\n\n logger.verbose(`Found ${Object.keys(allDependencies).length} total dependencies`);\n\n // Find matching sibling packages\n const startTime = Date.now();\n const packagesToLink = await findPackagesByScope(allDependencies, scopeRoots, storage);\n const scanTime = Date.now() - startTime;\n logger.verbose(`Directory scan completed in ${scanTime}ms`);\n\n if (packagesToLink.size === 0) {\n logger.info('✅ No matching sibling packages found for linking.');\n return 'No matching sibling packages found for linking.';\n }\n\n logger.info(`Found ${packagesToLink.size} package(s) to link: ${[...packagesToLink.keys()].join(', ')}`);\n\n // Read existing workspace configuration\n const workspaceFilePath = path.join(process.cwd(), workspaceFileName);\n const workspaceConfig = await readCurrentWorkspaceFile(workspaceFilePath, storage);\n\n // Create overrides\n const newOverrides: Record<string, string> = {};\n for (const [packageName, packagePath] of packagesToLink.entries()) {\n newOverrides[packageName] = `link:${packagePath}`;\n }\n\n const updatedOverrides = { ...(workspaceConfig.overrides || {}), ...newOverrides };\n\n const sortedOverrides = Object.keys(updatedOverrides)\n .sort()\n .reduce((obj, key) => {\n obj[key] = updatedOverrides[key];\n return obj;\n }, {} as Record<string, string>);\n\n const updatedConfig: PnpmWorkspaceFile = {\n ...workspaceConfig,\n overrides: sortedOverrides\n };\n\n // Write the updated workspace file\n if (isDryRun) {\n logger.info('DRY RUN: Would update workspace configuration and run pnpm install');\n logger.verbose('DRY RUN: Would write the following workspace configuration:');\n logger.silly(yaml.dump(updatedConfig, { indent: 2 }));\n } else {\n await writeWorkspaceFile(workspaceFilePath, updatedConfig, storage);\n logger.info(`Updated ${workspaceFileName} with linked packages`);\n\n // Rebuild pnpm lock file and node_modules\n logger.info('⏳ Running pnpm install to apply links (this may take a moment)...');\n const installStart = Date.now();\n try {\n await run('pnpm install');\n const installTime = Date.now() - installStart;\n logger.info(`✅ Links applied successfully (${installTime}ms)`);\n } catch (error) {\n logger.warn(`Failed to run pnpm install: ${error}. You may need to run 'pnpm install' manually.`);\n }\n }\n\n const summary = `Successfully linked ${packagesToLink.size} sibling packages:\\n${[...packagesToLink.entries()].map(([name, path]) => ` - ${name}: link:${path}`).join('\\n')}`;\n\n return summary;\n};\n"],"names":["scanDirectoryForPackages","rootDir","storage","logger","getLogger","packageMap","Map","absoluteRootDir","path","resolve","process","cwd","verbose","rootStat","exists","isDirectory","items","listFiles","directories","item","itemPath","join","push","error","length","packageJsonPath","packageJsonContent","readFile","packageJson","JSON","parse","name","relativePath","relative","set","debug","message","warn","findPackagesByScope","dependencies","scopeRoots","workspacePackages","silly","stringify","allPackages","scope","Object","entries","scopePackages","packageName","packagePath","startsWith","depName","depVersion","has","get","readCurrentWorkspaceFile","workspaceFilePath","content","yaml","load","Error","writeWorkspaceFile","config","yamlContent","dump","indent","lineWidth","noRefs","sortKeys","writeFile","execute","runConfig","createStorage","log","info","link","workspaceFileName","workspaceFile","isDryRun","dryRun","keys","allDependencies","devDependencies","peerDependencies","startTime","Date","now","packagesToLink","scanTime","size","workspaceConfig","newOverrides","updatedOverrides","overrides","sortedOverrides","sort","reduce","obj","key","updatedConfig","installStart","run","installTime","summary","map"],"mappings":";;;;;;AAoBA,MAAMA,wBAAAA,GAA2B,OAAOC,OAAAA,EAAiBC,OAAAA,GAAAA;AACrD,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;IACf,MAAMC,UAAAA,GAAa,IAAIC,GAAAA,EAAAA,CAAAA;AAEvB,IAAA,MAAMC,kBAAkBC,IAAAA,CAAKC,OAAO,CAACC,OAAAA,CAAQC,GAAG,EAAA,EAAIV,OAAAA,CAAAA;AACpDE,IAAAA,MAAAA,CAAOS,OAAO,CAAC,CAAC,iCAAiC,EAAEL,eAAAA,CAAAA,CAAiB,CAAA;IAEpE,IAAI;;AAEA,QAAA,MAAMM,QAAAA,GAAW,MAAMX,OAAAA,CAAQY,MAAM,CAACP,eAAAA,CAAAA;AACtC,QAAA,IAAI,CAACM,QAAAA,EAAU;AACXV,YAAAA,MAAAA,CAAOS,OAAO,CAAC,CAAC,+BAA+B,EAAEL,eAAAA,CAAAA,CAAiB,CAAA;YAClE,OAAOF,UAAAA;AACX,QAAA;AAEA,QAAA,IAAI,CAAC,MAAMH,OAAAA,CAAQa,WAAW,CAACR,eAAAA,CAAAA,EAAkB;AAC7CJ,YAAAA,MAAAA,CAAOS,OAAO,CAAC,CAAC,8BAA8B,EAAEL,eAAAA,CAAAA,CAAiB,CAAA;YACjE,OAAOF,UAAAA;AACX,QAAA;;AAGA,QAAA,MAAMW,KAAAA,GAAQ,MAAMd,OAAAA,CAAQe,SAAS,CAACV,eAAAA,CAAAA;;AAGtC,QAAA,MAAMW,cAAc,EAAE;QACtB,KAAK,MAAMC,QAAQH,KAAAA,CAAO;AACtB,YAAA,MAAMI,QAAAA,GAAWZ,IAAAA,CAAKa,IAAI,CAACd,eAAAA,EAAiBY,IAAAA,CAAAA;YAC5C,IAAI;;AAEA,gBAAA,IAAI,MAAMjB,OAAAA,CAAQa,WAAW,CAACK,QAAAA,CAAAA,EAAW;AACrCF,oBAAAA,WAAAA,CAAYI,IAAI,CAAC;AAAEH,wBAAAA,IAAAA;AAAMC,wBAAAA;AAAS,qBAAA,CAAA;AACtC,gBAAA;AACJ,YAAA,CAAA,CAAE,OAAOG,KAAAA,EAAY;AAEjB,gBAAA;AACJ,YAAA;AACJ,QAAA;QAEApB,MAAAA,CAAOS,OAAO,CAAC,CAAC,MAAM,EAAEM,WAAAA,CAAYM,MAAM,CAAC,qCAAqC,CAAC,CAAA;;AAGjF,QAAA,KAAK,MAAM,EAAEL,IAAI,EAAEC,QAAQ,EAAE,IAAIF,WAAAA,CAAa;AAC1C,YAAA,MAAMO,eAAAA,GAAkBjB,IAAAA,CAAKa,IAAI,CAACD,QAAAA,EAAU,cAAA,CAAA;YAE5C,IAAI;AACA,gBAAA,IAAI,MAAMlB,OAAAA,CAAQY,MAAM,CAACW,eAAAA,CAAAA,EAAkB;AACvC,oBAAA,MAAMC,kBAAAA,GAAqB,MAAMxB,OAAAA,CAAQyB,QAAQ,CAACF,eAAAA,EAAiB,OAAA,CAAA;oBACnE,MAAMG,WAAAA,GAAcC,IAAAA,CAAKC,KAAK,CAACJ,kBAAAA,CAAAA;oBAE/B,IAAIE,WAAAA,CAAYG,IAAI,EAAE;AAClB,wBAAA,MAAMC,eAAexB,IAAAA,CAAKyB,QAAQ,CAACvB,OAAAA,CAAQC,GAAG,EAAA,EAAIS,QAAAA,CAAAA;AAClDf,wBAAAA,UAAAA,CAAW6B,GAAG,CAACN,WAAAA,CAAYG,IAAI,EAAEC,YAAAA,CAAAA;wBACjC7B,MAAAA,CAAOgC,KAAK,CAAC,CAAC,eAAe,EAAEP,YAAYG,IAAI,CAAC,IAAI,EAAEC,YAAAA,CAAAA,CAAc,CAAA;AACxE,oBAAA;AACJ,gBAAA;AACJ,YAAA,CAAA,CAAE,OAAOT,KAAAA,EAAY;;gBAEjBpB,MAAAA,CAAOgC,KAAK,CAAC,CAAC,QAAQ,EAAEV,eAAAA,CAAgB,EAAE,EAAEF,KAAAA,CAAMa,OAAO,IAAIb,KAAAA,CAAAA,CAAO,CAAA;AACpE,gBAAA;AACJ,YAAA;AACJ,QAAA;AACJ,IAAA,CAAA,CAAE,OAAOA,KAAAA,EAAO;QACZpB,MAAAA,CAAOkC,IAAI,CAAC,CAAC,yBAAyB,EAAE9B,eAAAA,CAAgB,EAAE,EAAEgB,KAAAA,CAAAA,CAAO,CAAA;AACvE,IAAA;IAEA,OAAOlB,UAAAA;AACX,CAAA;AAEA,MAAMiC,mBAAAA,GAAsB,OAAOC,YAAAA,EAAsCC,UAAAA,EAAoCtC,OAAAA,GAAAA;AACzG,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;AACf,IAAA,MAAMqC,oBAAoB,IAAInC,GAAAA,EAAAA;IAE9BH,MAAAA,CAAOuC,KAAK,CAAC,CAAC,2CAA2C,EAAEb,IAAAA,CAAKc,SAAS,CAACH,UAAAA,CAAAA,CAAAA,CAAa,CAAA;;IAGvF,MAAMI,WAAAA,GAAc,IAAItC,GAAAA,EAAAA,CAAAA;IAExB,KAAK,MAAM,CAACuC,KAAAA,EAAO5C,OAAAA,CAAQ,IAAI6C,MAAAA,CAAOC,OAAO,CAACP,UAAAA,CAAAA,CAAa;QACvDrC,MAAAA,CAAOS,OAAO,CAAC,CAAC,eAAe,EAAEiC,KAAAA,CAAM,oBAAoB,EAAE5C,OAAAA,CAAAA,CAAS,CAAA;QACtE,MAAM+C,aAAAA,GAAgB,MAAMhD,wBAAAA,CAAyBC,OAAAA,EAASC,OAAAA,CAAAA;;AAG9D,QAAA,KAAK,MAAM,CAAC+C,WAAAA,EAAaC,WAAAA,CAAY,IAAIF,aAAAA,CAAe;YACpD,IAAIC,WAAAA,CAAYE,UAAU,CAACN,KAAAA,CAAAA,EAAQ;gBAC/BD,WAAAA,CAAYV,GAAG,CAACe,WAAAA,EAAaC,WAAAA,CAAAA;gBAC7B/C,MAAAA,CAAOgC,KAAK,CAAC,CAAC,oBAAoB,EAAEc,WAAAA,CAAY,IAAI,EAAEC,WAAAA,CAAAA,CAAa,CAAA;AACvE,YAAA;AACJ,QAAA;AACJ,IAAA;;IAGA,KAAK,MAAM,CAACE,OAAAA,EAASC,UAAAA,CAAW,IAAIP,MAAAA,CAAOC,OAAO,CAACR,YAAAA,CAAAA,CAAe;QAC9DpC,MAAAA,CAAOgC,KAAK,CAAC,CAAC,uBAAuB,EAAEiB,OAAAA,CAAQ,CAAC,EAAEC,UAAAA,CAAAA,CAAY,CAAA;QAE9D,IAAIT,WAAAA,CAAYU,GAAG,CAACF,OAAAA,CAAAA,EAAU;YAC1B,MAAMF,WAAAA,GAAcN,WAAAA,CAAYW,GAAG,CAACH,OAAAA,CAAAA;YACpCX,iBAAAA,CAAkBP,GAAG,CAACkB,OAAAA,EAASF,WAAAA,CAAAA;YAC/B/C,MAAAA,CAAOS,OAAO,CAAC,CAAC,uBAAuB,EAAEwC,OAAAA,CAAQ,IAAI,EAAEF,WAAAA,CAAAA,CAAa,CAAA;AACxE,QAAA;AACJ,IAAA;IAEA,OAAOT,iBAAAA;AACX,CAAA;AAEA,MAAMe,wBAAAA,GAA2B,OAAOC,iBAAAA,EAA2BvD,OAAAA,GAAAA;AAC/D,IAAA,IAAI,MAAMA,OAAAA,CAAQY,MAAM,CAAC2C,iBAAAA,CAAAA,EAAoB;QACzC,IAAI;AACA,YAAA,MAAMC,OAAAA,GAAU,MAAMxD,OAAAA,CAAQyB,QAAQ,CAAC8B,iBAAAA,EAAmB,OAAA,CAAA;AAC1D,YAAA,OAAO,IAACE,CAAKC,IAAI,CAACF,YAAkC,EAAC;AACzD,QAAA,CAAA,CAAE,OAAOnC,KAAAA,EAAO;AACZ,YAAA,MAAM,IAAIsC,KAAAA,CAAM,CAAC,yCAAyC,EAAEtC,KAAAA,CAAAA,CAAO,CAAA;AACvE,QAAA;AACJ,IAAA;AACA,IAAA,OAAO,EAAC;AACZ,CAAA;AAEA,MAAMuC,kBAAAA,GAAqB,OAAOL,iBAAAA,EAA2BM,MAAAA,EAA2B7D,OAAAA,GAAAA;AACpF,IAAA,MAAM8D,WAAAA,GAAcL,IAAAA,CAAKM,IAAI,CAACF,MAAAA,EAAQ;QAClCG,MAAAA,EAAQ,CAAA;AACRC,QAAAA,SAAAA,EAAW,EAAC;QACZC,MAAAA,EAAQ,IAAA;QACRC,QAAAA,EAAU;AACd,KAAA,CAAA;AACA,IAAA,MAAMnE,OAAAA,CAAQoE,SAAS,CAACb,iBAAAA,EAAmBO,WAAAA,EAAa,OAAA,CAAA;AAC5D,CAAA;AAEO,MAAMO,UAAU,OAAOC,SAAAA,GAAAA;AAqBPA,IAAAA,IAAAA,eAAAA,EACOA,gBAAAA,EACWA,gBAAAA;AAtBrC,IAAA,MAAMrE,MAAAA,GAASC,SAAAA,EAAAA;AACf,IAAA,MAAMF,UAAUuE,MAAAA,CAAc;AAAEC,QAAAA,GAAAA,EAAKvE,OAAOwE;AAAK,KAAA,CAAA;AAEjDxE,IAAAA,MAAAA,CAAOwE,IAAI,CAAC,kCAAA,CAAA;;AAGZ,IAAA,MAAMlD,kBAAkBjB,IAAAA,CAAKa,IAAI,CAACX,OAAAA,CAAQC,GAAG,EAAA,EAAI,cAAA,CAAA;AACjD,IAAA,IAAI,CAAC,MAAMT,OAAAA,CAAQY,MAAM,CAACW,eAAAA,CAAAA,EAAkB;AACxC,QAAA,MAAM,IAAIoC,KAAAA,CAAM,8CAAA,CAAA;AACpB,IAAA;IAEA,IAAIjC,WAAAA;IACJ,IAAI;AACA,QAAA,MAAMF,kBAAAA,GAAqB,MAAMxB,OAAAA,CAAQyB,QAAQ,CAACF,eAAAA,EAAiB,OAAA,CAAA;QACnEG,WAAAA,GAAcC,IAAAA,CAAKC,KAAK,CAACJ,kBAAAA,CAAAA;AAC7B,IAAA,CAAA,CAAE,OAAOH,KAAAA,EAAO;AACZ,QAAA,MAAM,IAAIsC,KAAAA,CAAM,CAAC,8BAA8B,EAAEtC,KAAAA,CAAAA,CAAO,CAAA;AAC5D,IAAA;;IAGA,MAAMiB,UAAAA,GAAagC,CAAAA,CAAAA,eAAAA,GAAAA,SAAAA,CAAUI,IAAI,cAAdJ,eAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,eAAAA,CAAgBhC,UAAU,KAAI,EAAC;IAClD,MAAMqC,iBAAAA,GAAoBL,EAAAA,gBAAAA,GAAAA,SAAAA,CAAUI,IAAI,MAAA,IAAA,IAAdJ,gBAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,gBAAAA,CAAgBM,aAAa,KAAI,qBAAA;IAC3D,MAAMC,QAAAA,GAAWP,SAAAA,CAAUQ,MAAM,KAAA,CAAIR,gBAAAA,GAAAA,SAAAA,CAAUI,IAAI,MAAA,IAAA,IAAdJ,gBAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,gBAAAA,CAAgBQ,MAAM,CAAA,IAAI,KAAA;AAE/D,IAAA,IAAIlC,OAAOmC,IAAI,CAACzC,UAAAA,CAAAA,CAAYhB,MAAM,KAAK,CAAA,EAAG;AACtCrB,QAAAA,MAAAA,CAAOwE,IAAI,CAAC,sDAAA,CAAA;QACZ,OAAO,sDAAA;AACX,IAAA;AAEAxE,IAAAA,MAAAA,CAAOwE,IAAI,CAAC,CAAC,SAAS,EAAE7B,MAAAA,CAAOmC,IAAI,CAACzC,UAAAA,CAAAA,CAAYhB,MAAM,CAAC,gBAAgB,EAAEsB,MAAAA,CAAOmC,IAAI,CAACzC,UAAAA,CAAAA,CAAYnB,IAAI,CAAC,IAAA,CAAA,CAAA,CAAO,CAAA;;AAG7G,IAAA,MAAM6D,eAAAA,GAAkB;AACpB,QAAA,GAAGtD,YAAYW,YAAY;AAC3B,QAAA,GAAGX,YAAYuD,eAAe;AAC9B,QAAA,GAAGvD,YAAYwD;AACnB,KAAA;AAEAjF,IAAAA,MAAAA,CAAOS,OAAO,CAAC,CAAC,MAAM,EAAEkC,MAAAA,CAAOmC,IAAI,CAACC,eAAAA,CAAAA,CAAiB1D,MAAM,CAAC,mBAAmB,CAAC,CAAA;;IAGhF,MAAM6D,SAAAA,GAAYC,KAAKC,GAAG,EAAA;AAC1B,IAAA,MAAMC,cAAAA,GAAiB,MAAMlD,mBAAAA,CAAoB4C,eAAAA,EAAiB1C,UAAAA,EAAYtC,OAAAA,CAAAA;IAC9E,MAAMuF,QAAAA,GAAWH,IAAAA,CAAKC,GAAG,EAAA,GAAKF,SAAAA;AAC9BlF,IAAAA,MAAAA,CAAOS,OAAO,CAAC,CAAC,4BAA4B,EAAE6E,QAAAA,CAAS,EAAE,CAAC,CAAA;IAE1D,IAAID,cAAAA,CAAeE,IAAI,KAAK,CAAA,EAAG;AAC3BvF,QAAAA,MAAAA,CAAOwE,IAAI,CAAC,mDAAA,CAAA;QACZ,OAAO,iDAAA;AACX,IAAA;IAEAxE,MAAAA,CAAOwE,IAAI,CAAC,CAAC,MAAM,EAAEa,cAAAA,CAAeE,IAAI,CAAC,qBAAqB,EAAE;AAAIF,QAAAA,GAAAA,cAAAA,CAAeP,IAAI;KAAG,CAAC5D,IAAI,CAAC,IAAA,CAAA,CAAA,CAAO,CAAA;;AAGvG,IAAA,MAAMoC,oBAAoBjD,IAAAA,CAAKa,IAAI,CAACX,OAAAA,CAAQC,GAAG,EAAA,EAAIkE,iBAAAA,CAAAA;IACnD,MAAMc,eAAAA,GAAkB,MAAMnC,wBAAAA,CAAyBC,iBAAAA,EAAmBvD,OAAAA,CAAAA;;AAG1E,IAAA,MAAM0F,eAAuC,EAAC;AAC9C,IAAA,KAAK,MAAM,CAAC3C,WAAAA,EAAaC,YAAY,IAAIsC,cAAAA,CAAezC,OAAO,EAAA,CAAI;AAC/D6C,QAAAA,YAAY,CAAC3C,WAAAA,CAAY,GAAG,CAAC,KAAK,EAAEC,WAAAA,CAAAA,CAAa;AACrD,IAAA;AAEA,IAAA,MAAM2C,gBAAAA,GAAmB;AAAE,QAAA,GAAIF,eAAAA,CAAgBG,SAAS,IAAI,EAAE;AAAG,QAAA,GAAGF;AAAa,KAAA;IAEjF,MAAMG,eAAAA,GAAkBjD,MAAAA,CAAOmC,IAAI,CAACY,gBAAAA,CAAAA,CAC/BG,IAAI,EAAA,CACJC,MAAM,CAAC,CAACC,GAAAA,EAAKC,GAAAA,GAAAA;AACVD,QAAAA,GAAG,CAACC,GAAAA,CAAI,GAAGN,gBAAgB,CAACM,GAAAA,CAAI;QAChC,OAAOD,GAAAA;AACX,IAAA,CAAA,EAAG,EAAC,CAAA;AAER,IAAA,MAAME,aAAAA,GAAmC;AACrC,QAAA,GAAGT,eAAe;QAClBG,SAAAA,EAAWC;AACf,KAAA;;AAGA,IAAA,IAAIhB,QAAAA,EAAU;AACV5E,QAAAA,MAAAA,CAAOwE,IAAI,CAAC,oEAAA,CAAA;AACZxE,QAAAA,MAAAA,CAAOS,OAAO,CAAC,6DAAA,CAAA;AACfT,QAAAA,MAAAA,CAAOuC,KAAK,CAACiB,IAAAA,CAAKM,IAAI,CAACmC,aAAAA,EAAe;YAAElC,MAAAA,EAAQ;AAAE,SAAA,CAAA,CAAA;IACtD,CAAA,MAAO;QACH,MAAMJ,kBAAAA,CAAmBL,mBAAmB2C,aAAAA,EAAelG,OAAAA,CAAAA;AAC3DC,QAAAA,MAAAA,CAAOwE,IAAI,CAAC,CAAC,QAAQ,EAAEE,iBAAAA,CAAkB,qBAAqB,CAAC,CAAA;;AAG/D1E,QAAAA,MAAAA,CAAOwE,IAAI,CAAC,mEAAA,CAAA;QACZ,MAAM0B,YAAAA,GAAef,KAAKC,GAAG,EAAA;QAC7B,IAAI;AACA,YAAA,MAAMe,GAAAA,CAAI,cAAA,CAAA;YACV,MAAMC,WAAAA,GAAcjB,IAAAA,CAAKC,GAAG,EAAA,GAAKc,YAAAA;AACjClG,YAAAA,MAAAA,CAAOwE,IAAI,CAAC,CAAC,8BAA8B,EAAE4B,WAAAA,CAAY,GAAG,CAAC,CAAA;AACjE,QAAA,CAAA,CAAE,OAAOhF,KAAAA,EAAO;AACZpB,YAAAA,MAAAA,CAAOkC,IAAI,CAAC,CAAC,4BAA4B,EAAEd,KAAAA,CAAM,8CAA8C,CAAC,CAAA;AACpG,QAAA;AACJ,IAAA;IAEA,MAAMiF,OAAAA,GAAU,CAAC,oBAAoB,EAAEhB,eAAeE,IAAI,CAAC,oBAAoB,EAAE;AAAIF,QAAAA,GAAAA,cAAAA,CAAezC,OAAO;AAAG,KAAA,CAAC0D,GAAG,CAAC,CAAC,CAAC1E,IAAAA,EAAMvB,KAAK,GAAK,CAAC,IAAI,EAAEuB,KAAK,OAAO,EAAEvB,MAAM,CAAA,CAAEa,IAAI,CAAC,IAAA,CAAA,CAAA,CAAO;IAE9K,OAAOmF,OAAAA;AACX;;;;"}
1
+ {"version":3,"file":"link.js","sources":["../../src/commands/link.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport path from 'path';\nimport { ValidationError, CommandError } from '../error/CommandErrors';\nimport { getLogger, getDryRunLogger } from '../logging';\nimport { Config } from '../types';\nimport { create as createStorage } from '../util/storage';\nimport { safeJsonParse, validateLinkBackup, type LinkBackup } from '../util/validation';\nimport {\n PerformanceTimer,\n PackageJson,\n PackageJsonLocation,\n findAllPackageJsonFiles,\n scanDirectoryForPackages\n} from '../util/performance';\nimport { smartNpmInstall } from '../util/npmOptimizations';\n\ninterface ExtendedPackageJson extends PackageJson {\n overrides?: Record<string, string>;\n}\n\n\n\nconst EXCLUDED_DIRECTORIES = [\n 'node_modules',\n 'dist',\n 'build',\n 'coverage',\n '.git',\n '.next',\n '.nuxt',\n 'out',\n 'public',\n 'static',\n 'assets'\n];\n\nconst findPackagesToLink = async (scopeRoots: Record<string, string>, storage: any): Promise<Map<string, string>> => {\n const logger = getLogger();\n const timer = PerformanceTimer.start(logger, 'Finding packages to link');\n const packagesToLink = new Map<string, string>();\n\n logger.silly(`Finding packages to link from scope roots: ${JSON.stringify(scopeRoots)}`);\n\n // Scan all scope roots to build a comprehensive map of packages that can be linked\n const scopeTimer = PerformanceTimer.start(logger, 'Scanning all scope roots for linkable packages');\n const allScopePackages = new Map<string, string>(); // packageName -> relativePath\n\n // Process all scopes in parallel for better performance\n const scopePromises = Object.entries(scopeRoots).map(async ([scope, rootDir]) => {\n logger.verbose(`Scanning scope ${scope} at root directory: ${rootDir}`);\n const scopePackages = await scanDirectoryForPackages(rootDir, storage);\n\n // Add packages from this scope to the overall map\n const scopeResults: Array<[string, string]> = [];\n for (const [packageName, packagePath] of scopePackages) {\n if (packageName.startsWith(scope)) {\n scopeResults.push([packageName, packagePath]);\n logger.debug(`Linkable package: ${packageName} -> ${packagePath}`);\n }\n }\n return scopeResults;\n });\n\n const allScopeResults = await Promise.all(scopePromises);\n\n // Flatten results\n for (const scopeResults of allScopeResults) {\n for (const [packageName, packagePath] of scopeResults) {\n allScopePackages.set(packageName, packagePath);\n }\n }\n\n scopeTimer.end(`Scanned ${Object.keys(scopeRoots).length} scope roots, found ${allScopePackages.size} packages`);\n\n // Now we have all scope packages, we can resolve the ones we want to link\n for (const [packageName, packagePath] of allScopePackages) {\n packagesToLink.set(packageName, packagePath);\n }\n\n timer.end(`Found ${packagesToLink.size} packages to link`);\n return packagesToLink;\n};\n\nconst readLinkBackup = async (storage: any, logger?: any): Promise<LinkBackup> => {\n const backupPath = path.join(process.cwd(), '.kodrdriv-link-backup.json');\n if (await storage.exists(backupPath)) {\n try {\n const content = await storage.readFile(backupPath, 'utf-8');\n return JSON.parse(content) as LinkBackup;\n } catch (error) {\n // Log warning but continue with empty backup instead of throwing\n if (logger) {\n logger.warn(`Failed to parse link backup file: ${error}`);\n }\n return {};\n }\n }\n return {};\n};\n\nconst writeLinkBackup = async (backup: LinkBackup, storage: any): Promise<void> => {\n const backupPath = path.join(process.cwd(), '.kodrdriv-link-backup.json');\n await storage.writeFile(backupPath, JSON.stringify(backup, null, 2), 'utf-8');\n};\n\nconst updatePackageJson = async (\n packageJsonLocation: PackageJsonLocation,\n packagesToLink: Map<string, string>,\n backup: LinkBackup,\n storage: any\n): Promise<number> => {\n const logger = getLogger();\n let linkedCount = 0;\n const { packageJson, path: packageJsonPath, relativePath } = packageJsonLocation;\n\n // Process dependencies, devDependencies, and peerDependencies\n const depTypes: Array<keyof Pick<PackageJson, 'dependencies' | 'devDependencies' | 'peerDependencies'>> = [\n 'dependencies', 'devDependencies', 'peerDependencies'\n ];\n\n for (const depType of depTypes) {\n const dependencies = packageJson[depType];\n if (!dependencies) continue;\n\n for (const [packageName, targetPath] of packagesToLink) {\n if (dependencies[packageName]) {\n // Backup original version before linking\n const backupKey = `${relativePath}:${packageName}`;\n if (!backup[backupKey]) {\n backup[backupKey] = {\n originalVersion: dependencies[packageName],\n dependencyType: depType,\n relativePath\n };\n }\n\n // Update to file: dependency\n const targetAbsolutePath = path.resolve(process.cwd(), targetPath);\n const fileReferencePath = path.relative(path.dirname(packageJsonPath), targetAbsolutePath);\n dependencies[packageName] = `file:${fileReferencePath}`;\n linkedCount++;\n logger.verbose(`Linked ${relativePath}/${depType}.${packageName}: ${backup[backupKey].originalVersion} -> file:${fileReferencePath}`);\n }\n }\n }\n\n // NOTE: Don't write the file here - let the caller handle all modifications\n return linkedCount;\n};\n\nconst executeInternal = async (runConfig: Config): Promise<string> => {\n const isDryRun = runConfig.dryRun || runConfig.link?.dryRun || false;\n const logger = getDryRunLogger(isDryRun);\n const overallTimer = PerformanceTimer.start(logger, 'Link command execution');\n const storage = createStorage({ log: logger.info });\n\n logger.info('🔗 Linking workspace packages...');\n\n // Get configuration\n const configTimer = PerformanceTimer.start(logger, 'Reading configuration');\n const scopeRoots = runConfig.link?.scopeRoots || {};\n configTimer.end('Configuration loaded');\n\n if (Object.keys(scopeRoots).length === 0) {\n logger.info('No scope roots configured. Skipping link management.');\n overallTimer.end('Link command (no scope roots)');\n return 'No scope roots configured. Skipping link management.';\n }\n\n // Find all package.json files in current directory tree\n const packageJsonFiles = await findAllPackageJsonFiles(process.cwd(), storage);\n\n if (packageJsonFiles.length === 0) {\n overallTimer.end('Link command (no package.json files)');\n throw new ValidationError('No package.json files found in current directory or subdirectories.');\n }\n\n logger.info(`Found ${packageJsonFiles.length} package.json file(s) to process`);\n logger.info(`Scanning ${Object.keys(scopeRoots).length} scope root(s): ${Object.keys(scopeRoots).join(', ')}`);\n\n // Check if any package.json files already have file: dependencies (safety check)\n const safetyTimer = PerformanceTimer.start(logger, 'Safety check for existing file: dependencies');\n // checkForFileDependencies(packageJsonFiles); // This function is no longer imported\n safetyTimer.end('Safety check completed');\n\n // Collect all dependencies from all package.json files using optimized function\n // const allDependencies = collectAllDependencies(packageJsonFiles); // This function is no longer imported\n\n // logger.verbose(`Found ${Object.keys(allDependencies).length} total unique dependencies across all package.json files`);\n\n // Find matching sibling packages\n const packagesToLink = await findPackagesToLink(scopeRoots, storage);\n\n if (packagesToLink.size === 0) {\n logger.info('✅ No matching sibling packages found for linking.');\n overallTimer.end('Link command (no packages to link)');\n return 'No matching sibling packages found for linking.';\n }\n\n logger.info(`Found ${packagesToLink.size} package(s) to link: ${[...packagesToLink.keys()].join(', ')}`);\n\n // Read existing backup\n const backupTimer = PerformanceTimer.start(logger, 'Reading link backup');\n const backup = await readLinkBackup(storage, logger);\n backupTimer.end('Link backup loaded');\n\n if (isDryRun) {\n logger.info('Would update package.json files with file: dependencies and run npm install');\n for (const { relativePath } of packageJsonFiles) {\n logger.verbose(`Would process ${relativePath}/package.json`);\n }\n for (const [packageName, packagePath] of packagesToLink.entries()) {\n logger.verbose(`Would link ${packageName} -> file:${packagePath}`);\n }\n overallTimer.end('Link command (dry run)');\n return `DRY RUN: Would link ${packagesToLink.size} packages across ${packageJsonFiles.length} package.json files`;\n } else {\n // Update all package.json files with file: dependencies\n const updateTimer = PerformanceTimer.start(logger, 'Updating package.json files');\n let totalLinksCreated = 0;\n for (const packageJsonLocation of packageJsonFiles) {\n const linksCreated = await updatePackageJson(packageJsonLocation, packagesToLink, backup, storage);\n totalLinksCreated += linksCreated;\n\n // Write the modified package.json file to disk\n if (linksCreated > 0) {\n await storage.writeFile(packageJsonLocation.path, JSON.stringify(packageJsonLocation.packageJson, null, 2) + '\\n', 'utf-8');\n logger.verbose(`Updated ${packageJsonLocation.relativePath}/package.json with ${linksCreated} file: dependencies`);\n }\n }\n updateTimer.end(`Updated ${packageJsonFiles.length} package.json files, created ${totalLinksCreated} links`);\n\n if (totalLinksCreated === 0) {\n logger.info('✅ No dependencies were linked (packages may not be referenced).');\n overallTimer.end('Link command (no links created)');\n return 'No dependencies were linked.';\n }\n\n // Save backup after all changes\n const saveTimer = PerformanceTimer.start(logger, 'Saving link backup');\n await writeLinkBackup(backup, storage);\n saveTimer.end('Link backup saved');\n logger.info(`Updated ${packageJsonFiles.length} package.json file(s) with file: dependencies`);\n\n // Run optimized npm install to create symlinks\n logger.info('⏳ Installing dependencies to create symlinks...');\n try {\n const installResult = await smartNpmInstall({\n skipIfNotNeeded: false, // Always install after linking changes\n preferCi: false, // Use npm install to handle new file: dependencies\n verbose: false\n });\n\n if (installResult.skipped) {\n logger.info(`⚡ Dependencies were up to date (${installResult.method})`);\n } else {\n logger.info(`✅ Links applied successfully using ${installResult.method} (${installResult.duration}ms)`);\n }\n } catch (error) {\n logger.warn(`Failed to install dependencies: ${error}. You may need to run 'npm install' manually.`);\n }\n\n const summary = `Successfully linked ${totalLinksCreated} dependency reference(s) across ${packageJsonFiles.length} package.json file(s):\\n${[...packagesToLink.entries()].map(([name, path]) => ` - ${name}: file:${path}`).join('\\n')}`;\n\n overallTimer.end('Link command execution completed');\n return summary;\n }\n};\n\nexport const execute = async (runConfig: Config): Promise<string> => {\n try {\n return await executeInternal(runConfig);\n } catch (error: any) {\n const logger = getLogger();\n\n if (error instanceof ValidationError || error instanceof CommandError) {\n logger.error(`link failed: ${error.message}`);\n if (error.cause) {\n logger.debug(`Caused by: ${error.cause.message}`);\n }\n process.exit(1);\n }\n\n // Unexpected errors\n logger.error(`link encountered unexpected error: ${error.message}`);\n process.exit(1);\n }\n};\n"],"names":["findPackagesToLink","scopeRoots","storage","logger","getLogger","timer","PerformanceTimer","start","packagesToLink","Map","silly","JSON","stringify","scopeTimer","allScopePackages","scopePromises","Object","entries","map","scope","rootDir","verbose","scopePackages","scanDirectoryForPackages","scopeResults","packageName","packagePath","startsWith","push","debug","allScopeResults","Promise","all","set","end","keys","length","size","readLinkBackup","backupPath","path","join","process","cwd","exists","content","readFile","parse","error","warn","writeLinkBackup","backup","writeFile","updatePackageJson","packageJsonLocation","linkedCount","packageJson","packageJsonPath","relativePath","depTypes","depType","dependencies","targetPath","backupKey","originalVersion","dependencyType","targetAbsolutePath","resolve","fileReferencePath","relative","dirname","executeInternal","runConfig","isDryRun","dryRun","link","getDryRunLogger","overallTimer","createStorage","log","info","configTimer","packageJsonFiles","findAllPackageJsonFiles","ValidationError","safetyTimer","backupTimer","updateTimer","totalLinksCreated","linksCreated","saveTimer","installResult","smartNpmInstall","skipIfNotNeeded","preferCi","skipped","method","duration","summary","name","execute","CommandError","message","cause","exit"],"mappings":";;;;;;;AAoCA,MAAMA,kBAAAA,GAAqB,OAAOC,UAAAA,EAAoCC,OAAAA,GAAAA;AAClE,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;AACf,IAAA,MAAMC,KAAAA,GAAQC,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,0BAAA,CAAA;AAC7C,IAAA,MAAMK,iBAAiB,IAAIC,GAAAA,EAAAA;IAE3BN,MAAAA,CAAOO,KAAK,CAAC,CAAC,2CAA2C,EAAEC,IAAAA,CAAKC,SAAS,CAACX,UAAAA,CAAAA,CAAAA,CAAa,CAAA;;AAGvF,IAAA,MAAMY,UAAAA,GAAaP,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,gDAAA,CAAA;IAClD,MAAMW,gBAAAA,GAAmB,IAAIL,GAAAA,EAAAA,CAAAA;;IAG7B,MAAMM,aAAAA,GAAgBC,MAAAA,CAAOC,OAAO,CAAChB,UAAAA,CAAAA,CAAYiB,GAAG,CAAC,OAAO,CAACC,KAAAA,EAAOC,OAAAA,CAAQ,GAAA;QACxEjB,MAAAA,CAAOkB,OAAO,CAAC,CAAC,eAAe,EAAEF,KAAAA,CAAM,oBAAoB,EAAEC,OAAAA,CAAAA,CAAS,CAAA;QACtE,MAAME,aAAAA,GAAgB,MAAMC,wBAAAA,CAAyBH,OAAAA,EAASlB,OAAAA,CAAAA;;AAG9D,QAAA,MAAMsB,eAAwC,EAAE;AAChD,QAAA,KAAK,MAAM,CAACC,WAAAA,EAAaC,WAAAA,CAAY,IAAIJ,aAAAA,CAAe;YACpD,IAAIG,WAAAA,CAAYE,UAAU,CAACR,KAAAA,CAAAA,EAAQ;AAC/BK,gBAAAA,YAAAA,CAAaI,IAAI,CAAC;AAACH,oBAAAA,WAAAA;AAAaC,oBAAAA;AAAY,iBAAA,CAAA;gBAC5CvB,MAAAA,CAAO0B,KAAK,CAAC,CAAC,kBAAkB,EAAEJ,WAAAA,CAAY,IAAI,EAAEC,WAAAA,CAAAA,CAAa,CAAA;AACrE,YAAA;AACJ,QAAA;QACA,OAAOF,YAAAA;AACX,IAAA,CAAA,CAAA;AAEA,IAAA,MAAMM,eAAAA,GAAkB,MAAMC,OAAAA,CAAQC,GAAG,CAACjB,aAAAA,CAAAA;;IAG1C,KAAK,MAAMS,gBAAgBM,eAAAA,CAAiB;AACxC,QAAA,KAAK,MAAM,CAACL,WAAAA,EAAaC,WAAAA,CAAY,IAAIF,YAAAA,CAAc;YACnDV,gBAAAA,CAAiBmB,GAAG,CAACR,WAAAA,EAAaC,WAAAA,CAAAA;AACtC,QAAA;AACJ,IAAA;AAEAb,IAAAA,UAAAA,CAAWqB,GAAG,CAAC,CAAC,QAAQ,EAAElB,OAAOmB,IAAI,CAAClC,UAAAA,CAAAA,CAAYmC,MAAM,CAAC,oBAAoB,EAAEtB,iBAAiBuB,IAAI,CAAC,SAAS,CAAC,CAAA;;AAG/G,IAAA,KAAK,MAAM,CAACZ,WAAAA,EAAaC,WAAAA,CAAY,IAAIZ,gBAAAA,CAAkB;QACvDN,cAAAA,CAAeyB,GAAG,CAACR,WAAAA,EAAaC,WAAAA,CAAAA;AACpC,IAAA;IAEArB,KAAAA,CAAM6B,GAAG,CAAC,CAAC,MAAM,EAAE1B,cAAAA,CAAe6B,IAAI,CAAC,iBAAiB,CAAC,CAAA;IACzD,OAAO7B,cAAAA;AACX,CAAA;AAEA,MAAM8B,cAAAA,GAAiB,OAAOpC,OAAAA,EAAcC,MAAAA,GAAAA;AACxC,IAAA,MAAMoC,aAAaC,IAAAA,CAAKC,IAAI,CAACC,OAAAA,CAAQC,GAAG,EAAA,EAAI,4BAAA,CAAA;AAC5C,IAAA,IAAI,MAAMzC,OAAAA,CAAQ0C,MAAM,CAACL,UAAAA,CAAAA,EAAa;QAClC,IAAI;AACA,YAAA,MAAMM,OAAAA,GAAU,MAAM3C,OAAAA,CAAQ4C,QAAQ,CAACP,UAAAA,EAAY,OAAA,CAAA;YACnD,OAAO5B,IAAAA,CAAKoC,KAAK,CAACF,OAAAA,CAAAA;AACtB,QAAA,CAAA,CAAE,OAAOG,KAAAA,EAAO;;AAEZ,YAAA,IAAI7C,MAAAA,EAAQ;AACRA,gBAAAA,MAAAA,CAAO8C,IAAI,CAAC,CAAC,kCAAkC,EAAED,KAAAA,CAAAA,CAAO,CAAA;AAC5D,YAAA;AACA,YAAA,OAAO,EAAC;AACZ,QAAA;AACJ,IAAA;AACA,IAAA,OAAO,EAAC;AACZ,CAAA;AAEA,MAAME,eAAAA,GAAkB,OAAOC,MAAAA,EAAoBjD,OAAAA,GAAAA;AAC/C,IAAA,MAAMqC,aAAaC,IAAAA,CAAKC,IAAI,CAACC,OAAAA,CAAQC,GAAG,EAAA,EAAI,4BAAA,CAAA;IAC5C,MAAMzC,OAAAA,CAAQkD,SAAS,CAACb,UAAAA,EAAY5B,KAAKC,SAAS,CAACuC,MAAAA,EAAQ,IAAA,EAAM,CAAA,CAAA,EAAI,OAAA,CAAA;AACzE,CAAA;AAEA,MAAME,iBAAAA,GAAoB,OACtBC,mBAAAA,EACA9C,cAAAA,EACA2C,MAAAA,EACAjD,OAAAA,GAAAA;AAEA,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;AACf,IAAA,IAAImD,WAAAA,GAAc,CAAA;IAClB,MAAM,EAAEC,WAAW,EAAEhB,IAAAA,EAAMiB,eAAe,EAAEC,YAAY,EAAE,GAAGJ,mBAAAA;;AAG7D,IAAA,MAAMK,QAAAA,GAAoG;AACtG,QAAA,cAAA;AAAgB,QAAA,iBAAA;AAAmB,QAAA;AACtC,KAAA;IAED,KAAK,MAAMC,WAAWD,QAAAA,CAAU;QAC5B,MAAME,YAAAA,GAAeL,WAAW,CAACI,OAAAA,CAAQ;AACzC,QAAA,IAAI,CAACC,YAAAA,EAAc;AAEnB,QAAA,KAAK,MAAM,CAACpC,WAAAA,EAAaqC,UAAAA,CAAW,IAAItD,cAAAA,CAAgB;YACpD,IAAIqD,YAAY,CAACpC,WAAAA,CAAY,EAAE;;AAE3B,gBAAA,MAAMsC,SAAAA,GAAY,CAAA,EAAGL,YAAAA,CAAa,CAAC,EAAEjC,WAAAA,CAAAA,CAAa;AAClD,gBAAA,IAAI,CAAC0B,MAAM,CAACY,SAAAA,CAAU,EAAE;oBACpBZ,MAAM,CAACY,UAAU,GAAG;wBAChBC,eAAAA,EAAiBH,YAAY,CAACpC,WAAAA,CAAY;wBAC1CwC,cAAAA,EAAgBL,OAAAA;AAChBF,wBAAAA;AACJ,qBAAA;AACJ,gBAAA;;AAGA,gBAAA,MAAMQ,qBAAqB1B,IAAAA,CAAK2B,OAAO,CAACzB,OAAAA,CAAQC,GAAG,EAAA,EAAImB,UAAAA,CAAAA;AACvD,gBAAA,MAAMM,oBAAoB5B,IAAAA,CAAK6B,QAAQ,CAAC7B,IAAAA,CAAK8B,OAAO,CAACb,eAAAA,CAAAA,EAAkBS,kBAAAA,CAAAA;AACvEL,gBAAAA,YAAY,CAACpC,WAAAA,CAAY,GAAG,CAAC,KAAK,EAAE2C,iBAAAA,CAAAA,CAAmB;AACvDb,gBAAAA,WAAAA,EAAAA;gBACApD,MAAAA,CAAOkB,OAAO,CAAC,CAAC,OAAO,EAAEqC,YAAAA,CAAa,CAAC,EAAEE,OAAAA,CAAQ,CAAC,EAAEnC,YAAY,EAAE,EAAE0B,MAAM,CAACY,SAAAA,CAAU,CAACC,eAAe,CAAC,SAAS,EAAEI,iBAAAA,CAAAA,CAAmB,CAAA;AACxI,YAAA;AACJ,QAAA;AACJ,IAAA;;IAGA,OAAOb,WAAAA;AACX,CAAA;AAEA,MAAMgB,kBAAkB,OAAOC,SAAAA,GAAAA;QACUA,eAAAA,EASlBA,gBAAAA;IATnB,MAAMC,QAAAA,GAAWD,SAAAA,CAAUE,MAAM,KAAA,CAAIF,eAAAA,GAAAA,SAAAA,CAAUG,IAAI,MAAA,IAAA,IAAdH,eAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,eAAAA,CAAgBE,MAAM,CAAA,IAAI,KAAA;AAC/D,IAAA,MAAMvE,SAASyE,eAAAA,CAAgBH,QAAAA,CAAAA;AAC/B,IAAA,MAAMI,YAAAA,GAAevE,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,wBAAA,CAAA;AACpD,IAAA,MAAMD,UAAU4E,MAAAA,CAAc;AAAEC,QAAAA,GAAAA,EAAK5E,OAAO6E;AAAK,KAAA,CAAA;AAEjD7E,IAAAA,MAAAA,CAAO6E,IAAI,CAAC,kCAAA,CAAA;;AAGZ,IAAA,MAAMC,WAAAA,GAAc3E,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,uBAAA,CAAA;IACnD,MAAMF,UAAAA,GAAauE,CAAAA,CAAAA,gBAAAA,GAAAA,SAAAA,CAAUG,IAAI,cAAdH,gBAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,gBAAAA,CAAgBvE,UAAU,KAAI,EAAC;AAClDgF,IAAAA,WAAAA,CAAY/C,GAAG,CAAC,sBAAA,CAAA;AAEhB,IAAA,IAAIlB,OAAOmB,IAAI,CAAClC,UAAAA,CAAAA,CAAYmC,MAAM,KAAK,CAAA,EAAG;AACtCjC,QAAAA,MAAAA,CAAO6E,IAAI,CAAC,sDAAA,CAAA;AACZH,QAAAA,YAAAA,CAAa3C,GAAG,CAAC,+BAAA,CAAA;QACjB,OAAO,sDAAA;AACX,IAAA;;AAGA,IAAA,MAAMgD,gBAAAA,GAAmB,MAAMC,uBAAAA,CAAwBzC,OAAAA,CAAQC,GAAG,EAAA,EAAIzC,OAAAA,CAAAA;IAEtE,IAAIgF,gBAAAA,CAAiB9C,MAAM,KAAK,CAAA,EAAG;AAC/ByC,QAAAA,YAAAA,CAAa3C,GAAG,CAAC,sCAAA,CAAA;AACjB,QAAA,MAAM,IAAIkD,eAAAA,CAAgB,qEAAA,CAAA;AAC9B,IAAA;IAEAjF,MAAAA,CAAO6E,IAAI,CAAC,CAAC,MAAM,EAAEE,gBAAAA,CAAiB9C,MAAM,CAAC,gCAAgC,CAAC,CAAA;AAC9EjC,IAAAA,MAAAA,CAAO6E,IAAI,CAAC,CAAC,SAAS,EAAEhE,MAAAA,CAAOmB,IAAI,CAAClC,UAAAA,CAAAA,CAAYmC,MAAM,CAAC,gBAAgB,EAAEpB,MAAAA,CAAOmB,IAAI,CAAClC,UAAAA,CAAAA,CAAYwC,IAAI,CAAC,IAAA,CAAA,CAAA,CAAO,CAAA;;AAG7G,IAAA,MAAM4C,WAAAA,GAAc/E,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,8CAAA,CAAA;;AAEnDkF,IAAAA,WAAAA,CAAYnD,GAAG,CAAC,wBAAA,CAAA;;;;;IAQhB,MAAM1B,cAAAA,GAAiB,MAAMR,kBAAAA,CAAmBC,UAAAA,EAAYC,OAAAA,CAAAA;IAE5D,IAAIM,cAAAA,CAAe6B,IAAI,KAAK,CAAA,EAAG;AAC3BlC,QAAAA,MAAAA,CAAO6E,IAAI,CAAC,mDAAA,CAAA;AACZH,QAAAA,YAAAA,CAAa3C,GAAG,CAAC,oCAAA,CAAA;QACjB,OAAO,iDAAA;AACX,IAAA;IAEA/B,MAAAA,CAAO6E,IAAI,CAAC,CAAC,MAAM,EAAExE,cAAAA,CAAe6B,IAAI,CAAC,qBAAqB,EAAE;AAAI7B,QAAAA,GAAAA,cAAAA,CAAe2B,IAAI;KAAG,CAACM,IAAI,CAAC,IAAA,CAAA,CAAA,CAAO,CAAA;;AAGvG,IAAA,MAAM6C,WAAAA,GAAchF,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,qBAAA,CAAA;IACnD,MAAMgD,MAAAA,GAAS,MAAMb,cAAAA,CAAepC,OAAAA,EAASC,MAAAA,CAAAA;AAC7CmF,IAAAA,WAAAA,CAAYpD,GAAG,CAAC,oBAAA,CAAA;AAEhB,IAAA,IAAIuC,QAAAA,EAAU;AACVtE,QAAAA,MAAAA,CAAO6E,IAAI,CAAC,6EAAA,CAAA;AACZ,QAAA,KAAK,MAAM,EAAEtB,YAAY,EAAE,IAAIwB,gBAAAA,CAAkB;AAC7C/E,YAAAA,MAAAA,CAAOkB,OAAO,CAAC,CAAC,cAAc,EAAEqC,YAAAA,CAAa,aAAa,CAAC,CAAA;AAC/D,QAAA;AACA,QAAA,KAAK,MAAM,CAACjC,WAAAA,EAAaC,YAAY,IAAIlB,cAAAA,CAAeS,OAAO,EAAA,CAAI;YAC/Dd,MAAAA,CAAOkB,OAAO,CAAC,CAAC,WAAW,EAAEI,WAAAA,CAAY,SAAS,EAAEC,WAAAA,CAAAA,CAAa,CAAA;AACrE,QAAA;AACAmD,QAAAA,YAAAA,CAAa3C,GAAG,CAAC,wBAAA,CAAA;AACjB,QAAA,OAAO,CAAC,oBAAoB,EAAE1B,cAAAA,CAAe6B,IAAI,CAAC,iBAAiB,EAAE6C,gBAAAA,CAAiB9C,MAAM,CAAC,mBAAmB,CAAC;IACrH,CAAA,MAAO;;AAEH,QAAA,MAAMmD,WAAAA,GAAcjF,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,6BAAA,CAAA;AACnD,QAAA,IAAIqF,iBAAAA,GAAoB,CAAA;QACxB,KAAK,MAAMlC,uBAAuB4B,gBAAAA,CAAkB;AAChD,YAAA,MAAMO,YAAAA,GAAe,MAAMpC,iBAAAA,CAAkBC,mBAAAA,EAAqB9C,gBAAgB2C,MAAQjD,CAAAA;YAC1FsF,iBAAAA,IAAqBC,YAAAA;;AAGrB,YAAA,IAAIA,eAAe,CAAA,EAAG;AAClB,gBAAA,MAAMvF,OAAAA,CAAQkD,SAAS,CAACE,mBAAAA,CAAoBd,IAAI,EAAE7B,IAAAA,CAAKC,SAAS,CAAC0C,mBAAAA,CAAoBE,WAAW,EAAE,IAAA,EAAM,KAAK,IAAA,EAAM,OAAA,CAAA;AACnHrD,gBAAAA,MAAAA,CAAOkB,OAAO,CAAC,CAAC,QAAQ,EAAEiC,mBAAAA,CAAoBI,YAAY,CAAC,mBAAmB,EAAE+B,YAAAA,CAAa,mBAAmB,CAAC,CAAA;AACrH,YAAA;AACJ,QAAA;AACAF,QAAAA,WAAAA,CAAYrD,GAAG,CAAC,CAAC,QAAQ,EAAEgD,gBAAAA,CAAiB9C,MAAM,CAAC,6BAA6B,EAAEoD,iBAAAA,CAAkB,MAAM,CAAC,CAAA;AAE3G,QAAA,IAAIA,sBAAsB,CAAA,EAAG;AACzBrF,YAAAA,MAAAA,CAAO6E,IAAI,CAAC,iEAAA,CAAA;AACZH,YAAAA,YAAAA,CAAa3C,GAAG,CAAC,iCAAA,CAAA;YACjB,OAAO,8BAAA;AACX,QAAA;;AAGA,QAAA,MAAMwD,SAAAA,GAAYpF,gBAAAA,CAAiBC,KAAK,CAACJ,MAAAA,EAAQ,oBAAA,CAAA;AACjD,QAAA,MAAM+C,gBAAgBC,MAAAA,EAAQjD,OAAAA,CAAAA;AAC9BwF,QAAAA,SAAAA,CAAUxD,GAAG,CAAC,mBAAA,CAAA;QACd/B,MAAAA,CAAO6E,IAAI,CAAC,CAAC,QAAQ,EAAEE,gBAAAA,CAAiB9C,MAAM,CAAC,6CAA6C,CAAC,CAAA;;AAG7FjC,QAAAA,MAAAA,CAAO6E,IAAI,CAAC,iDAAA,CAAA;QACZ,IAAI;YACA,MAAMW,aAAAA,GAAgB,MAAMC,eAAAA,CAAgB;gBACxCC,eAAAA,EAAiB,KAAA;gBACjBC,QAAAA,EAAU,KAAA;gBACVzE,OAAAA,EAAS;AACb,aAAA,CAAA;YAEA,IAAIsE,aAAAA,CAAcI,OAAO,EAAE;gBACvB5F,MAAAA,CAAO6E,IAAI,CAAC,CAAC,gCAAgC,EAAEW,aAAAA,CAAcK,MAAM,CAAC,CAAC,CAAC,CAAA;YAC1E,CAAA,MAAO;AACH7F,gBAAAA,MAAAA,CAAO6E,IAAI,CAAC,CAAC,mCAAmC,EAAEW,aAAAA,CAAcK,MAAM,CAAC,EAAE,EAAEL,aAAAA,CAAcM,QAAQ,CAAC,GAAG,CAAC,CAAA;AAC1G,YAAA;AACJ,QAAA,CAAA,CAAE,OAAOjD,KAAAA,EAAO;AACZ7C,YAAAA,MAAAA,CAAO8C,IAAI,CAAC,CAAC,gCAAgC,EAAED,KAAAA,CAAM,6CAA6C,CAAC,CAAA;AACvG,QAAA;QAEA,MAAMkD,OAAAA,GAAU,CAAC,oBAAoB,EAAEV,iBAAAA,CAAkB,gCAAgC,EAAEN,gBAAAA,CAAiB9C,MAAM,CAAC,wBAAwB,EAAE;AAAI5B,YAAAA,GAAAA,cAAAA,CAAeS,OAAO;AAAG,SAAA,CAACC,GAAG,CAAC,CAAC,CAACiF,IAAAA,EAAM3D,KAAK,GAAK,CAAC,IAAI,EAAE2D,KAAK,OAAO,EAAE3D,MAAM,CAAA,CAAEC,IAAI,CAAC,IAAA,CAAA,CAAA,CAAO;AAE1OoC,QAAAA,YAAAA,CAAa3C,GAAG,CAAC,kCAAA,CAAA;QACjB,OAAOgE,OAAAA;AACX,IAAA;AACJ,CAAA;AAEO,MAAME,UAAU,OAAO5B,SAAAA,GAAAA;IAC1B,IAAI;AACA,QAAA,OAAO,MAAMD,eAAAA,CAAgBC,SAAAA,CAAAA;AACjC,IAAA,CAAA,CAAE,OAAOxB,KAAAA,EAAY;AACjB,QAAA,MAAM7C,MAAAA,GAASC,SAAAA,EAAAA;QAEf,IAAI4C,KAAAA,YAAiBoC,eAAAA,IAAmBpC,KAAAA,YAAiBqD,YAAAA,EAAc;AACnElG,YAAAA,MAAAA,CAAO6C,KAAK,CAAC,CAAC,aAAa,EAAEA,KAAAA,CAAMsD,OAAO,CAAA,CAAE,CAAA;YAC5C,IAAItD,KAAAA,CAAMuD,KAAK,EAAE;gBACbpG,MAAAA,CAAO0B,KAAK,CAAC,CAAC,WAAW,EAAEmB,KAAAA,CAAMuD,KAAK,CAACD,OAAO,CAAA,CAAE,CAAA;AACpD,YAAA;AACA5D,YAAAA,OAAAA,CAAQ8D,IAAI,CAAC,CAAA,CAAA;AACjB,QAAA;;AAGArG,QAAAA,MAAAA,CAAO6C,KAAK,CAAC,CAAC,mCAAmC,EAAEA,KAAAA,CAAMsD,OAAO,CAAA,CAAE,CAAA;AAClE5D,QAAAA,OAAAA,CAAQ8D,IAAI,CAAC,CAAA,CAAA;AACjB,IAAA;AACJ;;;;"}
@@ -4,6 +4,8 @@ import fs from 'fs/promises';
4
4
  import { getLogger } from '../logging.js';
5
5
  import { create } from '../util/storage.js';
6
6
  import { run } from '../util/child.js';
7
+ import { execute as execute$1 } from './publish.js';
8
+ import { safeJsonParse, validatePackageJson } from '../util/validation.js';
7
9
 
8
10
  // Helper function to format subproject error output
9
11
  const formatSubprojectError = (packageName, error)=>{
@@ -83,7 +85,8 @@ const parsePackageJson = async (packageJsonPath)=>{
83
85
  });
84
86
  try {
85
87
  const content = await storage.readFile(packageJsonPath, 'utf-8');
86
- const packageJson = JSON.parse(content);
88
+ const parsed = safeJsonParse(content, packageJsonPath);
89
+ const packageJson = validatePackageJson(parsed, packageJsonPath);
87
90
  if (!packageJson.name) {
88
91
  throw new Error(`Package at ${packageJsonPath} has no name field`);
89
92
  }
@@ -263,7 +266,7 @@ const execute = async (runConfig)=>{
263
266
  ].filter(Boolean).join(' and ');
264
267
  logger.warn(`Multiple execution options provided (${conflicting} and --publish). Using --publish (ignoring others).`);
265
268
  }
266
- commandToRun = 'pnpm dlx @eldrforge/kodrdriv publish';
269
+ // Will use direct function call instead of npx command
267
270
  actionName = 'publish';
268
271
  } else if (cmd) {
269
272
  if (script) {
@@ -275,8 +278,9 @@ const execute = async (runConfig)=>{
275
278
  commandToRun = script;
276
279
  actionName = 'script';
277
280
  }
278
- if (commandToRun) {
279
- logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Executing ${actionName} "${commandToRun}" in ${buildOrder.length} packages...`);
281
+ if (commandToRun || shouldPublish) {
282
+ const executionDescription = shouldPublish ? 'publish command' : `"${commandToRun}"`;
283
+ logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Executing ${actionName} ${executionDescription} in ${buildOrder.length} packages...`);
280
284
  let successCount = 0;
281
285
  let failedPackage = null;
282
286
  for(let i = 0; i < buildOrder.length; i++){
@@ -287,14 +291,23 @@ const execute = async (runConfig)=>{
287
291
  logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Working directory: ${packageDir}`);
288
292
  try {
289
293
  if (isDryRun) {
290
- logger.info(`DRY RUN: Would execute: ${commandToRun}`);
294
+ if (shouldPublish) {
295
+ logger.info(`DRY RUN: Would execute publish command directly`);
296
+ } else {
297
+ logger.info(`DRY RUN: Would execute: ${commandToRun}`);
298
+ }
291
299
  logger.info(`DRY RUN: In directory: ${packageDir}`);
292
300
  } else {
293
301
  // Change to the package directory and run the command
294
302
  const originalCwd = process.cwd();
295
303
  try {
296
304
  process.chdir(packageDir);
297
- await run(commandToRun); // Non-null assertion since we're inside if (commandToRun)
305
+ if (shouldPublish) {
306
+ // Call publish command directly instead of shelling out to npx
307
+ await execute$1(runConfig);
308
+ } else {
309
+ await run(commandToRun); // Non-null assertion since we're inside if (commandToRun)
310
+ }
298
311
  successCount++;
299
312
  logger.info(`✅ [${i + 1}/${buildOrder.length}] ${packageName} completed successfully`);
300
313
  } finally{