@bobfrankston/npmglobalize 1.0.78 → 1.0.79
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/cli.js +69 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/lib.d.ts +41 -0
- package/lib.js +229 -2
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* npmglobalize CLI - Transform file: dependencies to npm versions for publishing
|
|
4
4
|
*/
|
|
5
|
-
import { globalize, readConfig } from './lib.js';
|
|
5
|
+
import { globalize, globalizeWorkspace, readConfig, readPackageJson, writePackageJson } from './lib.js';
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
@@ -78,6 +78,11 @@ Git/npm Visibility:
|
|
|
78
78
|
--npm private Mark npm package private (skip publish) (default)
|
|
79
79
|
--npm public Publish to npm
|
|
80
80
|
|
|
81
|
+
Workspace Options:
|
|
82
|
+
-w, --workspace <pkg> Filter to specific package (repeatable)
|
|
83
|
+
--no-workspace Disable workspace mode at a workspace root
|
|
84
|
+
--continue-on-error Continue if a package fails in workspace mode
|
|
85
|
+
|
|
81
86
|
Other Options:
|
|
82
87
|
--init Initialize git/npm if needed
|
|
83
88
|
--force Continue despite git errors
|
|
@@ -88,6 +93,7 @@ Other Options:
|
|
|
88
93
|
--asis Skip ignore file checks (or set "asis": true in .globalize.json5)
|
|
89
94
|
--rebase Automatically rebase if local is behind remote
|
|
90
95
|
--show Show package.json dependency changes
|
|
96
|
+
--package, -pkg Update package.json scripts to use npmglobalize
|
|
91
97
|
-h, --help Show this help
|
|
92
98
|
-v, --version Show version number
|
|
93
99
|
|
|
@@ -107,6 +113,13 @@ Examples:
|
|
|
107
113
|
npmglobalize --cleanup Restore original dependencies
|
|
108
114
|
npmglobalize --init Initialize new git repo + release
|
|
109
115
|
npmglobalize --dry-run Preview what would happen
|
|
116
|
+
npmglobalize --package Migrate scripts to use npmglobalize
|
|
117
|
+
|
|
118
|
+
Workspace (auto-detected when run from a workspace root):
|
|
119
|
+
npmglobalize Publish all workspace packages in dependency order
|
|
120
|
+
npmglobalize -w msgcommon Publish only msgcommon
|
|
121
|
+
npmglobalize --no-workspace Skip workspace detection, run single-package mode
|
|
122
|
+
npmglobalize --continue-on-error Keep going if a package fails
|
|
110
123
|
`);
|
|
111
124
|
}
|
|
112
125
|
function parseArgs(args) {
|
|
@@ -248,6 +261,28 @@ function parseArgs(args) {
|
|
|
248
261
|
case '--no-fix':
|
|
249
262
|
options.fix = false;
|
|
250
263
|
break;
|
|
264
|
+
case '--workspace':
|
|
265
|
+
case '-w':
|
|
266
|
+
i++;
|
|
267
|
+
if (args[i]) {
|
|
268
|
+
if (!options.workspaceFilter)
|
|
269
|
+
options.workspaceFilter = [];
|
|
270
|
+
options.workspaceFilter.push(args[i]);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
options.error = '-w/--workspace requires a package name';
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
case '--no-workspace':
|
|
277
|
+
options.noWorkspace = true;
|
|
278
|
+
break;
|
|
279
|
+
case '--continue-on-error':
|
|
280
|
+
options.continueOnError = true;
|
|
281
|
+
break;
|
|
282
|
+
case '--package':
|
|
283
|
+
case '-pkg':
|
|
284
|
+
options.package = true;
|
|
285
|
+
break;
|
|
251
286
|
default:
|
|
252
287
|
if (arg.startsWith('-')) {
|
|
253
288
|
unrecognized.push(arg);
|
|
@@ -341,10 +376,43 @@ export async function main() {
|
|
|
341
376
|
process.exit(1);
|
|
342
377
|
}
|
|
343
378
|
}
|
|
379
|
+
// Handle --package: update scripts in target package.json
|
|
380
|
+
if (cliOptions.package) {
|
|
381
|
+
const pkg = readPackageJson(cwd);
|
|
382
|
+
if (!pkg.scripts)
|
|
383
|
+
pkg.scripts = {};
|
|
384
|
+
const scripts = pkg.scripts;
|
|
385
|
+
const changes = [];
|
|
386
|
+
if (scripts.release) {
|
|
387
|
+
scripts['old-release'] = scripts.release;
|
|
388
|
+
changes.push(`renamed release → old-release`);
|
|
389
|
+
}
|
|
390
|
+
if (scripts.installer) {
|
|
391
|
+
scripts['old-installer'] = scripts.installer;
|
|
392
|
+
changes.push(`renamed installer → old-installer`);
|
|
393
|
+
}
|
|
394
|
+
scripts.release = 'npmglobalize';
|
|
395
|
+
changes.push(`added release: "npmglobalize"`);
|
|
396
|
+
writePackageJson(cwd, pkg);
|
|
397
|
+
console.log(`Updated ${path.join(cwd, 'package.json')} scripts:`);
|
|
398
|
+
changes.forEach(c => console.log(` ${c}`));
|
|
399
|
+
process.exit(0);
|
|
400
|
+
}
|
|
344
401
|
// Load config file and merge with CLI options (CLI takes precedence)
|
|
345
402
|
const configOptions = readConfig(cwd);
|
|
346
403
|
const options = { ...configOptions, ...cliOptions };
|
|
347
404
|
try {
|
|
405
|
+
// Auto-detect workspace root: private package with workspaces[] field
|
|
406
|
+
if (!options.noWorkspace) {
|
|
407
|
+
const pkgJsonPath = path.join(cwd, 'package.json');
|
|
408
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
409
|
+
const rootPkg = readPackageJson(cwd);
|
|
410
|
+
if (rootPkg.private && Array.isArray(rootPkg.workspaces)) {
|
|
411
|
+
const result = await globalizeWorkspace(cwd, options, configOptions);
|
|
412
|
+
process.exit(result.success ? 0 : 1);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
348
416
|
const success = await globalize(cwd, options, configOptions);
|
|
349
417
|
process.exit(success ? 0 : 1);
|
|
350
418
|
}
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/lib.d.ts
CHANGED
|
@@ -59,6 +59,30 @@ export interface GlobalizeOptions {
|
|
|
59
59
|
rebase?: boolean;
|
|
60
60
|
/** Show package.json dependency changes */
|
|
61
61
|
show?: boolean;
|
|
62
|
+
/** Filter to specific workspace packages (by name or dir name) */
|
|
63
|
+
workspaceFilter?: string[];
|
|
64
|
+
/** Disable workspace mode even at a workspace root */
|
|
65
|
+
noWorkspace?: boolean;
|
|
66
|
+
/** Continue processing remaining packages if one fails (workspace mode) */
|
|
67
|
+
continueOnError?: boolean;
|
|
68
|
+
/** Update package.json scripts to use npmglobalize */
|
|
69
|
+
package?: boolean;
|
|
70
|
+
/** Internal: signals this call is from workspace orchestrator */
|
|
71
|
+
_fromWorkspace?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/** Result from a single package in workspace mode */
|
|
74
|
+
interface WorkspacePackageResult {
|
|
75
|
+
name: string;
|
|
76
|
+
dir: string;
|
|
77
|
+
success: boolean;
|
|
78
|
+
version?: string;
|
|
79
|
+
error?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Aggregate result from workspace orchestration */
|
|
82
|
+
export interface WorkspaceResult {
|
|
83
|
+
success: boolean;
|
|
84
|
+
packages: WorkspacePackageResult[];
|
|
85
|
+
publishOrder: string[];
|
|
62
86
|
}
|
|
63
87
|
/** Read and parse package.json from a directory */
|
|
64
88
|
export declare function readPackageJson(dir: string): any;
|
|
@@ -101,6 +125,20 @@ export declare function getFileRefs(pkg: any): Map<string, {
|
|
|
101
125
|
name: string;
|
|
102
126
|
value: string;
|
|
103
127
|
}>;
|
|
128
|
+
/** Resolve workspace entries to package info. Skips dirs without package.json or with private:true. */
|
|
129
|
+
export declare function resolveWorkspacePackages(rootDir: string): Array<{
|
|
130
|
+
name: string;
|
|
131
|
+
dir: string;
|
|
132
|
+
pkg: any;
|
|
133
|
+
}>;
|
|
134
|
+
/** Build a dependency graph among workspace packages. Returns Map<name, Set<depName>>. */
|
|
135
|
+
export declare function buildDependencyGraph(packages: Array<{
|
|
136
|
+
name: string;
|
|
137
|
+
dir: string;
|
|
138
|
+
pkg: any;
|
|
139
|
+
}>): Map<string, Set<string>>;
|
|
140
|
+
/** Topological sort with cycle detection. Returns package names in dependency order. */
|
|
141
|
+
export declare function topologicalSort(graph: Map<string, Set<string>>): string[];
|
|
104
142
|
/** Transform file: dependencies to npm versions */
|
|
105
143
|
export declare function transformDeps(pkg: any, baseDir: string, verbose?: boolean, forcePublish?: boolean): {
|
|
106
144
|
transformed: boolean;
|
|
@@ -173,8 +211,11 @@ export declare function runNpmAudit(cwd: string, fix?: boolean, verbose?: boolea
|
|
|
173
211
|
/** Get the version of npmglobalize itself */
|
|
174
212
|
export declare function getToolVersion(): string;
|
|
175
213
|
export declare function globalize(cwd: string, options?: GlobalizeOptions, configOptions?: Partial<GlobalizeOptions>): Promise<boolean>;
|
|
214
|
+
/** Orchestrate globalize across all packages in an npm workspace */
|
|
215
|
+
export declare function globalizeWorkspace(rootDir: string, options?: GlobalizeOptions, configOptions?: Partial<GlobalizeOptions>): Promise<WorkspaceResult>;
|
|
176
216
|
declare const _default: {
|
|
177
217
|
globalize: typeof globalize;
|
|
218
|
+
globalizeWorkspace: typeof globalizeWorkspace;
|
|
178
219
|
transformDeps: typeof transformDeps;
|
|
179
220
|
restoreDeps: typeof restoreDeps;
|
|
180
221
|
readPackageJson: typeof readPackageJson;
|
package/lib.js
CHANGED
|
@@ -415,6 +415,91 @@ export function getFileRefs(pkg) {
|
|
|
415
415
|
}
|
|
416
416
|
return refs;
|
|
417
417
|
}
|
|
418
|
+
// ─── Workspace helpers ───────────────────────────────────────────────
|
|
419
|
+
/** Resolve workspace entries to package info. Skips dirs without package.json or with private:true. */
|
|
420
|
+
export function resolveWorkspacePackages(rootDir) {
|
|
421
|
+
const rootPkg = readPackageJson(rootDir);
|
|
422
|
+
const workspaces = rootPkg.workspaces;
|
|
423
|
+
if (!Array.isArray(workspaces))
|
|
424
|
+
return [];
|
|
425
|
+
const results = [];
|
|
426
|
+
for (const entry of workspaces) {
|
|
427
|
+
const pkgDir = path.resolve(rootDir, entry);
|
|
428
|
+
const pkgJsonPath = path.join(pkgDir, 'package.json');
|
|
429
|
+
if (!fs.existsSync(pkgJsonPath))
|
|
430
|
+
continue;
|
|
431
|
+
const pkg = readPackageJson(pkgDir);
|
|
432
|
+
if (pkg.private)
|
|
433
|
+
continue; // skip private packages (they can't be published)
|
|
434
|
+
results.push({ name: pkg.name || entry, dir: pkgDir, pkg });
|
|
435
|
+
}
|
|
436
|
+
return results;
|
|
437
|
+
}
|
|
438
|
+
/** Build a dependency graph among workspace packages. Returns Map<name, Set<depName>>. */
|
|
439
|
+
export function buildDependencyGraph(packages) {
|
|
440
|
+
const nameSet = new Set(packages.map(p => p.name));
|
|
441
|
+
const dirToName = new Map();
|
|
442
|
+
for (const p of packages) {
|
|
443
|
+
dirToName.set(p.dir, p.name);
|
|
444
|
+
}
|
|
445
|
+
const graph = new Map();
|
|
446
|
+
for (const p of packages) {
|
|
447
|
+
const deps = new Set();
|
|
448
|
+
for (const depKey of DEP_KEYS) {
|
|
449
|
+
if (!p.pkg[depKey])
|
|
450
|
+
continue;
|
|
451
|
+
for (const [depName, depValue] of Object.entries(p.pkg[depKey])) {
|
|
452
|
+
// Check by npm name
|
|
453
|
+
if (nameSet.has(depName)) {
|
|
454
|
+
deps.add(depName);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
// Check file: refs that resolve to a sibling workspace dir
|
|
458
|
+
if (isFileRef(depValue)) {
|
|
459
|
+
const resolved = resolveFilePath(depValue, p.dir);
|
|
460
|
+
const resolvedNorm = path.resolve(resolved);
|
|
461
|
+
const match = dirToName.get(resolvedNorm);
|
|
462
|
+
if (match) {
|
|
463
|
+
deps.add(match);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
graph.set(p.name, deps);
|
|
469
|
+
}
|
|
470
|
+
return graph;
|
|
471
|
+
}
|
|
472
|
+
/** Topological sort with cycle detection. Returns package names in dependency order. */
|
|
473
|
+
export function topologicalSort(graph) {
|
|
474
|
+
const visited = new Set();
|
|
475
|
+
const visiting = new Set(); // cycle detection
|
|
476
|
+
const result = [];
|
|
477
|
+
function visit(node) {
|
|
478
|
+
if (visited.has(node))
|
|
479
|
+
return;
|
|
480
|
+
if (visiting.has(node)) {
|
|
481
|
+
throw new Error(`Circular dependency detected involving: ${node}`);
|
|
482
|
+
}
|
|
483
|
+
visiting.add(node);
|
|
484
|
+
const deps = graph.get(node);
|
|
485
|
+
if (deps) {
|
|
486
|
+
for (const dep of deps) {
|
|
487
|
+
if (dep === node)
|
|
488
|
+
continue; // skip self-references
|
|
489
|
+
if (graph.has(dep)) { // only visit workspace-internal deps
|
|
490
|
+
visit(dep);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
visiting.delete(node);
|
|
495
|
+
visited.add(node);
|
|
496
|
+
result.push(node);
|
|
497
|
+
}
|
|
498
|
+
for (const node of graph.keys()) {
|
|
499
|
+
visit(node);
|
|
500
|
+
}
|
|
501
|
+
return result;
|
|
502
|
+
}
|
|
418
503
|
/** Transform file: dependencies to npm versions */
|
|
419
504
|
export function transformDeps(pkg, baseDir, verbose = false, forcePublish = false) {
|
|
420
505
|
let transformed = false;
|
|
@@ -1310,9 +1395,11 @@ export function getToolVersion() {
|
|
|
1310
1395
|
export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
1311
1396
|
const { bump = 'patch', noPublish = false, cleanup = false, install = false, wsl = false, force = false, files = true, dryRun = false, quiet = true, verbose = false, init = false, gitVisibility = 'private', npmVisibility = 'private', message, conform = false, asis = false, updateDeps = false, updateMajor = false, publishDeps = true, // Default to publishing deps for safety
|
|
1312
1397
|
forcePublish = false, fix = false, fixTags = false, rebase = false, show = false } = options;
|
|
1313
|
-
// Show tool version
|
|
1398
|
+
// Show tool version (skip when called from workspace orchestrator)
|
|
1314
1399
|
const toolVersion = getToolVersion();
|
|
1315
|
-
|
|
1400
|
+
if (!options._fromWorkspace) {
|
|
1401
|
+
console.log(colors.italic(`npmglobalize v${toolVersion}`));
|
|
1402
|
+
}
|
|
1316
1403
|
// Show settings from .globalize.json5 if any
|
|
1317
1404
|
if (Object.keys(configOptions).length > 0) {
|
|
1318
1405
|
const settings = [];
|
|
@@ -1579,6 +1666,26 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
1579
1666
|
}
|
|
1580
1667
|
// Read package.json
|
|
1581
1668
|
const pkg = readPackageJson(cwd);
|
|
1669
|
+
// Run build step if package.json has a build script
|
|
1670
|
+
if (pkg.scripts?.build) {
|
|
1671
|
+
console.log('Running build...');
|
|
1672
|
+
if (!dryRun) {
|
|
1673
|
+
const buildResult = runCommand('npm', ['run', 'build'], { cwd, silent: !verbose });
|
|
1674
|
+
if (!buildResult.success) {
|
|
1675
|
+
console.error(colors.red('ERROR: Build failed:'), buildResult.stderr || buildResult.output);
|
|
1676
|
+
if (!force) {
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
console.log(colors.yellow('Continuing with --force despite build failure...'));
|
|
1680
|
+
}
|
|
1681
|
+
else {
|
|
1682
|
+
console.log(colors.green('✓ Build succeeded'));
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
else {
|
|
1686
|
+
console.log(' [dry-run] Would run: npm run build');
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1582
1689
|
// Pre-flight check: fix version/tag mismatches silently
|
|
1583
1690
|
if (!dryRun) {
|
|
1584
1691
|
fixVersionTagMismatch(cwd, pkg, verbose);
|
|
@@ -2457,8 +2564,128 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2457
2564
|
}
|
|
2458
2565
|
return true;
|
|
2459
2566
|
}
|
|
2567
|
+
// ─── Workspace orchestration ─────────────────────────────────────────
|
|
2568
|
+
/** Orchestrate globalize across all packages in an npm workspace */
|
|
2569
|
+
export async function globalizeWorkspace(rootDir, options = {}, configOptions = {}) {
|
|
2570
|
+
const toolVersion = getToolVersion();
|
|
2571
|
+
console.log(colors.italic(`npmglobalize v${toolVersion}`) + colors.dim(' (workspace mode)'));
|
|
2572
|
+
console.log('');
|
|
2573
|
+
// Resolve workspace packages
|
|
2574
|
+
const packages = resolveWorkspacePackages(rootDir);
|
|
2575
|
+
if (packages.length === 0) {
|
|
2576
|
+
console.error(colors.red('No publishable workspace packages found.'));
|
|
2577
|
+
return { success: false, packages: [], publishOrder: [] };
|
|
2578
|
+
}
|
|
2579
|
+
// Build dependency graph and determine publish order
|
|
2580
|
+
const graph = buildDependencyGraph(packages);
|
|
2581
|
+
const publishOrder = topologicalSort(graph);
|
|
2582
|
+
console.log(`Workspace: ${colors.green(path.basename(rootDir))}`);
|
|
2583
|
+
console.log(`Packages (${packages.length}): ${packages.map(p => p.name).join(', ')}`);
|
|
2584
|
+
console.log(`Publish order: ${publishOrder.join(' → ')}`);
|
|
2585
|
+
console.log('');
|
|
2586
|
+
// Handle --cleanup: restore deps for all packages and return
|
|
2587
|
+
if (options.cleanup) {
|
|
2588
|
+
console.log('Restoring workspace dependencies...');
|
|
2589
|
+
for (const pkgName of publishOrder) {
|
|
2590
|
+
const pkgInfo = packages.find(p => p.name === pkgName);
|
|
2591
|
+
if (!pkgInfo)
|
|
2592
|
+
continue;
|
|
2593
|
+
const pkg = readPackageJson(pkgInfo.dir);
|
|
2594
|
+
const restored = restoreDeps(pkg);
|
|
2595
|
+
if (restored) {
|
|
2596
|
+
writePackageJson(pkgInfo.dir, pkg);
|
|
2597
|
+
console.log(` ${colors.green('✓')} ${pkgName}: restored`);
|
|
2598
|
+
}
|
|
2599
|
+
else {
|
|
2600
|
+
console.log(` ${colors.dim('–')} ${pkgName}: nothing to restore`);
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
return { success: true, packages: [], publishOrder };
|
|
2604
|
+
}
|
|
2605
|
+
// Apply workspace filter if specified
|
|
2606
|
+
let filteredOrder = publishOrder;
|
|
2607
|
+
if (options.workspaceFilter && options.workspaceFilter.length > 0) {
|
|
2608
|
+
const filter = new Set(options.workspaceFilter);
|
|
2609
|
+
filteredOrder = publishOrder.filter(name => {
|
|
2610
|
+
const pkgInfo = packages.find(p => p.name === name);
|
|
2611
|
+
if (!pkgInfo)
|
|
2612
|
+
return false;
|
|
2613
|
+
// Match by package name or directory basename
|
|
2614
|
+
return filter.has(name) || filter.has(path.basename(pkgInfo.dir));
|
|
2615
|
+
});
|
|
2616
|
+
if (filteredOrder.length === 0) {
|
|
2617
|
+
console.error(colors.red(`No packages matched filter: ${options.workspaceFilter.join(', ')}`));
|
|
2618
|
+
return { success: false, packages: [], publishOrder };
|
|
2619
|
+
}
|
|
2620
|
+
console.log(`Filtered to: ${filteredOrder.join(', ')}`);
|
|
2621
|
+
console.log('');
|
|
2622
|
+
}
|
|
2623
|
+
// Process each package in dependency order
|
|
2624
|
+
const results = [];
|
|
2625
|
+
for (const pkgName of filteredOrder) {
|
|
2626
|
+
const pkgInfo = packages.find(p => p.name === pkgName);
|
|
2627
|
+
if (!pkgInfo)
|
|
2628
|
+
continue;
|
|
2629
|
+
console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2630
|
+
console.log(` Package: ${colors.green(pkgName)}`);
|
|
2631
|
+
console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2632
|
+
// Merge configs: root config < package config < CLI options
|
|
2633
|
+
const pkgConfig = readConfig(pkgInfo.dir);
|
|
2634
|
+
const mergedConfig = { ...configOptions, ...pkgConfig };
|
|
2635
|
+
const mergedOptions = {
|
|
2636
|
+
...mergedConfig,
|
|
2637
|
+
...options,
|
|
2638
|
+
publishDeps: false, // workspace handles ordering; avoid double-publish
|
|
2639
|
+
_fromWorkspace: true,
|
|
2640
|
+
};
|
|
2641
|
+
try {
|
|
2642
|
+
const success = await globalize(pkgInfo.dir, mergedOptions, mergedConfig);
|
|
2643
|
+
const updatedPkg = readPackageJson(pkgInfo.dir);
|
|
2644
|
+
results.push({
|
|
2645
|
+
name: pkgName,
|
|
2646
|
+
dir: pkgInfo.dir,
|
|
2647
|
+
success,
|
|
2648
|
+
version: updatedPkg.version,
|
|
2649
|
+
});
|
|
2650
|
+
if (!success && !options.continueOnError) {
|
|
2651
|
+
console.error(colors.red(`\nStopping: ${pkgName} failed. Use --continue-on-error to keep going.`));
|
|
2652
|
+
break;
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
catch (error) {
|
|
2656
|
+
results.push({
|
|
2657
|
+
name: pkgName,
|
|
2658
|
+
dir: pkgInfo.dir,
|
|
2659
|
+
success: false,
|
|
2660
|
+
error: error.message,
|
|
2661
|
+
});
|
|
2662
|
+
console.error(colors.red(`\nError processing ${pkgName}: ${error.message}`));
|
|
2663
|
+
if (!options.continueOnError) {
|
|
2664
|
+
console.error(colors.red('Use --continue-on-error to continue with remaining packages.'));
|
|
2665
|
+
break;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
console.log('');
|
|
2669
|
+
}
|
|
2670
|
+
// Print workspace summary
|
|
2671
|
+
const allSuccess = results.every(r => r.success);
|
|
2672
|
+
console.log('');
|
|
2673
|
+
console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2674
|
+
console.log(allSuccess ? colors.green('✓ Workspace Summary') : colors.red('✗ Workspace Summary'));
|
|
2675
|
+
console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2676
|
+
for (const r of results) {
|
|
2677
|
+
const status = r.success ? colors.green('✓') : colors.red('✗');
|
|
2678
|
+
const ver = r.version ? ` v${r.version}` : '';
|
|
2679
|
+
const err = r.error ? colors.red(` (${r.error})`) : '';
|
|
2680
|
+
console.log(` ${status} ${r.name}${ver}${err}`);
|
|
2681
|
+
}
|
|
2682
|
+
console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2683
|
+
console.log('');
|
|
2684
|
+
return { success: allSuccess, packages: results, publishOrder };
|
|
2685
|
+
}
|
|
2460
2686
|
export default {
|
|
2461
2687
|
globalize,
|
|
2688
|
+
globalizeWorkspace,
|
|
2462
2689
|
transformDeps,
|
|
2463
2690
|
restoreDeps,
|
|
2464
2691
|
readPackageJson,
|