@git.zone/cli 2.14.3 → 2.15.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.
Files changed (46) hide show
  1. package/.smartconfig.json +36 -11
  2. package/assets/templates/service/npmextra.json +8 -2
  3. package/assets/templates/smartconfig/_smartconfig.json +5 -1
  4. package/assets/templates/website/npmextra.json +8 -2
  5. package/dist_ts/00_commitinfo_data.js +1 -1
  6. package/dist_ts/gitzone.cli.js +8 -1
  7. package/dist_ts/helpers.changelog.d.ts +16 -0
  8. package/dist_ts/helpers.changelog.js +114 -0
  9. package/dist_ts/helpers.smartconfigmigrations.d.ts +7 -0
  10. package/dist_ts/helpers.smartconfigmigrations.js +161 -0
  11. package/dist_ts/helpers.workflow.d.ts +97 -0
  12. package/dist_ts/helpers.workflow.js +258 -0
  13. package/dist_ts/mod_commit/index.js +190 -303
  14. package/dist_ts/mod_commit/mod.helpers.d.ts +23 -0
  15. package/dist_ts/mod_commit/mod.helpers.js +22 -15
  16. package/dist_ts/mod_commit/mod.ui.d.ts +1 -1
  17. package/dist_ts/mod_commit/mod.ui.js +7 -2
  18. package/dist_ts/mod_config/classes.commitconfig.d.ts +6 -0
  19. package/dist_ts/mod_config/classes.commitconfig.js +28 -4
  20. package/dist_ts/mod_config/classes.releaseconfig.js +13 -7
  21. package/dist_ts/mod_config/index.js +77 -29
  22. package/dist_ts/mod_format/formatters/smartconfig.formatter.js +3 -57
  23. package/dist_ts/mod_release/index.d.ts +3 -0
  24. package/dist_ts/mod_release/index.js +299 -0
  25. package/dist_ts/mod_release/mod.plugins.d.ts +3 -0
  26. package/dist_ts/mod_release/mod.plugins.js +4 -0
  27. package/dist_ts/mod_standard/index.js +16 -3
  28. package/license +2 -2
  29. package/package.json +20 -30
  30. package/readme.hints.md +15 -17
  31. package/readme.md +239 -421
  32. package/ts/00_commitinfo_data.ts +1 -1
  33. package/ts/gitzone.cli.ts +8 -0
  34. package/ts/helpers.changelog.ts +165 -0
  35. package/ts/helpers.smartconfigmigrations.ts +192 -0
  36. package/ts/helpers.workflow.ts +387 -0
  37. package/ts/mod_commit/index.ts +233 -435
  38. package/ts/mod_commit/mod.helpers.ts +28 -16
  39. package/ts/mod_commit/mod.ui.ts +7 -2
  40. package/ts/mod_config/classes.commitconfig.ts +33 -3
  41. package/ts/mod_config/classes.releaseconfig.ts +14 -7
  42. package/ts/mod_config/index.ts +89 -28
  43. package/ts/mod_format/formatters/smartconfig.formatter.ts +2 -62
  44. package/ts/mod_release/index.ts +393 -0
  45. package/ts/mod_release/mod.plugins.ts +5 -0
  46. package/ts/mod_standard/index.ts +15 -2
@@ -63,7 +63,7 @@ export async function detectProjectType(): Promise<ProjectType> {
63
63
  * @param versionType Type of version bump
64
64
  * @returns New version string
65
65
  */
66
- function calculateNewVersion(currentVersion: string, versionType: VersionType): string {
66
+ export function calculateNewVersion(currentVersion: string, versionType: VersionType): string {
67
67
  const versionMatch = currentVersion.match(/^(\d+)\.(\d+)\.(\d+)/);
68
68
 
69
69
  if (!versionMatch) {
@@ -95,7 +95,7 @@ function calculateNewVersion(currentVersion: string, versionType: VersionType):
95
95
  * @param projectType The project type to determine which file to read
96
96
  * @returns The current version string
97
97
  */
98
- async function readCurrentVersion(projectType: ProjectType): Promise<string> {
98
+ export async function readCurrentVersion(projectType: ProjectType): Promise<string> {
99
99
  if (projectType === 'npm' || projectType === 'both') {
100
100
  const packageJsonPath = plugins.path.join(paths.cwd, 'package.json');
101
101
  const content = (await plugins.smartfs
@@ -128,7 +128,7 @@ async function readCurrentVersion(projectType: ProjectType): Promise<string> {
128
128
  * @param filePath Path to the JSON file
129
129
  * @param newVersion The new version to write
130
130
  */
131
- async function updateVersionFile(filePath: string, newVersion: string): Promise<void> {
131
+ export async function updateVersionFile(filePath: string, newVersion: string): Promise<void> {
132
132
  const content = (await plugins.smartfs
133
133
  .file(filePath)
134
134
  .encoding('utf8')
@@ -141,6 +141,30 @@ async function updateVersionFile(filePath: string, newVersion: string): Promise<
141
141
  .write(JSON.stringify(config, null, 2) + '\n');
142
142
  }
143
143
 
144
+ /**
145
+ * Updates project version files without creating commits or tags.
146
+ */
147
+ export async function updateProjectVersionFiles(
148
+ projectType: ProjectType,
149
+ newVersion: string,
150
+ ): Promise<string[]> {
151
+ const filesToUpdate: string[] = [];
152
+ const packageJsonPath = plugins.path.join(paths.cwd, 'package.json');
153
+ const denoJsonPath = plugins.path.join(paths.cwd, 'deno.json');
154
+
155
+ if (projectType === 'npm' || projectType === 'both') {
156
+ await updateVersionFile(packageJsonPath, newVersion);
157
+ filesToUpdate.push('package.json');
158
+ }
159
+
160
+ if (projectType === 'deno' || projectType === 'both') {
161
+ await updateVersionFile(denoJsonPath, newVersion);
162
+ filesToUpdate.push('deno.json');
163
+ }
164
+
165
+ return filesToUpdate;
166
+ }
167
+
144
168
  /**
145
169
  * Bumps the project version based on project type
146
170
  * Handles npm-only, deno-only, and dual projects with unified logic
@@ -182,19 +206,7 @@ export async function bumpProjectVersion(
182
206
  logger.log('info', `Bumping version: ${currentVersion} → ${newVersion}`);
183
207
 
184
208
  // 3. Determine which files to update
185
- const filesToUpdate: string[] = [];
186
- const packageJsonPath = plugins.path.join(paths.cwd, 'package.json');
187
- const denoJsonPath = plugins.path.join(paths.cwd, 'deno.json');
188
-
189
- if (projectType === 'npm' || projectType === 'both') {
190
- await updateVersionFile(packageJsonPath, newVersion);
191
- filesToUpdate.push('package.json');
192
- }
193
-
194
- if (projectType === 'deno' || projectType === 'both') {
195
- await updateVersionFile(denoJsonPath, newVersion);
196
- filesToUpdate.push('deno.json');
197
- }
209
+ const filesToUpdate = await updateProjectVersionFiles(projectType, newVersion);
198
210
 
199
211
  // 4. Stage all updated files
200
212
  await smartshellInstance.exec(`git add ${filesToUpdate.join(' ')}`);
@@ -10,7 +10,7 @@ interface ICommitSummary {
10
10
  commitType: string;
11
11
  commitScope: string;
12
12
  commitMessage: string;
13
- newVersion: string;
13
+ newVersion?: string;
14
14
  commitSha?: string;
15
15
  pushed: boolean;
16
16
  repoUrl?: string;
@@ -197,9 +197,14 @@ export function printSummary(summary: ICommitSummary): void {
197
197
  `Branch: 🌿 ${summary.branch}`,
198
198
  `Commit Type: ${getCommitTypeEmoji(summary.commitType)}`,
199
199
  `Scope: 📍 ${summary.commitScope}`,
200
- `New Version: 🏷️ v${summary.newVersion}`,
201
200
  ];
202
201
 
202
+ if (summary.newVersion) {
203
+ lines.push(`New Version: 🏷️ v${summary.newVersion}`);
204
+ } else {
205
+ lines.push(`Version: ⊘ Not bumped`);
206
+ }
207
+
203
208
  if (summary.commitSha) {
204
209
  lines.push(`Commit SHA: 📌 ${summary.commitSha}`);
205
210
  }
@@ -3,6 +3,8 @@ import * as plugins from './mod.plugins.js';
3
3
  export interface ICommitConfig {
4
4
  alwaysTest: boolean;
5
5
  alwaysBuild: boolean;
6
+ confirmation: 'prompt' | 'auto' | 'plan';
7
+ steps: string[];
6
8
  }
7
9
 
8
10
  /**
@@ -15,7 +17,7 @@ export class CommitConfig {
15
17
 
16
18
  constructor(cwd: string = process.cwd()) {
17
19
  this.cwd = cwd;
18
- this.config = { alwaysTest: false, alwaysBuild: false };
20
+ this.config = { alwaysTest: false, alwaysBuild: false, confirmation: 'prompt', steps: ['analyze', 'changelog', 'commit'] };
19
21
  }
20
22
 
21
23
  /**
@@ -34,9 +36,19 @@ export class CommitConfig {
34
36
  const smartconfigInstance = new plugins.smartconfig.Smartconfig(this.cwd);
35
37
  const gitzoneConfig = smartconfigInstance.dataFor<any>('@git.zone/cli', {});
36
38
 
39
+ const alwaysTest = gitzoneConfig?.commit?.alwaysTest ?? false;
40
+ const alwaysBuild = gitzoneConfig?.commit?.alwaysBuild ?? false;
37
41
  this.config = {
38
- alwaysTest: gitzoneConfig?.commit?.alwaysTest ?? false,
39
- alwaysBuild: gitzoneConfig?.commit?.alwaysBuild ?? false,
42
+ alwaysTest,
43
+ alwaysBuild,
44
+ confirmation: gitzoneConfig?.commit?.confirmation ?? 'prompt',
45
+ steps: gitzoneConfig?.commit?.steps || [
46
+ 'analyze',
47
+ ...(alwaysTest ? ['test'] : []),
48
+ ...(alwaysBuild ? ['build'] : []),
49
+ 'changelog',
50
+ 'commit',
51
+ ],
40
52
  };
41
53
  }
42
54
 
@@ -66,6 +78,8 @@ export class CommitConfig {
66
78
  // Update commit settings
67
79
  smartconfigData['@git.zone/cli'].commit.alwaysTest = this.config.alwaysTest;
68
80
  smartconfigData['@git.zone/cli'].commit.alwaysBuild = this.config.alwaysBuild;
81
+ smartconfigData['@git.zone/cli'].commit.confirmation = this.config.confirmation;
82
+ smartconfigData['@git.zone/cli'].commit.steps = this.config.steps;
69
83
 
70
84
  // Write back to file
71
85
  await plugins.smartfs
@@ -101,4 +115,20 @@ export class CommitConfig {
101
115
  public setAlwaysBuild(value: boolean): void {
102
116
  this.config.alwaysBuild = value;
103
117
  }
118
+
119
+ public getConfirmation(): 'prompt' | 'auto' | 'plan' {
120
+ return this.config.confirmation;
121
+ }
122
+
123
+ public setConfirmation(value: 'prompt' | 'auto' | 'plan'): void {
124
+ this.config.confirmation = value;
125
+ }
126
+
127
+ public getSteps(): string[] {
128
+ return [...this.config.steps];
129
+ }
130
+
131
+ public setSteps(steps: string[]): void {
132
+ this.config.steps = [...steps];
133
+ }
104
134
  }
@@ -35,13 +35,11 @@ export class ReleaseConfig {
35
35
  public async load(): Promise<void> {
36
36
  const smartconfigInstance = new plugins.smartconfig.Smartconfig(this.cwd);
37
37
  const gitzoneConfig = smartconfigInstance.dataFor<any>('@git.zone/cli', {});
38
-
39
- // Also check szci for backward compatibility
40
- const szciConfig = smartconfigInstance.dataFor<any>('@ship.zone/szci', {});
38
+ const npmTarget = gitzoneConfig?.release?.targets?.npm || {};
41
39
 
42
40
  this.config = {
43
- registries: gitzoneConfig?.release?.registries || [],
44
- accessLevel: gitzoneConfig?.release?.accessLevel || szciConfig?.npmAccessLevel || 'public',
41
+ registries: npmTarget.registries || [],
42
+ accessLevel: npmTarget.accessLevel || 'public',
45
43
  };
46
44
  }
47
45
 
@@ -68,9 +66,18 @@ export class ReleaseConfig {
68
66
  smartconfigData['@git.zone/cli'].release = {};
69
67
  }
70
68
 
69
+ if (!smartconfigData['@git.zone/cli'].release.targets) {
70
+ smartconfigData['@git.zone/cli'].release.targets = {};
71
+ }
72
+
73
+ if (!smartconfigData['@git.zone/cli'].release.targets.npm) {
74
+ smartconfigData['@git.zone/cli'].release.targets.npm = {};
75
+ }
76
+
71
77
  // Update registries and accessLevel
72
- smartconfigData['@git.zone/cli'].release.registries = this.config.registries;
73
- smartconfigData['@git.zone/cli'].release.accessLevel = this.config.accessLevel;
78
+ smartconfigData['@git.zone/cli'].release.targets.npm.enabled = this.config.registries.length > 0;
79
+ smartconfigData['@git.zone/cli'].release.targets.npm.registries = this.config.registries;
80
+ smartconfigData['@git.zone/cli'].release.targets.npm.accessLevel = this.config.accessLevel;
74
81
 
75
82
  // Write back to file
76
83
  await plugins.smartfs
@@ -1,4 +1,4 @@
1
- // gitzone config - manage release registry configuration
1
+ // gitzone config - manage CLI smartconfig configuration
2
2
 
3
3
  import * as plugins from "./mod.plugins.js";
4
4
  import { ReleaseConfig } from "./classes.releaseconfig.js";
@@ -13,6 +13,10 @@ import {
13
13
  unsetCliConfigValueInData,
14
14
  writeSmartconfigFile,
15
15
  } from "../helpers.smartconfig.js";
16
+ import {
17
+ CURRENT_GITZONE_CLI_SCHEMA_VERSION,
18
+ migrateSmartconfigData,
19
+ } from "../helpers.smartconfigmigrations.js";
16
20
 
17
21
  export { ReleaseConfig, CommitConfig };
18
22
 
@@ -99,6 +103,9 @@ export const run = async (argvArg: any) => {
99
103
  case "services":
100
104
  await handleServices(mode);
101
105
  break;
106
+ case "migrate":
107
+ await handleMigrate(value, mode);
108
+ break;
102
109
  case "get":
103
110
  await handleGet(value, mode);
104
111
  break;
@@ -138,10 +145,11 @@ async function handleInteractiveMenu(): Promise<void> {
138
145
  default: "show",
139
146
  choices: [
140
147
  { name: "Show current configuration", value: "show" },
141
- { name: "Add a registry", value: "add" },
142
- { name: "Remove a registry", value: "remove" },
143
- { name: "Clear all registries", value: "clear" },
148
+ { name: "Add an npm target registry", value: "add" },
149
+ { name: "Remove an npm target registry", value: "remove" },
150
+ { name: "Clear npm target registries", value: "clear" },
144
151
  { name: "Set access level (public/private)", value: "access" },
152
+ { name: "Migrate smartconfig schema", value: "migrate" },
145
153
  { name: "Configure commit options", value: "commit" },
146
154
  { name: "Configure services", value: "services" },
147
155
  { name: "Show help", value: "help" },
@@ -166,6 +174,9 @@ async function handleInteractiveMenu(): Promise<void> {
166
174
  case "access":
167
175
  await handleAccessLevel(undefined, defaultCliMode);
168
176
  break;
177
+ case "migrate":
178
+ await handleMigrate(undefined, defaultCliMode);
179
+ break;
169
180
  case "commit":
170
181
  await handleCommit(undefined, undefined, defaultCliMode);
171
182
  break;
@@ -197,7 +208,7 @@ async function handleShow(mode: ICliMode): Promise<void> {
197
208
  "╭─────────────────────────────────────────────────────────────╮",
198
209
  );
199
210
  console.log(
200
- "│ Release Configuration │",
211
+ "│ Release NPM Target Configuration │",
201
212
  );
202
213
  console.log(
203
214
  "╰─────────────────────────────────────────────────────────────╯",
@@ -209,12 +220,12 @@ async function handleShow(mode: ICliMode): Promise<void> {
209
220
  console.log("");
210
221
 
211
222
  if (registries.length === 0) {
212
- plugins.logger.log("info", "No release registries configured.");
223
+ plugins.logger.log("info", "No npm target registries configured.");
213
224
  console.log("");
214
225
  console.log(" Run `gitzone config add <registry-url>` to add one.");
215
226
  console.log("");
216
227
  } else {
217
- plugins.logger.log("info", `Configured registries (${registries.length}):`);
228
+ plugins.logger.log("info", `Configured npm target registries (${registries.length}):`);
218
229
  console.log("");
219
230
  registries.forEach((url, index) => {
220
231
  console.log(` ${index + 1}. ${url}`);
@@ -224,7 +235,7 @@ async function handleShow(mode: ICliMode): Promise<void> {
224
235
  }
225
236
 
226
237
  /**
227
- * Add a registry URL
238
+ * Add an npm target registry URL
228
239
  */
229
240
  async function handleAdd(
230
241
  url: string | undefined,
@@ -240,7 +251,7 @@ async function handleAdd(
240
251
  const response = await interactInstance.askQuestion({
241
252
  type: "input",
242
253
  name: "registryUrl",
243
- message: "Enter registry URL:",
254
+ message: "Enter npm target registry URL:",
244
255
  default: "https://registry.npmjs.org",
245
256
  validate: (input: string) => {
246
257
  return !!(input && input.trim() !== "");
@@ -263,7 +274,7 @@ async function handleAdd(
263
274
  });
264
275
  return;
265
276
  }
266
- plugins.logger.log("success", `Added registry: ${url}`);
277
+ plugins.logger.log("success", `Added npm target registry: ${url}`);
267
278
  await formatSmartconfigWithDiff(mode);
268
279
  } else {
269
280
  plugins.logger.log("warn", `Registry already exists: ${url}`);
@@ -271,7 +282,7 @@ async function handleAdd(
271
282
  }
272
283
 
273
284
  /**
274
- * Remove a registry URL
285
+ * Remove an npm target registry URL
275
286
  */
276
287
  async function handleRemove(
277
288
  url: string | undefined,
@@ -281,7 +292,7 @@ async function handleRemove(
281
292
  const registries = config.getRegistries();
282
293
 
283
294
  if (registries.length === 0) {
284
- plugins.logger.log("warn", "No registries configured to remove.");
295
+ plugins.logger.log("warn", "No npm target registries configured to remove.");
285
296
  return;
286
297
  }
287
298
 
@@ -295,7 +306,7 @@ async function handleRemove(
295
306
  const response = await interactInstance.askQuestion({
296
307
  type: "list",
297
308
  name: "registryUrl",
298
- message: "Select registry to remove:",
309
+ message: "Select npm target registry to remove:",
299
310
  choices: registries,
300
311
  default: registries[0],
301
312
  });
@@ -315,7 +326,7 @@ async function handleRemove(
315
326
  });
316
327
  return;
317
328
  }
318
- plugins.logger.log("success", `Removed registry: ${url}`);
329
+ plugins.logger.log("success", `Removed npm target registry: ${url}`);
319
330
  await formatSmartconfigWithDiff(mode);
320
331
  } else {
321
332
  plugins.logger.log("warn", `Registry not found: ${url}`);
@@ -323,20 +334,20 @@ async function handleRemove(
323
334
  }
324
335
 
325
336
  /**
326
- * Clear all registries
337
+ * Clear all npm target registries
327
338
  */
328
339
  async function handleClear(mode: ICliMode): Promise<void> {
329
340
  const config = await ReleaseConfig.fromCwd();
330
341
 
331
342
  if (!config.hasRegistries()) {
332
- plugins.logger.log("info", "No registries to clear.");
343
+ plugins.logger.log("info", "No npm target registries to clear.");
333
344
  return;
334
345
  }
335
346
 
336
347
  // Confirm before clearing
337
348
  const confirmed = mode.interactive
338
349
  ? await plugins.smartinteract.SmartInteract.getCliConfirmation(
339
- "Clear all configured registries?",
350
+ "Clear all configured npm target registries?",
340
351
  false,
341
352
  )
342
353
  : true;
@@ -348,7 +359,7 @@ async function handleClear(mode: ICliMode): Promise<void> {
348
359
  printJson({ ok: true, action: "clear", registries: [] });
349
360
  return;
350
361
  }
351
- plugins.logger.log("success", "All registries cleared.");
362
+ plugins.logger.log("success", "All npm target registries cleared.");
352
363
  await formatSmartconfigWithDiff(mode);
353
364
  } else {
354
365
  plugins.logger.log("info", "Operation cancelled.");
@@ -473,6 +484,7 @@ async function handleCommitInteractive(config: CommitConfig): Promise<void> {
473
484
  const selected = (response as any).value || [];
474
485
  config.setAlwaysTest(selected.includes("alwaysTest"));
475
486
  config.setAlwaysBuild(selected.includes("alwaysBuild"));
487
+ syncCommitStepsFromBooleans(config);
476
488
  await config.save();
477
489
 
478
490
  plugins.logger.log("success", "Commit configuration updated");
@@ -496,6 +508,7 @@ async function handleCommitSetting(
496
508
  } else if (setting === "alwaysBuild") {
497
509
  config.setAlwaysBuild(boolValue);
498
510
  }
511
+ syncCommitStepsFromBooleans(config);
499
512
 
500
513
  await config.save();
501
514
  if (mode.json) {
@@ -506,6 +519,16 @@ async function handleCommitSetting(
506
519
  await formatSmartconfigWithDiff(mode);
507
520
  }
508
521
 
522
+ function syncCommitStepsFromBooleans(config: CommitConfig): void {
523
+ config.setSteps([
524
+ "analyze",
525
+ ...(config.getAlwaysTest() ? ["test"] : []),
526
+ ...(config.getAlwaysBuild() ? ["build"] : []),
527
+ "changelog",
528
+ "commit",
529
+ ]);
530
+ }
531
+
509
532
  /**
510
533
  * Show help for commit subcommand
511
534
  */
@@ -636,6 +659,38 @@ async function handleUnset(
636
659
  plugins.logger.log("success", `Unset ${configPath}`);
637
660
  }
638
661
 
662
+ async function handleMigrate(
663
+ rawTargetVersion: string | undefined,
664
+ mode: ICliMode,
665
+ ): Promise<void> {
666
+ const targetVersion = rawTargetVersion
667
+ ? Number(rawTargetVersion)
668
+ : CURRENT_GITZONE_CLI_SCHEMA_VERSION;
669
+ if (!Number.isInteger(targetVersion) || targetVersion < 1) {
670
+ throw new Error("Migration target version must be a positive integer");
671
+ }
672
+
673
+ const smartconfigData = await readSmartconfigFile();
674
+ const result = migrateSmartconfigData(smartconfigData, targetVersion);
675
+ if (result.migrated) {
676
+ await writeSmartconfigFile(smartconfigData);
677
+ }
678
+
679
+ if (mode.json) {
680
+ printJson({ ok: true, action: "migrate", ...result });
681
+ return;
682
+ }
683
+
684
+ if (result.migrated) {
685
+ plugins.logger.log(
686
+ "success",
687
+ `Migrated .smartconfig.json from schema v${result.fromVersion} to v${result.toVersion}`,
688
+ );
689
+ } else {
690
+ plugins.logger.log("info", `.smartconfig.json already at schema v${result.toVersion}`);
691
+ }
692
+ }
693
+
639
694
  function parseConfigValue(rawValue: string): any {
640
695
  const trimmedValue = rawValue.trim();
641
696
  if (trimmedValue === "true") {
@@ -676,21 +731,25 @@ export function showHelp(mode?: ICliMode): void {
676
731
  { name: "get <path>", description: "Read a single config value" },
677
732
  { name: "set <path> <value>", description: "Write a config value" },
678
733
  { name: "unset <path>", description: "Delete a config value" },
679
- { name: "add [url]", description: "Add a release registry" },
680
- { name: "remove [url]", description: "Remove a release registry" },
681
- { name: "clear", description: "Clear all release registries" },
734
+ { name: "add [url]", description: "Add an npm release target registry" },
735
+ { name: "remove [url]", description: "Remove an npm release target registry" },
736
+ { name: "clear", description: "Clear npm release target registries" },
682
737
  {
683
738
  name: "access [public|private]",
684
- description: "Set npm publish access level",
739
+ description: "Set npm target publish access level",
685
740
  },
686
741
  {
687
742
  name: "commit <setting> <value>",
688
743
  description: "Set commit defaults",
689
744
  },
745
+ {
746
+ name: "migrate [version]",
747
+ description: "Run version-targeted .smartconfig.json migrations",
748
+ },
690
749
  ],
691
750
  examples: [
692
751
  "gitzone config show --json",
693
- "gitzone config get release.accessLevel",
752
+ "gitzone config get release.targets.npm.accessLevel",
694
753
  "gitzone config set cli.interactive false",
695
754
  "gitzone config set cli.output json",
696
755
  ],
@@ -708,13 +767,14 @@ export function showHelp(mode?: ICliMode): void {
708
767
  console.log(" get <path> Read a single config value");
709
768
  console.log(" set <path> <value> Write a config value");
710
769
  console.log(" unset <path> Delete a config value");
711
- console.log(" add [url] Add a registry URL");
712
- console.log(" remove [url] Remove a registry URL");
713
- console.log(" clear Clear all registries");
770
+ console.log(" add [url] Add an npm target registry URL");
771
+ console.log(" remove [url] Remove an npm target registry URL");
772
+ console.log(" clear Clear npm target registries");
714
773
  console.log(
715
- " access [public|private] Set npm access level for publishing",
774
+ " access [public|private] Set npm target access level for publishing",
716
775
  );
717
776
  console.log(" commit [setting] [value] Configure commit options");
777
+ console.log(" migrate [version] Run version-targeted smartconfig migrations");
718
778
  console.log(
719
779
  " services Configure which services are enabled",
720
780
  );
@@ -722,7 +782,7 @@ export function showHelp(mode?: ICliMode): void {
722
782
  console.log("Examples:");
723
783
  console.log(" gitzone config show");
724
784
  console.log(" gitzone config show --json");
725
- console.log(" gitzone config get release.accessLevel");
785
+ console.log(" gitzone config get release.targets.npm.accessLevel");
726
786
  console.log(" gitzone config set cli.interactive false");
727
787
  console.log(" gitzone config set cli.output json");
728
788
  console.log(" gitzone config unset cli.output");
@@ -732,6 +792,7 @@ export function showHelp(mode?: ICliMode): void {
732
792
  console.log(" gitzone config clear");
733
793
  console.log(" gitzone config access public");
734
794
  console.log(" gitzone config access private");
795
+ console.log(" gitzone config migrate 2");
735
796
  console.log(" gitzone config commit # Interactive");
736
797
  console.log(" gitzone config commit alwaysTest true");
737
798
  console.log(" gitzone config services # Interactive");
@@ -2,65 +2,7 @@ import { BaseFormatter } from "../classes.baseformatter.js";
2
2
  import type { IPlannedChange } from "../interfaces.format.js";
3
3
  import * as plugins from "../mod.plugins.js";
4
4
  import { logger, logVerbose } from "../../gitzone.logging.js";
5
-
6
- /**
7
- * Migrates .smartconfig.json from old namespace keys to new package-scoped keys
8
- */
9
- const migrateNamespaceKeys = (smartconfigJson: any): boolean => {
10
- let migrated = false;
11
- const migrations = [
12
- { oldKey: "gitzone", newKey: "@git.zone/cli" },
13
- { oldKey: "tsdoc", newKey: "@git.zone/tsdoc" },
14
- { oldKey: "npmdocker", newKey: "@git.zone/tsdocker" },
15
- { oldKey: "npmci", newKey: "@ship.zone/szci" },
16
- { oldKey: "szci", newKey: "@ship.zone/szci" },
17
- ];
18
- for (const { oldKey, newKey } of migrations) {
19
- if (smartconfigJson[oldKey]) {
20
- if (!smartconfigJson[newKey]) {
21
- smartconfigJson[newKey] = smartconfigJson[oldKey];
22
- } else {
23
- smartconfigJson[newKey] = {
24
- ...smartconfigJson[oldKey],
25
- ...smartconfigJson[newKey],
26
- };
27
- }
28
- delete smartconfigJson[oldKey];
29
- migrated = true;
30
- }
31
- }
32
- return migrated;
33
- };
34
-
35
- /**
36
- * Migrates npmAccessLevel from @ship.zone/szci to @git.zone/cli.release.accessLevel
37
- */
38
- const migrateAccessLevel = (smartconfigJson: any): boolean => {
39
- const szciConfig = smartconfigJson["@ship.zone/szci"];
40
-
41
- if (!szciConfig?.npmAccessLevel) {
42
- return false;
43
- }
44
-
45
- const gitzoneConfig = smartconfigJson["@git.zone/cli"] || {};
46
- if (gitzoneConfig?.release?.accessLevel) {
47
- delete szciConfig.npmAccessLevel;
48
- return true;
49
- }
50
-
51
- if (!smartconfigJson["@git.zone/cli"]) {
52
- smartconfigJson["@git.zone/cli"] = {};
53
- }
54
- if (!smartconfigJson["@git.zone/cli"].release) {
55
- smartconfigJson["@git.zone/cli"].release = {};
56
- }
57
-
58
- smartconfigJson["@git.zone/cli"].release.accessLevel =
59
- szciConfig.npmAccessLevel;
60
- delete szciConfig.npmAccessLevel;
61
-
62
- return true;
63
- };
5
+ import { migrateSmartconfigData } from "../../helpers.smartconfigmigrations.js";
64
6
 
65
7
  const CONFIG_FILE = ".smartconfig.json";
66
8
 
@@ -88,9 +30,7 @@ export class SmartconfigFormatter extends BaseFormatter {
88
30
 
89
31
  const smartconfigJson = JSON.parse(currentContent);
90
32
 
91
- // Apply key migrations
92
- migrateNamespaceKeys(smartconfigJson);
93
- migrateAccessLevel(smartconfigJson);
33
+ migrateSmartconfigData(smartconfigJson);
94
34
 
95
35
  // Ensure namespaces exist
96
36
  if (!smartconfigJson["@git.zone/cli"]) {