@solid-stack/mason 1.0.14 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import fs4 from 'fs';
2
2
  import path2 from 'path';
3
- import * as p4 from '@clack/prompts';
3
+ import * as p14 from '@clack/prompts';
4
4
  import pc14 from 'picocolors';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { execSync } from 'child_process';
@@ -112,17 +112,17 @@ function writeFileSafely(absolutePath, content, options = {}) {
112
112
  function printGeneratedFiles(files, isDryRun = false) {
113
113
  console.log("");
114
114
  if (isDryRun) {
115
- p4.log.warn(pc14.yellow(pc14.bold("[DRY RUN PREVIEW] No files were written to disk.")));
115
+ p14.log.warn(pc14.yellow(pc14.bold("[DRY RUN PREVIEW] No files were written to disk.")));
116
116
  }
117
117
  for (const f of files) {
118
118
  if (f.action === "created") {
119
- p4.log.success(`${pc14.bold(f.relativePath)} ${pc14.dim("(created)")}`);
119
+ p14.log.success(`${pc14.bold(f.relativePath)} ${pc14.dim("(created)")}`);
120
120
  } else if (f.action === "overwritten") {
121
- p4.log.warn(`${pc14.bold(f.relativePath)} ${pc14.dim("(overwritten)")}`);
121
+ p14.log.warn(`${pc14.bold(f.relativePath)} ${pc14.dim("(overwritten)")}`);
122
122
  } else if (f.action === "skipped") {
123
- p4.log.info(`${pc14.dim(f.relativePath)} ${pc14.dim("(skipped - already exists, pass -o to overwrite)")}`);
123
+ p14.log.info(`${pc14.dim(f.relativePath)} ${pc14.dim("(skipped - already exists, pass -o to overwrite)")}`);
124
124
  } else {
125
- p4.log.info(`${pc14.bold(f.relativePath)} ${pc14.dim("(preview)")}`);
125
+ p14.log.info(`${pc14.bold(f.relativePath)} ${pc14.dim("(preview)")}`);
126
126
  }
127
127
  }
128
128
  }
@@ -318,23 +318,23 @@ var PromptCancelledError = class extends Error {
318
318
  }
319
319
  };
320
320
  function handleCancel(result) {
321
- if (p4.isCancel(result)) {
322
- p4.cancel("Operation cancelled.");
321
+ if (p14.isCancel(result)) {
322
+ p14.cancel("Operation cancelled.");
323
323
  throw new PromptCancelledError();
324
324
  }
325
325
  return result;
326
326
  }
327
327
  function printBanner() {
328
328
  console.log("");
329
- p4.intro(pc14.bgCyan(pc14.black(" @solid-stack/mason ")));
329
+ p14.intro(pc14.bgCyan(pc14.black(" @solid-stack/mason ")));
330
330
  }
331
331
  async function promptProperties(options = {}) {
332
332
  const properties = options.defaults ? [...options.defaults] : [];
333
333
  if (properties.length > 0) {
334
334
  const summary = properties.map((p16) => `${p16.name}: ${p16.type}${p16.optional ? "?" : ""}`).join(", ");
335
- p4.log.info(pc14.dim(`Pre-configured fields: ${summary}`));
335
+ p14.log.info(pc14.dim(`Pre-configured fields: ${summary}`));
336
336
  const addMore = handleCancel(
337
- await p4.confirm({
337
+ await p14.confirm({
338
338
  message: "Would you like to add custom fields/properties?",
339
339
  initialValue: false
340
340
  })
@@ -343,10 +343,10 @@ async function promptProperties(options = {}) {
343
343
  return properties;
344
344
  }
345
345
  }
346
- p4.log.info(pc14.cyan("Enter properties (leave name blank when finished):"));
346
+ p14.log.info(pc14.cyan("Enter properties (leave name blank when finished):"));
347
347
  while (true) {
348
348
  const name = handleCancel(
349
- await p4.text({
349
+ await p14.text({
350
350
  message: "Property name (or press Enter to finish):",
351
351
  placeholder: "e.g. title, email, status"
352
352
  })
@@ -355,7 +355,7 @@ async function promptProperties(options = {}) {
355
355
  break;
356
356
  }
357
357
  const type = handleCancel(
358
- await p4.select({
358
+ await p14.select({
359
359
  message: `Type for property "${name.trim()}":`,
360
360
  options: [
361
361
  { value: "string", label: "string" },
@@ -372,7 +372,7 @@ async function promptProperties(options = {}) {
372
372
  let finalType = type;
373
373
  if (type === "custom") {
374
374
  finalType = handleCancel(
375
- await p4.text({
375
+ await p14.text({
376
376
  message: `Enter custom type for "${name.trim()}":`,
377
377
  placeholder: "e.g. UserRole, string | null",
378
378
  validate: (val) => val && val.trim() ? void 0 : "Type cannot be empty"
@@ -380,7 +380,7 @@ async function promptProperties(options = {}) {
380
380
  );
381
381
  }
382
382
  const optional = handleCancel(
383
- await p4.confirm({
383
+ await p14.confirm({
384
384
  message: `Is "${name.trim()}" optional?`,
385
385
  initialValue: false
386
386
  })
@@ -390,7 +390,7 @@ async function promptProperties(options = {}) {
390
390
  type: finalType.trim(),
391
391
  optional
392
392
  });
393
- p4.log.success(
393
+ p14.log.success(
394
394
  pc14.green(`Added: ${name.trim()}${optional ? "?" : ""}: ${finalType.trim()}`)
395
395
  );
396
396
  }
@@ -613,7 +613,7 @@ function installNpmPackages(projectRoot, packages, pm) {
613
613
  installCmd = `npm install ${packages.join(" ")}`;
614
614
  break;
615
615
  }
616
- p4.log.info(`Installing missing dependencies with ${manager}: ${pc14.cyan(packages.join(", "))}`);
616
+ p14.log.info(`Installing missing dependencies with ${manager}: ${pc14.cyan(packages.join(", "))}`);
617
617
  execSync(installCmd, {
618
618
  cwd: projectRoot,
619
619
  stdio: "inherit"
@@ -2086,7 +2086,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2086
2086
  }
2087
2087
  if (!name) {
2088
2088
  name = handleCancel(
2089
- await p4.text({
2089
+ await p14.text({
2090
2090
  message: "What is the feature name?",
2091
2091
  placeholder: "e.g. users, auth, orders, billing",
2092
2092
  validate: (val) => {
@@ -2102,7 +2102,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2102
2102
  let targetDirRel = defaultDir;
2103
2103
  if (!flags.yes && !flags.target && !flags.dest) {
2104
2104
  targetDirRel = handleCancel(
2105
- await p4.text({
2105
+ await p14.text({
2106
2106
  message: "Target directory for the feature:",
2107
2107
  initialValue: defaultDir,
2108
2108
  defaultValue: defaultDir
@@ -2124,14 +2124,14 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2124
2124
  const customUseCases = [];
2125
2125
  if (!flags.yes) {
2126
2126
  includeExpress = handleCancel(
2127
- await p4.confirm({
2127
+ await p14.confirm({
2128
2128
  message: "Include Express Presentation layer (pxExpress routes & handlers)?",
2129
2129
  initialValue: true
2130
2130
  })
2131
2131
  );
2132
2132
  if (includeExpress) {
2133
2133
  routePath = handleCancel(
2134
- await p4.text({
2134
+ await p14.text({
2135
2135
  message: "Express route prefix:",
2136
2136
  initialValue: `/${normalizedName}`,
2137
2137
  defaultValue: `/${normalizedName}`
@@ -2139,14 +2139,14 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2139
2139
  ).trim();
2140
2140
  }
2141
2141
  includeDomain = handleCancel(
2142
- await p4.confirm({
2142
+ await p14.confirm({
2143
2143
  message: "Include Domain Entity/Entities?",
2144
2144
  initialValue: true
2145
2145
  })
2146
2146
  );
2147
2147
  if (includeDomain) {
2148
2148
  const domainInput = handleCancel(
2149
- await p4.text({
2149
+ await p14.text({
2150
2150
  message: "Domain entity name(s) (comma-separated):",
2151
2151
  initialValue: defaultEntity,
2152
2152
  defaultValue: defaultEntity,
@@ -2165,21 +2165,21 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2165
2165
  entityNames = [defaultEntity];
2166
2166
  }
2167
2167
  includeInterface = handleCancel(
2168
- await p4.confirm({
2168
+ await p14.confirm({
2169
2169
  message: `Include Domain Repository interface(s) for ${entityNames.join(", ")}?`,
2170
2170
  initialValue: true
2171
2171
  })
2172
2172
  );
2173
2173
  if (includeInterface) {
2174
2174
  includeInfra = handleCancel(
2175
- await p4.confirm({
2175
+ await p14.confirm({
2176
2176
  message: `Include Infrastructure Stub implementation(s) for ${entityNames.join(", ")}?`,
2177
2177
  initialValue: true
2178
2178
  })
2179
2179
  );
2180
2180
  }
2181
2181
  includeUseCase = handleCancel(
2182
- await p4.confirm({
2182
+ await p14.confirm({
2183
2183
  message: "Include Domain Use Cases?",
2184
2184
  initialValue: true
2185
2185
  })
@@ -2193,7 +2193,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2193
2193
  { value: "delete", label: "Delete (Delete<Entity>)", hint: "DELETE /:id" }
2194
2194
  ];
2195
2195
  crudOperations = handleCancel(
2196
- await p4.multiselect({
2196
+ await p14.multiselect({
2197
2197
  message: "Select standard CRUD use cases to generate:",
2198
2198
  options: crudChoices,
2199
2199
  initialValues: ["create", "read", "list", "update", "delete"],
@@ -2201,13 +2201,13 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2201
2201
  })
2202
2202
  );
2203
2203
  includeTests = handleCancel(
2204
- await p4.confirm({
2204
+ await p14.confirm({
2205
2205
  message: "Generate Vitest unit tests for use cases?",
2206
2206
  initialValue: true
2207
2207
  })
2208
2208
  );
2209
2209
  const wantCustom = handleCancel(
2210
- await p4.confirm({
2210
+ await p14.confirm({
2211
2211
  message: "Do you want to add any custom use cases to this feature?",
2212
2212
  initialValue: false
2213
2213
  })
@@ -2217,7 +2217,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2217
2217
  const availableIfaces = entityNames.map((e) => `I${e}Repository`);
2218
2218
  while (addMore) {
2219
2219
  const customName = handleCancel(
2220
- await p4.text({
2220
+ await p14.text({
2221
2221
  message: "Custom Use Case name:",
2222
2222
  placeholder: "e.g. ResetPassword, VerifyEmail, AssignRole",
2223
2223
  validate: (v) => v && v.trim() ? void 0 : "Use Case name cannot be empty"
@@ -2227,7 +2227,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2227
2227
  let selectedDeps = [];
2228
2228
  if (availableIfaces.length > 0) {
2229
2229
  selectedDeps = handleCancel(
2230
- await p4.multiselect({
2230
+ await p14.multiselect({
2231
2231
  message: `Select domain interfaces to inject into ${customUcName}:`,
2232
2232
  options: availableIfaces.map((i) => ({ value: i, label: i })),
2233
2233
  required: false
@@ -2236,7 +2236,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2236
2236
  }
2237
2237
  let customInputProps = [];
2238
2238
  const hasInput = handleCancel(
2239
- await p4.confirm({
2239
+ await p14.confirm({
2240
2240
  message: `Does ${customUcName} accept input arguments?`,
2241
2241
  initialValue: true
2242
2242
  })
@@ -2247,7 +2247,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2247
2247
  }
2248
2248
  let customOutputProps = [];
2249
2249
  const hasCustomOutput = handleCancel(
2250
- await p4.confirm({
2250
+ await p14.confirm({
2251
2251
  message: `Does ${customUcName} return custom output data?`,
2252
2252
  initialValue: false
2253
2253
  })
@@ -2257,7 +2257,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2257
2257
  });
2258
2258
  }
2259
2259
  const customIncludeTest = handleCancel(
2260
- await p4.confirm({
2260
+ await p14.confirm({
2261
2261
  message: `Generate Vitest unit test for ${customUcName}?`,
2262
2262
  initialValue: true
2263
2263
  })
@@ -2267,14 +2267,14 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2267
2267
  let customHttpPath = `/${toKebabCase(customUcName)}`;
2268
2268
  if (includeExpress) {
2269
2269
  customCreateHttp = handleCancel(
2270
- await p4.confirm({
2270
+ await p14.confirm({
2271
2271
  message: `Generate a matching ExpressRoute HTTP handler for ${customUcName}?`,
2272
2272
  initialValue: true
2273
2273
  })
2274
2274
  );
2275
2275
  if (customCreateHttp) {
2276
2276
  customHttpMethod = handleCancel(
2277
- await p4.select({
2277
+ await p14.select({
2278
2278
  message: "HTTP method for route:",
2279
2279
  options: [
2280
2280
  { value: "post", label: "POST" },
@@ -2287,7 +2287,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2287
2287
  })
2288
2288
  );
2289
2289
  customHttpPath = handleCancel(
2290
- await p4.text({
2290
+ await p14.text({
2291
2291
  message: "Route subpath (relative to feature prefix):",
2292
2292
  initialValue: `/${toKebabCase(customUcName)}`,
2293
2293
  defaultValue: `/${toKebabCase(customUcName)}`
@@ -2308,7 +2308,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2308
2308
  validationFields: customInputProps
2309
2309
  });
2310
2310
  addMore = handleCancel(
2311
- await p4.confirm({
2311
+ await p14.confirm({
2312
2312
  message: "Add another custom use case?",
2313
2313
  initialValue: false
2314
2314
  })
@@ -2317,7 +2317,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2317
2317
  }
2318
2318
  }
2319
2319
  includeDiProvider = handleCancel(
2320
- await p4.confirm({
2320
+ await p14.confirm({
2321
2321
  message: "Generate / update feature DI provider (diProvider.ts)?",
2322
2322
  initialValue: true
2323
2323
  })
@@ -2329,7 +2329,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2329
2329
  entityNames = [defaultEntity];
2330
2330
  }
2331
2331
  }
2332
- const s = p4.spinner();
2332
+ const s = p14.spinner();
2333
2333
  s.start(`Generating feature '${pc14.cyan(normalizedName)}'...`);
2334
2334
  const options = {
2335
2335
  name: normalizedName,
@@ -2376,7 +2376,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2376
2376
  }
2377
2377
  s.stop("Feature scaffolded successfully!");
2378
2378
  printGeneratedFiles(files, options.dryRun);
2379
- p4.outro(
2379
+ p14.outro(
2380
2380
  pc14.green(
2381
2381
  `\u2713 Feature '${normalizedName}' initialized in ${path2.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2382
2382
  )
@@ -2491,7 +2491,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2491
2491
  }
2492
2492
  if (!name) {
2493
2493
  name = handleCancel(
2494
- await p4.text({
2494
+ await p14.text({
2495
2495
  message: "What is the shared module name?",
2496
2496
  placeholder: "e.g. hasher, time, uuid, cache, logger",
2497
2497
  validate: (val) => {
@@ -2507,7 +2507,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2507
2507
  let targetDirRel = defaultDir;
2508
2508
  if (!flags.yes && !flags.target && !flags.dest) {
2509
2509
  targetDirRel = handleCancel(
2510
- await p4.text({
2510
+ await p14.text({
2511
2511
  message: "Target directory for the shared module:",
2512
2512
  initialValue: defaultDir,
2513
2513
  defaultValue: defaultDir
@@ -2519,20 +2519,20 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2519
2519
  let includeStub = true;
2520
2520
  if (!flags.yes) {
2521
2521
  description = handleCancel(
2522
- await p4.text({
2522
+ await p14.text({
2523
2523
  message: "Module description (optional):",
2524
2524
  placeholder: "e.g. In-memory caching and Redis port abstraction",
2525
2525
  initialValue: ""
2526
2526
  })
2527
2527
  ).trim();
2528
2528
  includeStub = handleCancel(
2529
- await p4.confirm({
2529
+ await p14.confirm({
2530
2530
  message: "Include stub implementation in infrastructure/?",
2531
2531
  initialValue: true
2532
2532
  })
2533
2533
  );
2534
2534
  }
2535
- const s = p4.spinner();
2535
+ const s = p14.spinner();
2536
2536
  s.start(`Generating shared module '${pc14.cyan(normalizedName)}'...`);
2537
2537
  const files = generateShared({
2538
2538
  name: normalizedName,
@@ -2546,7 +2546,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2546
2546
  });
2547
2547
  s.stop("Shared module generated successfully!");
2548
2548
  printGeneratedFiles(files, Boolean(flags.dryRun));
2549
- p4.outro(
2549
+ p14.outro(
2550
2550
  pc14.green(
2551
2551
  `\u2713 Shared module '${normalizedName}' initialized in ${path2.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2552
2552
  )
@@ -2561,14 +2561,14 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2561
2561
  const featureOptions = existingFeatures.map((f) => ({ value: f, label: f }));
2562
2562
  featureOptions.push({ value: "__custom__", label: "\u270F\uFE0F Enter custom feature name..." });
2563
2563
  const selected = handleCancel(
2564
- await p4.select({
2564
+ await p14.select({
2565
2565
  message: "Select target feature:",
2566
2566
  options: featureOptions
2567
2567
  })
2568
2568
  );
2569
2569
  if (selected === "__custom__") {
2570
2570
  feature = handleCancel(
2571
- await p4.text({
2571
+ await p14.text({
2572
2572
  message: "Enter feature name:",
2573
2573
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
2574
2574
  })
@@ -2578,7 +2578,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2578
2578
  }
2579
2579
  } else {
2580
2580
  feature = handleCancel(
2581
- await p4.text({
2581
+ await p14.text({
2582
2582
  message: "Enter target feature name:",
2583
2583
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
2584
2584
  })
@@ -2589,7 +2589,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2589
2589
  let name = useCaseNameArg?.trim();
2590
2590
  if (!name) {
2591
2591
  name = handleCancel(
2592
- await p4.text({
2592
+ await p14.text({
2593
2593
  message: "Use Case name:",
2594
2594
  placeholder: "e.g. CreateUser, GetUser, CancelOrder",
2595
2595
  validate: (v) => v && v.trim() ? void 0 : "Use Case name cannot be empty"
@@ -2605,7 +2605,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2605
2605
  label: i.name
2606
2606
  }));
2607
2607
  selectedDeps = handleCancel(
2608
- await p4.multiselect({
2608
+ await p14.multiselect({
2609
2609
  message: "Select domain interfaces to inject into use case:",
2610
2610
  options: multiOptions,
2611
2611
  required: false
@@ -2620,7 +2620,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2620
2620
  let httpPath = "/";
2621
2621
  if (!flags.yes) {
2622
2622
  const hasInput = handleCancel(
2623
- await p4.confirm({
2623
+ await p14.confirm({
2624
2624
  message: "Does this use case accept input arguments?",
2625
2625
  initialValue: true
2626
2626
  })
@@ -2630,7 +2630,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2630
2630
  });
2631
2631
  }
2632
2632
  const hasCustomOutput = handleCancel(
2633
- await p4.confirm({
2633
+ await p14.confirm({
2634
2634
  message: "Does this use case return custom output data?",
2635
2635
  initialValue: false
2636
2636
  })
@@ -2640,20 +2640,20 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2640
2640
  });
2641
2641
  }
2642
2642
  includeTest = handleCancel(
2643
- await p4.confirm({
2643
+ await p14.confirm({
2644
2644
  message: "Generate Vitest unit test skeleton (.test.ts)?",
2645
2645
  initialValue: true
2646
2646
  })
2647
2647
  );
2648
2648
  createHttp = handleCancel(
2649
- await p4.confirm({
2649
+ await p14.confirm({
2650
2650
  message: "Generate a matching ExpressRoute HTTP handler?",
2651
2651
  initialValue: false
2652
2652
  })
2653
2653
  );
2654
2654
  if (createHttp) {
2655
2655
  httpMethod = handleCancel(
2656
- await p4.select({
2656
+ await p14.select({
2657
2657
  message: "HTTP method for route:",
2658
2658
  options: [
2659
2659
  { value: "post", label: "POST" },
@@ -2666,7 +2666,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2666
2666
  })
2667
2667
  );
2668
2668
  httpPath = handleCancel(
2669
- await p4.text({
2669
+ await p14.text({
2670
2670
  message: "Route subpath (relative to feature prefix):",
2671
2671
  initialValue: "/",
2672
2672
  defaultValue: "/"
@@ -2674,7 +2674,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2674
2674
  ).trim();
2675
2675
  }
2676
2676
  }
2677
- const s = p4.spinner();
2677
+ const s = p14.spinner();
2678
2678
  s.start(`Generating use case '${pc14.cyan(ucName)}'...`);
2679
2679
  const options = {
2680
2680
  name: ucName,
@@ -2707,7 +2707,7 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2707
2707
  }
2708
2708
  s.stop("Use case generated successfully!");
2709
2709
  printGeneratedFiles(files, options.dryRun);
2710
- p4.outro(pc14.green(`Use case '${ucName}' created in feature '${feature}'!`));
2710
+ p14.outro(pc14.green(`Use case '${ucName}' created in feature '${feature}'!`));
2711
2711
  }
2712
2712
  async function runDomainCommand(domainNameArg, flags = {}) {
2713
2713
  const projectRoot = findProjectRoot();
@@ -2718,14 +2718,14 @@ async function runDomainCommand(domainNameArg, flags = {}) {
2718
2718
  const featureOptions = existingFeatures.map((f) => ({ value: f, label: f }));
2719
2719
  featureOptions.push({ value: "__custom__", label: "\u270F\uFE0F Enter custom feature name..." });
2720
2720
  const selected = handleCancel(
2721
- await p4.select({
2721
+ await p14.select({
2722
2722
  message: "Select target feature:",
2723
2723
  options: featureOptions
2724
2724
  })
2725
2725
  );
2726
2726
  if (selected === "__custom__") {
2727
2727
  feature = handleCancel(
2728
- await p4.text({
2728
+ await p14.text({
2729
2729
  message: "Enter feature name:",
2730
2730
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
2731
2731
  })
@@ -2735,7 +2735,7 @@ async function runDomainCommand(domainNameArg, flags = {}) {
2735
2735
  }
2736
2736
  } else {
2737
2737
  feature = handleCancel(
2738
- await p4.text({
2738
+ await p14.text({
2739
2739
  message: "Enter target feature name:",
2740
2740
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
2741
2741
  })
@@ -2746,7 +2746,7 @@ async function runDomainCommand(domainNameArg, flags = {}) {
2746
2746
  let name = domainNameArg?.trim();
2747
2747
  if (!name) {
2748
2748
  name = handleCancel(
2749
- await p4.text({
2749
+ await p14.text({
2750
2750
  message: "Domain model / entity name:",
2751
2751
  placeholder: "e.g. User, Order, Product, Address",
2752
2752
  validate: (v) => v && v.trim() ? void 0 : "Domain name cannot be empty"
@@ -2758,7 +2758,7 @@ async function runDomainCommand(domainNameArg, flags = {}) {
2758
2758
  let properties = [];
2759
2759
  if (!flags.yes) {
2760
2760
  kind = handleCancel(
2761
- await p4.select({
2761
+ await p14.select({
2762
2762
  message: "Select domain model type:",
2763
2763
  options: [
2764
2764
  { value: "interface", label: "TypeScript Interface (pure data structure)" },
@@ -2777,7 +2777,7 @@ async function runDomainCommand(domainNameArg, flags = {}) {
2777
2777
  defaults: kind === "valueObject" ? [{ name: "value", type: "string" }] : defaultProps
2778
2778
  });
2779
2779
  }
2780
- const s = p4.spinner();
2780
+ const s = p14.spinner();
2781
2781
  s.start(`Generating domain model '${pc14.cyan(entityName)}'...`);
2782
2782
  const options = {
2783
2783
  name: entityName,
@@ -2791,7 +2791,7 @@ async function runDomainCommand(domainNameArg, flags = {}) {
2791
2791
  const file = generateDomain(options);
2792
2792
  s.stop("Domain model generated successfully!");
2793
2793
  printGeneratedFiles([file], options.dryRun);
2794
- p4.outro(pc14.green(`Domain model '${entityName}' created in feature '${feature}'!`));
2794
+ p14.outro(pc14.green(`Domain model '${entityName}' created in feature '${feature}'!`));
2795
2795
  }
2796
2796
  async function runInfrastructureCommand(classNameArg, flags = {}) {
2797
2797
  const projectRoot = findProjectRoot();
@@ -2800,7 +2800,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2800
2800
  let feature = flags.feature?.trim();
2801
2801
  if (!flags.yes && !flags.global && !flags.feature) {
2802
2802
  scope = handleCancel(
2803
- await p4.select({
2803
+ await p14.select({
2804
2804
  message: "Where should this infrastructure implementation be placed?",
2805
2805
  options: [
2806
2806
  { value: "feature", label: "Feature-level (features/<feature>/infrastructure)" },
@@ -2815,14 +2815,14 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2815
2815
  const featureOptions = existingFeatures.map((f) => ({ value: f, label: f }));
2816
2816
  featureOptions.push({ value: "__custom__", label: "\u270F\uFE0F Enter custom feature name..." });
2817
2817
  const selected = handleCancel(
2818
- await p4.select({
2818
+ await p14.select({
2819
2819
  message: "Select target feature:",
2820
2820
  options: featureOptions
2821
2821
  })
2822
2822
  );
2823
2823
  if (selected === "__custom__") {
2824
2824
  feature = handleCancel(
2825
- await p4.text({
2825
+ await p14.text({
2826
2826
  message: "Enter feature name:",
2827
2827
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
2828
2828
  })
@@ -2832,7 +2832,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2832
2832
  }
2833
2833
  } else {
2834
2834
  feature = handleCancel(
2835
- await p4.text({
2835
+ await p14.text({
2836
2836
  message: "Enter target feature name:",
2837
2837
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
2838
2838
  })
@@ -2845,7 +2845,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2845
2845
  let name = classNameArg?.trim();
2846
2846
  if (!name) {
2847
2847
  name = handleCancel(
2848
- await p4.text({
2848
+ await p14.text({
2849
2849
  message: "Infrastructure class name:",
2850
2850
  placeholder: "e.g. StubUserRepository, PostgresUserRepository, S3FileStorage",
2851
2851
  validate: (v) => v && v.trim() ? void 0 : "Class name cannot be empty"
@@ -2864,7 +2864,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2864
2864
  (i) => className.toLowerCase().includes(removeInterfacePrefix(i.name).toLowerCase())
2865
2865
  );
2866
2866
  const ifaceChoice = handleCancel(
2867
- await p4.select({
2867
+ await p14.select({
2868
2868
  message: "Does this class implement a domain interface or abstract class?",
2869
2869
  options: [
2870
2870
  ...interfaces.map((i) => ({ value: i.name, label: i.name })),
@@ -2876,7 +2876,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2876
2876
  );
2877
2877
  if (ifaceChoice === "__custom__") {
2878
2878
  implementsInterface = handleCancel(
2879
- await p4.text({
2879
+ await p14.text({
2880
2880
  message: "Enter interface or abstract class name:",
2881
2881
  placeholder: "e.g. IUserRepository, BaseStorageAdapter",
2882
2882
  validate: (v) => v && v.trim() ? void 0 : "Name cannot be empty"
@@ -2887,14 +2887,14 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2887
2887
  }
2888
2888
  } else {
2889
2889
  const wantImpl = handleCancel(
2890
- await p4.confirm({
2890
+ await p14.confirm({
2891
2891
  message: "Does this class implement a domain interface or abstract class?",
2892
2892
  initialValue: false
2893
2893
  })
2894
2894
  );
2895
2895
  if (wantImpl) {
2896
2896
  implementsInterface = handleCancel(
2897
- await p4.text({
2897
+ await p14.text({
2898
2898
  message: "Enter interface or abstract class name:",
2899
2899
  placeholder: "e.g. IUserRepository, BaseStorageAdapter",
2900
2900
  validate: (v) => v && v.trim() ? void 0 : "Name cannot be empty"
@@ -2914,7 +2914,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2914
2914
  const allInterfaces = listDomainInterfaces(projectRoot);
2915
2915
  if (allInterfaces.length > 0) {
2916
2916
  const ifaceChoice = handleCancel(
2917
- await p4.select({
2917
+ await p14.select({
2918
2918
  message: "Does this class implement an interface or abstract class?",
2919
2919
  options: [
2920
2920
  ...allInterfaces.map((i) => ({ value: i.name, label: `${i.name} (${i.feature})` })),
@@ -2926,7 +2926,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2926
2926
  );
2927
2927
  if (ifaceChoice === "__custom__") {
2928
2928
  implementsInterface = handleCancel(
2929
- await p4.text({
2929
+ await p14.text({
2930
2930
  message: "Enter interface or abstract class name:",
2931
2931
  placeholder: "e.g. IAuthRepository",
2932
2932
  validate: (v) => v && v.trim() ? void 0 : "Name cannot be empty"
@@ -2939,7 +2939,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2939
2939
  }
2940
2940
  if (!flags.yes && !flags.kind) {
2941
2941
  kind = handleCancel(
2942
- await p4.select({
2942
+ await p14.select({
2943
2943
  message: "Select implementation kind:",
2944
2944
  options: [
2945
2945
  { value: "stub", label: "In-Memory Stub (with in-memory store and test helper methods)" },
@@ -2950,7 +2950,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2950
2950
  );
2951
2951
  if (scope === "feature" && feature && implementsInterface) {
2952
2952
  registerInProvider = handleCancel(
2953
- await p4.confirm({
2953
+ await p14.confirm({
2954
2954
  message: "Register this implementation in feature diProvider.ts?",
2955
2955
  initialValue: true
2956
2956
  })
@@ -2959,7 +2959,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2959
2959
  } else if (flags.yes && scope === "feature" && feature && implementsInterface) {
2960
2960
  registerInProvider = !flags.noProvider;
2961
2961
  }
2962
- const s = p4.spinner();
2962
+ const s = p14.spinner();
2963
2963
  s.start(`Generating infrastructure class '${pc14.cyan(className)}'...`);
2964
2964
  const files = [];
2965
2965
  const options = {
@@ -2995,7 +2995,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2995
2995
  }
2996
2996
  s.stop("Infrastructure class generated successfully!");
2997
2997
  printGeneratedFiles(files, options.dryRun);
2998
- p4.outro(pc14.green(`Infrastructure class '${className}' created!`));
2998
+ p14.outro(pc14.green(`Infrastructure class '${className}' created!`));
2999
2999
  }
3000
3000
  async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3001
3001
  const projectRoot = findProjectRoot();
@@ -3006,14 +3006,14 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3006
3006
  const featureOptions = existingFeatures.map((f) => ({ value: f, label: f }));
3007
3007
  featureOptions.push({ value: "__custom__", label: "\u270F\uFE0F Enter custom feature name..." });
3008
3008
  const selected = handleCancel(
3009
- await p4.select({
3009
+ await p14.select({
3010
3010
  message: "Select target feature:",
3011
3011
  options: featureOptions
3012
3012
  })
3013
3013
  );
3014
3014
  if (selected === "__custom__") {
3015
3015
  feature = handleCancel(
3016
- await p4.text({
3016
+ await p14.text({
3017
3017
  message: "Enter feature name:",
3018
3018
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
3019
3019
  })
@@ -3023,7 +3023,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3023
3023
  }
3024
3024
  } else {
3025
3025
  feature = handleCancel(
3026
- await p4.text({
3026
+ await p14.text({
3027
3027
  message: "Enter target feature name:",
3028
3028
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
3029
3029
  })
@@ -3034,7 +3034,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3034
3034
  let name = interfaceNameArg?.trim();
3035
3035
  if (!name) {
3036
3036
  name = handleCancel(
3037
- await p4.text({
3037
+ await p14.text({
3038
3038
  message: "Domain interface name:",
3039
3039
  placeholder: "e.g. IUserRepository, IPaymentService",
3040
3040
  validate: (v) => v && v.trim() ? void 0 : "Interface name cannot be empty"
@@ -3052,7 +3052,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3052
3052
  if (!flags.yes) {
3053
3053
  if (existingEntities.length > 0) {
3054
3054
  const selectedEntity = handleCancel(
3055
- await p4.select({
3055
+ await p14.select({
3056
3056
  message: "Select domain entity associated with this interface:",
3057
3057
  options: [
3058
3058
  ...existingEntities.map((e) => ({ value: e.name, label: e.name })),
@@ -3063,7 +3063,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3063
3063
  );
3064
3064
  if (selectedEntity === "__custom__") {
3065
3065
  entityName = handleCancel(
3066
- await p4.text({
3066
+ await p14.text({
3067
3067
  message: "Enter entity name:",
3068
3068
  defaultValue: removeInterfacePrefix(ifaceName).replace(/Repository$|Service$/, "")
3069
3069
  })
@@ -3073,7 +3073,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3073
3073
  }
3074
3074
  }
3075
3075
  kind = handleCancel(
3076
- await p4.select({
3076
+ await p14.select({
3077
3077
  message: "Interface definition style:",
3078
3078
  options: [
3079
3079
  { value: "abstractClass", label: "Abstract Class (Recommended - acts as DI token & type)" },
@@ -3083,7 +3083,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3083
3083
  })
3084
3084
  );
3085
3085
  methodsPreset = handleCancel(
3086
- await p4.select({
3086
+ await p14.select({
3087
3087
  message: "Method signature preset:",
3088
3088
  options: [
3089
3089
  { value: "crud", label: "Standard CRUD (GetById, List, Create, Update, Delete)" },
@@ -3093,21 +3093,21 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3093
3093
  })
3094
3094
  );
3095
3095
  generateStub = handleCancel(
3096
- await p4.confirm({
3096
+ await p14.confirm({
3097
3097
  message: "Auto-generate Infrastructure Stub implementation?",
3098
3098
  initialValue: true
3099
3099
  })
3100
3100
  );
3101
3101
  if (generateStub) {
3102
3102
  registerInProvider = handleCancel(
3103
- await p4.confirm({
3103
+ await p14.confirm({
3104
3104
  message: "Auto-register interface & stub in feature diProvider.ts?",
3105
3105
  initialValue: true
3106
3106
  })
3107
3107
  );
3108
3108
  }
3109
3109
  }
3110
- const s = p4.spinner();
3110
+ const s = p14.spinner();
3111
3111
  s.start(`Generating interface '${pc14.cyan(ifaceName)}'...`);
3112
3112
  const files = [];
3113
3113
  const options = {
@@ -3157,7 +3157,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3157
3157
  }
3158
3158
  s.stop("Interface generated successfully!");
3159
3159
  printGeneratedFiles(files, options.dryRun);
3160
- p4.outro(pc14.green(`Interface '${ifaceName}' created in feature '${feature}'!`));
3160
+ p14.outro(pc14.green(`Interface '${ifaceName}' created in feature '${feature}'!`));
3161
3161
  }
3162
3162
  async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3163
3163
  const projectRoot = findProjectRoot();
@@ -3168,14 +3168,14 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3168
3168
  const featureOptions = existingFeatures.map((f) => ({ value: f, label: f }));
3169
3169
  featureOptions.push({ value: "__custom__", label: "\u270F\uFE0F Enter custom feature name..." });
3170
3170
  const selected = handleCancel(
3171
- await p4.select({
3171
+ await p14.select({
3172
3172
  message: "Select target feature:",
3173
3173
  options: featureOptions
3174
3174
  })
3175
3175
  );
3176
3176
  if (selected === "__custom__") {
3177
3177
  feature = handleCancel(
3178
- await p4.text({
3178
+ await p14.text({
3179
3179
  message: "Enter feature name:",
3180
3180
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
3181
3181
  })
@@ -3185,7 +3185,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3185
3185
  }
3186
3186
  } else {
3187
3187
  feature = handleCancel(
3188
- await p4.text({
3188
+ await p14.text({
3189
3189
  message: "Enter target feature name:",
3190
3190
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
3191
3191
  })
@@ -3196,7 +3196,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3196
3196
  let name = handlerNameArg?.trim();
3197
3197
  if (!name) {
3198
3198
  name = handleCancel(
3199
- await p4.text({
3199
+ await p14.text({
3200
3200
  message: "HTTP Route Handler class name:",
3201
3201
  placeholder: "e.g. CreateUserHttp, GetUserHttp, HealthHttp",
3202
3202
  validate: (v) => v && v.trim() ? void 0 : "Handler name cannot be empty"
@@ -3215,7 +3215,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3215
3215
  let validationFields = [];
3216
3216
  if (!flags.yes) {
3217
3217
  method = handleCancel(
3218
- await p4.select({
3218
+ await p14.select({
3219
3219
  message: "HTTP Method:",
3220
3220
  options: [
3221
3221
  { value: "get", label: "GET" },
@@ -3229,7 +3229,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3229
3229
  );
3230
3230
  const defaultPath = method === "get" ? "/" : "/";
3231
3231
  subPath = handleCancel(
3232
- await p4.text({
3232
+ await p14.text({
3233
3233
  message: "Route subpath (relative to feature prefix):",
3234
3234
  initialValue: defaultPath,
3235
3235
  defaultValue: defaultPath
@@ -3240,7 +3240,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3240
3240
  const ucOptions = useCases.map((u) => ({ value: u.name, label: u.name }));
3241
3241
  ucOptions.push({ value: "__none__", label: "None / Standalone Handler" });
3242
3242
  const chosenUc = handleCancel(
3243
- await p4.select({
3243
+ await p14.select({
3244
3244
  message: "Connect this handler to a domain Use Case?",
3245
3245
  options: ucOptions,
3246
3246
  initialValue: ucOptions[0]?.value
@@ -3251,7 +3251,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3251
3251
  }
3252
3252
  }
3253
3253
  includeValidation = handleCancel(
3254
- await p4.confirm({
3254
+ await p14.confirm({
3255
3255
  message: "Include Zod inbound request validation?",
3256
3256
  initialValue: method !== "delete"
3257
3257
  })
@@ -3259,7 +3259,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3259
3259
  if (includeValidation) {
3260
3260
  const defaultSource = method === "get" ? "query" : "body";
3261
3261
  validationSource = handleCancel(
3262
- await p4.select({
3262
+ await p14.select({
3263
3263
  message: "Validation data source:",
3264
3264
  options: [
3265
3265
  { value: "body", label: "req.body (for POST / PUT / PATCH payloads)" },
@@ -3273,7 +3273,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3273
3273
  });
3274
3274
  }
3275
3275
  }
3276
- const s = p4.spinner();
3276
+ const s = p14.spinner();
3277
3277
  s.start(`Generating HTTP handler '${pc14.cyan(className)}'...`);
3278
3278
  const options = {
3279
3279
  name: className,
@@ -3292,7 +3292,7 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3292
3292
  const files = generateHttpHandler(options);
3293
3293
  s.stop("HTTP handler generated successfully!");
3294
3294
  printGeneratedFiles(files, options.dryRun);
3295
- p4.outro(pc14.green(`HTTP handler '${className}' created in feature '${feature}'!`));
3295
+ p14.outro(pc14.green(`HTTP handler '${className}' created in feature '${feature}'!`));
3296
3296
  }
3297
3297
  function generateInjectableCode(className, dependencies = [], methods = [], implementsInterface) {
3298
3298
  const formattedDeps = dependencies.map((dep) => ({
@@ -3372,7 +3372,7 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3372
3372
  let name = classNameArg?.trim();
3373
3373
  if (!name) {
3374
3374
  name = handleCancel(
3375
- await p4.text({
3375
+ await p14.text({
3376
3376
  message: "Injectable class name:",
3377
3377
  placeholder: "e.g. PasswordHasher, TokenService, UserTransformer",
3378
3378
  validate: (v) => v && v.trim() ? void 0 : "Class name cannot be empty"
@@ -3385,7 +3385,7 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3385
3385
  let customPath;
3386
3386
  if (!flags.yes) {
3387
3387
  location = handleCancel(
3388
- await p4.select({
3388
+ await p14.select({
3389
3389
  message: "Select target architectural location:",
3390
3390
  options: [
3391
3391
  { value: "feature-service", label: "Feature Service (features/<feature>/services/)" },
@@ -3403,14 +3403,14 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3403
3403
  const featureOptions = existingFeatures.map((f) => ({ value: f, label: f }));
3404
3404
  featureOptions.push({ value: "__custom__", label: "\u270F\uFE0F Enter custom feature name..." });
3405
3405
  const selected = handleCancel(
3406
- await p4.select({
3406
+ await p14.select({
3407
3407
  message: "Select target feature:",
3408
3408
  options: featureOptions
3409
3409
  })
3410
3410
  );
3411
3411
  if (selected === "__custom__") {
3412
3412
  feature = handleCancel(
3413
- await p4.text({
3413
+ await p14.text({
3414
3414
  message: "Enter feature name:",
3415
3415
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
3416
3416
  })
@@ -3420,7 +3420,7 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3420
3420
  }
3421
3421
  } else {
3422
3422
  feature = handleCancel(
3423
- await p4.text({
3423
+ await p14.text({
3424
3424
  message: "Enter target feature name:",
3425
3425
  validate: (v) => v && v.trim() ? void 0 : "Feature name cannot be empty"
3426
3426
  })
@@ -3430,7 +3430,7 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3430
3430
  feature = toCamelCase(feature);
3431
3431
  } else if (location === "custom") {
3432
3432
  customPath = handleCancel(
3433
- await p4.text({
3433
+ await p14.text({
3434
3434
  message: "Enter destination directory path:",
3435
3435
  placeholder: "e.g. src/services or lib/utils",
3436
3436
  validate: (v) => v && v.trim() ? void 0 : "Path cannot be empty"
@@ -3441,13 +3441,13 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3441
3441
  let generateInterface2 = false;
3442
3442
  if (!flags.yes) {
3443
3443
  generateInterface2 = handleCancel(
3444
- await p4.confirm({
3444
+ await p14.confirm({
3445
3445
  message: `Generate abstract class interface (I${className}) as runtime DI token?`,
3446
3446
  initialValue: false
3447
3447
  })
3448
3448
  );
3449
3449
  }
3450
- const s = p4.spinner();
3450
+ const s = p14.spinner();
3451
3451
  s.start(`Generating injectable '${pc14.cyan(className)}'...`);
3452
3452
  const options = {
3453
3453
  name: className,
@@ -3462,12 +3462,12 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3462
3462
  const files = generateInjectable(options);
3463
3463
  s.stop("Injectable class generated successfully!");
3464
3464
  printGeneratedFiles(files, options.dryRun);
3465
- p4.outro(pc14.green(`Injectable '${className}' created successfully!`));
3465
+ p14.outro(pc14.green(`Injectable '${className}' created successfully!`));
3466
3466
  }
3467
3467
  async function runInteractiveMenu(flags = {}) {
3468
3468
  printBanner();
3469
3469
  const choice = handleCancel(
3470
- await p4.select({
3470
+ await p14.select({
3471
3471
  message: "What would you like to create in your architecture?",
3472
3472
  options: [
3473
3473
  {
@@ -3575,7 +3575,7 @@ async function handleCreate(type, name, flags = {}) {
3575
3575
  await runInjectableCommand(name, flags);
3576
3576
  break;
3577
3577
  default:
3578
- p4.log.error(
3578
+ p14.log.error(
3579
3579
  pc14.red(
3580
3580
  `Unknown component type: "${type}". Allowed types: feature, shared, usecase, domain, infrastructure, interface, httpHandler, injectable.`
3581
3581
  )
@@ -3584,8 +3584,8 @@ async function handleCreate(type, name, flags = {}) {
3584
3584
  }
3585
3585
  }
3586
3586
  var importPrompts = {
3587
- select: p4.select,
3588
- text: p4.text
3587
+ select: p14.select,
3588
+ text: p14.text
3589
3589
  };
3590
3590
  function rewriteImports(content, aliasMap) {
3591
3591
  if (aliasMap.size === 0) return content;
@@ -3614,126 +3614,6 @@ function getExistingModuleDir(projectRoot, modType, modName) {
3614
3614
  function checkModuleExists(projectRoot, modType, modName) {
3615
3615
  return getExistingModuleDir(projectRoot, modType, modName) !== null;
3616
3616
  }
3617
- async function resolveDependency(depType, depName, aliasMap, projectRoot, flags, importModuleRecursive, importedModules, registryBase, index) {
3618
- const folder = depType === "shared" ? "shared" : "features";
3619
- const isAlreadyImportedThisRun = importedModules.has(`${depType}:${depName}`);
3620
- if (isAlreadyImportedThisRun) return;
3621
- const programmaticAlias = flags.alias?.[depName] || flags.alias?.[`${depType}/${depName}`];
3622
- if (programmaticAlias) {
3623
- aliasMap.set(`@/${folder}/${depName}/`, `@/${folder}/${programmaticAlias}/`);
3624
- const baseDir = getModuleBaseDir(projectRoot, depType);
3625
- const displayDest = path2.relative(
3626
- projectRoot,
3627
- path2.join(baseDir, programmaticAlias)
3628
- );
3629
- p4.log.step(`Importing '${depName}' into '${displayDest}'...`);
3630
- await importModuleRecursive(depType, depName, programmaticAlias);
3631
- return;
3632
- }
3633
- const existingDir = getExistingModuleDir(projectRoot, depType, depName);
3634
- if (!existingDir) {
3635
- p4.log.info(` \u21B3 Resolving required ${depType} dependency: ${pc14.cyan(depName)}`);
3636
- await importModuleRecursive(depType, depName, depName);
3637
- return;
3638
- }
3639
- const entry = (depType === "shared" ? index?.shared : index?.features)?.find(
3640
- (item) => item.name === depName
3641
- );
3642
- let remoteIntegrity = entry?.integrity;
3643
- if (!remoteIntegrity) {
3644
- try {
3645
- const depManifest = await fetchModuleManifest(registryBase, depType, depName);
3646
- remoteIntegrity = depManifest.integrity;
3647
- } catch {
3648
- }
3649
- }
3650
- const localHash = computeDirectoryHash(existingDir);
3651
- if (remoteIntegrity && localHash === remoteIntegrity) {
3652
- p4.log.step(`\u2713 ${depType}/${depName} is up to date (reusing existing)`);
3653
- importedModules.add(`${depType}:${depName}`);
3654
- return;
3655
- }
3656
- if (flags.overwrite) {
3657
- p4.log.step(`Overwriting '${depType}/${depName}' with registry version (--overwrite)...`);
3658
- const baseDir = getModuleBaseDir(projectRoot, depType);
3659
- const targetDir = path2.join(baseDir, depName);
3660
- if (!flags.dryRun) {
3661
- if (existingDir !== targetDir) {
3662
- fs4.rmSync(existingDir, { recursive: true, force: true });
3663
- }
3664
- fs4.rmSync(targetDir, { recursive: true, force: true });
3665
- }
3666
- await importModuleRecursive(depType, depName, depName, { overwrite: true });
3667
- return;
3668
- }
3669
- if (flags.yes) {
3670
- p4.log.info(`Using existing '${depType}/${depName}'`);
3671
- importedModules.add(`${depType}:${depName}`);
3672
- return;
3673
- }
3674
- const choice = handleCancel(
3675
- await importPrompts.select({
3676
- message: `Local '${depType}/${depName}' differs from the registry version.`,
3677
- options: [
3678
- {
3679
- value: "keep_existing",
3680
- label: `Keep existing local version (Recommended)`
3681
- },
3682
- {
3683
- value: "rename",
3684
- label: "Import fresh copy under a new name (alias)"
3685
- },
3686
- {
3687
- value: "overwrite",
3688
- label: "Overwrite local version with registry version"
3689
- }
3690
- ]
3691
- })
3692
- );
3693
- if (choice === "keep_existing" || choice === "use_existing") {
3694
- p4.log.step(`Skipping '${depType}/${depName}' (keeping existing)`);
3695
- importedModules.add(`${depType}:${depName}`);
3696
- return;
3697
- }
3698
- if (choice === "rename") {
3699
- const newName = handleCancel(
3700
- await importPrompts.text({
3701
- message: "What should we name the new copy?",
3702
- placeholder: `${depName}-copy`,
3703
- validate(val) {
3704
- const v = val?.trim();
3705
- if (!v) return "Name cannot be empty";
3706
- if (v === depName) return `Name must be different from '${depName}'`;
3707
- if (!/^[a-zA-Z0-9_-]+$/.test(v)) {
3708
- return "Name can only contain alphanumeric characters, dashes, and underscores";
3709
- }
3710
- if (checkModuleExists(projectRoot, depType, v)) {
3711
- return `'${v}' already exists in ${folder}, please choose another name`;
3712
- }
3713
- }
3714
- })
3715
- ).trim();
3716
- aliasMap.set(`@/${folder}/${depName}/`, `@/${folder}/${newName}/`);
3717
- const baseDir = getModuleBaseDir(projectRoot, depType);
3718
- const displayDest = path2.relative(projectRoot, path2.join(baseDir, newName));
3719
- p4.log.step(`Importing '${depName}' into '${displayDest}'...`);
3720
- await importModuleRecursive(depType, depName, newName);
3721
- return;
3722
- }
3723
- if (choice === "overwrite") {
3724
- p4.log.step(`Overwriting '${depType}/${depName}' with registry version...`);
3725
- const baseDir = getModuleBaseDir(projectRoot, depType);
3726
- const targetDir = path2.join(baseDir, depName);
3727
- if (!flags.dryRun) {
3728
- if (existingDir !== targetDir) {
3729
- fs4.rmSync(existingDir, { recursive: true, force: true });
3730
- }
3731
- fs4.rmSync(targetDir, { recursive: true, force: true });
3732
- }
3733
- await importModuleRecursive(depType, depName, depName, { overwrite: true });
3734
- return;
3735
- }
3736
- }
3737
3617
  async function handleImport(typeArg, nameArg, flags = {}) {
3738
3618
  const projectRoot = findProjectRoot();
3739
3619
  let type = typeArg?.trim().toLowerCase();
@@ -3758,11 +3638,11 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3758
3638
  );
3759
3639
  }
3760
3640
  if (type !== "shared" && type !== "feature") {
3761
- p4.log.error(pc14.red(`Invalid module type: "${typeArg}". Must be "shared" or "feature".`));
3641
+ p14.log.error(pc14.red(`Invalid module type: "${typeArg}". Must be "shared" or "feature".`));
3762
3642
  process.exit(1);
3763
3643
  }
3764
3644
  const registryBase = getRegistryBase(projectRoot, flags.registry);
3765
- const s = p4.spinner();
3645
+ const s = p14.spinner();
3766
3646
  s.start(`Connecting to registry at ${pc14.dim(registryBase)}...`);
3767
3647
  let index;
3768
3648
  try {
@@ -3770,7 +3650,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3770
3650
  s.stop("Registry index loaded.");
3771
3651
  } catch (err) {
3772
3652
  s.stop(pc14.red("Failed to load registry index."));
3773
- p4.log.error(pc14.red(err.message || String(err)));
3653
+ p14.log.error(pc14.red(err.message || String(err)));
3774
3654
  process.exit(1);
3775
3655
  }
3776
3656
  const availableList = type === "shared" ? index.shared : index.features;
@@ -3778,7 +3658,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3778
3658
  let name = nameArg?.trim();
3779
3659
  if (!name) {
3780
3660
  if (availableList.length === 0) {
3781
- p4.log.warn(`No ${type} modules available in the registry.`);
3661
+ p14.log.warn(`No ${type} modules available in the registry.`);
3782
3662
  return;
3783
3663
  }
3784
3664
  name = handleCancel(
@@ -3794,108 +3674,294 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3794
3674
  }
3795
3675
  if (!candidateNames.includes(name)) {
3796
3676
  const closest = findClosestMatch(name, candidateNames);
3797
- p4.log.error(pc14.red(`\u274C Module '${name}' not found in the ${type} registry.`));
3677
+ p14.log.error(pc14.red(`\u274C Module '${name}' not found in the ${type} registry.`));
3798
3678
  if (closest) {
3799
- p4.log.info(pc14.yellow(`Did you mean '${pc14.cyan(closest)}'?`));
3679
+ p14.log.info(pc14.yellow(`Did you mean '${pc14.cyan(closest)}'?`));
3800
3680
  }
3801
3681
  process.exit(1);
3802
3682
  }
3803
- const importedModules = /* @__PURE__ */ new Set();
3804
- const totalWrittenFiles = [];
3805
- const requiredNpmPackages = /* @__PURE__ */ new Set();
3806
- async function importModuleRecursive(modType, registryName, targetName = registryName, options) {
3807
- const modKey = `${modType}:${targetName}`;
3808
- if (importedModules.has(modKey)) return;
3809
- p4.log.step(
3810
- `Importing ${modType}: ${pc14.cyan(targetName)}${targetName !== registryName ? pc14.dim(` (from ${registryName})`) : ""}...`
3811
- );
3683
+ const nodes = /* @__PURE__ */ new Map();
3684
+ async function discoverGraph(modType, modName) {
3685
+ const key = `${modType}:${modName}`;
3686
+ if (nodes.has(key)) return;
3812
3687
  let manifest;
3813
3688
  try {
3814
- manifest = await fetchModuleManifest(registryBase, modType, registryName);
3689
+ manifest = await fetchModuleManifest(registryBase, modType, modName);
3815
3690
  } catch (err) {
3816
- p4.log.error(pc14.red(`Failed to fetch manifest for ${modType} '${registryName}': ${err.message}`));
3691
+ p14.log.error(pc14.red(`Failed to fetch manifest for ${modType} '${modName}': ${err.message}`));
3817
3692
  process.exit(1);
3818
3693
  }
3819
- const aliasMap = /* @__PURE__ */ new Map();
3820
- if (targetName !== registryName) {
3821
- const folder2 = modType === "shared" ? "shared" : "features";
3822
- aliasMap.set(`@/${folder2}/${registryName}/`, `@/${folder2}/${targetName}/`);
3823
- }
3824
- const sharedDeps = manifest.dependencies?.shared || [];
3825
- for (const dep of sharedDeps) {
3826
- await resolveDependency(
3827
- "shared",
3828
- dep,
3829
- aliasMap,
3830
- projectRoot,
3831
- flags,
3832
- importModuleRecursive,
3833
- importedModules,
3834
- registryBase,
3835
- index
3836
- );
3694
+ nodes.set(key, {
3695
+ type: modType,
3696
+ name: modName,
3697
+ manifest
3698
+ });
3699
+ for (const dep of manifest.dependencies?.shared || []) {
3700
+ await discoverGraph("shared", dep);
3837
3701
  }
3838
- const featureDeps = manifest.dependencies?.features || [];
3839
- for (const dep of featureDeps) {
3840
- await resolveDependency(
3841
- "feature",
3842
- dep,
3843
- aliasMap,
3844
- projectRoot,
3845
- flags,
3846
- importModuleRecursive,
3847
- importedModules,
3848
- registryBase,
3849
- index
3850
- );
3702
+ for (const dep of manifest.dependencies?.features || []) {
3703
+ await discoverGraph("feature", dep);
3851
3704
  }
3852
- for (const pkg of manifest.dependencies?.npm || []) {
3853
- requiredNpmPackages.add(pkg);
3705
+ }
3706
+ await discoverGraph(type, name);
3707
+ const orderedKeys = [];
3708
+ const visiting = /* @__PURE__ */ new Set();
3709
+ const visited = /* @__PURE__ */ new Set();
3710
+ function buildTopologicalOrder(key) {
3711
+ if (visited.has(key)) return;
3712
+ if (visiting.has(key)) return;
3713
+ visiting.add(key);
3714
+ const node = nodes.get(key);
3715
+ if (node) {
3716
+ for (const dep of node.manifest.dependencies?.shared || []) {
3717
+ buildTopologicalOrder(`shared:${dep}`);
3718
+ }
3719
+ for (const dep of node.manifest.dependencies?.features || []) {
3720
+ buildTopologicalOrder(`feature:${dep}`);
3721
+ }
3854
3722
  }
3723
+ visiting.delete(key);
3724
+ visited.add(key);
3725
+ orderedKeys.push(key);
3726
+ }
3727
+ const rootKey = `${type}:${name}`;
3728
+ buildTopologicalOrder(rootKey);
3729
+ const resolutions = /* @__PURE__ */ new Map();
3730
+ const globalAliasMap = /* @__PURE__ */ new Map();
3731
+ p14.log.step(`Importing ${type}: ${pc14.cyan(name)}...`);
3732
+ for (const key of orderedKeys) {
3733
+ const node = nodes.get(key);
3734
+ const { type: modType, name: registryName, manifest } = node;
3855
3735
  const folder = modType === "shared" ? "shared" : "features";
3856
- const targetDir = path2.join(getModuleBaseDir(projectRoot, modType), targetName);
3857
- const isOverwrite = Boolean(flags.overwrite || options?.overwrite);
3858
- for (const file of manifest.files || []) {
3736
+ if (key === rootKey) {
3737
+ const programmaticAlias2 = flags.alias?.[registryName] || flags.alias?.[`${modType}/${registryName}`];
3738
+ const targetName = programmaticAlias2 || registryName;
3739
+ if (targetName !== registryName) {
3740
+ globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${targetName}/`);
3741
+ globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${targetName}`);
3742
+ }
3743
+ resolutions.set(key, {
3744
+ type: modType,
3745
+ registryName,
3746
+ targetName,
3747
+ action: flags.overwrite ? "overwrite" : "download",
3748
+ manifest
3749
+ });
3750
+ continue;
3751
+ }
3752
+ const programmaticAlias = flags.alias?.[registryName] || flags.alias?.[`${modType}/${registryName}`];
3753
+ if (programmaticAlias) {
3754
+ globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${programmaticAlias}/`);
3755
+ globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${programmaticAlias}`);
3756
+ const baseDir = getModuleBaseDir(projectRoot, modType);
3757
+ const displayDest = path2.relative(projectRoot, path2.join(baseDir, programmaticAlias));
3758
+ p14.log.step(`Importing '${registryName}' into '${displayDest}'...`);
3759
+ resolutions.set(key, {
3760
+ type: modType,
3761
+ registryName,
3762
+ targetName: programmaticAlias,
3763
+ action: "alias",
3764
+ manifest
3765
+ });
3766
+ continue;
3767
+ }
3768
+ const existingDir = getExistingModuleDir(projectRoot, modType, registryName);
3769
+ if (!existingDir) {
3770
+ p14.log.info(` \u21B3 Resolving required ${modType} dependency: ${pc14.cyan(registryName)}`);
3771
+ resolutions.set(key, {
3772
+ type: modType,
3773
+ registryName,
3774
+ targetName: registryName,
3775
+ action: "download",
3776
+ manifest
3777
+ });
3778
+ continue;
3779
+ }
3780
+ const entry = (modType === "shared" ? index.shared : index.features)?.find(
3781
+ (item) => item.name === registryName
3782
+ );
3783
+ const remoteIntegrity = manifest.integrity || entry?.integrity;
3784
+ const localHash = computeDirectoryHash(existingDir);
3785
+ if (remoteIntegrity && localHash === remoteIntegrity) {
3786
+ p14.log.step(`\u2713 ${modType}/${registryName} is up to date (reusing existing)`);
3787
+ resolutions.set(key, {
3788
+ type: modType,
3789
+ registryName,
3790
+ targetName: registryName,
3791
+ action: "reuse",
3792
+ manifest
3793
+ });
3794
+ continue;
3795
+ }
3796
+ if (flags.overwrite) {
3797
+ p14.log.step(`Overwriting '${modType}/${registryName}' with registry version (--overwrite)...`);
3798
+ resolutions.set(key, {
3799
+ type: modType,
3800
+ registryName,
3801
+ targetName: registryName,
3802
+ action: "overwrite",
3803
+ manifest
3804
+ });
3805
+ continue;
3806
+ }
3807
+ if (flags.yes) {
3808
+ p14.log.info(`Using existing '${modType}/${registryName}'`);
3809
+ resolutions.set(key, {
3810
+ type: modType,
3811
+ registryName,
3812
+ targetName: registryName,
3813
+ action: "reuse",
3814
+ manifest
3815
+ });
3816
+ continue;
3817
+ }
3818
+ const choice = handleCancel(
3819
+ await importPrompts.select({
3820
+ message: `Local '${modType}/${registryName}' differs from the registry version.`,
3821
+ options: [
3822
+ {
3823
+ value: "keep_existing",
3824
+ label: `Keep existing local version (Recommended)`
3825
+ },
3826
+ {
3827
+ value: "rename",
3828
+ label: "Import fresh copy under a new name (alias)"
3829
+ },
3830
+ {
3831
+ value: "overwrite",
3832
+ label: "Overwrite local version with registry version"
3833
+ }
3834
+ ]
3835
+ })
3836
+ );
3837
+ if (choice === "keep_existing" || choice === "use_existing") {
3838
+ p14.log.step(`Skipping '${modType}/${registryName}' (keeping existing)`);
3839
+ resolutions.set(key, {
3840
+ type: modType,
3841
+ registryName,
3842
+ targetName: registryName,
3843
+ action: "reuse",
3844
+ manifest
3845
+ });
3846
+ continue;
3847
+ }
3848
+ if (choice === "rename") {
3849
+ const newName = handleCancel(
3850
+ await importPrompts.text({
3851
+ message: "What should we name the new copy?",
3852
+ placeholder: `${registryName}-copy`,
3853
+ validate(val) {
3854
+ const v = val?.trim();
3855
+ if (!v) return "Name cannot be empty";
3856
+ if (v === registryName) return `Name must be different from '${registryName}'`;
3857
+ if (!/^[a-zA-Z0-9_-]+$/.test(v)) {
3858
+ return "Name can only contain alphanumeric characters, dashes, and underscores";
3859
+ }
3860
+ if (checkModuleExists(projectRoot, modType, v)) {
3861
+ return `'${v}' already exists in ${folder}, please choose another name`;
3862
+ }
3863
+ }
3864
+ })
3865
+ ).trim();
3866
+ globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${newName}/`);
3867
+ globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${newName}`);
3868
+ const baseDir = getModuleBaseDir(projectRoot, modType);
3869
+ const displayDest = path2.relative(projectRoot, path2.join(baseDir, newName));
3870
+ p14.log.step(`Importing '${registryName}' into '${displayDest}'...`);
3871
+ resolutions.set(key, {
3872
+ type: modType,
3873
+ registryName,
3874
+ targetName: newName,
3875
+ action: "alias",
3876
+ manifest
3877
+ });
3878
+ continue;
3879
+ }
3880
+ if (choice === "overwrite") {
3881
+ p14.log.step(`Overwriting '${modType}/${registryName}' with registry version...`);
3882
+ resolutions.set(key, {
3883
+ type: modType,
3884
+ registryName,
3885
+ targetName: registryName,
3886
+ action: "overwrite",
3887
+ manifest
3888
+ });
3889
+ continue;
3890
+ }
3891
+ }
3892
+ const totalWrittenFiles = [];
3893
+ const requiredNpmPackages = /* @__PURE__ */ new Set();
3894
+ for (const node of nodes.values()) {
3895
+ for (const pkg of node.manifest.dependencies?.npm || []) {
3896
+ requiredNpmPackages.add(pkg);
3897
+ }
3898
+ }
3899
+ for (const key of orderedKeys) {
3900
+ const res = resolutions.get(key);
3901
+ if (res.action === "reuse") {
3902
+ continue;
3903
+ }
3904
+ const folder = res.type === "shared" ? "shared" : "features";
3905
+ const targetDir = path2.join(getModuleBaseDir(projectRoot, res.type), res.targetName);
3906
+ const isOverwrite = Boolean(flags.overwrite || res.action === "overwrite");
3907
+ if (key !== rootKey) {
3908
+ p14.log.step(
3909
+ `Importing ${res.type}: ${pc14.cyan(res.targetName)}${res.targetName !== res.registryName ? pc14.dim(` (from ${res.registryName})`) : ""}...`
3910
+ );
3911
+ }
3912
+ if (res.action === "overwrite" && !flags.dryRun) {
3913
+ const existingDir = getExistingModuleDir(projectRoot, res.type, res.targetName);
3914
+ if (existingDir && existingDir !== targetDir) {
3915
+ fs4.rmSync(existingDir, { recursive: true, force: true });
3916
+ }
3917
+ if (fs4.existsSync(targetDir)) {
3918
+ fs4.rmSync(targetDir, { recursive: true, force: true });
3919
+ }
3920
+ }
3921
+ for (const file of res.manifest.files || []) {
3859
3922
  if (file === "registry.json") continue;
3860
- const remoteFilePath = `${folder}/${registryName}/${file}`;
3923
+ const remoteFilePath = `${folder}/${res.registryName}/${file}`;
3861
3924
  const localFilePath = path2.join(targetDir, file);
3862
3925
  if (fs4.existsSync(localFilePath) && !isOverwrite) {
3863
- p4.log.warn(
3926
+ p14.log.warn(
3864
3927
  ` \u21B3 Skipping existing file: ${pc14.dim(path2.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
3865
3928
  );
3866
3929
  continue;
3867
3930
  }
3868
3931
  let content = await fetchRegistryFile(registryBase, remoteFilePath);
3869
- content = rewriteImports(content, aliasMap);
3932
+ content = rewriteImports(content, globalAliasMap);
3870
3933
  if (!flags.dryRun) {
3871
3934
  fs4.mkdirSync(path2.dirname(localFilePath), { recursive: true });
3872
3935
  fs4.writeFileSync(localFilePath, content, "utf-8");
3873
3936
  }
3874
3937
  const displayPath = path2.relative(projectRoot, localFilePath);
3875
3938
  totalWrittenFiles.push(displayPath);
3876
- p4.log.message(` ${pc14.green("+")} ${displayPath}`);
3939
+ p14.log.message(` ${pc14.green("+")} ${displayPath}`);
3877
3940
  }
3878
- importedModules.add(modKey);
3879
3941
  }
3880
- await importModuleRecursive(type, name, name);
3881
3942
  const missingNpm = getMissingNpmPackages(projectRoot, Array.from(requiredNpmPackages));
3882
3943
  if (missingNpm.length > 0) {
3883
3944
  if (flags.skipInstall || flags.dryRun) {
3884
- p4.log.info(`Required npm dependencies to install: ${pc14.cyan(missingNpm.join(", "))}`);
3945
+ p14.log.info(`Required npm dependencies to install: ${pc14.cyan(missingNpm.join(", "))}`);
3885
3946
  } else {
3886
3947
  try {
3887
3948
  installNpmPackages(projectRoot, missingNpm);
3888
3949
  } catch (err) {
3889
- p4.log.warn(`Could not automatically install packages (${err.message}). Please run: npm install ${missingNpm.join(" ")}`);
3950
+ p14.log.warn(
3951
+ `Could not automatically install packages (${err.message}). Please run: npm install ${missingNpm.join(
3952
+ " "
3953
+ )}`
3954
+ );
3890
3955
  }
3891
3956
  }
3892
3957
  }
3893
3958
  if (flags.dryRun) {
3894
- p4.log.info(pc14.yellow("Dry run complete: No files were written to disk."));
3959
+ p14.log.info(pc14.yellow("Dry run complete: No files were written to disk."));
3895
3960
  } else {
3961
+ const rootRes = resolutions.get(rootKey);
3896
3962
  const baseDir = getModuleBaseDir(projectRoot, type);
3897
- const displayTarget = path2.relative(projectRoot, path2.join(baseDir, name));
3898
- p4.log.success(
3963
+ const displayTarget = path2.relative(projectRoot, path2.join(baseDir, rootRes.targetName));
3964
+ p14.log.success(
3899
3965
  pc14.green(
3900
3966
  `Successfully imported ${type} '${name}' (${totalWrittenFiles.length} file${totalWrittenFiles.length === 1 ? "" : "s"} placed in ${displayTarget})`
3901
3967
  )
@@ -3908,7 +3974,7 @@ function createCli() {
3908
3974
  const cli = cac("mason");
3909
3975
  cli.command("[...args]", "Interactive scaffolding and import wizard").option("-d, --dry-run", "Preview changes without writing to disk").option("-o, --overwrite", "Overwrite existing files").option("-y, --yes", "Accept defaults and skip interactive prompts").option("--registry", "Run in registry mode").action(async (args, flags) => {
3910
3976
  if (args && args.length > 0) {
3911
- p4.log.error(
3977
+ p14.log.error(
3912
3978
  pc14.red(
3913
3979
  `Unknown command: "${args.join(" ")}". Use --help to list available commands.`
3914
3980
  )
@@ -3920,7 +3986,7 @@ function createCli() {
3920
3986
  const mode = getEffectiveMode(projectRoot, flags);
3921
3987
  if (mode === "registry") {
3922
3988
  const choice2 = handleCancel(
3923
- await p4.select({
3989
+ await p14.select({
3924
3990
  message: "\u{1F3DB}\uFE0F Mason (Registry Mode): What would you like to scaffold?",
3925
3991
  options: [
3926
3992
  {
@@ -3963,7 +4029,7 @@ function createCli() {
3963
4029
  return;
3964
4030
  }
3965
4031
  const choice = handleCancel(
3966
- await p4.select({
4032
+ await p14.select({
3967
4033
  message: "\u{1F9F1} Mason: What would you like to do?",
3968
4034
  options: [
3969
4035
  {
@@ -4031,7 +4097,7 @@ function createCli() {
4031
4097
  });
4032
4098
  }
4033
4099
  cli.help();
4034
- cli.version("1.0.14");
4100
+ cli.version("1.0.16");
4035
4101
  return cli;
4036
4102
  }
4037
4103
  function handleCliError(err) {
@@ -4039,7 +4105,7 @@ function handleCliError(err) {
4039
4105
  process.exit(0);
4040
4106
  }
4041
4107
  const message = err instanceof Error ? err.message : String(err);
4042
- p4.log.error(pc14.red(`Error: ${message}`));
4108
+ p14.log.error(pc14.red(`Error: ${message}`));
4043
4109
  process.exit(1);
4044
4110
  }
4045
4111
  async function runCli(argv = process.argv) {