@eldrforge/kodrdriv 0.0.33 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -69
- package/dist/application.js +146 -0
- package/dist/application.js.map +1 -0
- package/dist/arguments.js +22 -21
- package/dist/arguments.js.map +1 -1
- package/dist/commands/audio-commit.js +43 -21
- package/dist/commands/audio-commit.js.map +1 -1
- package/dist/commands/audio-review.js +46 -38
- package/dist/commands/audio-review.js.map +1 -1
- package/dist/commands/clean.js +28 -12
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/commit.js +132 -39
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/link.js +177 -159
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/publish-tree.js +19 -6
- package/dist/commands/publish-tree.js.map +1 -1
- package/dist/commands/publish.js +152 -82
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/release.js +21 -16
- package/dist/commands/release.js.map +1 -1
- package/dist/commands/review.js +286 -60
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/select-audio.js +25 -8
- package/dist/commands/select-audio.js.map +1 -1
- package/dist/commands/unlink.js +349 -159
- package/dist/commands/unlink.js.map +1 -1
- package/dist/constants.js +14 -5
- package/dist/constants.js.map +1 -1
- package/dist/content/diff.js +7 -5
- package/dist/content/diff.js.map +1 -1
- package/dist/content/log.js +4 -1
- package/dist/content/log.js.map +1 -1
- package/dist/error/CancellationError.js +9 -0
- package/dist/error/CancellationError.js.map +1 -0
- package/dist/error/CommandErrors.js +120 -0
- package/dist/error/CommandErrors.js.map +1 -0
- package/dist/logging.js +55 -12
- package/dist/logging.js.map +1 -1
- package/dist/main.js +6 -131
- package/dist/main.js.map +1 -1
- package/dist/prompt/commit.js +4 -0
- package/dist/prompt/commit.js.map +1 -1
- package/dist/prompt/instructions/commit.md +33 -24
- package/dist/prompt/instructions/release.md +39 -5
- package/dist/prompt/release.js +41 -1
- package/dist/prompt/release.js.map +1 -1
- package/dist/types.js +9 -2
- package/dist/types.js.map +1 -1
- package/dist/util/github.js +71 -4
- package/dist/util/github.js.map +1 -1
- package/dist/util/npmOptimizations.js +174 -0
- package/dist/util/npmOptimizations.js.map +1 -0
- package/dist/util/openai.js +4 -2
- package/dist/util/openai.js.map +1 -1
- package/dist/util/performance.js +202 -0
- package/dist/util/performance.js.map +1 -0
- package/dist/util/safety.js +166 -0
- package/dist/util/safety.js.map +1 -0
- package/dist/util/storage.js +10 -0
- package/dist/util/storage.js.map +1 -1
- package/dist/util/validation.js +81 -0
- package/dist/util/validation.js.map +1 -0
- package/package.json +19 -18
- package/packages/components/package.json +4 -0
- package/packages/tools/package.json +4 -0
- package/packages/utils/package.json +4 -0
- package/scripts/pre-commit-hook.sh +52 -0
- package/test-project/package.json +1 -0
package/dist/commands/link.js
CHANGED
|
@@ -1,208 +1,226 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import
|
|
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 {
|
|
5
|
+
import { PerformanceTimer, findAllPackageJsonFiles, scanDirectoryForPackages } from '../util/performance.js';
|
|
6
|
+
import { smartNpmInstall } from '../util/npmOptimizations.js';
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const findPackagesToLink = async (scopeRoots, storage)=>{
|
|
8
9
|
const logger = getLogger();
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
logger.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
79
|
-
|
|
24
|
+
scopeResults.push([
|
|
25
|
+
packageName,
|
|
26
|
+
packagePath
|
|
27
|
+
]);
|
|
28
|
+
logger.debug(`Linkable package: ${packageName} -> ${packagePath}`);
|
|
80
29
|
}
|
|
81
30
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
|
95
|
-
|
|
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(
|
|
98
|
-
return
|
|
52
|
+
const content = await storage.readFile(backupPath, 'utf-8');
|
|
53
|
+
return JSON.parse(content);
|
|
99
54
|
} catch (error) {
|
|
100
|
-
|
|
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
|
|
106
|
-
const
|
|
107
|
-
|
|
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
|
|
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
|
|
135
|
-
const
|
|
136
|
-
|
|
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
|
-
//
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
|
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
|
|
162
|
-
const
|
|
163
|
-
const
|
|
164
|
-
|
|
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('
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
|
196
|
-
|
|
197
|
-
|
|
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
|
|
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":"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"}
|
|
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":"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"}
|
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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{
|