@kb-labs/devlink-entry 2.109.0 → 2.110.0

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.
@@ -22,7 +22,7 @@ var backups_default = defineCommand({
22
22
  } catch (err) {
23
23
  loader.fail("Restore failed");
24
24
  handleError(ctx, err, outputJson);
25
- return { exitCode: 1 };
25
+ return { ok: false, error: "Backup operation failed" };
26
26
  }
27
27
  loader.succeed(`Restored ${restored} file(s)`);
28
28
  tracker.checkpoint("restore");
@@ -40,7 +40,7 @@ var backups_default = defineCommand({
40
40
  timing: tracker.total()
41
41
  });
42
42
  }
43
- return { exitCode: 0, result: result2, meta: { timing: tracker.total() } };
43
+ return { ok: true, result: result2, meta: { timing: tracker.total() } };
44
44
  }
45
45
  const backups = listBackups(rootDir);
46
46
  tracker.checkpoint("list");
@@ -64,7 +64,7 @@ var backups_default = defineCommand({
64
64
  });
65
65
  }
66
66
  }
67
- return { exitCode: 0, result, meta: { timing: tracker.total() } };
67
+ return { ok: true, result, meta: { timing: tracker.total() } };
68
68
  }
69
69
  }
70
70
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/backups.ts"],"names":["backups","result"],"mappings":"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","file":"backups.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { listBackups, restoreBackup } from '@kb-labs/devlink-core';\nimport type { DevlinkBackup } from '@kb-labs/devlink-contracts';\n\ninterface BackupsFlags {\n restore?: string;\n json?: boolean;\n}\n\ninterface BackupsInput {\n argv?: string[];\n flags?: BackupsFlags;\n restore?: string;\n json?: boolean;\n}\n\ninterface BackupsResult {\n backups: DevlinkBackup[];\n restored?: number;\n}\n\nexport default defineCommand<unknown, BackupsInput, BackupsResult>({\n id: 'devlink:backups',\n description: 'List and restore backups',\n\n handler: {\n async execute(ctx: PluginContextV3, input: BackupsInput): Promise<CommandResult<BackupsResult>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as BackupsFlags;\n const outputJson = flags.json ?? false;\n const restoreId = flags.restore;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n // ─── Restore mode ────────────────────────────────────────────────────────\n if (restoreId) {\n const loader = useLoader(`Restoring backup ${restoreId}...`);\n loader.start();\n\n let restored: number;\n let errors: string[];\n try {\n ({ restored, errors } = restoreBackup(rootDir, restoreId));\n } catch (err) {\n loader.fail('Restore failed');\n handleError(ctx, err, outputJson);\n return { exitCode: 1 };\n }\n loader.succeed(`Restored ${restored} file(s)`);\n tracker.checkpoint('restore');\n\n const backups = listBackups(rootDir);\n const result: BackupsResult = { backups, restored };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n ctx.ui?.success?.(`Restored ${restored} file(s) from backup ${restoreId}`, {\n title: 'DevLink — Restore Backup',\n sections: [\n ...(errors.length > 0 ? [{ header: 'Errors', items: errors }] : []),\n { header: 'Next step', items: ['Run pnpm install to apply changes'] },\n ],\n timing: tracker.total(),\n });\n }\n\n return { exitCode: 0, result, meta: { timing: tracker.total() } };\n }\n\n // ─── List mode ───────────────────────────────────────────────────────────\n const backups = listBackups(rootDir);\n tracker.checkpoint('list');\n\n const result: BackupsResult = { backups };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n if (backups.length === 0) {\n ctx.ui?.info?.('No backups found. Backups are created automatically before each switch.');\n } else {\n const items = backups.map(b =>\n `[${b.id}] ${b.timestamp.slice(0, 19).replace('T', ' ')} — ${b.description} (${b.files.length} files)`\n );\n ctx.ui?.success?.(`${backups.length} backup(s) available`, {\n title: 'DevLink — Backups',\n sections: [\n { header: 'Backups (newest first)', items },\n { header: 'Restore', items: ['kb devlink backups --restore <id>'] },\n ],\n timing: tracker.total(),\n });\n }\n }\n\n return { exitCode: 0, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/backups.ts"],"names":["backups","result"],"mappings":"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","file":"backups.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { listBackups, restoreBackup } from '@kb-labs/devlink-core';\nimport type { DevlinkBackup } from '@kb-labs/devlink-contracts';\n\ninterface BackupsFlags {\n restore?: string;\n json?: boolean;\n}\n\ninterface BackupsInput {\n argv?: string[];\n flags?: BackupsFlags;\n restore?: string;\n json?: boolean;\n}\n\ninterface BackupsResult {\n backups: DevlinkBackup[];\n restored?: number;\n}\n\nexport default defineCommand<unknown, BackupsInput, BackupsResult>({\n id: 'devlink:backups',\n description: 'List and restore backups',\n\n handler: {\n async execute(ctx: PluginContextV3, input: BackupsInput): Promise<CommandResult<BackupsResult>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as BackupsFlags;\n const outputJson = flags.json ?? false;\n const restoreId = flags.restore;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n // ─── Restore mode ────────────────────────────────────────────────────────\n if (restoreId) {\n const loader = useLoader(`Restoring backup ${restoreId}...`);\n loader.start();\n\n let restored: number;\n let errors: string[];\n try {\n ({ restored, errors } = restoreBackup(rootDir, restoreId));\n } catch (err) {\n loader.fail('Restore failed');\n handleError(ctx, err, outputJson);\n return { ok: false, error: 'Backup operation failed' };\n }\n loader.succeed(`Restored ${restored} file(s)`);\n tracker.checkpoint('restore');\n\n const backups = listBackups(rootDir);\n const result: BackupsResult = { backups, restored };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n ctx.ui?.success?.(`Restored ${restored} file(s) from backup ${restoreId}`, {\n title: 'DevLink — Restore Backup',\n sections: [\n ...(errors.length > 0 ? [{ header: 'Errors', items: errors }] : []),\n { header: 'Next step', items: ['Run pnpm install to apply changes'] },\n ],\n timing: tracker.total(),\n });\n }\n\n return { ok: true, result, meta: { timing: tracker.total() } };\n }\n\n // ─── List mode ───────────────────────────────────────────────────────────\n const backups = listBackups(rootDir);\n tracker.checkpoint('list');\n\n const result: BackupsResult = { backups };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n if (backups.length === 0) {\n ctx.ui?.info?.('No backups found. Backups are created automatically before each switch.');\n } else {\n const items = backups.map(b =>\n `[${b.id}] ${b.timestamp.slice(0, 19).replace('T', ' ')} — ${b.description} (${b.files.length} files)`\n );\n ctx.ui?.success?.(`${backups.length} backup(s) available`, {\n title: 'DevLink — Backups',\n sections: [\n { header: 'Backups (newest first)', items },\n { header: 'Restore', items: ['kb devlink backups --restore <id>'] },\n ],\n timing: tracker.total(),\n });\n }\n }\n\n return { ok: true, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
@@ -32,7 +32,7 @@ var freeze_default = defineCommand({
32
32
  } catch (err) {
33
33
  loader.fail("Failed to freeze state");
34
34
  handleError(ctx, err, outputJson);
35
- return { exitCode: 1 };
35
+ return { ok: false, error: "Freeze operation failed" };
36
36
  }
37
37
  loader.succeed("State frozen");
38
38
  tracker.checkpoint("freeze");
@@ -54,7 +54,7 @@ var freeze_default = defineCommand({
54
54
  timing: tracker.total()
55
55
  });
56
56
  }
57
- return { exitCode: 0, result: lock, meta: { timing: tracker.total() } };
57
+ return { ok: true, result: lock, meta: { timing: tracker.total() } };
58
58
  }
59
59
  }
60
60
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/freeze.ts"],"names":[],"mappings":";;;;AAcA,IAAO,iBAAQ,aAAA,CAA8C;AAAA,EAC3D,EAAA,EAAI,gBAAA;AAAA,EACJ,WAAA,EAAa,8CAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,MAAA,CAAO,IAAA,EAAuB,MAAA,EAAqB;AACvD,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,8CAAA;AAAA,QACT,UAAA,EAAY;AAAA,UACV,EAAE,MAAM,QAAA,EAAmB,QAAA,EAAU,QAAQ,OAAA,EAAS,EAAE,IAAA,EAAM,uBAAA,EAAwB;AAAE;AAC1F,OACF;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAsD;AACxF,MAAA,MAAM,OAAA,GAAU,IAAI,aAAA,EAAc;AAClC,MAAA,MAAM,KAAA,GAAS,MAAM,KAAA,IAAS,KAAA;AAC9B,MAAA,MAAM,UAAA,GAAa,MAAM,IAAA,IAAQ,KAAA;AAEjC,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEvC,MAAA,MAAM,MAAA,GAAS,UAAU,2BAA2B,CAAA;AACpD,MAAA,MAAA,CAAO,KAAA,EAAM;AAEb,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,UAAU,OAAO,CAAA;AAC/B,QAAA,MAAM,SAAA,GAAY,kBAAkB,OAAO,CAAA;AAC3C,QAAA,MAAM,WAAA,GAAc,MAAM,WAAA,IAAe,KAAA;AACzC,QAAA,MAAM,aAAa,MAAM,uBAAA,CAAwB,SAAA,EAAW,OAAA,EAAS,QAAW,WAAW,CAAA;AAC3F,QAAA,MAAM,IAAA,GAAO,SAAA,CAAU,WAAA,EAAa,UAAA,EAAY,WAAW,OAAO,CAAA;AAClE,QAAA,IAAA,GAAO,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,MAC7B,SAAS,GAAA,EAAK;AACZ,QAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AACpC,QAAA,WAAA,CAAY,GAAA,EAAK,KAAK,UAAU,CAAA;AAChC,QAAA,OAAO,EAAE,UAAU,CAAA,EAAE;AAAA,MACvB;AACA,MAAA,MAAA,CAAO,QAAQ,cAAc,CAAA;AAC7B,MAAA,OAAA,CAAQ,WAAW,QAAQ,CAAA;AAE3B,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,OAAO,IAAI,CAAA;AAAA,MACrB,CAAA,MAAO;AACL,QAAA,GAAA,CAAI,EAAA,EAAI,UAAU,mCAAA,EAAqC;AAAA,UACrD,KAAA,EAAO,uBAAA;AAAA,UACP,QAAA,EAAU;AAAA,YACR;AAAA,cACE,MAAA,EAAQ,WAAA;AAAA,cACR,KAAA,EAAO;AAAA,gBACL,CAAA,MAAA,EAAS,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,gBACvB,CAAA,WAAA,EAAc,KAAK,QAAQ,CAAA,CAAA;AAAA,gBAC3B,CAAA,+BAAA;AAAA;AACF;AACF,WACF;AAAA,UACA,MAAA,EAAQ,QAAQ,KAAA;AAAM,SACvB,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,EAAE,MAAA,EAAQ,OAAA,CAAQ,KAAA,EAAM,EAAE,EAAE;AAAA,IACxE;AAAA;AAEJ,CAAC","file":"freeze.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, buildPlan, freeze, loadState } from '@kb-labs/devlink-core';\nimport type { LockFile } from '@kb-labs/devlink-core';\n\ninterface FreezeFlags {\n json?: boolean;\n}\n\ninterface FreezeInput {\n argv?: string[];\n flags?: FreezeFlags;\n json?: boolean;\n}\n\nexport default defineCommand<unknown, FreezeInput, LockFile>({\n id: 'devlink:freeze',\n description: 'Freeze current dependency state to lock file',\n\n handler: {\n async intent(_ctx: PluginContextV3, _input: FreezeInput) {\n return {\n summary: 'Freeze current dependency state to lock file',\n operations: [\n { type: 'create' as const, resource: 'file', details: { path: '.kb/devlink/lock.json' } },\n ],\n };\n },\n\n async execute(ctx: PluginContextV3, input: FreezeInput): Promise<CommandResult<LockFile>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as FreezeFlags;\n const outputJson = flags.json ?? false;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const loader = useLoader('Freezing current state...');\n loader.start();\n\n let lock;\n try {\n const state = loadState(rootDir);\n const monorepos = discoverMonorepos(rootDir);\n const currentMode = state.currentMode ?? 'npm';\n const packageMap = await buildPackageMapFiltered(monorepos, rootDir, undefined, currentMode);\n const plan = buildPlan(currentMode, packageMap, monorepos, rootDir);\n lock = freeze(rootDir, plan);\n } catch (err) {\n loader.fail('Failed to freeze state');\n handleError(ctx, err, outputJson);\n return { exitCode: 1 };\n }\n loader.succeed('State frozen');\n tracker.checkpoint('freeze');\n\n if (outputJson) {\n ctx.ui?.json?.(lock);\n } else {\n ctx.ui?.success?.('Current state frozen to lock file', {\n title: 'DevLink — Freeze',\n sections: [\n {\n header: 'Lock file',\n items: [\n `Mode: ${lock.plan.mode}`,\n `Frozen at: ${lock.frozenAt}`,\n `Location: .kb/devlink/lock.json`,\n ],\n },\n ],\n timing: tracker.total(),\n });\n }\n\n return { exitCode: 0, result: lock, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/freeze.ts"],"names":[],"mappings":";;;;AAcA,IAAO,iBAAQ,aAAA,CAA8C;AAAA,EAC3D,EAAA,EAAI,gBAAA;AAAA,EACJ,WAAA,EAAa,8CAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,MAAA,CAAO,IAAA,EAAuB,MAAA,EAAqB;AACvD,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,8CAAA;AAAA,QACT,UAAA,EAAY;AAAA,UACV,EAAE,MAAM,QAAA,EAAmB,QAAA,EAAU,QAAQ,OAAA,EAAS,EAAE,IAAA,EAAM,uBAAA,EAAwB;AAAE;AAC1F,OACF;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAsD;AACxF,MAAA,MAAM,OAAA,GAAU,IAAI,aAAA,EAAc;AAClC,MAAA,MAAM,KAAA,GAAS,MAAM,KAAA,IAAS,KAAA;AAC9B,MAAA,MAAM,UAAA,GAAa,MAAM,IAAA,IAAQ,KAAA;AAEjC,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEvC,MAAA,MAAM,MAAA,GAAS,UAAU,2BAA2B,CAAA;AACpD,MAAA,MAAA,CAAO,KAAA,EAAM;AAEb,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,UAAU,OAAO,CAAA;AAC/B,QAAA,MAAM,SAAA,GAAY,kBAAkB,OAAO,CAAA;AAC3C,QAAA,MAAM,WAAA,GAAc,MAAM,WAAA,IAAe,KAAA;AACzC,QAAA,MAAM,aAAa,MAAM,uBAAA,CAAwB,SAAA,EAAW,OAAA,EAAS,QAAW,WAAW,CAAA;AAC3F,QAAA,MAAM,IAAA,GAAO,SAAA,CAAU,WAAA,EAAa,UAAA,EAAY,WAAW,OAAO,CAAA;AAClE,QAAA,IAAA,GAAO,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,MAC7B,SAAS,GAAA,EAAK;AACZ,QAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AACpC,QAAA,WAAA,CAAY,GAAA,EAAK,KAAK,UAAU,CAAA;AAChC,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,yBAAA,EAA0B;AAAA,MACvD;AACA,MAAA,MAAA,CAAO,QAAQ,cAAc,CAAA;AAC7B,MAAA,OAAA,CAAQ,WAAW,QAAQ,CAAA;AAE3B,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,OAAO,IAAI,CAAA;AAAA,MACrB,CAAA,MAAO;AACL,QAAA,GAAA,CAAI,EAAA,EAAI,UAAU,mCAAA,EAAqC;AAAA,UACrD,KAAA,EAAO,uBAAA;AAAA,UACP,QAAA,EAAU;AAAA,YACR;AAAA,cACE,MAAA,EAAQ,WAAA;AAAA,cACR,KAAA,EAAO;AAAA,gBACL,CAAA,MAAA,EAAS,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,gBACvB,CAAA,WAAA,EAAc,KAAK,QAAQ,CAAA,CAAA;AAAA,gBAC3B,CAAA,+BAAA;AAAA;AACF;AACF,WACF;AAAA,UACA,MAAA,EAAQ,QAAQ,KAAA;AAAM,SACvB,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,EAAE,MAAA,EAAQ,OAAA,CAAQ,KAAA,EAAM,EAAE,EAAE;AAAA,IACrE;AAAA;AAEJ,CAAC","file":"freeze.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, buildPlan, freeze, loadState } from '@kb-labs/devlink-core';\nimport type { LockFile } from '@kb-labs/devlink-core';\n\ninterface FreezeFlags {\n json?: boolean;\n}\n\ninterface FreezeInput {\n argv?: string[];\n flags?: FreezeFlags;\n json?: boolean;\n}\n\nexport default defineCommand<unknown, FreezeInput, LockFile>({\n id: 'devlink:freeze',\n description: 'Freeze current dependency state to lock file',\n\n handler: {\n async intent(_ctx: PluginContextV3, _input: FreezeInput) {\n return {\n summary: 'Freeze current dependency state to lock file',\n operations: [\n { type: 'create' as const, resource: 'file', details: { path: '.kb/devlink/lock.json' } },\n ],\n };\n },\n\n async execute(ctx: PluginContextV3, input: FreezeInput): Promise<CommandResult<LockFile>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as FreezeFlags;\n const outputJson = flags.json ?? false;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const loader = useLoader('Freezing current state...');\n loader.start();\n\n let lock;\n try {\n const state = loadState(rootDir);\n const monorepos = discoverMonorepos(rootDir);\n const currentMode = state.currentMode ?? 'npm';\n const packageMap = await buildPackageMapFiltered(monorepos, rootDir, undefined, currentMode);\n const plan = buildPlan(currentMode, packageMap, monorepos, rootDir);\n lock = freeze(rootDir, plan);\n } catch (err) {\n loader.fail('Failed to freeze state');\n handleError(ctx, err, outputJson);\n return { ok: false, error: 'Freeze operation failed' };\n }\n loader.succeed('State frozen');\n tracker.checkpoint('freeze');\n\n if (outputJson) {\n ctx.ui?.json?.(lock);\n } else {\n ctx.ui?.success?.('Current state frozen to lock file', {\n title: 'DevLink — Freeze',\n sections: [\n {\n header: 'Lock file',\n items: [\n `Mode: ${lock.plan.mode}`,\n `Frozen at: ${lock.frozenAt}`,\n `Location: .kb/devlink/lock.json`,\n ],\n },\n ],\n timing: tracker.total(),\n });\n }\n\n return { ok: true, result: lock, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
@@ -28,7 +28,7 @@ var plan_default = defineCommand({
28
28
  } catch (err) {
29
29
  loader.fail("Failed to build plan");
30
30
  handleError(ctx, err, outputJson);
31
- return { exitCode: 1 };
31
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
32
32
  }
33
33
  loader.succeed(`Plan ready: ${plan.items.length} change(s)`);
34
34
  tracker.checkpoint("plan");
@@ -75,7 +75,7 @@ var plan_default = defineCommand({
75
75
  });
76
76
  }
77
77
  }
78
- return { exitCode: 0, result: plan, meta: { timing: tracker.total() } };
78
+ return { ok: true, result: plan, meta: { timing: tracker.total() } };
79
79
  }
80
80
  }
81
81
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/plan.ts"],"names":[],"mappings":"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","file":"plan.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, buildPlan, groupByMonorepo, loadState } from '@kb-labs/devlink-core';\nimport type { DevlinkMode, DevlinkPlan } from '@kb-labs/devlink-contracts';\n\ninterface PlanFlags {\n mode?: DevlinkMode;\n repos?: string;\n json?: boolean;\n ttl?: number;\n}\n\ninterface PlanInput {\n argv?: string[];\n flags?: PlanFlags;\n mode?: DevlinkMode;\n repos?: string;\n json?: boolean;\n}\n\nexport default defineCommand<unknown, PlanInput, DevlinkPlan>({\n id: 'devlink:plan',\n description: 'Preview what would change when switching mode',\n\n handler: {\n async execute(ctx: PluginContextV3, input: PlanInput): Promise<CommandResult<DevlinkPlan>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as PlanFlags;\n const outputJson = flags.json ?? false;\n const scopedRepos = flags.repos ? flags.repos.split(',').map(s => s.trim()) : undefined;\n const ttlMs = (flags.ttl ?? 24) * 60 * 60 * 1000;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const loader = useLoader('Building plan...');\n loader.start();\n\n let plan;\n let targetMode: DevlinkMode;\n let currentModeBefore: DevlinkMode | undefined;\n try {\n const state = loadState(rootDir);\n currentModeBefore = state.currentMode ?? undefined;\n const monorepos = discoverMonorepos(rootDir);\n targetMode = flags.mode ?? (state.currentMode === 'npm' ? 'local' : 'npm');\n const packageMap = await buildPackageMapFiltered(monorepos, rootDir, ttlMs, targetMode);\n plan = buildPlan(targetMode, packageMap, monorepos, rootDir, { scopedRepos });\n } catch (err) {\n loader.fail('Failed to build plan');\n handleError(ctx, err, outputJson);\n return { exitCode: 1 };\n }\n loader.succeed(`Plan ready: ${plan.items.length} change(s)`);\n tracker.checkpoint('plan');\n\n if (outputJson) {\n ctx.ui?.json?.(plan);\n } else {\n if (plan.items.length === 0) {\n ctx.ui?.info?.('No changes needed — already in the target mode.');\n } else {\n const byRepo = groupByMonorepo(plan.items);\n // Unique packages in npm map\n const uniquePkgs = new Set(plan.items.map(i => i.depName)).size;\n const uniqueFiles = new Set(plan.items.map(i => i.packageJsonPath)).size;\n\n const sections = [...byRepo.entries()].map(([repo, items]) => {\n // Group by depName within each repo — show \"×N files\" instead of N lines\n const byDep = new Map<string, { from: string; to: string; count: number }>();\n for (const item of items) {\n const existing = byDep.get(item.depName);\n if (existing) {\n existing.count++;\n } else {\n byDep.set(item.depName, { from: item.from, to: item.to, count: 1 });\n }\n }\n return {\n header: `${repo} (${byDep.size} dep${byDep.size !== 1 ? 's' : ''})`,\n items: [...byDep.entries()].map(([dep, { from, to, count }]) =>\n count > 1\n ? `${dep}: ${from} → ${to} ×${count} files`\n : `${dep}: ${from} → ${to}`\n ),\n };\n });\n\n ctx.ui?.sideBox?.({\n title: 'DevLink — Plan',\n status: 'info',\n summary: {\n 'Mode': `${currentModeBefore ?? '?'} → ${targetMode}`,\n 'Packages': uniquePkgs,\n 'Files affected': uniqueFiles,\n 'Total changes': plan.items.length,\n },\n sections: [\n ...sections,\n { header: 'Next step', items: [`kb devlink switch --mode=${targetMode}`] },\n ],\n timing: tracker.total(),\n });\n }\n }\n\n return { exitCode: 0, result: plan, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/plan.ts"],"names":[],"mappings":"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","file":"plan.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, buildPlan, groupByMonorepo, loadState } from '@kb-labs/devlink-core';\nimport type { DevlinkMode, DevlinkPlan } from '@kb-labs/devlink-contracts';\n\ninterface PlanFlags {\n mode?: DevlinkMode;\n repos?: string;\n json?: boolean;\n ttl?: number;\n}\n\ninterface PlanInput {\n argv?: string[];\n flags?: PlanFlags;\n mode?: DevlinkMode;\n repos?: string;\n json?: boolean;\n}\n\nexport default defineCommand<unknown, PlanInput, DevlinkPlan>({\n id: 'devlink:plan',\n description: 'Preview what would change when switching mode',\n\n handler: {\n async execute(ctx: PluginContextV3, input: PlanInput): Promise<CommandResult<DevlinkPlan>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as PlanFlags;\n const outputJson = flags.json ?? false;\n const scopedRepos = flags.repos ? flags.repos.split(',').map(s => s.trim()) : undefined;\n const ttlMs = (flags.ttl ?? 24) * 60 * 60 * 1000;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const loader = useLoader('Building plan...');\n loader.start();\n\n let plan;\n let targetMode: DevlinkMode;\n let currentModeBefore: DevlinkMode | undefined;\n try {\n const state = loadState(rootDir);\n currentModeBefore = state.currentMode ?? undefined;\n const monorepos = discoverMonorepos(rootDir);\n targetMode = flags.mode ?? (state.currentMode === 'npm' ? 'local' : 'npm');\n const packageMap = await buildPackageMapFiltered(monorepos, rootDir, ttlMs, targetMode);\n plan = buildPlan(targetMode, packageMap, monorepos, rootDir, { scopedRepos });\n } catch (err) {\n loader.fail('Failed to build plan');\n handleError(ctx, err, outputJson);\n return { ok: false, error: err instanceof Error ? err.message : String(err) };\n }\n loader.succeed(`Plan ready: ${plan.items.length} change(s)`);\n tracker.checkpoint('plan');\n\n if (outputJson) {\n ctx.ui?.json?.(plan);\n } else {\n if (plan.items.length === 0) {\n ctx.ui?.info?.('No changes needed — already in the target mode.');\n } else {\n const byRepo = groupByMonorepo(plan.items);\n // Unique packages in npm map\n const uniquePkgs = new Set(plan.items.map(i => i.depName)).size;\n const uniqueFiles = new Set(plan.items.map(i => i.packageJsonPath)).size;\n\n const sections = [...byRepo.entries()].map(([repo, items]) => {\n // Group by depName within each repo — show \"×N files\" instead of N lines\n const byDep = new Map<string, { from: string; to: string; count: number }>();\n for (const item of items) {\n const existing = byDep.get(item.depName);\n if (existing) {\n existing.count++;\n } else {\n byDep.set(item.depName, { from: item.from, to: item.to, count: 1 });\n }\n }\n return {\n header: `${repo} (${byDep.size} dep${byDep.size !== 1 ? 's' : ''})`,\n items: [...byDep.entries()].map(([dep, { from, to, count }]) =>\n count > 1\n ? `${dep}: ${from} → ${to} ×${count} files`\n : `${dep}: ${from} → ${to}`\n ),\n };\n });\n\n ctx.ui?.sideBox?.({\n title: 'DevLink — Plan',\n status: 'info',\n summary: {\n 'Mode': `${currentModeBefore ?? '?'} → ${targetMode}`,\n 'Packages': uniquePkgs,\n 'Files affected': uniqueFiles,\n 'Total changes': plan.items.length,\n },\n sections: [\n ...sections,\n { header: 'Next step', items: [`kb devlink switch --mode=${targetMode}`] },\n ],\n timing: tracker.total(),\n });\n }\n }\n\n return { ok: true, result: plan, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
@@ -34,7 +34,7 @@ var status_default = defineCommand({
34
34
  } catch (err) {
35
35
  loader.fail("Analysis failed");
36
36
  handleError(ctx, err, outputJson);
37
- return { exitCode: 1 };
37
+ return { ok: false, error: "Unable to read DevLink status" };
38
38
  }
39
39
  loader.succeed("Analysis complete");
40
40
  tracker.checkpoint("analysis");
@@ -95,7 +95,7 @@ var status_default = defineCommand({
95
95
  timing: tracker.total()
96
96
  });
97
97
  }
98
- return { exitCode: 0, result, meta: { timing: tracker.total() } };
98
+ return { ok: true, result, meta: { timing: tracker.total() } };
99
99
  }
100
100
  }
101
101
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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","file":"status.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, analyzePackageDeps, loadState, diagnose } from '@kb-labs/devlink-core';\nimport type { DevlinkStatus, DiagnosticIssue } from '@kb-labs/devlink-contracts';\n\ninterface StatusFlags {\n json?: boolean;\n}\n\ninterface StatusInput {\n argv?: string[];\n flags?: StatusFlags;\n json?: boolean;\n}\n\ninterface StatusResult extends DevlinkStatus {\n diagnostics: DiagnosticIssue[];\n}\n\nexport default defineCommand<unknown, StatusInput, StatusResult>({\n id: 'devlink:status',\n description: 'Show current state of cross-repo dependencies with diagnostics',\n\n handler: {\n async execute(ctx: PluginContextV3, input: StatusInput): Promise<CommandResult<StatusResult>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as StatusFlags;\n const outputJson = flags.json ?? false;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const loader = useLoader('Analyzing dependencies...');\n loader.start();\n\n let state: ReturnType<typeof loadState>;\n let totalLink = 0;\n let totalNpm = 0;\n let totalWorkspace = 0;\n let diagnostics: ReturnType<typeof diagnose>;\n try {\n state = loadState(rootDir);\n const monorepos = discoverMonorepos(rootDir);\n const packageMap = await buildPackageMapFiltered(monorepos, rootDir);\n\n for (const monorepo of monorepos) {\n for (const pkgPath of monorepo.packagePaths) {\n const counts = analyzePackageDeps(pkgPath, packageMap);\n totalLink += counts.linkCount;\n totalNpm += counts.npmCount;\n totalWorkspace += counts.workspaceCount;\n }\n }\n\n diagnostics = diagnose(monorepos, packageMap, rootDir);\n } catch (err) {\n loader.fail('Analysis failed');\n handleError(ctx, err, outputJson);\n return { exitCode: 1 };\n }\n\n loader.succeed('Analysis complete');\n tracker.checkpoint('analysis');\n\n const errors = diagnostics.filter(d => d.severity === 'error');\n const warnings = diagnostics.filter(d => d.severity === 'warning');\n\n const result: StatusResult = {\n currentMode: state.currentMode,\n lastApplied: state.lastApplied,\n linkCount: totalLink,\n npmCount: totalNpm,\n workspaceCount: totalWorkspace,\n discrepancies: [],\n diagnostics,\n };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n const sections = [\n {\n header: 'Current mode',\n items: [\n `Mode: ${state.currentMode ?? 'unknown'}`,\n `Last applied: ${state.lastApplied ?? 'never'}`,\n ],\n },\n {\n header: 'Dependency counts',\n items: [\n `link: (local) : ${totalLink}`,\n `npm (^version) : ${totalNpm}`,\n `workspace:* : ${totalWorkspace}`,\n ],\n },\n ];\n\n if (errors.length > 0) {\n sections.push({\n header: `❌ Errors (${errors.length})`,\n items: errors.slice(0, 10).map(d => `${d.dep ?? d.file}: ${d.message}`),\n });\n }\n\n if (warnings.length > 0) {\n sections.push({\n header: `⚠ Warnings (${warnings.length})`,\n items: warnings.slice(0, 10).map(d => `${d.dep ?? d.file}: ${d.message}`),\n });\n }\n\n if (diagnostics.length === 0) {\n sections.push({ header: '✅ Health', items: ['No issues detected'] });\n } else {\n sections.push({\n header: 'Fix',\n items: ['Run: kb devlink switch --mode=local --install'],\n });\n }\n\n ctx.ui?.success?.('Dependency status', {\n title: 'DevLink — Status',\n sections,\n timing: tracker.total(),\n });\n }\n\n return { exitCode: 0, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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","file":"status.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, analyzePackageDeps, loadState, diagnose } from '@kb-labs/devlink-core';\nimport type { DevlinkStatus, DiagnosticIssue } from '@kb-labs/devlink-contracts';\n\ninterface StatusFlags {\n json?: boolean;\n}\n\ninterface StatusInput {\n argv?: string[];\n flags?: StatusFlags;\n json?: boolean;\n}\n\ninterface StatusResult extends DevlinkStatus {\n diagnostics: DiagnosticIssue[];\n}\n\nexport default defineCommand<unknown, StatusInput, StatusResult>({\n id: 'devlink:status',\n description: 'Show current state of cross-repo dependencies with diagnostics',\n\n handler: {\n async execute(ctx: PluginContextV3, input: StatusInput): Promise<CommandResult<StatusResult>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as StatusFlags;\n const outputJson = flags.json ?? false;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const loader = useLoader('Analyzing dependencies...');\n loader.start();\n\n let state: ReturnType<typeof loadState>;\n let totalLink = 0;\n let totalNpm = 0;\n let totalWorkspace = 0;\n let diagnostics: ReturnType<typeof diagnose>;\n try {\n state = loadState(rootDir);\n const monorepos = discoverMonorepos(rootDir);\n const packageMap = await buildPackageMapFiltered(monorepos, rootDir);\n\n for (const monorepo of monorepos) {\n for (const pkgPath of monorepo.packagePaths) {\n const counts = analyzePackageDeps(pkgPath, packageMap);\n totalLink += counts.linkCount;\n totalNpm += counts.npmCount;\n totalWorkspace += counts.workspaceCount;\n }\n }\n\n diagnostics = diagnose(monorepos, packageMap, rootDir);\n } catch (err) {\n loader.fail('Analysis failed');\n handleError(ctx, err, outputJson);\n return { ok: false, error: 'Unable to read DevLink status' };\n }\n\n loader.succeed('Analysis complete');\n tracker.checkpoint('analysis');\n\n const errors = diagnostics.filter(d => d.severity === 'error');\n const warnings = diagnostics.filter(d => d.severity === 'warning');\n\n const result: StatusResult = {\n currentMode: state.currentMode,\n lastApplied: state.lastApplied,\n linkCount: totalLink,\n npmCount: totalNpm,\n workspaceCount: totalWorkspace,\n discrepancies: [],\n diagnostics,\n };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n const sections = [\n {\n header: 'Current mode',\n items: [\n `Mode: ${state.currentMode ?? 'unknown'}`,\n `Last applied: ${state.lastApplied ?? 'never'}`,\n ],\n },\n {\n header: 'Dependency counts',\n items: [\n `link: (local) : ${totalLink}`,\n `npm (^version) : ${totalNpm}`,\n `workspace:* : ${totalWorkspace}`,\n ],\n },\n ];\n\n if (errors.length > 0) {\n sections.push({\n header: `❌ Errors (${errors.length})`,\n items: errors.slice(0, 10).map(d => `${d.dep ?? d.file}: ${d.message}`),\n });\n }\n\n if (warnings.length > 0) {\n sections.push({\n header: `⚠ Warnings (${warnings.length})`,\n items: warnings.slice(0, 10).map(d => `${d.dep ?? d.file}: ${d.message}`),\n });\n }\n\n if (diagnostics.length === 0) {\n sections.push({ header: '✅ Health', items: ['No issues detected'] });\n } else {\n sections.push({\n header: 'Fix',\n items: ['Run: kb devlink switch --mode=local --install'],\n });\n }\n\n ctx.ui?.success?.('Dependency status', {\n title: 'DevLink — Status',\n sections,\n timing: tracker.total(),\n });\n }\n\n return { ok: true, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
@@ -58,7 +58,7 @@ var switch_default = defineCommand({
58
58
  } catch (err) {
59
59
  discoverLoader.fail("Discovery failed");
60
60
  handleError(ctx, err, outputJson);
61
- return { exitCode: 1 };
61
+ return { ok: false, error: "Switch operation failed" };
62
62
  }
63
63
  discoverLoader.succeed(`Found ${monorepos.length} monorepos, ${Object.keys(packageMap).length} packages`);
64
64
  tracker.checkpoint("discovery");
@@ -70,7 +70,7 @@ var switch_default = defineCommand({
70
70
  tracker.checkpoint("plan");
71
71
  if (plan.items.length === 0 && !flags.install) {
72
72
  ctx.ui?.info?.("No changes needed \u2014 dependencies are already in the requested mode.");
73
- return { exitCode: 0, result: { mode, changed: 0 }, meta: { timing: tracker.total() } };
73
+ return { ok: true, result: { mode, changed: 0 }, meta: { timing: tracker.total() } };
74
74
  }
75
75
  const currentState = loadState(rootDir);
76
76
  const modeAtBackup = currentState.currentMode ?? mode;
@@ -202,7 +202,7 @@ var switch_default = defineCommand({
202
202
  timing: tracker.total()
203
203
  });
204
204
  }
205
- return { exitCode: 0, result, meta: { timing: tracker.total() } };
205
+ return { ok: true, result, meta: { timing: tracker.total() } };
206
206
  }
207
207
  }
208
208
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/switch.ts"],"names":[],"mappings":"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","file":"switch.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult, type CLIInput } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, buildPlan, applyPlan, createBackup, loadState, saveState, checkGitDirty, updateWorkspaceYamls } from '@kb-labs/devlink-core';\nimport type { DevlinkMode } from '@kb-labs/devlink-contracts';\nimport { existsSync, unlinkSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { execSync } from 'node:child_process';\n\ninterface SwitchFlags {\n mode: DevlinkMode;\n 'dry-run'?: boolean;\n repos?: string;\n yes?: boolean;\n json?: boolean;\n ttl?: number;\n install?: boolean;\n 'clean-locks'?: boolean;\n}\n\ninterface SwitchResult {\n mode: DevlinkMode;\n changed: number;\n backupId?: string;\n}\n\nexport default defineCommand<unknown, CLIInput<SwitchFlags>, SwitchResult>({\n id: 'devlink:switch',\n description: 'Switch cross-repo deps between link: and npm mode',\n\n handler: {\n async intent(ctx: PluginContextV3, input: CLIInput<SwitchFlags>) {\n const flags = input.flags;\n const mode = flags.mode;\n const rootDir = ctx.cwd ?? process.cwd();\n const scopedRepos = flags.repos ? flags.repos.split(',').map(s => s.trim()) : undefined;\n const ttlMs = (flags.ttl ?? 24) * 60 * 60 * 1000;\n\n let monorepos;\n let packageMap;\n try {\n monorepos = discoverMonorepos(rootDir);\n packageMap = await buildPackageMapFiltered(monorepos, rootDir, ttlMs, mode);\n } catch {\n return {\n summary: `Switch dependencies to ${mode ?? '(unknown)'} mode`,\n operations: [{ type: 'update' as const, resource: 'package-json', details: { mode } }],\n };\n }\n\n const plan = buildPlan(mode, packageMap, monorepos, rootDir, { scopedRepos });\n const byRepo = new Map<string, number>();\n for (const item of plan.items) {\n byRepo.set(item.monorepo, (byRepo.get(item.monorepo) ?? 0) + 1);\n }\n\n return {\n summary: `Switch ${plan.items.length} dependencies to ${mode} mode across ${byRepo.size} repo(s)`,\n operations: [...byRepo.entries()].map(([repo, count]) => ({\n type: 'update' as const,\n resource: 'dependencies',\n details: { repo, count, mode },\n })),\n };\n },\n\n async execute(ctx: PluginContextV3, input: CLIInput<SwitchFlags>): Promise<CommandResult<SwitchResult>> {\n const tracker = new TimingTracker();\n const flags = input.flags;\n const mode = flags.mode;\n const outputJson = flags.json ?? false;\n const scopedRepos = flags.repos ? flags.repos.split(',').map(s => s.trim()) : undefined;\n const ttlMs = (flags.ttl ?? 24) * 60 * 60 * 1000;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n // 1. Discover\n const discoverLoader = useLoader('Discovering monorepos...');\n discoverLoader.start();\n\n let monorepos;\n let packageMap;\n try {\n monorepos = discoverMonorepos(rootDir);\n packageMap = await buildPackageMapFiltered(monorepos, rootDir, ttlMs, mode);\n } catch (err) {\n discoverLoader.fail('Discovery failed');\n handleError(ctx, err, outputJson);\n return { exitCode: 1 };\n }\n discoverLoader.succeed(`Found ${monorepos.length} monorepos, ${Object.keys(packageMap).length} packages`);\n tracker.checkpoint('discovery');\n\n // 2. Warn if git dirty\n const dirtyFiles = checkGitDirty(rootDir);\n if (dirtyFiles.length > 0) {\n ctx.ui?.warn?.(`Working tree has ${dirtyFiles.length} uncommitted changes`);\n }\n\n // 3. Build plan\n const plan = buildPlan(mode, packageMap, monorepos, rootDir, { scopedRepos });\n tracker.checkpoint('plan');\n\n if (plan.items.length === 0 && !flags.install) {\n ctx.ui?.info?.('No changes needed — dependencies are already in the requested mode.');\n return { exitCode: 0, result: { mode, changed: 0 }, meta: { timing: tracker.total() } };\n }\n\n // 4. Always create backup (even if no deps change — install cleans node_modules)\n const currentState = loadState(rootDir);\n const modeAtBackup = currentState.currentMode ?? mode;\n const allPackageJsons = monorepos.flatMap(m => m.packagePaths);\n const backup = createBackup(rootDir, allPackageJsons, `pre-switch to ${mode}`, modeAtBackup);\n const backupId = backup.id;\n tracker.checkpoint('backup');\n\n // 6. Apply dep changes (if any)\n let applyResult = { applied: 0, skipped: 0, errors: [] as Array<{ file: string; error: string }> };\n if (plan.items.length > 0) {\n const applyLoader = useLoader(`Switching ${plan.items.length} dependencies to ${mode} mode...`);\n applyLoader.start();\n applyResult = await applyPlan(plan, { dryRun: false });\n applyLoader.succeed(`Applied ${applyResult.applied} change(s)`);\n tracker.checkpoint('apply');\n }\n\n // 7. Update sub-repo pnpm-workspace.yaml with correct cross-repo paths\n const wsLoader = useLoader('Updating sub-repo workspace files...');\n wsLoader.start();\n const wsUpdates = updateWorkspaceYamls(monorepos, packageMap, rootDir);\n const wsChanged = wsUpdates.reduce((sum, u) => sum + u.added.length + u.removed.length, 0);\n wsLoader.succeed(wsChanged > 0\n ? `Updated ${wsUpdates.length} workspace file(s) (${wsChanged} path changes)`\n : 'Workspace files up to date'\n );\n tracker.checkpoint('workspace-yaml');\n\n // 8. Save state\n saveState(rootDir, {\n currentMode: mode,\n lastApplied: new Date().toISOString(),\n frozenAt: currentState.frozenAt,\n });\n\n // 9. Clean stale lockfiles + node_modules in all sub-repos (default: true)\n const shouldClean = flags['clean-locks'] !== false;\n let cleanedLocks = 0;\n let cleanedNodeModules = 0;\n if (shouldClean) {\n const cleanLoader = useLoader('Cleaning stale lockfiles and node_modules...');\n cleanLoader.start();\n for (const mono of monorepos) {\n // Clean lockfile\n const lockPath = join(mono.rootPath, 'pnpm-lock.yaml');\n if (existsSync(lockPath)) {\n try { unlinkSync(lockPath); cleanedLocks++; } catch { /* skip */ }\n }\n // Clean node_modules (contains stale shims with hardcoded paths)\n const nmPath = join(mono.rootPath, 'node_modules');\n if (existsSync(nmPath)) {\n try { rmSync(nmPath, { recursive: true, force: true }); cleanedNodeModules++; } catch { /* skip */ }\n }\n }\n cleanLoader.succeed(\n `Cleaned ${cleanedLocks} lockfile(s), ${cleanedNodeModules} node_modules`\n );\n tracker.checkpoint('clean');\n }\n\n // 10. Install: workspace root first, then per-sub-repo\n const shouldInstall = flags.install === true;\n let installedRepos = 0;\n const installErrors: string[] = [];\n if (shouldInstall) {\n // Phase 1: workspace root install\n const rootLoader = useLoader('Installing workspace root...');\n rootLoader.start();\n try {\n execSync('pnpm install --no-frozen-lockfile', {\n cwd: rootDir,\n stdio: 'pipe',\n timeout: 180_000,\n });\n rootLoader.succeed('Workspace root installed');\n } catch (err) {\n rootLoader.succeed('Workspace root install failed');\n installErrors.push(`root: ${err instanceof Error ? err.message.split('\\n')[0] : String(err)}`);\n }\n tracker.checkpoint('root-install');\n\n // Phase 2: per-sub-repo install (affected + repos missing lockfile)\n const affectedRepos = new Set(plan.items.map(i => i.monorepo));\n const affectedMonorepos = monorepos.filter(m =>\n affectedRepos.has(m.name) || !existsSync(join(m.rootPath, 'pnpm-lock.yaml'))\n );\n const repoLoader = useLoader(`Installing ${affectedMonorepos.length} sub-repo(s)...`);\n repoLoader.start();\n for (const mono of affectedMonorepos) {\n try {\n execSync('pnpm install --no-frozen-lockfile --prefer-offline', {\n cwd: mono.rootPath,\n stdio: 'pipe',\n timeout: 300_000, // 5 min per sub-repo\n });\n installedRepos++;\n } catch (err) {\n installErrors.push(`${mono.name}: ${err instanceof Error ? err.message.split('\\n')[0] : String(err)}`);\n }\n }\n repoLoader.succeed(`Installed ${installedRepos}/${affectedMonorepos.length} sub-repo(s)${installErrors.length > 0 ? `, ${installErrors.length} failed` : ''}`);\n tracker.checkpoint('sub-repo-install');\n }\n\n // 11. Output\n const result: SwitchResult = {\n mode,\n changed: applyResult.applied,\n backupId,\n };\n\n if (outputJson) {\n ctx.ui?.json?.({ ...result, cleanedLocks, wsUpdates: wsUpdates.length, installedRepos, installErrors });\n } else {\n const summaryItems = [\n `Mode: ${mode}`,\n `Changed: ${applyResult.applied} dependencies`,\n `Backup: ${backupId}`,\n ];\n if (wsChanged > 0) {\n summaryItems.push(`Workspace YAMLs: ${wsUpdates.length} updated`);\n }\n if (cleanedLocks > 0 || cleanedNodeModules > 0) {\n summaryItems.push(`Cleaned: ${cleanedLocks} lockfile(s), ${cleanedNodeModules} node_modules`);\n }\n if (shouldInstall) {\n summaryItems.push(`Installed: root + ${installedRepos} sub-repo(s)`);\n }\n\n const sections = [\n { header: 'Summary', items: summaryItems },\n ...(applyResult.errors.length > 0\n ? [{ header: 'Errors', items: applyResult.errors.map(e => `${e.file}: ${e.error}`) }]\n : []),\n ...(installErrors.length > 0\n ? [{ header: 'Install errors', items: installErrors }]\n : []),\n ...(!shouldInstall && applyResult.applied > 0\n ? [{ header: 'Next step', items: ['Re-run with --install to complete setup'] }]\n : []),\n ];\n ctx.ui?.success?.(`Switched to ${mode} mode`, {\n title: 'DevLink — Switch',\n sections,\n timing: tracker.total(),\n });\n }\n\n return { exitCode: 0, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/switch.ts"],"names":[],"mappings":"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","file":"switch.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, handleError, type PluginContextV3, type CommandResult, type CLIInput } from '@kb-labs/sdk';\nimport { discoverMonorepos, buildPackageMapFiltered, buildPlan, applyPlan, createBackup, loadState, saveState, checkGitDirty, updateWorkspaceYamls } from '@kb-labs/devlink-core';\nimport type { DevlinkMode } from '@kb-labs/devlink-contracts';\nimport { existsSync, unlinkSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { execSync } from 'node:child_process';\n\ninterface SwitchFlags {\n mode: DevlinkMode;\n 'dry-run'?: boolean;\n repos?: string;\n yes?: boolean;\n json?: boolean;\n ttl?: number;\n install?: boolean;\n 'clean-locks'?: boolean;\n}\n\ninterface SwitchResult {\n mode: DevlinkMode;\n changed: number;\n backupId?: string;\n}\n\nexport default defineCommand<unknown, CLIInput<SwitchFlags>, SwitchResult>({\n id: 'devlink:switch',\n description: 'Switch cross-repo deps between link: and npm mode',\n\n handler: {\n async intent(ctx: PluginContextV3, input: CLIInput<SwitchFlags>) {\n const flags = input.flags;\n const mode = flags.mode;\n const rootDir = ctx.cwd ?? process.cwd();\n const scopedRepos = flags.repos ? flags.repos.split(',').map(s => s.trim()) : undefined;\n const ttlMs = (flags.ttl ?? 24) * 60 * 60 * 1000;\n\n let monorepos;\n let packageMap;\n try {\n monorepos = discoverMonorepos(rootDir);\n packageMap = await buildPackageMapFiltered(monorepos, rootDir, ttlMs, mode);\n } catch {\n return {\n summary: `Switch dependencies to ${mode ?? '(unknown)'} mode`,\n operations: [{ type: 'update' as const, resource: 'package-json', details: { mode } }],\n };\n }\n\n const plan = buildPlan(mode, packageMap, monorepos, rootDir, { scopedRepos });\n const byRepo = new Map<string, number>();\n for (const item of plan.items) {\n byRepo.set(item.monorepo, (byRepo.get(item.monorepo) ?? 0) + 1);\n }\n\n return {\n summary: `Switch ${plan.items.length} dependencies to ${mode} mode across ${byRepo.size} repo(s)`,\n operations: [...byRepo.entries()].map(([repo, count]) => ({\n type: 'update' as const,\n resource: 'dependencies',\n details: { repo, count, mode },\n })),\n };\n },\n\n async execute(ctx: PluginContextV3, input: CLIInput<SwitchFlags>): Promise<CommandResult<SwitchResult>> {\n const tracker = new TimingTracker();\n const flags = input.flags;\n const mode = flags.mode;\n const outputJson = flags.json ?? false;\n const scopedRepos = flags.repos ? flags.repos.split(',').map(s => s.trim()) : undefined;\n const ttlMs = (flags.ttl ?? 24) * 60 * 60 * 1000;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n // 1. Discover\n const discoverLoader = useLoader('Discovering monorepos...');\n discoverLoader.start();\n\n let monorepos;\n let packageMap;\n try {\n monorepos = discoverMonorepos(rootDir);\n packageMap = await buildPackageMapFiltered(monorepos, rootDir, ttlMs, mode);\n } catch (err) {\n discoverLoader.fail('Discovery failed');\n handleError(ctx, err, outputJson);\n return { ok: false, error: 'Switch operation failed' };\n }\n discoverLoader.succeed(`Found ${monorepos.length} monorepos, ${Object.keys(packageMap).length} packages`);\n tracker.checkpoint('discovery');\n\n // 2. Warn if git dirty\n const dirtyFiles = checkGitDirty(rootDir);\n if (dirtyFiles.length > 0) {\n ctx.ui?.warn?.(`Working tree has ${dirtyFiles.length} uncommitted changes`);\n }\n\n // 3. Build plan\n const plan = buildPlan(mode, packageMap, monorepos, rootDir, { scopedRepos });\n tracker.checkpoint('plan');\n\n if (plan.items.length === 0 && !flags.install) {\n ctx.ui?.info?.('No changes needed — dependencies are already in the requested mode.');\n return { ok: true, result: { mode, changed: 0 }, meta: { timing: tracker.total() } };\n }\n\n // 4. Always create backup (even if no deps change — install cleans node_modules)\n const currentState = loadState(rootDir);\n const modeAtBackup = currentState.currentMode ?? mode;\n const allPackageJsons = monorepos.flatMap(m => m.packagePaths);\n const backup = createBackup(rootDir, allPackageJsons, `pre-switch to ${mode}`, modeAtBackup);\n const backupId = backup.id;\n tracker.checkpoint('backup');\n\n // 6. Apply dep changes (if any)\n let applyResult = { applied: 0, skipped: 0, errors: [] as Array<{ file: string; error: string }> };\n if (plan.items.length > 0) {\n const applyLoader = useLoader(`Switching ${plan.items.length} dependencies to ${mode} mode...`);\n applyLoader.start();\n applyResult = await applyPlan(plan, { dryRun: false });\n applyLoader.succeed(`Applied ${applyResult.applied} change(s)`);\n tracker.checkpoint('apply');\n }\n\n // 7. Update sub-repo pnpm-workspace.yaml with correct cross-repo paths\n const wsLoader = useLoader('Updating sub-repo workspace files...');\n wsLoader.start();\n const wsUpdates = updateWorkspaceYamls(monorepos, packageMap, rootDir);\n const wsChanged = wsUpdates.reduce((sum, u) => sum + u.added.length + u.removed.length, 0);\n wsLoader.succeed(wsChanged > 0\n ? `Updated ${wsUpdates.length} workspace file(s) (${wsChanged} path changes)`\n : 'Workspace files up to date'\n );\n tracker.checkpoint('workspace-yaml');\n\n // 8. Save state\n saveState(rootDir, {\n currentMode: mode,\n lastApplied: new Date().toISOString(),\n frozenAt: currentState.frozenAt,\n });\n\n // 9. Clean stale lockfiles + node_modules in all sub-repos (default: true)\n const shouldClean = flags['clean-locks'] !== false;\n let cleanedLocks = 0;\n let cleanedNodeModules = 0;\n if (shouldClean) {\n const cleanLoader = useLoader('Cleaning stale lockfiles and node_modules...');\n cleanLoader.start();\n for (const mono of monorepos) {\n // Clean lockfile\n const lockPath = join(mono.rootPath, 'pnpm-lock.yaml');\n if (existsSync(lockPath)) {\n try { unlinkSync(lockPath); cleanedLocks++; } catch { /* skip */ }\n }\n // Clean node_modules (contains stale shims with hardcoded paths)\n const nmPath = join(mono.rootPath, 'node_modules');\n if (existsSync(nmPath)) {\n try { rmSync(nmPath, { recursive: true, force: true }); cleanedNodeModules++; } catch { /* skip */ }\n }\n }\n cleanLoader.succeed(\n `Cleaned ${cleanedLocks} lockfile(s), ${cleanedNodeModules} node_modules`\n );\n tracker.checkpoint('clean');\n }\n\n // 10. Install: workspace root first, then per-sub-repo\n const shouldInstall = flags.install === true;\n let installedRepos = 0;\n const installErrors: string[] = [];\n if (shouldInstall) {\n // Phase 1: workspace root install\n const rootLoader = useLoader('Installing workspace root...');\n rootLoader.start();\n try {\n execSync('pnpm install --no-frozen-lockfile', {\n cwd: rootDir,\n stdio: 'pipe',\n timeout: 180_000,\n });\n rootLoader.succeed('Workspace root installed');\n } catch (err) {\n rootLoader.succeed('Workspace root install failed');\n installErrors.push(`root: ${err instanceof Error ? err.message.split('\\n')[0] : String(err)}`);\n }\n tracker.checkpoint('root-install');\n\n // Phase 2: per-sub-repo install (affected + repos missing lockfile)\n const affectedRepos = new Set(plan.items.map(i => i.monorepo));\n const affectedMonorepos = monorepos.filter(m =>\n affectedRepos.has(m.name) || !existsSync(join(m.rootPath, 'pnpm-lock.yaml'))\n );\n const repoLoader = useLoader(`Installing ${affectedMonorepos.length} sub-repo(s)...`);\n repoLoader.start();\n for (const mono of affectedMonorepos) {\n try {\n execSync('pnpm install --no-frozen-lockfile --prefer-offline', {\n cwd: mono.rootPath,\n stdio: 'pipe',\n timeout: 300_000, // 5 min per sub-repo\n });\n installedRepos++;\n } catch (err) {\n installErrors.push(`${mono.name}: ${err instanceof Error ? err.message.split('\\n')[0] : String(err)}`);\n }\n }\n repoLoader.succeed(`Installed ${installedRepos}/${affectedMonorepos.length} sub-repo(s)${installErrors.length > 0 ? `, ${installErrors.length} failed` : ''}`);\n tracker.checkpoint('sub-repo-install');\n }\n\n // 11. Output\n const result: SwitchResult = {\n mode,\n changed: applyResult.applied,\n backupId,\n };\n\n if (outputJson) {\n ctx.ui?.json?.({ ...result, cleanedLocks, wsUpdates: wsUpdates.length, installedRepos, installErrors });\n } else {\n const summaryItems = [\n `Mode: ${mode}`,\n `Changed: ${applyResult.applied} dependencies`,\n `Backup: ${backupId}`,\n ];\n if (wsChanged > 0) {\n summaryItems.push(`Workspace YAMLs: ${wsUpdates.length} updated`);\n }\n if (cleanedLocks > 0 || cleanedNodeModules > 0) {\n summaryItems.push(`Cleaned: ${cleanedLocks} lockfile(s), ${cleanedNodeModules} node_modules`);\n }\n if (shouldInstall) {\n summaryItems.push(`Installed: root + ${installedRepos} sub-repo(s)`);\n }\n\n const sections = [\n { header: 'Summary', items: summaryItems },\n ...(applyResult.errors.length > 0\n ? [{ header: 'Errors', items: applyResult.errors.map(e => `${e.file}: ${e.error}`) }]\n : []),\n ...(installErrors.length > 0\n ? [{ header: 'Install errors', items: installErrors }]\n : []),\n ...(!shouldInstall && applyResult.applied > 0\n ? [{ header: 'Next step', items: ['Re-run with --install to complete setup'] }]\n : []),\n ];\n ctx.ui?.success?.(`Switched to ${mode} mode`, {\n title: 'DevLink — Switch',\n sections,\n timing: tracker.total(),\n });\n }\n\n return { ok: true, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
@@ -22,7 +22,7 @@ var undo_default = defineCommand({
22
22
  const backup = getLastBackup(rootDir);
23
23
  if (!backup) {
24
24
  validationError(ctx, "No backups found. Run switch first to create a backup.", void 0, outputJson);
25
- return { exitCode: 1 };
25
+ return { ok: false, error: "Undo operation failed" };
26
26
  }
27
27
  const loader = useLoader(`Restoring from backup ${backup.id}...`);
28
28
  loader.start();
@@ -33,7 +33,7 @@ var undo_default = defineCommand({
33
33
  } catch (err) {
34
34
  loader.fail("Restore failed");
35
35
  handleError(ctx, err, outputJson);
36
- return { exitCode: 1 };
36
+ return { ok: false, error: "Undo operation failed" };
37
37
  }
38
38
  loader.succeed(`Restored ${restored} file(s)`);
39
39
  tracker.checkpoint("restore");
@@ -64,7 +64,7 @@ var undo_default = defineCommand({
64
64
  timing: tracker.total()
65
65
  });
66
66
  }
67
- return { exitCode: errors.length > 0 ? 1 : 0, result, meta: { timing: tracker.total() } };
67
+ return errors.length > 0 ? { ok: false, error: `${errors.length} undo operation(s) failed`, result, meta: { timing: tracker.total() } } : { ok: true, result, meta: { timing: tracker.total() } };
68
68
  }
69
69
  }
70
70
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/undo.ts"],"names":[],"mappings":"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","file":"undo.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { getLastBackup, restoreBackup, saveState, loadState } from '@kb-labs/devlink-core';\n\ninterface UndoFlags {\n json?: boolean;\n}\n\ninterface UndoInput {\n argv?: string[];\n flags?: UndoFlags;\n json?: boolean;\n}\n\ninterface UndoResult {\n restored: number;\n backupId: string;\n errors: string[];\n}\n\nexport default defineCommand<unknown, UndoInput, UndoResult>({\n id: 'devlink:undo',\n description: 'Restore previous dependency state from last backup',\n\n handler: {\n async intent(_ctx: PluginContextV3, _input: UndoInput) {\n return {\n summary: 'Restore previous dependency state from last backup',\n operations: [\n { type: 'update' as const, resource: 'package-json-files', details: { source: 'last-backup' } },\n ],\n };\n },\n\n async execute(ctx: PluginContextV3, input: UndoInput): Promise<CommandResult<UndoResult>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as UndoFlags;\n const outputJson = flags.json ?? false;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const backup = getLastBackup(rootDir);\n if (!backup) {\n validationError(ctx, 'No backups found. Run switch first to create a backup.', undefined, outputJson);\n return { exitCode: 1 };\n }\n\n const loader = useLoader(`Restoring from backup ${backup.id}...`);\n loader.start();\n\n let restored: number;\n let errors: string[];\n try {\n ({ restored, errors } = restoreBackup(rootDir, backup.id));\n } catch (err) {\n loader.fail('Restore failed');\n handleError(ctx, err, outputJson);\n return { exitCode: 1 };\n }\n loader.succeed(`Restored ${restored} file(s)`);\n tracker.checkpoint('restore');\n\n // Update state to backup's previous mode\n const currentState = loadState(rootDir);\n saveState(rootDir, {\n ...currentState,\n currentMode: backup.modeAtBackup,\n lastApplied: new Date().toISOString(),\n });\n\n const result: UndoResult = { restored, backupId: backup.id, errors };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n ctx.ui?.success?.(`Restored from backup (mode: ${backup.modeAtBackup ?? 'unknown'})`, {\n title: 'DevLink — Undo',\n sections: [\n {\n header: 'Summary',\n items: [\n `Backup ID: ${backup.id}`,\n `Created: ${backup.timestamp}`,\n `Restored files: ${restored}`,\n ],\n },\n ...(errors.length > 0 ? [{ header: 'Errors', items: errors }] : []),\n { header: 'Next step', items: ['Run pnpm install to apply changes'] },\n ],\n timing: tracker.total(),\n });\n }\n\n return { exitCode: errors.length > 0 ? 1 : 0, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/undo.ts"],"names":[],"mappings":"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","file":"undo.js","sourcesContent":["import { defineCommand, useLoader, TimingTracker, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { getLastBackup, restoreBackup, saveState, loadState } from '@kb-labs/devlink-core';\n\ninterface UndoFlags {\n json?: boolean;\n}\n\ninterface UndoInput {\n argv?: string[];\n flags?: UndoFlags;\n json?: boolean;\n}\n\ninterface UndoResult {\n restored: number;\n backupId: string;\n errors: string[];\n}\n\nexport default defineCommand<unknown, UndoInput, UndoResult>({\n id: 'devlink:undo',\n description: 'Restore previous dependency state from last backup',\n\n handler: {\n async intent(_ctx: PluginContextV3, _input: UndoInput) {\n return {\n summary: 'Restore previous dependency state from last backup',\n operations: [\n { type: 'update' as const, resource: 'package-json-files', details: { source: 'last-backup' } },\n ],\n };\n },\n\n async execute(ctx: PluginContextV3, input: UndoInput): Promise<CommandResult<UndoResult>> {\n const tracker = new TimingTracker();\n const flags = (input.flags ?? input) as UndoFlags;\n const outputJson = flags.json ?? false;\n\n const rootDir = ctx.cwd ?? process.cwd();\n\n const backup = getLastBackup(rootDir);\n if (!backup) {\n validationError(ctx, 'No backups found. Run switch first to create a backup.', undefined, outputJson);\n return { ok: false, error: 'Undo operation failed' };\n }\n\n const loader = useLoader(`Restoring from backup ${backup.id}...`);\n loader.start();\n\n let restored: number;\n let errors: string[];\n try {\n ({ restored, errors } = restoreBackup(rootDir, backup.id));\n } catch (err) {\n loader.fail('Restore failed');\n handleError(ctx, err, outputJson);\n return { ok: false, error: 'Undo operation failed' };\n }\n loader.succeed(`Restored ${restored} file(s)`);\n tracker.checkpoint('restore');\n\n // Update state to backup's previous mode\n const currentState = loadState(rootDir);\n saveState(rootDir, {\n ...currentState,\n currentMode: backup.modeAtBackup,\n lastApplied: new Date().toISOString(),\n });\n\n const result: UndoResult = { restored, backupId: backup.id, errors };\n\n if (outputJson) {\n ctx.ui?.json?.(result);\n } else {\n ctx.ui?.success?.(`Restored from backup (mode: ${backup.modeAtBackup ?? 'unknown'})`, {\n title: 'DevLink — Undo',\n sections: [\n {\n header: 'Summary',\n items: [\n `Backup ID: ${backup.id}`,\n `Created: ${backup.timestamp}`,\n `Restored files: ${restored}`,\n ],\n },\n ...(errors.length > 0 ? [{ header: 'Errors', items: errors }] : []),\n { header: 'Next step', items: ['Run pnpm install to apply changes'] },\n ],\n timing: tracker.total(),\n });\n }\n\n return errors.length > 0\n ? { ok: false, error: `${errors.length} undo operation(s) failed`, result, meta: { timing: tracker.total() } }\n : { ok: true, result, meta: { timing: tracker.total() } };\n },\n },\n});\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kb-labs/devlink-entry",
3
3
  "description": "CLI commands and manifest for DevLink plugin.",
4
- "version": "2.109.0",
4
+ "version": "2.110.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -32,8 +32,8 @@
32
32
  "type-check": "tsc --noEmit"
33
33
  },
34
34
  "dependencies": {
35
- "@kb-labs/devlink-contracts": "^2.109.0",
36
- "@kb-labs/devlink-core": "^2.109.0",
35
+ "@kb-labs/devlink-contracts": "^2.110.0",
36
+ "@kb-labs/devlink-core": "^2.110.0",
37
37
  "@kb-labs/sdk": "workspace:*"
38
38
  },
39
39
  "devDependencies": {