@eldrforge/kodrdriv 0.0.27 → 0.0.28
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/dist/arguments.js +29 -2
- package/dist/arguments.js.map +1 -1
- package/dist/commands/link.js +54 -29
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/publish-tree.js +289 -0
- package/dist/commands/publish-tree.js.map +1 -0
- package/dist/commands/publish.js +64 -14
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/unlink.js +56 -30
- package/dist/commands/unlink.js.map +1 -1
- package/dist/constants.js +4 -2
- package/dist/constants.js.map +1 -1
- package/dist/main.js +29 -15
- package/dist/main.js.map +1 -1
- package/dist/prompt/instructions/review.md +54 -87
- package/dist/types.js +11 -1
- package/dist/types.js.map +1 -1
- package/dist/util/github.js +135 -1
- package/dist/util/github.js.map +1 -1
- package/dist/util/storage.js +3 -2
- package/dist/util/storage.js.map +1 -1
- package/package.json +15 -15
package/dist/commands/link.js
CHANGED
|
@@ -9,30 +9,53 @@ const scanDirectoryForPackages = async (rootDir, storage)=>{
|
|
|
9
9
|
const packageMap = new Map(); // packageName -> relativePath
|
|
10
10
|
const absoluteRootDir = path.resolve(process.cwd(), rootDir);
|
|
11
11
|
logger.verbose(`Scanning directory for packages: ${absoluteRootDir}`);
|
|
12
|
-
if (!await storage.exists(absoluteRootDir) || !await storage.isDirectory(absoluteRootDir)) {
|
|
13
|
-
logger.verbose(`Root directory does not exist or is not a directory: ${absoluteRootDir}`);
|
|
14
|
-
return packageMap;
|
|
15
|
-
}
|
|
16
12
|
try {
|
|
17
|
-
//
|
|
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
|
|
18
24
|
const items = await storage.listFiles(absoluteRootDir);
|
|
25
|
+
// Process directories in batches to avoid overwhelming the filesystem
|
|
26
|
+
const directories = [];
|
|
19
27
|
for (const item of items){
|
|
20
28
|
const itemPath = path.join(absoluteRootDir, item);
|
|
21
|
-
|
|
22
|
-
|
|
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 {
|
|
23
46
|
if (await storage.exists(packageJsonPath)) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
logger.debug(`Found package: ${packageJson.name} at ${relativePath}`);
|
|
31
|
-
}
|
|
32
|
-
} catch (error) {
|
|
33
|
-
logger.debug(`Failed to parse package.json at ${packageJsonPath}: ${error}`);
|
|
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}`);
|
|
34
53
|
}
|
|
35
54
|
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
// Skip directories with unreadable or invalid package.json
|
|
57
|
+
logger.debug(`Skipped ${packageJsonPath}: ${error.message || error}`);
|
|
58
|
+
continue;
|
|
36
59
|
}
|
|
37
60
|
}
|
|
38
61
|
} catch (error) {
|
|
@@ -94,7 +117,7 @@ const execute = async (runConfig)=>{
|
|
|
94
117
|
const storage = create({
|
|
95
118
|
log: logger.info
|
|
96
119
|
});
|
|
97
|
-
logger.
|
|
120
|
+
logger.info('🔗 Linking workspace packages...');
|
|
98
121
|
// Read current package.json
|
|
99
122
|
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
100
123
|
if (!await storage.exists(packageJsonPath)) {
|
|
@@ -107,19 +130,15 @@ const execute = async (runConfig)=>{
|
|
|
107
130
|
} catch (error) {
|
|
108
131
|
throw new Error(`Failed to parse package.json: ${error}`);
|
|
109
132
|
}
|
|
110
|
-
logger.verbose(`Processing package: ${packageJson.name || 'unnamed'}`);
|
|
111
133
|
// Get configuration
|
|
112
134
|
const scopeRoots = ((_runConfig_link = runConfig.link) === null || _runConfig_link === void 0 ? void 0 : _runConfig_link.scopeRoots) || {};
|
|
113
135
|
const workspaceFileName = ((_runConfig_link1 = runConfig.link) === null || _runConfig_link1 === void 0 ? void 0 : _runConfig_link1.workspaceFile) || 'pnpm-workspace.yaml';
|
|
114
136
|
const isDryRun = runConfig.dryRun || ((_runConfig_link2 = runConfig.link) === null || _runConfig_link2 === void 0 ? void 0 : _runConfig_link2.dryRun) || false;
|
|
115
|
-
logger.silly('Extracted scopeRoots:', JSON.stringify(scopeRoots));
|
|
116
|
-
logger.debug('Extracted workspaceFileName:', workspaceFileName);
|
|
117
|
-
logger.debug('Extracted isDryRun:', isDryRun);
|
|
118
137
|
if (Object.keys(scopeRoots).length === 0) {
|
|
119
|
-
logger.
|
|
138
|
+
logger.info('No scope roots configured. Skipping link management.');
|
|
120
139
|
return 'No scope roots configured. Skipping link management.';
|
|
121
140
|
}
|
|
122
|
-
logger.
|
|
141
|
+
logger.info(`Scanning ${Object.keys(scopeRoots).length} scope root(s): ${Object.keys(scopeRoots).join(', ')}`);
|
|
123
142
|
// Collect all dependencies
|
|
124
143
|
const allDependencies = {
|
|
125
144
|
...packageJson.dependencies,
|
|
@@ -128,12 +147,15 @@ const execute = async (runConfig)=>{
|
|
|
128
147
|
};
|
|
129
148
|
logger.verbose(`Found ${Object.keys(allDependencies).length} total dependencies`);
|
|
130
149
|
// Find matching sibling packages
|
|
150
|
+
const startTime = Date.now();
|
|
131
151
|
const packagesToLink = await findPackagesByScope(allDependencies, scopeRoots, storage);
|
|
152
|
+
const scanTime = Date.now() - startTime;
|
|
153
|
+
logger.verbose(`Directory scan completed in ${scanTime}ms`);
|
|
132
154
|
if (packagesToLink.size === 0) {
|
|
133
|
-
logger.
|
|
155
|
+
logger.info('✅ No matching sibling packages found for linking.');
|
|
134
156
|
return 'No matching sibling packages found for linking.';
|
|
135
157
|
}
|
|
136
|
-
logger.
|
|
158
|
+
logger.info(`Found ${packagesToLink.size} package(s) to link: ${[
|
|
137
159
|
...packagesToLink.keys()
|
|
138
160
|
].join(', ')}`);
|
|
139
161
|
// Read existing workspace configuration
|
|
@@ -158,18 +180,21 @@ const execute = async (runConfig)=>{
|
|
|
158
180
|
};
|
|
159
181
|
// Write the updated workspace file
|
|
160
182
|
if (isDryRun) {
|
|
183
|
+
logger.info('DRY RUN: Would update workspace configuration and run pnpm install');
|
|
161
184
|
logger.verbose('DRY RUN: Would write the following workspace configuration:');
|
|
162
185
|
logger.silly(yaml.dump(updatedConfig, {
|
|
163
186
|
indent: 2
|
|
164
187
|
}));
|
|
165
188
|
} else {
|
|
166
189
|
await writeWorkspaceFile(workspaceFilePath, updatedConfig, storage);
|
|
167
|
-
logger.
|
|
190
|
+
logger.info(`Updated ${workspaceFileName} with linked packages`);
|
|
168
191
|
// Rebuild pnpm lock file and node_modules
|
|
169
|
-
logger.
|
|
192
|
+
logger.info('⏳ Running pnpm install to apply links (this may take a moment)...');
|
|
193
|
+
const installStart = Date.now();
|
|
170
194
|
try {
|
|
171
195
|
await run('pnpm install');
|
|
172
|
-
|
|
196
|
+
const installTime = Date.now() - installStart;
|
|
197
|
+
logger.info(`✅ Links applied successfully (${installTime}ms)`);
|
|
173
198
|
} catch (error) {
|
|
174
199
|
logger.warn(`Failed to run pnpm install: ${error}. You may need to run 'pnpm install' manually.`);
|
|
175
200
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sources":["../../src/commands/link.ts"],"sourcesContent":["import 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 if (!await storage.exists(absoluteRootDir) || !await storage.isDirectory(absoluteRootDir)) {\n logger.verbose(`Root directory does not exist or is not a directory: ${absoluteRootDir}`);\n return packageMap;\n }\n\n try {\n // Get all subdirectories in the root directory\n const items = await storage.listFiles(absoluteRootDir);\n\n for (const item of items) {\n const itemPath = path.join(absoluteRootDir, item);\n\n if (await storage.isDirectory(itemPath)) {\n const packageJsonPath = path.join(itemPath, 'package.json');\n\n if (await storage.exists(packageJsonPath)) {\n try {\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 } catch (error) {\n logger.debug(`Failed to parse package.json at ${packageJsonPath}: ${error}`);\n }\n }\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.verbose('Starting pnpm workspace link management using overrides...');\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 logger.verbose(`Processing package: ${packageJson.name || 'unnamed'}`);\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 logger.silly('Extracted scopeRoots:', JSON.stringify(scopeRoots));\n logger.debug('Extracted workspaceFileName:', workspaceFileName);\n logger.debug('Extracted isDryRun:', isDryRun);\n\n if (Object.keys(scopeRoots).length === 0) {\n logger.verbose('No scope roots configured. Skipping link management.');\n return 'No scope roots configured. Skipping link management.';\n }\n\n logger.silly(`Configured scope roots: ${JSON.stringify(scopeRoots)}`);\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 packagesToLink = await findPackagesByScope(allDependencies, scopeRoots, storage);\n\n if (packagesToLink.size === 0) {\n logger.verbose('No matching sibling packages found for linking.');\n return 'No matching sibling packages found for linking.';\n }\n\n logger.verbose(`Found ${packagesToLink.size} packages 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\n // Write the updated workspace file\n if (isDryRun) {\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.verbose(`Updated ${workspaceFileName} with ${packagesToLink.size} linked packages in overrides.`);\n\n // Rebuild pnpm lock file and node_modules\n logger.verbose('Running pnpm install to apply links...');\n try {\n await run('pnpm install');\n logger.verbose('Successfully applied links.');\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};"],"names":["scanDirectoryForPackages","rootDir","storage","logger","getLogger","packageMap","Map","absoluteRootDir","path","resolve","process","cwd","verbose","exists","isDirectory","items","listFiles","item","itemPath","join","packageJsonPath","packageJsonContent","readFile","packageJson","JSON","parse","name","relativePath","relative","set","debug","error","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","length","allDependencies","devDependencies","peerDependencies","packagesToLink","size","workspaceConfig","newOverrides","updatedOverrides","overrides","sortedOverrides","sort","reduce","obj","key","updatedConfig","run","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 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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"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs/promises';
|
|
4
|
+
import { getLogger } from '../logging.js';
|
|
5
|
+
import { create } from '../util/storage.js';
|
|
6
|
+
import { run } from '../util/child.js';
|
|
7
|
+
|
|
8
|
+
const matchesPattern = (filePath, pattern)=>{
|
|
9
|
+
// Convert simple glob patterns to regex
|
|
10
|
+
const regexPattern = pattern.replace(/\*\*/g, '.*') // ** matches any path segments
|
|
11
|
+
.replace(/\*/g, '[^/]*') // * matches any characters except path separator
|
|
12
|
+
.replace(/\?/g, '.') // ? matches any single character
|
|
13
|
+
.replace(/\./g, '\\.'); // Escape literal dots
|
|
14
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
15
|
+
return regex.test(filePath) || regex.test(path.basename(filePath));
|
|
16
|
+
};
|
|
17
|
+
const shouldExclude = (packageJsonPath, excludedPatterns)=>{
|
|
18
|
+
if (!excludedPatterns || excludedPatterns.length === 0) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// Check both the full path and relative path patterns
|
|
22
|
+
const relativePath = path.relative(process.cwd(), packageJsonPath);
|
|
23
|
+
return excludedPatterns.some((pattern)=>matchesPattern(packageJsonPath, pattern) || matchesPattern(relativePath, pattern) || matchesPattern(path.dirname(packageJsonPath), pattern) || matchesPattern(path.dirname(relativePath), pattern));
|
|
24
|
+
};
|
|
25
|
+
const scanForPackageJsonFiles = async (directory, excludedPatterns = [])=>{
|
|
26
|
+
const logger = getLogger();
|
|
27
|
+
const packageJsonPaths = [];
|
|
28
|
+
try {
|
|
29
|
+
const entries = await fs.readdir(directory, {
|
|
30
|
+
withFileTypes: true
|
|
31
|
+
});
|
|
32
|
+
for (const entry of entries){
|
|
33
|
+
if (entry.isDirectory()) {
|
|
34
|
+
const subDirPath = path.join(directory, entry.name);
|
|
35
|
+
const packageJsonPath = path.join(subDirPath, 'package.json');
|
|
36
|
+
try {
|
|
37
|
+
await fs.access(packageJsonPath);
|
|
38
|
+
// Check if this package should be excluded
|
|
39
|
+
if (shouldExclude(packageJsonPath, excludedPatterns)) {
|
|
40
|
+
logger.verbose(`Excluding package.json at: ${packageJsonPath} (matches exclusion pattern)`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
packageJsonPaths.push(packageJsonPath);
|
|
44
|
+
logger.verbose(`Found package.json at: ${packageJsonPath}`);
|
|
45
|
+
} catch {
|
|
46
|
+
// No package.json in this directory, continue
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
logger.error(`Failed to scan directory ${directory}: ${error}`);
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
return packageJsonPaths;
|
|
55
|
+
};
|
|
56
|
+
const parsePackageJson = async (packageJsonPath)=>{
|
|
57
|
+
const logger = getLogger();
|
|
58
|
+
const storage = create({
|
|
59
|
+
log: logger.info
|
|
60
|
+
});
|
|
61
|
+
try {
|
|
62
|
+
const content = await storage.readFile(packageJsonPath, 'utf-8');
|
|
63
|
+
const packageJson = JSON.parse(content);
|
|
64
|
+
if (!packageJson.name) {
|
|
65
|
+
throw new Error(`Package at ${packageJsonPath} has no name field`);
|
|
66
|
+
}
|
|
67
|
+
const dependencies = new Set();
|
|
68
|
+
// Collect all types of dependencies
|
|
69
|
+
const depTypes = [
|
|
70
|
+
'dependencies',
|
|
71
|
+
'devDependencies',
|
|
72
|
+
'peerDependencies',
|
|
73
|
+
'optionalDependencies'
|
|
74
|
+
];
|
|
75
|
+
for (const depType of depTypes){
|
|
76
|
+
if (packageJson[depType]) {
|
|
77
|
+
Object.keys(packageJson[depType]).forEach((dep)=>dependencies.add(dep));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
name: packageJson.name,
|
|
82
|
+
version: packageJson.version || '0.0.0',
|
|
83
|
+
path: path.dirname(packageJsonPath),
|
|
84
|
+
dependencies,
|
|
85
|
+
localDependencies: new Set() // Will be populated later
|
|
86
|
+
};
|
|
87
|
+
} catch (error) {
|
|
88
|
+
logger.error(`Failed to parse package.json at ${packageJsonPath}: ${error}`);
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const buildDependencyGraph = async (packageJsonPaths)=>{
|
|
93
|
+
const logger = getLogger();
|
|
94
|
+
const packages = new Map();
|
|
95
|
+
const edges = new Map();
|
|
96
|
+
// First pass: parse all package.json files
|
|
97
|
+
for (const packageJsonPath of packageJsonPaths){
|
|
98
|
+
const packageInfo = await parsePackageJson(packageJsonPath);
|
|
99
|
+
packages.set(packageInfo.name, packageInfo);
|
|
100
|
+
logger.verbose(`Parsed package: ${packageInfo.name} at ${packageInfo.path}`);
|
|
101
|
+
}
|
|
102
|
+
// Second pass: identify local dependencies and build edges
|
|
103
|
+
for (const [packageName, packageInfo] of packages){
|
|
104
|
+
const localDeps = new Set();
|
|
105
|
+
const edges_set = new Set();
|
|
106
|
+
for (const dep of packageInfo.dependencies){
|
|
107
|
+
if (packages.has(dep)) {
|
|
108
|
+
localDeps.add(dep);
|
|
109
|
+
edges_set.add(dep);
|
|
110
|
+
logger.verbose(`${packageName} depends on local package: ${dep}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
packageInfo.localDependencies = localDeps;
|
|
114
|
+
edges.set(packageName, edges_set);
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
packages,
|
|
118
|
+
edges
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const topologicalSort = (graph)=>{
|
|
122
|
+
const logger = getLogger();
|
|
123
|
+
const { packages, edges } = graph;
|
|
124
|
+
const visited = new Set();
|
|
125
|
+
const visiting = new Set();
|
|
126
|
+
const result = [];
|
|
127
|
+
const visit = (packageName)=>{
|
|
128
|
+
if (visited.has(packageName)) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (visiting.has(packageName)) {
|
|
132
|
+
throw new Error(`Circular dependency detected involving package: ${packageName}`);
|
|
133
|
+
}
|
|
134
|
+
visiting.add(packageName);
|
|
135
|
+
// Visit all dependencies first
|
|
136
|
+
const deps = edges.get(packageName) || new Set();
|
|
137
|
+
for (const dep of deps){
|
|
138
|
+
visit(dep);
|
|
139
|
+
}
|
|
140
|
+
visiting.delete(packageName);
|
|
141
|
+
visited.add(packageName);
|
|
142
|
+
result.push(packageName);
|
|
143
|
+
};
|
|
144
|
+
// Visit all packages
|
|
145
|
+
for (const packageName of packages.keys()){
|
|
146
|
+
if (!visited.has(packageName)) {
|
|
147
|
+
visit(packageName);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
logger.verbose(`Topological sort completed. Build order determined for ${result.length} packages.`);
|
|
151
|
+
return result;
|
|
152
|
+
};
|
|
153
|
+
const execute = async (runConfig)=>{
|
|
154
|
+
var _runConfig_publishTree;
|
|
155
|
+
const logger = getLogger();
|
|
156
|
+
const isDryRun = runConfig.dryRun || false;
|
|
157
|
+
// Determine the target directory - either specified or current working directory
|
|
158
|
+
const targetDirectory = ((_runConfig_publishTree = runConfig.publishTree) === null || _runConfig_publishTree === void 0 ? void 0 : _runConfig_publishTree.directory) || process.cwd();
|
|
159
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Analyzing workspace at: ${targetDirectory}`);
|
|
160
|
+
try {
|
|
161
|
+
var _runConfig_publishTree1, _runConfig_publishTree2, _runConfig_publishTree3, _runConfig_publishTree4;
|
|
162
|
+
// Get exclusion patterns from config, fallback to empty array
|
|
163
|
+
const excludedPatterns = ((_runConfig_publishTree1 = runConfig.publishTree) === null || _runConfig_publishTree1 === void 0 ? void 0 : _runConfig_publishTree1.excludedPatterns) || [];
|
|
164
|
+
if (excludedPatterns.length > 0) {
|
|
165
|
+
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Using exclusion patterns: ${excludedPatterns.join(', ')}`);
|
|
166
|
+
}
|
|
167
|
+
// Scan for package.json files
|
|
168
|
+
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Scanning for package.json files...`);
|
|
169
|
+
const packageJsonPaths = await scanForPackageJsonFiles(targetDirectory, excludedPatterns);
|
|
170
|
+
if (packageJsonPaths.length === 0) {
|
|
171
|
+
const message = `No package.json files found in subdirectories of ${targetDirectory}`;
|
|
172
|
+
logger.warn(message);
|
|
173
|
+
return message;
|
|
174
|
+
}
|
|
175
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Found ${packageJsonPaths.length} package.json files`);
|
|
176
|
+
// Build dependency graph
|
|
177
|
+
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Building dependency graph...`);
|
|
178
|
+
const dependencyGraph = await buildDependencyGraph(packageJsonPaths);
|
|
179
|
+
// Perform topological sort to determine build order
|
|
180
|
+
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Determining build order...`);
|
|
181
|
+
let buildOrder = topologicalSort(dependencyGraph);
|
|
182
|
+
// Handle start-from functionality if specified
|
|
183
|
+
const startFrom = (_runConfig_publishTree2 = runConfig.publishTree) === null || _runConfig_publishTree2 === void 0 ? void 0 : _runConfig_publishTree2.startFrom;
|
|
184
|
+
if (startFrom) {
|
|
185
|
+
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Looking for start package: ${startFrom}`);
|
|
186
|
+
// Find the package that matches the startFrom directory name
|
|
187
|
+
const startIndex = buildOrder.findIndex((packageName)=>{
|
|
188
|
+
const packageInfo = dependencyGraph.packages.get(packageName);
|
|
189
|
+
const dirName = path.basename(packageInfo.path);
|
|
190
|
+
return dirName === startFrom || packageName === startFrom;
|
|
191
|
+
});
|
|
192
|
+
if (startIndex === -1) {
|
|
193
|
+
const availablePackages = buildOrder.map((name)=>{
|
|
194
|
+
const packageInfo = dependencyGraph.packages.get(name);
|
|
195
|
+
return `${path.basename(packageInfo.path)} (${name})`;
|
|
196
|
+
}).join(', ');
|
|
197
|
+
throw new Error(`Package directory '${startFrom}' not found. Available packages: ${availablePackages}`);
|
|
198
|
+
}
|
|
199
|
+
const skippedCount = startIndex;
|
|
200
|
+
buildOrder = buildOrder.slice(startIndex);
|
|
201
|
+
if (skippedCount > 0) {
|
|
202
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Resuming from '${startFrom}' - skipping ${skippedCount} package${skippedCount === 1 ? '' : 's'}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Display results
|
|
206
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Build order determined:`);
|
|
207
|
+
let output = `\nBuild Order for ${buildOrder.length} packages${startFrom ? ` (starting from ${startFrom})` : ''}:\n`;
|
|
208
|
+
output += '==========================================\n\n';
|
|
209
|
+
buildOrder.forEach((packageName, index)=>{
|
|
210
|
+
const packageInfo = dependencyGraph.packages.get(packageName);
|
|
211
|
+
const localDeps = Array.from(packageInfo.localDependencies);
|
|
212
|
+
output += `${index + 1}. ${packageName} (${packageInfo.version})\n`;
|
|
213
|
+
output += ` Path: ${packageInfo.path}\n`;
|
|
214
|
+
if (localDeps.length > 0) {
|
|
215
|
+
output += ` Local Dependencies: ${localDeps.join(', ')}\n`;
|
|
216
|
+
} else {
|
|
217
|
+
output += ` Local Dependencies: none\n`;
|
|
218
|
+
}
|
|
219
|
+
output += '\n';
|
|
220
|
+
// Log each step
|
|
221
|
+
if (localDeps.length > 0) {
|
|
222
|
+
logger.info(`${index + 1}. ${packageName} (depends on: ${localDeps.join(', ')})`);
|
|
223
|
+
} else {
|
|
224
|
+
logger.info(`${index + 1}. ${packageName} (no local dependencies)`);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
// Execute script or publish if provided
|
|
228
|
+
const script = (_runConfig_publishTree3 = runConfig.publishTree) === null || _runConfig_publishTree3 === void 0 ? void 0 : _runConfig_publishTree3.script;
|
|
229
|
+
const shouldPublish = (_runConfig_publishTree4 = runConfig.publishTree) === null || _runConfig_publishTree4 === void 0 ? void 0 : _runConfig_publishTree4.publish;
|
|
230
|
+
// Handle conflicts between --script and --publish
|
|
231
|
+
if (script && shouldPublish) {
|
|
232
|
+
logger.warn('Both --script and --publish provided. Using --publish (ignoring --script).');
|
|
233
|
+
}
|
|
234
|
+
const commandToRun = shouldPublish ? 'kodrdriv publish' : script;
|
|
235
|
+
const actionName = shouldPublish ? 'publish' : 'script';
|
|
236
|
+
if (commandToRun) {
|
|
237
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Executing ${actionName} "${commandToRun}" in ${buildOrder.length} packages...`);
|
|
238
|
+
let successCount = 0;
|
|
239
|
+
let failedPackage = null;
|
|
240
|
+
for(let i = 0; i < buildOrder.length; i++){
|
|
241
|
+
const packageName = buildOrder[i];
|
|
242
|
+
const packageInfo = dependencyGraph.packages.get(packageName);
|
|
243
|
+
const packageDir = packageInfo.path;
|
|
244
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}[${i + 1}/${buildOrder.length}] Running "${commandToRun}" in ${packageName}...`);
|
|
245
|
+
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Working directory: ${packageDir}`);
|
|
246
|
+
try {
|
|
247
|
+
if (isDryRun) {
|
|
248
|
+
logger.info(`DRY RUN: Would execute: ${commandToRun}`);
|
|
249
|
+
logger.info(`DRY RUN: In directory: ${packageDir}`);
|
|
250
|
+
} else {
|
|
251
|
+
// Change to the package directory and run the command
|
|
252
|
+
const originalCwd = process.cwd();
|
|
253
|
+
try {
|
|
254
|
+
process.chdir(packageDir);
|
|
255
|
+
await run(commandToRun); // Non-null assertion since we're inside if (commandToRun)
|
|
256
|
+
successCount++;
|
|
257
|
+
logger.info(`✅ [${i + 1}/${buildOrder.length}] ${packageName} completed successfully`);
|
|
258
|
+
} finally{
|
|
259
|
+
process.chdir(originalCwd);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
} catch (error) {
|
|
263
|
+
failedPackage = packageName;
|
|
264
|
+
const errorMsg = `❌ Script failed in package ${packageName}: ${error.message}`;
|
|
265
|
+
logger.error(errorMsg);
|
|
266
|
+
if (!isDryRun) {
|
|
267
|
+
logger.error(`Failed after ${successCount} successful packages.`);
|
|
268
|
+
logger.error(`To resume from this package, use: --start-from ${path.basename(packageDir)}`);
|
|
269
|
+
throw new Error(errorMsg);
|
|
270
|
+
}
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (!failedPackage) {
|
|
275
|
+
const summary = `${isDryRun ? 'DRY RUN: ' : ''}All ${buildOrder.length} packages completed successfully! 🎉`;
|
|
276
|
+
logger.info(summary);
|
|
277
|
+
return output + `\n${summary}\n`;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return output;
|
|
281
|
+
} catch (error) {
|
|
282
|
+
const errorMessage = `Failed to analyze workspace: ${error.message}`;
|
|
283
|
+
logger.error(errorMessage);
|
|
284
|
+
throw new Error(errorMessage);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
export { execute };
|
|
289
|
+
//# sourceMappingURL=publish-tree.js.map
|