@solid-stack/mason 1.0.13 → 1.0.15

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,7 +1,7 @@
1
- import fs12 from 'fs';
1
+ import fs4 from 'fs';
2
2
  import path2 from 'path';
3
- import * as p15 from '@clack/prompts';
4
- import pc15 from 'picocolors';
3
+ import * as p4 from '@clack/prompts';
4
+ import pc14 from 'picocolors';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { execSync } from 'child_process';
7
7
  import { createHash } from 'crypto';
@@ -77,7 +77,7 @@ function isValidIdentifier(str) {
77
77
  function writeFileSafely(absolutePath, content, options = {}) {
78
78
  const projectRoot = options.projectRoot || process.cwd();
79
79
  const relPath = path2.relative(projectRoot, absolutePath).replace(/\\/g, "/");
80
- const existedBefore = fs12.existsSync(absolutePath);
80
+ const existedBefore = fs4.existsSync(absolutePath);
81
81
  if (options.dryRun) {
82
82
  return {
83
83
  relativePath: relPath,
@@ -97,10 +97,10 @@ function writeFileSafely(absolutePath, content, options = {}) {
97
97
  };
98
98
  }
99
99
  const dir = path2.dirname(absolutePath);
100
- if (!fs12.existsSync(dir)) {
101
- fs12.mkdirSync(dir, { recursive: true });
100
+ if (!fs4.existsSync(dir)) {
101
+ fs4.mkdirSync(dir, { recursive: true });
102
102
  }
103
- fs12.writeFileSync(absolutePath, content, "utf-8");
103
+ fs4.writeFileSync(absolutePath, content, "utf-8");
104
104
  return {
105
105
  relativePath: relPath,
106
106
  absolutePath,
@@ -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
- p15.log.warn(pc15.yellow(pc15.bold("[DRY RUN PREVIEW] No files were written to disk.")));
115
+ p4.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
- p15.log.success(`${pc15.bold(f.relativePath)} ${pc15.dim("(created)")}`);
119
+ p4.log.success(`${pc14.bold(f.relativePath)} ${pc14.dim("(created)")}`);
120
120
  } else if (f.action === "overwritten") {
121
- p15.log.warn(`${pc15.bold(f.relativePath)} ${pc15.dim("(overwritten)")}`);
121
+ p4.log.warn(`${pc14.bold(f.relativePath)} ${pc14.dim("(overwritten)")}`);
122
122
  } else if (f.action === "skipped") {
123
- p15.log.info(`${pc15.dim(f.relativePath)} ${pc15.dim("(skipped - already exists, pass -o to overwrite)")}`);
123
+ p4.log.info(`${pc14.dim(f.relativePath)} ${pc14.dim("(skipped - already exists, pass -o to overwrite)")}`);
124
124
  } else {
125
- p15.log.info(`${pc15.bold(f.relativePath)} ${pc15.dim("(preview)")}`);
125
+ p4.log.info(`${pc14.bold(f.relativePath)} ${pc14.dim("(preview)")}`);
126
126
  }
127
127
  }
128
128
  }
@@ -130,9 +130,9 @@ function loadMasonConfig(startDir = process.cwd()) {
130
130
  let current = path2.resolve(startDir);
131
131
  while (true) {
132
132
  const configPath = path2.join(current, "mason.config.json");
133
- if (fs12.existsSync(configPath)) {
133
+ if (fs4.existsSync(configPath)) {
134
134
  try {
135
- return JSON.parse(fs12.readFileSync(configPath, "utf-8"));
135
+ return JSON.parse(fs4.readFileSync(configPath, "utf-8"));
136
136
  } catch {
137
137
  return null;
138
138
  }
@@ -147,7 +147,7 @@ function getEffectiveMode(projectRoot, flags) {
147
147
  if (flags?.registry) return "registry";
148
148
  const config = loadMasonConfig(projectRoot);
149
149
  if (config?.mode) return config.mode;
150
- if (fs12.existsSync(path2.join(projectRoot, "index.json")) && (fs12.existsSync(path2.join(projectRoot, "features")) || fs12.existsSync(path2.join(projectRoot, "shared"))) && !fs12.existsSync(path2.join(projectRoot, "src"))) {
150
+ if (fs4.existsSync(path2.join(projectRoot, "index.json")) && (fs4.existsSync(path2.join(projectRoot, "features")) || fs4.existsSync(path2.join(projectRoot, "shared"))) && !fs4.existsSync(path2.join(projectRoot, "src"))) {
151
151
  return "registry";
152
152
  }
153
153
  return "app";
@@ -163,7 +163,7 @@ function getConfiguredFeaturesDir(projectRoot, flags) {
163
163
  if (mode === "registry") {
164
164
  return path2.join(projectRoot, "features");
165
165
  }
166
- if (fs12.existsSync(path2.join(projectRoot, "src/features"))) {
166
+ if (fs4.existsSync(path2.join(projectRoot, "src/features"))) {
167
167
  return path2.join(projectRoot, "src/features");
168
168
  }
169
169
  return path2.join(projectRoot, "features");
@@ -179,7 +179,7 @@ function getConfiguredSharedDir(projectRoot, flags) {
179
179
  if (mode === "registry") {
180
180
  return path2.join(projectRoot, "shared");
181
181
  }
182
- if (fs12.existsSync(path2.join(projectRoot, "src/shared"))) {
182
+ if (fs4.existsSync(path2.join(projectRoot, "src/shared"))) {
183
183
  return path2.join(projectRoot, "src/shared");
184
184
  }
185
185
  return path2.join(projectRoot, "shared");
@@ -189,7 +189,7 @@ function getConfiguredSharedDir(projectRoot, flags) {
189
189
  function findProjectRoot(startDir = process.cwd()) {
190
190
  let current = path2.resolve(startDir);
191
191
  while (true) {
192
- if (fs12.existsSync(path2.join(current, "package.json"))) {
192
+ if (fs4.existsSync(path2.join(current, "package.json"))) {
193
193
  return current;
194
194
  }
195
195
  const parent = path2.dirname(current);
@@ -207,9 +207,9 @@ function resolveSharedDir(projectRoot, flags) {
207
207
  }
208
208
  function listExistingShared(projectRoot) {
209
209
  const sharedDir = resolveSharedDir(projectRoot);
210
- if (!fs12.existsSync(sharedDir)) return [];
210
+ if (!fs4.existsSync(sharedDir)) return [];
211
211
  try {
212
- const entries = fs12.readdirSync(sharedDir, { withFileTypes: true });
212
+ const entries = fs4.readdirSync(sharedDir, { withFileTypes: true });
213
213
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
214
214
  } catch {
215
215
  return [];
@@ -217,9 +217,9 @@ function listExistingShared(projectRoot) {
217
217
  }
218
218
  function listExistingFeatures(projectRoot) {
219
219
  const featuresDir = resolveFeaturesDir(projectRoot);
220
- if (!fs12.existsSync(featuresDir)) return [];
220
+ if (!fs4.existsSync(featuresDir)) return [];
221
221
  try {
222
- const entries = fs12.readdirSync(featuresDir, { withFileTypes: true });
222
+ const entries = fs4.readdirSync(featuresDir, { withFileTypes: true });
223
223
  return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
224
224
  } catch {
225
225
  return [];
@@ -230,9 +230,9 @@ function listDomainInterfaces(projectRoot, featureName) {
230
230
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
231
231
  for (const feat of features) {
232
232
  const domainDir = path2.join(resolveFeaturesDir(projectRoot), feat, "domain");
233
- if (!fs12.existsSync(domainDir)) continue;
233
+ if (!fs4.existsSync(domainDir)) continue;
234
234
  try {
235
- const files = fs12.readdirSync(domainDir);
235
+ const files = fs4.readdirSync(domainDir);
236
236
  for (const file of files) {
237
237
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
238
238
  const name = file.replace(/\.ts$/, "");
@@ -245,7 +245,7 @@ function listDomainInterfaces(projectRoot, featureName) {
245
245
  });
246
246
  } else {
247
247
  try {
248
- const content = fs12.readFileSync(fullPath, "utf-8");
248
+ const content = fs4.readFileSync(fullPath, "utf-8");
249
249
  if (/export\s+(?:abstract\s+class|interface)\s+(\w+)/.test(content)) {
250
250
  results.push({
251
251
  name,
@@ -268,9 +268,9 @@ function listDomainEntities(projectRoot, featureName) {
268
268
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
269
269
  for (const feat of features) {
270
270
  const domainDir = path2.join(resolveFeaturesDir(projectRoot), feat, "domain");
271
- if (!fs12.existsSync(domainDir)) continue;
271
+ if (!fs4.existsSync(domainDir)) continue;
272
272
  try {
273
- const files = fs12.readdirSync(domainDir);
273
+ const files = fs4.readdirSync(domainDir);
274
274
  for (const file of files) {
275
275
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
276
276
  const name = file.replace(/\.ts$/, "");
@@ -293,9 +293,9 @@ function listUseCases(projectRoot, featureName) {
293
293
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
294
294
  for (const feat of features) {
295
295
  const useCasesDir = path2.join(resolveFeaturesDir(projectRoot), feat, "useCases");
296
- if (!fs12.existsSync(useCasesDir)) continue;
296
+ if (!fs4.existsSync(useCasesDir)) continue;
297
297
  try {
298
- const files = fs12.readdirSync(useCasesDir);
298
+ const files = fs4.readdirSync(useCasesDir);
299
299
  for (const file of files) {
300
300
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
301
301
  const name = file.replace(/\.ts$/, "");
@@ -318,23 +318,23 @@ var PromptCancelledError = class extends Error {
318
318
  }
319
319
  };
320
320
  function handleCancel(result) {
321
- if (p15.isCancel(result)) {
322
- p15.cancel("Operation cancelled.");
321
+ if (p4.isCancel(result)) {
322
+ p4.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
- p15.intro(pc15.bgCyan(pc15.black(" @solid-stack/mason ")));
329
+ p4.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
- const summary = properties.map((p17) => `${p17.name}: ${p17.type}${p17.optional ? "?" : ""}`).join(", ");
335
- p15.log.info(pc15.dim(`Pre-configured fields: ${summary}`));
334
+ const summary = properties.map((p16) => `${p16.name}: ${p16.type}${p16.optional ? "?" : ""}`).join(", ");
335
+ p4.log.info(pc14.dim(`Pre-configured fields: ${summary}`));
336
336
  const addMore = handleCancel(
337
- await p15.confirm({
337
+ await p4.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
- p15.log.info(pc15.cyan("Enter properties (leave name blank when finished):"));
346
+ p4.log.info(pc14.cyan("Enter properties (leave name blank when finished):"));
347
347
  while (true) {
348
348
  const name = handleCancel(
349
- await p15.text({
349
+ await p4.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 p15.select({
358
+ await p4.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 p15.text({
375
+ await p4.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 p15.confirm({
383
+ await p4.confirm({
384
384
  message: `Is "${name.trim()}" optional?`,
385
385
  initialValue: false
386
386
  })
@@ -390,8 +390,8 @@ async function promptProperties(options = {}) {
390
390
  type: finalType.trim(),
391
391
  optional
392
392
  });
393
- p15.log.success(
394
- pc15.green(`Added: ${name.trim()}${optional ? "?" : ""}: ${finalType.trim()}`)
393
+ p4.log.success(
394
+ pc14.green(`Added: ${name.trim()}${optional ? "?" : ""}: ${finalType.trim()}`)
395
395
  );
396
396
  }
397
397
  return properties;
@@ -421,7 +421,7 @@ function findLocalRegistry(startDir = process.cwd()) {
421
421
  let current = path2.resolve(startDir);
422
422
  while (true) {
423
423
  const candidate = path2.join(current, "mason-registry");
424
- if (fs12.existsSync(candidate) && fs12.existsSync(path2.join(candidate, "index.json"))) {
424
+ if (fs4.existsSync(candidate) && fs4.existsSync(path2.join(candidate, "index.json"))) {
425
425
  return candidate;
426
426
  }
427
427
  const parent = path2.dirname(current);
@@ -443,9 +443,9 @@ function getRegistryBase(projectRoot, override) {
443
443
  path2.join(process.cwd(), "mason.config.json")
444
444
  ];
445
445
  for (const configPath of configLocations) {
446
- if (fs12.existsSync(configPath)) {
446
+ if (fs4.existsSync(configPath)) {
447
447
  try {
448
- const config = JSON.parse(fs12.readFileSync(configPath, "utf-8"));
448
+ const config = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
449
449
  if (config.registry && typeof config.registry === "string") {
450
450
  return normalizeRegistryUrl(config.registry.trim(), path2.dirname(configPath));
451
451
  }
@@ -458,9 +458,9 @@ function getRegistryBase(projectRoot, override) {
458
458
  path2.join(process.cwd(), "package.json")
459
459
  ];
460
460
  for (const pkgPath of pkgLocations) {
461
- if (fs12.existsSync(pkgPath)) {
461
+ if (fs4.existsSync(pkgPath)) {
462
462
  try {
463
- const pkg = JSON.parse(fs12.readFileSync(pkgPath, "utf-8"));
463
+ const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
464
464
  if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
465
465
  return normalizeRegistryUrl(pkg.mason.registry.trim(), path2.dirname(pkgPath));
466
466
  }
@@ -504,10 +504,10 @@ async function fetchRegistryFile(registryBase, relPath) {
504
504
  baseDir = fileURLToPath(baseDir);
505
505
  }
506
506
  const filePath = path2.resolve(baseDir, cleanRelPath);
507
- if (!fs12.existsSync(filePath)) {
507
+ if (!fs4.existsSync(filePath)) {
508
508
  throw new Error(`Registry file not found at ${filePath}`);
509
509
  }
510
- return fs12.promises.readFile(filePath, "utf-8");
510
+ return fs4.promises.readFile(filePath, "utf-8");
511
511
  }
512
512
  async function fetchRegistryIndex(registryBase) {
513
513
  const content = await fetchRegistryFile(registryBase, "index.json");
@@ -569,26 +569,26 @@ function findClosestMatch(target, candidates) {
569
569
  return null;
570
570
  }
571
571
  function detectPackageManager(projectRoot) {
572
- if (fs12.existsSync(path2.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
573
- if (fs12.existsSync(path2.join(projectRoot, "yarn.lock"))) return "yarn";
574
- if (fs12.existsSync(path2.join(projectRoot, "bun.lockb")) || fs12.existsSync(path2.join(projectRoot, "bun.lock"))) return "bun";
572
+ if (fs4.existsSync(path2.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
573
+ if (fs4.existsSync(path2.join(projectRoot, "yarn.lock"))) return "yarn";
574
+ if (fs4.existsSync(path2.join(projectRoot, "bun.lockb")) || fs4.existsSync(path2.join(projectRoot, "bun.lock"))) return "bun";
575
575
  return "npm";
576
576
  }
577
577
  function getMissingNpmPackages(projectRoot, requiredPackages) {
578
578
  if (!requiredPackages || requiredPackages.length === 0) return [];
579
579
  const pkgJsonPath = path2.join(projectRoot, "package.json");
580
- if (!fs12.existsSync(pkgJsonPath)) {
580
+ if (!fs4.existsSync(pkgJsonPath)) {
581
581
  return requiredPackages;
582
582
  }
583
583
  try {
584
- const pkg = JSON.parse(fs12.readFileSync(pkgJsonPath, "utf-8"));
584
+ const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
585
585
  const installed = /* @__PURE__ */ new Set([
586
586
  ...Object.keys(pkg.dependencies || {}),
587
587
  ...Object.keys(pkg.devDependencies || {}),
588
588
  ...Object.keys(pkg.peerDependencies || {})
589
589
  ]);
590
- return requiredPackages.filter((p17) => {
591
- const nameOnly = p17.startsWith("@") ? `@${p17.slice(1).split("@")[0] || ""}` : p17.split("@")[0] || p17;
590
+ return requiredPackages.filter((p16) => {
591
+ const nameOnly = p16.startsWith("@") ? `@${p16.slice(1).split("@")[0] || ""}` : p16.split("@")[0] || p16;
592
592
  return !installed.has(nameOnly);
593
593
  });
594
594
  } catch {
@@ -613,15 +613,15 @@ function installNpmPackages(projectRoot, packages, pm) {
613
613
  installCmd = `npm install ${packages.join(" ")}`;
614
614
  break;
615
615
  }
616
- p15.log.info(`Installing missing dependencies with ${manager}: ${pc15.cyan(packages.join(", "))}`);
616
+ p4.log.info(`Installing missing dependencies with ${manager}: ${pc14.cyan(packages.join(", "))}`);
617
617
  execSync(installCmd, {
618
618
  cwd: projectRoot,
619
619
  stdio: "inherit"
620
620
  });
621
621
  }
622
622
  function getAllFiles(dir, baseDir = dir) {
623
- if (!fs12.existsSync(dir)) return [];
624
- const entries = fs12.readdirSync(dir, { withFileTypes: true });
623
+ if (!fs4.existsSync(dir)) return [];
624
+ const entries = fs4.readdirSync(dir, { withFileTypes: true });
625
625
  const files = [];
626
626
  for (const entry of entries) {
627
627
  const fullPath = path2.join(dir, entry.name);
@@ -641,13 +641,13 @@ function getAllFiles(dir, baseDir = dir) {
641
641
  return files.sort();
642
642
  }
643
643
  function computeDirectoryHash(dirPath, files) {
644
- if (!fs12.existsSync(dirPath)) return "";
644
+ if (!fs4.existsSync(dirPath)) return "";
645
645
  const hash = createHash("sha256");
646
646
  const fileList = (files ?? getAllFiles(dirPath)).sort();
647
647
  for (const relativePath of fileList) {
648
648
  const absolutePath = path2.join(dirPath, relativePath);
649
- if (!fs12.existsSync(absolutePath)) continue;
650
- const content = fs12.readFileSync(absolutePath, "utf8");
649
+ if (!fs4.existsSync(absolutePath)) continue;
650
+ const content = fs4.readFileSync(absolutePath, "utf8");
651
651
  const normalizedContent = content.replace(/\r\n/g, "\n");
652
652
  hash.update(relativePath);
653
653
  hash.update(normalizedContent);
@@ -670,29 +670,29 @@ hbs.registerHelper("join", (arr, sep) => {
670
670
  });
671
671
  var cachedTemplatesDir = null;
672
672
  function getTemplatesDir() {
673
- if (cachedTemplatesDir && fs12.existsSync(cachedTemplatesDir)) {
673
+ if (cachedTemplatesDir && fs4.existsSync(cachedTemplatesDir)) {
674
674
  return cachedTemplatesDir;
675
675
  }
676
676
  const currentDir = typeof __dirname !== "undefined" ? __dirname : path2.dirname(fileURLToPath(import.meta.url));
677
677
  const cand1 = path2.resolve(currentDir, "../../templates");
678
- if (fs12.existsSync(cand1)) {
678
+ if (fs4.existsSync(cand1)) {
679
679
  cachedTemplatesDir = cand1;
680
680
  return cand1;
681
681
  }
682
682
  const cand2 = path2.resolve(currentDir, "../templates");
683
- if (fs12.existsSync(cand2)) {
683
+ if (fs4.existsSync(cand2)) {
684
684
  cachedTemplatesDir = cand2;
685
685
  return cand2;
686
686
  }
687
687
  const cand3 = path2.resolve(currentDir, "templates");
688
- if (fs12.existsSync(cand3)) {
688
+ if (fs4.existsSync(cand3)) {
689
689
  cachedTemplatesDir = cand3;
690
690
  return cand3;
691
691
  }
692
692
  let curr = currentDir;
693
693
  while (true) {
694
694
  const candTemplates = path2.join(curr, "templates");
695
- if (fs12.existsSync(candTemplates)) {
695
+ if (fs4.existsSync(candTemplates)) {
696
696
  cachedTemplatesDir = candTemplates;
697
697
  return candTemplates;
698
698
  }
@@ -705,7 +705,7 @@ function getTemplatesDir() {
705
705
  var templateCache = /* @__PURE__ */ new Map();
706
706
  function loadTemplate(relativePath) {
707
707
  const fullPath = path2.isAbsolute(relativePath) ? relativePath : path2.join(getTemplatesDir(), relativePath);
708
- return fs12.readFileSync(fullPath, "utf-8");
708
+ return fs4.readFileSync(fullPath, "utf-8");
709
709
  }
710
710
  function renderTemplateFile(relativePath, context) {
711
711
  let compiled = templateCache.get(relativePath);
@@ -815,7 +815,7 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
815
815
  const idKey = `${entityKey}Id`;
816
816
  const listKey = `${entityKey}s`;
817
817
  const formattedCustomMethods = customMethods.map((m) => {
818
- const params = m.params && m.params.length > 0 ? m.params.map((p17) => `${p17.name}: ${p17.type}`).join("; ") : "";
818
+ const params = m.params && m.params.length > 0 ? m.params.map((p16) => `${p16.name}: ${p16.type}`).join("; ") : "";
819
819
  const returnType = m.returnType ? `Promise<${m.returnType}>` : "Promise<void>";
820
820
  return {
821
821
  name: m.name,
@@ -1076,7 +1076,7 @@ function parseInterfaceMethodsAndImports(content, targetIfaceName) {
1076
1076
  };
1077
1077
  }
1078
1078
  function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
1079
- if (customPath && fs12.existsSync(customPath)) {
1079
+ if (customPath && fs4.existsSync(customPath)) {
1080
1080
  return { filePath: customPath, ifaceName };
1081
1081
  }
1082
1082
  const candidateNames = [
@@ -1087,21 +1087,21 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
1087
1087
  const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
1088
1088
  for (const feat of features) {
1089
1089
  const domainDir = path2.join(resolveFeaturesDir(projectRoot), feat, "domain");
1090
- if (!fs12.existsSync(domainDir)) continue;
1090
+ if (!fs4.existsSync(domainDir)) continue;
1091
1091
  for (const cand of candidateNames) {
1092
1092
  const p1 = path2.join(domainDir, `${cand}.ts`);
1093
- if (fs12.existsSync(p1)) {
1093
+ if (fs4.existsSync(p1)) {
1094
1094
  return { filePath: p1, ifaceName: cand, feature: feat };
1095
1095
  }
1096
1096
  }
1097
1097
  }
1098
1098
  for (const cand of candidateNames) {
1099
1099
  const p1 = path2.join(projectRoot, "domain", `${cand}.ts`);
1100
- if (fs12.existsSync(p1)) return { filePath: p1, ifaceName: cand };
1100
+ if (fs4.existsSync(p1)) return { filePath: p1, ifaceName: cand };
1101
1101
  const p22 = path2.join(projectRoot, "src", "domain", `${cand}.ts`);
1102
- if (fs12.existsSync(p22)) return { filePath: p22, ifaceName: cand };
1102
+ if (fs4.existsSync(p22)) return { filePath: p22, ifaceName: cand };
1103
1103
  const p32 = path2.join(projectRoot, "interfaces", `${cand}.ts`);
1104
- if (fs12.existsSync(p32)) return { filePath: p32, ifaceName: cand };
1104
+ if (fs4.existsSync(p32)) return { filePath: p32, ifaceName: cand };
1105
1105
  }
1106
1106
  return null;
1107
1107
  }
@@ -1124,7 +1124,7 @@ function loadInterfaceHierarchy(projectRoot, initialIfaceName, featureName, cust
1124
1124
  while (currentFile && !visited.has(currentFile)) {
1125
1125
  visited.add(currentFile);
1126
1126
  try {
1127
- const content = fs12.readFileSync(currentFile, "utf-8");
1127
+ const content = fs4.readFileSync(currentFile, "utf-8");
1128
1128
  const parsed = parseInterfaceMethodsAndImports(content, currentName);
1129
1129
  for (const m of parsed.methods) {
1130
1130
  if (!allMethods.some((existing) => existing.name === m.name)) {
@@ -1396,22 +1396,22 @@ function generateUseCaseCode(useCaseName, dependencies = [], inputProps = [], ou
1396
1396
  from: /^I[A-Z]/.test(dep) ? `../domain/${dep}.js` : `./${dep}.js`
1397
1397
  }));
1398
1398
  const domainTypesToImport = new Set(domainImports);
1399
- for (const p17 of [...inputProps, ...outputProps]) {
1400
- const rawType = p17.type.trim();
1399
+ for (const p16 of [...inputProps, ...outputProps]) {
1400
+ const rawType = p16.type.trim();
1401
1401
  const baseType = rawType.replace(/\[\]$/, "").trim();
1402
1402
  if (!primitiveTypes.has(baseType) && /^[A-Z][A-Za-z0-9_]*$/.test(baseType) && !dependencies.includes(baseType)) {
1403
1403
  domainTypesToImport.add(baseType);
1404
1404
  }
1405
1405
  }
1406
- const formattedInputProps = inputProps.map((p17) => ({
1407
- name: p17.name,
1408
- optional: p17.optional,
1409
- type: p17.optional && !p17.type.includes("undefined") ? `${p17.type} | undefined` : p17.type
1406
+ const formattedInputProps = inputProps.map((p16) => ({
1407
+ name: p16.name,
1408
+ optional: p16.optional,
1409
+ type: p16.optional && !p16.type.includes("undefined") ? `${p16.type} | undefined` : p16.type
1410
1410
  }));
1411
- const formattedOutputProps = outputProps.map((p17) => ({
1412
- name: p17.name,
1413
- optional: p17.optional,
1414
- type: p17.optional && !p17.type.includes("undefined") ? `${p17.type} | undefined` : p17.type
1411
+ const formattedOutputProps = outputProps.map((p16) => ({
1412
+ name: p16.name,
1413
+ optional: p16.optional,
1414
+ type: p16.optional && !p16.type.includes("undefined") ? `${p16.type} | undefined` : p16.type
1415
1415
  }));
1416
1416
  const formattedDeps = dependencies.map((dep) => ({
1417
1417
  key: toCamelCase(dep),
@@ -1598,7 +1598,7 @@ function generateHttpHandler(options) {
1598
1598
  const pxDir = path2.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1599
1599
  const handlersDir = path2.join(pxDir, "handlers");
1600
1600
  const pxIndexPath = path2.join(pxDir, "index.ts");
1601
- if (!fs12.existsSync(pxIndexPath)) {
1601
+ if (!fs4.existsSync(pxIndexPath)) {
1602
1602
  const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
1603
1603
  const pxIndexContent = renderTemplate(expressIndexTemplate, {
1604
1604
  routePath: featurePath
@@ -1635,8 +1635,8 @@ function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], opti
1635
1635
  const providerPath = path2.join(featureDir, "diProvider.ts");
1636
1636
  const pascalFeature = toPascalCase(featureName);
1637
1637
  const providerModuleName = `${pascalFeature}Provider`;
1638
- if (fs12.existsSync(providerPath) && !options.overwrite) {
1639
- let content = fs12.readFileSync(providerPath, "utf-8");
1638
+ if (fs4.existsSync(providerPath) && !options.overwrite) {
1639
+ let content = fs4.readFileSync(providerPath, "utf-8");
1640
1640
  content = content.replace(/\n*export\s+const\s+ScaffoldProvider\s*=[^;]+;?/g, "");
1641
1641
  for (const b of bindings) {
1642
1642
  const ifaceImp = b.ifaceImportPath || `./domain/${b.ifaceName}.js`;
@@ -2086,7 +2086,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2086
2086
  }
2087
2087
  if (!name) {
2088
2088
  name = handleCancel(
2089
- await p15.text({
2089
+ await p4.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 p15.text({
2105
+ await p4.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 p15.confirm({
2127
+ await p4.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 p15.text({
2134
+ await p4.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 p15.confirm({
2142
+ await p4.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 p15.text({
2149
+ await p4.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 p15.confirm({
2168
+ await p4.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 p15.confirm({
2175
+ await p4.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 p15.confirm({
2182
+ await p4.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 p15.multiselect({
2196
+ await p4.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 p15.confirm({
2204
+ await p4.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 p15.confirm({
2210
+ await p4.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 p15.text({
2220
+ await p4.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 p15.multiselect({
2230
+ await p4.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 p15.confirm({
2239
+ await p4.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 p15.confirm({
2250
+ await p4.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 p15.confirm({
2260
+ await p4.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 p15.confirm({
2270
+ await p4.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 p15.select({
2277
+ await p4.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 p15.text({
2290
+ await p4.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 p15.confirm({
2311
+ await p4.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 p15.confirm({
2320
+ await p4.confirm({
2321
2321
  message: "Generate / update feature DI provider (diProvider.ts)?",
2322
2322
  initialValue: true
2323
2323
  })
@@ -2329,8 +2329,8 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2329
2329
  entityNames = [defaultEntity];
2330
2330
  }
2331
2331
  }
2332
- const s = p15.spinner();
2333
- s.start(`Generating feature '${pc15.cyan(normalizedName)}'...`);
2332
+ const s = p4.spinner();
2333
+ s.start(`Generating feature '${pc14.cyan(normalizedName)}'...`);
2334
2334
  const options = {
2335
2335
  name: normalizedName,
2336
2336
  projectRoot,
@@ -2352,7 +2352,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2352
2352
  const files = generateFeature(options);
2353
2353
  if (isRegistry) {
2354
2354
  const registryPath = path2.join(targetDir, "registry.json");
2355
- if (!fs12.existsSync(registryPath)) {
2355
+ if (!fs4.existsSync(registryPath)) {
2356
2356
  const manifest = {
2357
2357
  name: toKebabCase(normalizedName),
2358
2358
  type: "feature",
@@ -2376,8 +2376,8 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2376
2376
  }
2377
2377
  s.stop("Feature scaffolded successfully!");
2378
2378
  printGeneratedFiles(files, options.dryRun);
2379
- p15.outro(
2380
- pc15.green(
2379
+ p4.outro(
2380
+ pc14.green(
2381
2381
  `\u2713 Feature '${normalizedName}' initialized in ${path2.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2382
2382
  )
2383
2383
  );
@@ -2491,7 +2491,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2491
2491
  }
2492
2492
  if (!name) {
2493
2493
  name = handleCancel(
2494
- await p15.text({
2494
+ await p4.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 p15.text({
2510
+ await p4.text({
2511
2511
  message: "Target directory for the shared module:",
2512
2512
  initialValue: defaultDir,
2513
2513
  defaultValue: defaultDir
@@ -2519,21 +2519,21 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2519
2519
  let includeStub = true;
2520
2520
  if (!flags.yes) {
2521
2521
  description = handleCancel(
2522
- await p15.text({
2522
+ await p4.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 p15.confirm({
2529
+ await p4.confirm({
2530
2530
  message: "Include stub implementation in infrastructure/?",
2531
2531
  initialValue: true
2532
2532
  })
2533
2533
  );
2534
2534
  }
2535
- const s = p15.spinner();
2536
- s.start(`Generating shared module '${pc15.cyan(normalizedName)}'...`);
2535
+ const s = p4.spinner();
2536
+ s.start(`Generating shared module '${pc14.cyan(normalizedName)}'...`);
2537
2537
  const files = generateShared({
2538
2538
  name: normalizedName,
2539
2539
  description,
@@ -2546,8 +2546,8 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2546
2546
  });
2547
2547
  s.stop("Shared module generated successfully!");
2548
2548
  printGeneratedFiles(files, Boolean(flags.dryRun));
2549
- p15.outro(
2550
- pc15.green(
2549
+ p4.outro(
2550
+ pc14.green(
2551
2551
  `\u2713 Shared module '${normalizedName}' initialized in ${path2.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2552
2552
  )
2553
2553
  );
@@ -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 p15.select({
2564
+ await p4.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 p15.text({
2571
+ await p4.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 p15.text({
2581
+ await p4.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 p15.text({
2592
+ await p4.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 p15.multiselect({
2608
+ await p4.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 p15.confirm({
2623
+ await p4.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 p15.confirm({
2633
+ await p4.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 p15.confirm({
2643
+ await p4.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 p15.confirm({
2649
+ await p4.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 p15.select({
2656
+ await p4.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 p15.text({
2669
+ await p4.text({
2670
2670
  message: "Route subpath (relative to feature prefix):",
2671
2671
  initialValue: "/",
2672
2672
  defaultValue: "/"
@@ -2674,8 +2674,8 @@ async function runUseCaseCommand(useCaseNameArg, flags = {}) {
2674
2674
  ).trim();
2675
2675
  }
2676
2676
  }
2677
- const s = p15.spinner();
2678
- s.start(`Generating use case '${pc15.cyan(ucName)}'...`);
2677
+ const s = p4.spinner();
2678
+ s.start(`Generating use case '${pc14.cyan(ucName)}'...`);
2679
2679
  const options = {
2680
2680
  name: ucName,
2681
2681
  feature,
@@ -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
- p15.outro(pc15.green(`Use case '${ucName}' created in feature '${feature}'!`));
2710
+ p4.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 p15.select({
2721
+ await p4.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 p15.text({
2728
+ await p4.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 p15.text({
2738
+ await p4.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 p15.text({
2749
+ await p4.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 p15.select({
2761
+ await p4.select({
2762
2762
  message: "Select domain model type:",
2763
2763
  options: [
2764
2764
  { value: "interface", label: "TypeScript Interface (pure data structure)" },
@@ -2777,8 +2777,8 @@ async function runDomainCommand(domainNameArg, flags = {}) {
2777
2777
  defaults: kind === "valueObject" ? [{ name: "value", type: "string" }] : defaultProps
2778
2778
  });
2779
2779
  }
2780
- const s = p15.spinner();
2781
- s.start(`Generating domain model '${pc15.cyan(entityName)}'...`);
2780
+ const s = p4.spinner();
2781
+ s.start(`Generating domain model '${pc14.cyan(entityName)}'...`);
2782
2782
  const options = {
2783
2783
  name: entityName,
2784
2784
  feature,
@@ -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
- p15.outro(pc15.green(`Domain model '${entityName}' created in feature '${feature}'!`));
2794
+ p4.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 p15.select({
2803
+ await p4.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 p15.select({
2818
+ await p4.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 p15.text({
2825
+ await p4.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 p15.text({
2835
+ await p4.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 p15.text({
2848
+ await p4.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 p15.select({
2867
+ await p4.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 p15.text({
2879
+ await p4.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 p15.confirm({
2890
+ await p4.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 p15.text({
2897
+ await p4.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 p15.select({
2917
+ await p4.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 p15.text({
2929
+ await p4.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 p15.select({
2942
+ await p4.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 p15.confirm({
2953
+ await p4.confirm({
2954
2954
  message: "Register this implementation in feature diProvider.ts?",
2955
2955
  initialValue: true
2956
2956
  })
@@ -2959,8 +2959,8 @@ 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 = p15.spinner();
2963
- s.start(`Generating infrastructure class '${pc15.cyan(className)}'...`);
2962
+ const s = p4.spinner();
2963
+ s.start(`Generating infrastructure class '${pc14.cyan(className)}'...`);
2964
2964
  const files = [];
2965
2965
  const options = {
2966
2966
  name: className,
@@ -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
- p15.outro(pc15.green(`Infrastructure class '${className}' created!`));
2998
+ p4.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 p15.select({
3009
+ await p4.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 p15.text({
3016
+ await p4.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 p15.text({
3026
+ await p4.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 p15.text({
3037
+ await p4.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 p15.select({
3055
+ await p4.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 p15.text({
3066
+ await p4.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 p15.select({
3076
+ await p4.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 p15.select({
3086
+ await p4.select({
3087
3087
  message: "Method signature preset:",
3088
3088
  options: [
3089
3089
  { value: "crud", label: "Standard CRUD (GetById, List, Create, Update, Delete)" },
@@ -3093,22 +3093,22 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
3093
3093
  })
3094
3094
  );
3095
3095
  generateStub = handleCancel(
3096
- await p15.confirm({
3096
+ await p4.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 p15.confirm({
3103
+ await p4.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 = p15.spinner();
3111
- s.start(`Generating interface '${pc15.cyan(ifaceName)}'...`);
3110
+ const s = p4.spinner();
3111
+ s.start(`Generating interface '${pc14.cyan(ifaceName)}'...`);
3112
3112
  const files = [];
3113
3113
  const options = {
3114
3114
  name: ifaceName,
@@ -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
- p15.outro(pc15.green(`Interface '${ifaceName}' created in feature '${feature}'!`));
3160
+ p4.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 p15.select({
3171
+ await p4.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 p15.text({
3178
+ await p4.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 p15.text({
3188
+ await p4.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 p15.text({
3199
+ await p4.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 p15.select({
3218
+ await p4.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 p15.text({
3232
+ await p4.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 p15.select({
3243
+ await p4.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 p15.confirm({
3254
+ await p4.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 p15.select({
3262
+ await p4.select({
3263
3263
  message: "Validation data source:",
3264
3264
  options: [
3265
3265
  { value: "body", label: "req.body (for POST / PUT / PATCH payloads)" },
@@ -3273,8 +3273,8 @@ async function runHttpHandlerCommand(handlerNameArg, flags = {}) {
3273
3273
  });
3274
3274
  }
3275
3275
  }
3276
- const s = p15.spinner();
3277
- s.start(`Generating HTTP handler '${pc15.cyan(className)}'...`);
3276
+ const s = p4.spinner();
3277
+ s.start(`Generating HTTP handler '${pc14.cyan(className)}'...`);
3278
3278
  const options = {
3279
3279
  name: className,
3280
3280
  feature,
@@ -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
- p15.outro(pc15.green(`HTTP handler '${className}' created in feature '${feature}'!`));
3295
+ p4.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) => ({
@@ -3302,7 +3302,7 @@ function generateInjectableCode(className, dependencies = [], methods = [], impl
3302
3302
  const formattedMethods = methods.map((m) => {
3303
3303
  const isAsync = m.async !== false;
3304
3304
  const retType = m.returnType ? isAsync ? `Promise<${m.returnType}>` : m.returnType : isAsync ? "Promise<void>" : "void";
3305
- const params = m.params && m.params.length > 0 ? m.params.map((p17) => `${p17.name}: ${p17.type}`).join(", ") : "";
3305
+ const params = m.params && m.params.length > 0 ? m.params.map((p16) => `${p16.name}: ${p16.type}`).join(", ") : "";
3306
3306
  return {
3307
3307
  name: m.name,
3308
3308
  isAsync,
@@ -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 p15.text({
3375
+ await p4.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 p15.select({
3388
+ await p4.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 p15.select({
3406
+ await p4.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 p15.text({
3413
+ await p4.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 p15.text({
3423
+ await p4.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 p15.text({
3433
+ await p4.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,14 +3441,14 @@ async function runInjectableCommand(classNameArg, flags = {}) {
3441
3441
  let generateInterface2 = false;
3442
3442
  if (!flags.yes) {
3443
3443
  generateInterface2 = handleCancel(
3444
- await p15.confirm({
3444
+ await p4.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 = p15.spinner();
3451
- s.start(`Generating injectable '${pc15.cyan(className)}'...`);
3450
+ const s = p4.spinner();
3451
+ s.start(`Generating injectable '${pc14.cyan(className)}'...`);
3452
3452
  const options = {
3453
3453
  name: className,
3454
3454
  feature,
@@ -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
- p15.outro(pc15.green(`Injectable '${className}' created successfully!`));
3465
+ p4.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 p15.select({
3470
+ await p4.select({
3471
3471
  message: "What would you like to create in your architecture?",
3472
3472
  options: [
3473
3473
  {
@@ -3575,8 +3575,8 @@ async function handleCreate(type, name, flags = {}) {
3575
3575
  await runInjectableCommand(name, flags);
3576
3576
  break;
3577
3577
  default:
3578
- p15.log.error(
3579
- pc15.red(
3578
+ p4.log.error(
3579
+ pc14.red(
3580
3580
  `Unknown component type: "${type}". Allowed types: feature, shared, usecase, domain, infrastructure, interface, httpHandler, injectable.`
3581
3581
  )
3582
3582
  );
@@ -3584,8 +3584,8 @@ async function handleCreate(type, name, flags = {}) {
3584
3584
  }
3585
3585
  }
3586
3586
  var importPrompts = {
3587
- select: p15.select,
3588
- text: p15.text
3587
+ select: p4.select,
3588
+ text: p4.text
3589
3589
  };
3590
3590
  function rewriteImports(content, aliasMap) {
3591
3591
  if (aliasMap.size === 0) return content;
@@ -3606,9 +3606,9 @@ function getModuleBaseDir(projectRoot, modType) {
3606
3606
  function getExistingModuleDir(projectRoot, modType, modName) {
3607
3607
  const folder = modType === "shared" ? "shared" : "features";
3608
3608
  const inSrc = path2.join(projectRoot, "src", folder, modName);
3609
- if (fs12.existsSync(inSrc)) return inSrc;
3609
+ if (fs4.existsSync(inSrc)) return inSrc;
3610
3610
  const inRoot = path2.join(projectRoot, folder, modName);
3611
- if (fs12.existsSync(inRoot)) return inRoot;
3611
+ if (fs4.existsSync(inRoot)) return inRoot;
3612
3612
  return null;
3613
3613
  }
3614
3614
  function checkModuleExists(projectRoot, modType, modName) {
@@ -3626,13 +3626,13 @@ async function resolveDependency(depType, depName, aliasMap, projectRoot, flags,
3626
3626
  projectRoot,
3627
3627
  path2.join(baseDir, programmaticAlias)
3628
3628
  );
3629
- p15.log.step(`Importing '${depName}' into '${displayDest}'...`);
3629
+ p4.log.step(`Importing '${depName}' into '${displayDest}'...`);
3630
3630
  await importModuleRecursive(depType, depName, programmaticAlias);
3631
3631
  return;
3632
3632
  }
3633
3633
  const existingDir = getExistingModuleDir(projectRoot, depType, depName);
3634
3634
  if (!existingDir) {
3635
- p15.log.info(` \u21B3 Resolving required ${depType} dependency: ${pc15.cyan(depName)}`);
3635
+ p4.log.info(` \u21B3 Resolving required ${depType} dependency: ${pc14.cyan(depName)}`);
3636
3636
  await importModuleRecursive(depType, depName, depName);
3637
3637
  return;
3638
3638
  }
@@ -3649,25 +3649,25 @@ async function resolveDependency(depType, depName, aliasMap, projectRoot, flags,
3649
3649
  }
3650
3650
  const localHash = computeDirectoryHash(existingDir);
3651
3651
  if (remoteIntegrity && localHash === remoteIntegrity) {
3652
- p15.log.step(`\u2713 ${depType}/${depName} is up to date (reusing existing)`);
3652
+ p4.log.step(`\u2713 ${depType}/${depName} is up to date (reusing existing)`);
3653
3653
  importedModules.add(`${depType}:${depName}`);
3654
3654
  return;
3655
3655
  }
3656
3656
  if (flags.overwrite) {
3657
- p15.log.step(`Overwriting '${depType}/${depName}' with registry version (--overwrite)...`);
3657
+ p4.log.step(`Overwriting '${depType}/${depName}' with registry version (--overwrite)...`);
3658
3658
  const baseDir = getModuleBaseDir(projectRoot, depType);
3659
3659
  const targetDir = path2.join(baseDir, depName);
3660
3660
  if (!flags.dryRun) {
3661
3661
  if (existingDir !== targetDir) {
3662
- fs12.rmSync(existingDir, { recursive: true, force: true });
3662
+ fs4.rmSync(existingDir, { recursive: true, force: true });
3663
3663
  }
3664
- fs12.rmSync(targetDir, { recursive: true, force: true });
3664
+ fs4.rmSync(targetDir, { recursive: true, force: true });
3665
3665
  }
3666
3666
  await importModuleRecursive(depType, depName, depName, { overwrite: true });
3667
3667
  return;
3668
3668
  }
3669
3669
  if (flags.yes) {
3670
- p15.log.info(`Using existing '${depType}/${depName}'`);
3670
+ p4.log.info(`Using existing '${depType}/${depName}'`);
3671
3671
  importedModules.add(`${depType}:${depName}`);
3672
3672
  return;
3673
3673
  }
@@ -3691,7 +3691,7 @@ async function resolveDependency(depType, depName, aliasMap, projectRoot, flags,
3691
3691
  })
3692
3692
  );
3693
3693
  if (choice === "keep_existing" || choice === "use_existing") {
3694
- p15.log.step(`Skipping '${depType}/${depName}' (keeping existing)`);
3694
+ p4.log.step(`Skipping '${depType}/${depName}' (keeping existing)`);
3695
3695
  importedModules.add(`${depType}:${depName}`);
3696
3696
  return;
3697
3697
  }
@@ -3716,19 +3716,19 @@ async function resolveDependency(depType, depName, aliasMap, projectRoot, flags,
3716
3716
  aliasMap.set(`@/${folder}/${depName}/`, `@/${folder}/${newName}/`);
3717
3717
  const baseDir = getModuleBaseDir(projectRoot, depType);
3718
3718
  const displayDest = path2.relative(projectRoot, path2.join(baseDir, newName));
3719
- p15.log.step(`Importing '${depName}' into '${displayDest}'...`);
3719
+ p4.log.step(`Importing '${depName}' into '${displayDest}'...`);
3720
3720
  await importModuleRecursive(depType, depName, newName);
3721
3721
  return;
3722
3722
  }
3723
3723
  if (choice === "overwrite") {
3724
- p15.log.step(`Overwriting '${depType}/${depName}' with registry version...`);
3724
+ p4.log.step(`Overwriting '${depType}/${depName}' with registry version...`);
3725
3725
  const baseDir = getModuleBaseDir(projectRoot, depType);
3726
3726
  const targetDir = path2.join(baseDir, depName);
3727
3727
  if (!flags.dryRun) {
3728
3728
  if (existingDir !== targetDir) {
3729
- fs12.rmSync(existingDir, { recursive: true, force: true });
3729
+ fs4.rmSync(existingDir, { recursive: true, force: true });
3730
3730
  }
3731
- fs12.rmSync(targetDir, { recursive: true, force: true });
3731
+ fs4.rmSync(targetDir, { recursive: true, force: true });
3732
3732
  }
3733
3733
  await importModuleRecursive(depType, depName, depName, { overwrite: true });
3734
3734
  return;
@@ -3758,19 +3758,19 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3758
3758
  );
3759
3759
  }
3760
3760
  if (type !== "shared" && type !== "feature") {
3761
- p15.log.error(pc15.red(`Invalid module type: "${typeArg}". Must be "shared" or "feature".`));
3761
+ p4.log.error(pc14.red(`Invalid module type: "${typeArg}". Must be "shared" or "feature".`));
3762
3762
  process.exit(1);
3763
3763
  }
3764
3764
  const registryBase = getRegistryBase(projectRoot, flags.registry);
3765
- const s = p15.spinner();
3766
- s.start(`Connecting to registry at ${pc15.dim(registryBase)}...`);
3765
+ const s = p4.spinner();
3766
+ s.start(`Connecting to registry at ${pc14.dim(registryBase)}...`);
3767
3767
  let index;
3768
3768
  try {
3769
3769
  index = await fetchRegistryIndex(registryBase);
3770
3770
  s.stop("Registry index loaded.");
3771
3771
  } catch (err) {
3772
- s.stop(pc15.red("Failed to load registry index."));
3773
- p15.log.error(pc15.red(err.message || String(err)));
3772
+ s.stop(pc14.red("Failed to load registry index."));
3773
+ p4.log.error(pc14.red(err.message || String(err)));
3774
3774
  process.exit(1);
3775
3775
  }
3776
3776
  const availableList = type === "shared" ? index.shared : index.features;
@@ -3778,7 +3778,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3778
3778
  let name = nameArg?.trim();
3779
3779
  if (!name) {
3780
3780
  if (availableList.length === 0) {
3781
- p15.log.warn(`No ${type} modules available in the registry.`);
3781
+ p4.log.warn(`No ${type} modules available in the registry.`);
3782
3782
  return;
3783
3783
  }
3784
3784
  name = handleCancel(
@@ -3794,9 +3794,9 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3794
3794
  }
3795
3795
  if (!candidateNames.includes(name)) {
3796
3796
  const closest = findClosestMatch(name, candidateNames);
3797
- p15.log.error(pc15.red(`\u274C Module '${name}' not found in the ${type} registry.`));
3797
+ p4.log.error(pc14.red(`\u274C Module '${name}' not found in the ${type} registry.`));
3798
3798
  if (closest) {
3799
- p15.log.info(pc15.yellow(`Did you mean '${pc15.cyan(closest)}'?`));
3799
+ p4.log.info(pc14.yellow(`Did you mean '${pc14.cyan(closest)}'?`));
3800
3800
  }
3801
3801
  process.exit(1);
3802
3802
  }
@@ -3806,14 +3806,14 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3806
3806
  async function importModuleRecursive(modType, registryName, targetName = registryName, options) {
3807
3807
  const modKey = `${modType}:${targetName}`;
3808
3808
  if (importedModules.has(modKey)) return;
3809
- p15.log.step(
3810
- `Importing ${modType}: ${pc15.cyan(targetName)}${targetName !== registryName ? pc15.dim(` (from ${registryName})`) : ""}...`
3809
+ p4.log.step(
3810
+ `Importing ${modType}: ${pc14.cyan(targetName)}${targetName !== registryName ? pc14.dim(` (from ${registryName})`) : ""}...`
3811
3811
  );
3812
3812
  let manifest;
3813
3813
  try {
3814
3814
  manifest = await fetchModuleManifest(registryBase, modType, registryName);
3815
3815
  } catch (err) {
3816
- p15.log.error(pc15.red(`Failed to fetch manifest for ${modType} '${registryName}': ${err.message}`));
3816
+ p4.log.error(pc14.red(`Failed to fetch manifest for ${modType} '${registryName}': ${err.message}`));
3817
3817
  process.exit(1);
3818
3818
  }
3819
3819
  const aliasMap = /* @__PURE__ */ new Map();
@@ -3859,21 +3859,21 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3859
3859
  if (file === "registry.json") continue;
3860
3860
  const remoteFilePath = `${folder}/${registryName}/${file}`;
3861
3861
  const localFilePath = path2.join(targetDir, file);
3862
- if (fs12.existsSync(localFilePath) && !isOverwrite) {
3863
- p15.log.warn(
3864
- ` \u21B3 Skipping existing file: ${pc15.dim(path2.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
3862
+ if (fs4.existsSync(localFilePath) && !isOverwrite) {
3863
+ p4.log.warn(
3864
+ ` \u21B3 Skipping existing file: ${pc14.dim(path2.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
3865
3865
  );
3866
3866
  continue;
3867
3867
  }
3868
3868
  let content = await fetchRegistryFile(registryBase, remoteFilePath);
3869
3869
  content = rewriteImports(content, aliasMap);
3870
3870
  if (!flags.dryRun) {
3871
- fs12.mkdirSync(path2.dirname(localFilePath), { recursive: true });
3872
- fs12.writeFileSync(localFilePath, content, "utf-8");
3871
+ fs4.mkdirSync(path2.dirname(localFilePath), { recursive: true });
3872
+ fs4.writeFileSync(localFilePath, content, "utf-8");
3873
3873
  }
3874
3874
  const displayPath = path2.relative(projectRoot, localFilePath);
3875
3875
  totalWrittenFiles.push(displayPath);
3876
- p15.log.message(` ${pc15.green("+")} ${displayPath}`);
3876
+ p4.log.message(` ${pc14.green("+")} ${displayPath}`);
3877
3877
  }
3878
3878
  importedModules.add(modKey);
3879
3879
  }
@@ -3881,564 +3881,35 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3881
3881
  const missingNpm = getMissingNpmPackages(projectRoot, Array.from(requiredNpmPackages));
3882
3882
  if (missingNpm.length > 0) {
3883
3883
  if (flags.skipInstall || flags.dryRun) {
3884
- p15.log.info(`Required npm dependencies to install: ${pc15.cyan(missingNpm.join(", "))}`);
3884
+ p4.log.info(`Required npm dependencies to install: ${pc14.cyan(missingNpm.join(", "))}`);
3885
3885
  } else {
3886
3886
  try {
3887
3887
  installNpmPackages(projectRoot, missingNpm);
3888
3888
  } catch (err) {
3889
- p15.log.warn(`Could not automatically install packages (${err.message}). Please run: npm install ${missingNpm.join(" ")}`);
3889
+ p4.log.warn(`Could not automatically install packages (${err.message}). Please run: npm install ${missingNpm.join(" ")}`);
3890
3890
  }
3891
3891
  }
3892
3892
  }
3893
3893
  if (flags.dryRun) {
3894
- p15.log.info(pc15.yellow("Dry run complete: No files were written to disk."));
3894
+ p4.log.info(pc14.yellow("Dry run complete: No files were written to disk."));
3895
3895
  } else {
3896
3896
  const baseDir = getModuleBaseDir(projectRoot, type);
3897
3897
  const displayTarget = path2.relative(projectRoot, path2.join(baseDir, name));
3898
- p15.log.success(
3899
- pc15.green(
3898
+ p4.log.success(
3899
+ pc14.green(
3900
3900
  `Successfully imported ${type} '${name}' (${totalWrittenFiles.length} file${totalWrittenFiles.length === 1 ? "" : "s"} placed in ${displayTarget})`
3901
3901
  )
3902
3902
  );
3903
3903
  }
3904
3904
  }
3905
- function loadMasterIndex(projectRoot) {
3906
- const indexPath = path2.join(projectRoot, "index.json");
3907
- if (!fs12.existsSync(indexPath)) {
3908
- const initialIndex = { shared: [], features: [] };
3909
- fs12.writeFileSync(indexPath, JSON.stringify(initialIndex, null, 2) + "\n", "utf-8");
3910
- return initialIndex;
3911
- }
3912
- return JSON.parse(fs12.readFileSync(indexPath, "utf-8"));
3913
- }
3914
- function saveMasterIndex(projectRoot, index) {
3915
- const indexPath = path2.join(projectRoot, "index.json");
3916
- index.shared.sort((a, b) => a.name.localeCompare(b.name));
3917
- index.features.sort((a, b) => a.name.localeCompare(b.name));
3918
- fs12.writeFileSync(indexPath, JSON.stringify(index, null, 2) + "\n", "utf-8");
3919
- }
3920
- function discoverDiskModules(projectRoot) {
3921
- const results = [];
3922
- const sharedDir = resolveSharedDir(projectRoot);
3923
- if (fs12.existsSync(sharedDir)) {
3924
- const entries = fs12.readdirSync(sharedDir, { withFileTypes: true });
3925
- for (const entry of entries) {
3926
- if (entry.isDirectory() && !entry.name.startsWith(".")) {
3927
- results.push({ name: entry.name, type: "shared", dir: path2.join(sharedDir, entry.name) });
3928
- }
3929
- }
3930
- }
3931
- const featuresDir = resolveFeaturesDir(projectRoot);
3932
- if (fs12.existsSync(featuresDir)) {
3933
- const entries = fs12.readdirSync(featuresDir, { withFileTypes: true });
3934
- for (const entry of entries) {
3935
- if (entry.isDirectory() && !entry.name.startsWith(".")) {
3936
- results.push({ name: entry.name, type: "feature", dir: path2.join(featuresDir, entry.name) });
3937
- }
3938
- }
3939
- }
3940
- return results;
3941
- }
3942
- function checkGitStatusForDir(projectRoot, dirPath) {
3943
- try {
3944
- const relPath = path2.relative(projectRoot, dirPath);
3945
- const output = execSync(`git status --porcelain -- "${relPath}"`, {
3946
- cwd: projectRoot,
3947
- stdio: ["ignore", "pipe", "ignore"],
3948
- encoding: "utf-8"
3949
- }).trim();
3950
- if (!output) {
3951
- return { hasChanges: false, filesCount: 0 };
3952
- }
3953
- const lines = output.split("\n").filter((l) => l.trim().length > 0);
3954
- return { hasChanges: true, filesCount: lines.length };
3955
- } catch {
3956
- return { hasChanges: false, filesCount: 0 };
3957
- }
3958
- }
3959
- function getRegistryDiff(projectRoot) {
3960
- const index = loadMasterIndex(projectRoot);
3961
- const diskModules = discoverDiskModules(projectRoot);
3962
- const diskMap = /* @__PURE__ */ new Map();
3963
- for (const mod of diskModules) {
3964
- diskMap.set(`${mod.type}:${mod.name}`, mod);
3965
- }
3966
- const allKeys = /* @__PURE__ */ new Set();
3967
- for (const item of index.shared) {
3968
- allKeys.add(`shared:${item.name}`);
3969
- }
3970
- for (const item of index.features) {
3971
- allKeys.add(`feature:${item.name}`);
3972
- }
3973
- for (const mod of diskModules) {
3974
- allKeys.add(`${mod.type}:${mod.name}`);
3975
- }
3976
- const statuses = [];
3977
- for (const key of allKeys) {
3978
- const [typeStr, name] = key.split(":");
3979
- const type = typeStr;
3980
- const registeredEntry = (type === "shared" ? index.shared : index.features).find(
3981
- (e) => e.name === name
3982
- );
3983
- const isRegistered = Boolean(registeredEntry);
3984
- const diskInfo = diskMap.get(key);
3985
- const existsOnDisk = Boolean(diskInfo && fs12.existsSync(diskInfo.dir));
3986
- let hasUncommittedGitChanges = false;
3987
- let uncommittedFilesCount = 0;
3988
- let hasIntegrityDrift = false;
3989
- let localIntegrity;
3990
- if (existsOnDisk && diskInfo) {
3991
- const git = checkGitStatusForDir(projectRoot, diskInfo.dir);
3992
- hasUncommittedGitChanges = git.hasChanges;
3993
- uncommittedFilesCount = git.filesCount;
3994
- localIntegrity = computeDirectoryHash(diskInfo.dir);
3995
- if (isRegistered && registeredEntry?.integrity) {
3996
- hasIntegrityDrift = localIntegrity !== registeredEntry.integrity;
3997
- }
3998
- }
3999
- statuses.push({
4000
- name,
4001
- type,
4002
- isRegistered,
4003
- existsOnDisk,
4004
- hasUncommittedGitChanges,
4005
- uncommittedFilesCount,
4006
- hasIntegrityDrift,
4007
- localIntegrity,
4008
- registeredIntegrity: registeredEntry?.integrity
4009
- });
4010
- }
4011
- return statuses.sort((a, b) => a.type.localeCompare(b.type) || a.name.localeCompare(b.name));
4012
- }
4013
- async function registerModule(typeArg, nameArg, flags = {}) {
4014
- const projectRoot = findProjectRoot();
4015
- const index = loadMasterIndex(projectRoot);
4016
- let type = typeArg?.trim();
4017
- if (!type) {
4018
- type = handleCancel(
4019
- await p15.select({
4020
- message: "Module type to register:",
4021
- options: [
4022
- { value: "feature", label: "Feature" },
4023
- { value: "shared", label: "Shared Module" }
4024
- ]
4025
- })
4026
- );
4027
- }
4028
- const diskModules = discoverDiskModules(projectRoot).filter((m) => m.type === type);
4029
- const registeredNames = new Set((type === "shared" ? index.shared : index.features).map((m) => m.name));
4030
- const unregistered = diskModules.filter((m) => !registeredNames.has(m.name));
4031
- let name = nameArg?.trim();
4032
- if (!name) {
4033
- if (unregistered.length > 0) {
4034
- const opts = unregistered.map((m) => ({ value: m.name, label: m.name, hint: "unregistered on disk" }));
4035
- opts.push({ value: "__custom__", label: "\u270F\uFE0F Enter custom name...", hint: "" });
4036
- const choice = handleCancel(
4037
- await p15.select({
4038
- message: `Select a ${type} to register:`,
4039
- options: opts
4040
- })
4041
- );
4042
- if (choice === "__custom__") {
4043
- name = handleCancel(
4044
- await p15.text({
4045
- message: `Enter ${type} name:`,
4046
- validate: (v) => v && v.trim() ? void 0 : "Name cannot be empty"
4047
- })
4048
- ).trim();
4049
- } else {
4050
- name = choice;
4051
- }
4052
- } else {
4053
- name = handleCancel(
4054
- await p15.text({
4055
- message: `Enter ${type} name to register:`,
4056
- validate: (v) => v && v.trim() ? void 0 : "Name cannot be empty"
4057
- })
4058
- ).trim();
4059
- }
4060
- }
4061
- const folder = type === "shared" ? resolveSharedDir(projectRoot) : resolveFeaturesDir(projectRoot);
4062
- const modDir = path2.join(folder, name);
4063
- if (!fs12.existsSync(modDir)) {
4064
- p15.log.error(pc15.red(`Module directory does not exist: ${path2.relative(projectRoot, modDir)}`));
4065
- process.exit(1);
4066
- }
4067
- const files = getAllFiles(modDir);
4068
- const integrity = computeDirectoryHash(modDir, files);
4069
- const manifestPath = path2.join(modDir, "registry.json");
4070
- let manifest;
4071
- if (fs12.existsSync(manifestPath)) {
4072
- manifest = JSON.parse(fs12.readFileSync(manifestPath, "utf-8"));
4073
- } else {
4074
- manifest = {
4075
- name,
4076
- type,
4077
- description: `${name} ${type} module`,
4078
- version: "1.0.0",
4079
- dependencies: {
4080
- npm: [],
4081
- shared: [],
4082
- features: []
4083
- },
4084
- files: []
4085
- };
4086
- }
4087
- manifest.name = name;
4088
- manifest.type = type;
4089
- manifest.files = files;
4090
- manifest.integrity = integrity;
4091
- fs12.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
4092
- const targetList = type === "shared" ? index.shared : index.features;
4093
- const existingIdx = targetList.findIndex((item) => item.name === name);
4094
- if (existingIdx >= 0) {
4095
- targetList[existingIdx] = {
4096
- name,
4097
- description: manifest.description,
4098
- version: manifest.version,
4099
- integrity
4100
- };
4101
- } else {
4102
- targetList.push({
4103
- name,
4104
- description: manifest.description,
4105
- version: manifest.version,
4106
- integrity
4107
- });
4108
- }
4109
- saveMasterIndex(projectRoot, index);
4110
- p15.log.success(
4111
- pc15.green(
4112
- `\u2713 Module '${type}/${name}' registered in index.json (${files.length} files, ${integrity.slice(0, 18)}...)`
4113
- )
4114
- );
4115
- }
4116
- async function commitModule(typeArg, nameArg, flags = {}) {
4117
- const projectRoot = findProjectRoot();
4118
- let type = typeArg?.trim();
4119
- if (!type) {
4120
- type = handleCancel(
4121
- await p15.select({
4122
- message: "Module type to commit:",
4123
- options: [
4124
- { value: "feature", label: "Feature" },
4125
- { value: "shared", label: "Shared Module" }
4126
- ]
4127
- })
4128
- );
4129
- }
4130
- let name = nameArg?.trim();
4131
- if (!name) {
4132
- const diskModules = discoverDiskModules(projectRoot).filter((m) => m.type === type);
4133
- const opts = diskModules.map((m) => {
4134
- const git = checkGitStatusForDir(projectRoot, m.dir);
4135
- return {
4136
- value: m.name,
4137
- label: m.name,
4138
- hint: git.hasChanges ? `${git.filesCount} uncommitted files` : "clean working tree"
4139
- };
4140
- });
4141
- name = handleCancel(
4142
- await p15.select({
4143
- message: `Select ${type} to commit:`,
4144
- options: opts
4145
- })
4146
- );
4147
- }
4148
- const folder = type === "shared" ? resolveSharedDir(projectRoot) : resolveFeaturesDir(projectRoot);
4149
- const modDir = path2.join(folder, name);
4150
- if (!fs12.existsSync(modDir)) {
4151
- p15.log.error(pc15.red(`Module directory does not exist: ${path2.relative(projectRoot, modDir)}`));
4152
- process.exit(1);
4153
- }
4154
- const relModDir = path2.relative(projectRoot, modDir);
4155
- const gitStatus = checkGitStatusForDir(projectRoot, modDir);
4156
- if (!gitStatus.hasChanges) {
4157
- p15.log.warn(pc15.yellow(`No uncommitted git changes found in '${type}/${name}'.`));
4158
- return;
4159
- }
4160
- let message = flags.message?.trim();
4161
- if (!message) {
4162
- message = handleCancel(
4163
- await p15.text({
4164
- message: `Commit message for ${type}/${name}:`,
4165
- placeholder: `e.g. feat(${name}): update use cases and dependencies`,
4166
- validate: (v) => v && v.trim() ? void 0 : "Commit message cannot be empty"
4167
- })
4168
- ).trim();
4169
- }
4170
- const s = p15.spinner();
4171
- s.start(`Committing '${type}/${name}' to git repository...`);
4172
- try {
4173
- execSync(`git add "${relModDir}"`, { cwd: projectRoot, stdio: ["ignore", "pipe", "pipe"] });
4174
- execSync(`git commit -m "${message.replace(/"/g, '\\"')}" -- "${relModDir}"`, {
4175
- cwd: projectRoot,
4176
- stdio: ["ignore", "pipe", "pipe"]
4177
- });
4178
- s.stop(`Changes for '${type}/${name}' committed to git.`);
4179
- p15.log.success(pc15.green(`\u2713 Committed '${type}/${name}': "${message}"`));
4180
- } catch (err) {
4181
- s.stop(pc15.red("Git commit failed."));
4182
- p15.log.error(pc15.red(err.message || String(err)));
4183
- process.exit(1);
4184
- }
4185
- }
4186
- async function registerModuleChanges(typeArg, nameArg, flags = {}) {
4187
- const projectRoot = findProjectRoot();
4188
- const index = loadMasterIndex(projectRoot);
4189
- let type = typeArg?.trim();
4190
- if (!type) {
4191
- type = handleCancel(
4192
- await p15.select({
4193
- message: "Module type to update:",
4194
- options: [
4195
- { value: "feature", label: "Feature" },
4196
- { value: "shared", label: "Shared Module" }
4197
- ]
4198
- })
4199
- );
4200
- }
4201
- let name = nameArg?.trim();
4202
- if (!name) {
4203
- const diskModules = discoverDiskModules(projectRoot).filter((m) => m.type === type);
4204
- const diffs = getRegistryDiff(projectRoot).filter((d) => d.type === type && d.isRegistered);
4205
- const opts = diskModules.map((m) => {
4206
- const d = diffs.find((item) => item.name === m.name);
4207
- return {
4208
- value: m.name,
4209
- label: m.name,
4210
- hint: d?.hasIntegrityDrift ? "drift detected (needs register)" : "up to date"
4211
- };
4212
- });
4213
- name = handleCancel(
4214
- await p15.select({
4215
- message: `Select ${type} to register changes:`,
4216
- options: opts
4217
- })
4218
- );
4219
- }
4220
- const folder = type === "shared" ? resolveSharedDir(projectRoot) : resolveFeaturesDir(projectRoot);
4221
- const modDir = path2.join(folder, name);
4222
- if (!fs12.existsSync(modDir)) {
4223
- p15.log.error(pc15.red(`Module directory does not exist: ${path2.relative(projectRoot, modDir)}`));
4224
- process.exit(1);
4225
- }
4226
- const files = getAllFiles(modDir);
4227
- const integrity = computeDirectoryHash(modDir, files);
4228
- const manifestPath = path2.join(modDir, "registry.json");
4229
- let manifest;
4230
- if (fs12.existsSync(manifestPath)) {
4231
- manifest = JSON.parse(fs12.readFileSync(manifestPath, "utf-8"));
4232
- } else {
4233
- manifest = {
4234
- name,
4235
- type,
4236
- description: `${name} ${type} module`,
4237
- version: "1.0.0",
4238
- dependencies: { npm: [], shared: [], features: [] },
4239
- files: []
4240
- };
4241
- }
4242
- manifest.files = files;
4243
- manifest.integrity = integrity;
4244
- if (flags.version) {
4245
- manifest.version = flags.version;
4246
- }
4247
- fs12.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
4248
- const targetList = type === "shared" ? index.shared : index.features;
4249
- const existingIdx = targetList.findIndex((item) => item.name === name);
4250
- if (existingIdx >= 0) {
4251
- targetList[existingIdx] = {
4252
- name,
4253
- description: manifest.description,
4254
- version: manifest.version,
4255
- integrity
4256
- };
4257
- } else {
4258
- targetList.push({
4259
- name,
4260
- description: manifest.description,
4261
- version: manifest.version,
4262
- integrity
4263
- });
4264
- }
4265
- saveMasterIndex(projectRoot, index);
4266
- p15.log.success(
4267
- pc15.green(`\u2713 Registered changes for '${type}/${name}' (new integrity: ${integrity.slice(0, 18)}...)`)
4268
- );
4269
- }
4270
- async function unregisterModule(typeArg, nameArg, flags = {}) {
4271
- const projectRoot = findProjectRoot();
4272
- const index = loadMasterIndex(projectRoot);
4273
- let type = typeArg?.trim();
4274
- if (!type) {
4275
- type = handleCancel(
4276
- await p15.select({
4277
- message: "Module type to unregister:",
4278
- options: [
4279
- { value: "feature", label: "Feature" },
4280
- { value: "shared", label: "Shared Module" }
4281
- ]
4282
- })
4283
- );
4284
- }
4285
- const registeredList = type === "shared" ? index.shared : index.features;
4286
- if (registeredList.length === 0) {
4287
- p15.log.warn(`No registered ${type} modules found in index.json.`);
4288
- return;
4289
- }
4290
- let name = nameArg?.trim();
4291
- if (!name) {
4292
- name = handleCancel(
4293
- await p15.select({
4294
- message: `Select ${type} to unregister from index.json:`,
4295
- options: registeredList.map((item) => ({
4296
- value: item.name,
4297
- label: item.name,
4298
- hint: item.description
4299
- }))
4300
- })
4301
- );
4302
- }
4303
- if (type === "shared") {
4304
- index.shared = index.shared.filter((item) => item.name !== name);
4305
- } else {
4306
- index.features = index.features.filter((item) => item.name !== name);
4307
- }
4308
- saveMasterIndex(projectRoot, index);
4309
- p15.log.success(
4310
- pc15.green(
4311
- `\u2713 Unregistered module '${type}/${name}' from index.json (source code retained on disk in ${type === "shared" ? "shared" : "features"}/${name})`
4312
- )
4313
- );
4314
- }
4315
- function diffRegistry(flags = {}) {
4316
- const projectRoot = findProjectRoot();
4317
- const diffs = getRegistryDiff(projectRoot);
4318
- p15.log.step(pc15.bold("\u{1F4CB} Mason Registry Diff & Status Summary"));
4319
- const unregistered = diffs.filter((d) => d.existsOnDisk && !d.isRegistered);
4320
- const uncommitted = diffs.filter((d) => d.existsOnDisk && d.hasUncommittedGitChanges);
4321
- const committedDrift = diffs.filter(
4322
- (d) => d.existsOnDisk && d.isRegistered && !d.hasUncommittedGitChanges && d.hasIntegrityDrift
4323
- );
4324
- const upToDate = diffs.filter(
4325
- (d) => d.existsOnDisk && d.isRegistered && !d.hasUncommittedGitChanges && !d.hasIntegrityDrift
4326
- );
4327
- const missing = diffs.filter((d) => !d.existsOnDisk && d.isRegistered);
4328
- if (unregistered.length > 0) {
4329
- p15.log.message(pc15.yellow(`
4330
- \u{1F4E6} Unregistered Modules (${unregistered.length}):`));
4331
- for (const mod of unregistered) {
4332
- p15.log.message(` ${pc15.red("\u25CF")} ${pc15.bold(`${mod.type}/${mod.name}`)} ${pc15.dim("(not registered in index.json)")}`);
4333
- }
4334
- }
4335
- if (uncommitted.length > 0) {
4336
- p15.log.message(pc15.yellow(`
4337
- \u{1F4BE} Uncommitted Changes in Git (${uncommitted.length}):`));
4338
- for (const mod of uncommitted) {
4339
- p15.log.message(
4340
- ` ${pc15.yellow("\u25B2")} ${pc15.bold(`${mod.type}/${mod.name}`)} ${pc15.dim(`(${mod.uncommittedFilesCount} modified/untracked files)`)}`
4341
- );
4342
- }
4343
- }
4344
- if (committedDrift.length > 0) {
4345
- p15.log.message(pc15.cyan(`
4346
- \u{1F680} Committed But Unregistered Changes (${committedDrift.length}):`));
4347
- for (const mod of committedDrift) {
4348
- p15.log.message(
4349
- ` ${pc15.cyan("\u25C6")} ${pc15.bold(`${mod.type}/${mod.name}`)} ${pc15.dim(
4350
- `local: ${mod.localIntegrity?.slice(0, 16)}... != registered: ${mod.registeredIntegrity?.slice(0, 16)}...`
4351
- )}`
4352
- );
4353
- }
4354
- }
4355
- if (missing.length > 0) {
4356
- p15.log.message(pc15.red(`
4357
- \u26A0\uFE0F Missing on Disk (${missing.length}):`));
4358
- for (const mod of missing) {
4359
- p15.log.message(` ${pc15.red("\u2715")} ${pc15.bold(`${mod.type}/${mod.name}`)} ${pc15.dim("(in index.json, but folder missing)")}`);
4360
- }
4361
- }
4362
- if (upToDate.length > 0) {
4363
- p15.log.message(pc15.green(`
4364
- \u2713 Up to Date & Registered (${upToDate.length}):`));
4365
- for (const mod of upToDate) {
4366
- p15.log.message(` ${pc15.green("\u2714")} ${mod.type}/${mod.name} ${pc15.dim(`(${mod.registeredIntegrity?.slice(0, 18)}...)`)}`);
4367
- }
4368
- }
4369
- p15.log.message("");
4370
- }
4371
- async function handleRegistry(actionArg, typeArg, nameArg, flags = {}) {
4372
- let action = actionArg?.trim().toLowerCase();
4373
- if (!action) {
4374
- action = handleCancel(
4375
- await p15.select({
4376
- message: "\u{1F3DB}\uFE0F Mason Registry: What would you like to do?",
4377
- options: [
4378
- {
4379
- value: "diff",
4380
- label: "Inspect Diff & Status",
4381
- hint: "Summary of unregistered, uncommitted, and drifted modules"
4382
- },
4383
- {
4384
- value: "register",
4385
- label: "Register Module",
4386
- hint: "Add an existing module to index.json with integrity checksum"
4387
- },
4388
- {
4389
- value: "commit",
4390
- label: "Commit Changes",
4391
- hint: "Commit a module's working changes to git in the background"
4392
- },
4393
- {
4394
- value: "register-changes",
4395
- label: "Register Changes",
4396
- hint: "Update index.json & registry.json with latest checksums"
4397
- },
4398
- {
4399
- value: "unregister",
4400
- label: "Unregister Module",
4401
- hint: "Remove module from index.json (source code stays on disk)"
4402
- }
4403
- ]
4404
- })
4405
- );
4406
- }
4407
- switch (action) {
4408
- case "diff":
4409
- case "status":
4410
- diffRegistry(flags);
4411
- break;
4412
- case "register":
4413
- await registerModule(typeArg, nameArg, flags);
4414
- break;
4415
- case "commit":
4416
- await commitModule(typeArg, nameArg, flags);
4417
- break;
4418
- case "register-changes":
4419
- case "update":
4420
- await registerModuleChanges(typeArg, nameArg, flags);
4421
- break;
4422
- case "unregister":
4423
- await unregisterModule(typeArg, nameArg, flags);
4424
- break;
4425
- default:
4426
- p15.log.error(
4427
- pc15.red(
4428
- `Unknown registry action: "${action}". Valid actions: diff, register, commit, register-changes, unregister.`
4429
- )
4430
- );
4431
- process.exit(1);
4432
- }
4433
- }
4434
3905
 
4435
3906
  // src/cli.ts
4436
3907
  function createCli() {
4437
3908
  const cli = cac("mason");
4438
3909
  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) => {
4439
3910
  if (args && args.length > 0) {
4440
- p15.log.error(
4441
- pc15.red(
3911
+ p4.log.error(
3912
+ pc14.red(
4442
3913
  `Unknown command: "${args.join(" ")}". Use --help to list available commands.`
4443
3914
  )
4444
3915
  );
@@ -4449,14 +3920,9 @@ function createCli() {
4449
3920
  const mode = getEffectiveMode(projectRoot, flags);
4450
3921
  if (mode === "registry") {
4451
3922
  const choice2 = handleCancel(
4452
- await p15.select({
4453
- message: "\u{1F3DB}\uFE0F Mason Registry Maintainer: What would you like to do?",
3923
+ await p4.select({
3924
+ message: "\u{1F3DB}\uFE0F Mason (Registry Mode): What would you like to scaffold?",
4454
3925
  options: [
4455
- {
4456
- value: "diff",
4457
- label: "Inspect Diff & Status",
4458
- hint: "Overview of unregistered, uncommitted, or drifted modules"
4459
- },
4460
3926
  {
4461
3927
  value: "create_feature",
4462
3928
  label: "Initialize New Feature",
@@ -4472,26 +3938,6 @@ function createCli() {
4472
3938
  label: "Create New Use Case",
4473
3939
  hint: "Add a new use case to an existing feature"
4474
3940
  },
4475
- {
4476
- value: "register",
4477
- label: "Register Module",
4478
- hint: "Add a module to index.json with integrity checksum"
4479
- },
4480
- {
4481
- value: "commit",
4482
- label: "Commit Module Changes",
4483
- hint: "Commit working changes in a module to git"
4484
- },
4485
- {
4486
- value: "register_changes",
4487
- label: "Register Changes",
4488
- hint: "Recompute checksums and update index.json"
4489
- },
4490
- {
4491
- value: "unregister",
4492
- label: "Unregister Module",
4493
- hint: "Remove from index.json but keep source on disk"
4494
- },
4495
3941
  {
4496
3942
  value: "import",
4497
3943
  label: "Import from Remote Registry",
@@ -4501,9 +3947,6 @@ function createCli() {
4501
3947
  })
4502
3948
  );
4503
3949
  switch (choice2) {
4504
- case "diff":
4505
- await handleRegistry("diff", void 0, void 0, flags);
4506
- break;
4507
3950
  case "create_feature":
4508
3951
  await handleCreate("feature", void 0, flags);
4509
3952
  break;
@@ -4513,18 +3956,6 @@ function createCli() {
4513
3956
  case "create_usecase":
4514
3957
  await handleCreate("usecase", void 0, flags);
4515
3958
  break;
4516
- case "register":
4517
- await handleRegistry("register", void 0, void 0, flags);
4518
- break;
4519
- case "commit":
4520
- await handleRegistry("commit", void 0, void 0, flags);
4521
- break;
4522
- case "register_changes":
4523
- await handleRegistry("register-changes", void 0, void 0, flags);
4524
- break;
4525
- case "unregister":
4526
- await handleRegistry("unregister", void 0, void 0, flags);
4527
- break;
4528
3959
  case "import":
4529
3960
  await handleImport(void 0, void 0, flags);
4530
3961
  break;
@@ -4532,31 +3963,24 @@ function createCli() {
4532
3963
  return;
4533
3964
  }
4534
3965
  const choice = handleCancel(
4535
- await p15.select({
3966
+ await p4.select({
4536
3967
  message: "\u{1F9F1} Mason: What would you like to do?",
4537
3968
  options: [
4538
3969
  {
4539
3970
  value: "create",
4540
- label: "Create local component",
3971
+ label: "Create component",
4541
3972
  hint: "Scaffold a new feature, shared module, use case, domain entity, etc."
4542
3973
  },
4543
3974
  {
4544
3975
  value: "import",
4545
3976
  label: "Import from registry",
4546
3977
  hint: "Download and link pre-built shared modules or features from the registry"
4547
- },
4548
- {
4549
- value: "registry",
4550
- label: "Registry management",
4551
- hint: "Inspect diff, register modules, or commit module changes"
4552
3978
  }
4553
3979
  ]
4554
3980
  })
4555
3981
  );
4556
3982
  if (choice === "create") {
4557
3983
  await handleCreate(void 0, void 0, flags);
4558
- } else if (choice === "registry") {
4559
- await handleRegistry(void 0, void 0, void 0, flags);
4560
3984
  } else {
4561
3985
  await handleImport(void 0, void 0, flags);
4562
3986
  }
@@ -4584,25 +4008,6 @@ function createCli() {
4584
4008
  handleCliError(err);
4585
4009
  }
4586
4010
  });
4587
- cli.command(
4588
- "registry [action] [type] [name]",
4589
- "Registry & version management (diff, register, commit, register-changes, unregister)"
4590
- ).option("-m, --message <message>", "Commit message for 'commit' command").option("-y, --yes", "Accept defaults and skip interactive prompts").example("mason registry diff").example("mason registry register feature authn").example("mason registry commit shared hasher -m 'Add bcrypt engine'").example("mason registry register-changes shared hasher").example("mason registry unregister feature oldFeature").action(
4591
- async (action, type, name, flags = {}) => {
4592
- try {
4593
- await handleRegistry(action, type, name, flags);
4594
- } catch (err) {
4595
- handleCliError(err);
4596
- }
4597
- }
4598
- );
4599
- cli.command("diff", "Inspect registry status and diff (alias for 'mason registry diff')").allowUnknownOptions().action(async (flags = {}) => {
4600
- try {
4601
- await handleRegistry("diff", void 0, void 0, flags);
4602
- } catch (err) {
4603
- handleCliError(err);
4604
- }
4605
- });
4606
4011
  const createSubtypes = [
4607
4012
  "feature",
4608
4013
  "shared",
@@ -4626,7 +4031,7 @@ function createCli() {
4626
4031
  });
4627
4032
  }
4628
4033
  cli.help();
4629
- cli.version("1.0.13");
4034
+ cli.version("1.0.14");
4630
4035
  return cli;
4631
4036
  }
4632
4037
  function handleCliError(err) {
@@ -4634,7 +4039,7 @@ function handleCliError(err) {
4634
4039
  process.exit(0);
4635
4040
  }
4636
4041
  const message = err instanceof Error ? err.message : String(err);
4637
- p15.log.error(pc15.red(`Error: ${message}`));
4042
+ p4.log.error(pc14.red(`Error: ${message}`));
4638
4043
  process.exit(1);
4639
4044
  }
4640
4045
  async function runCli(argv = process.argv) {
@@ -4642,6 +4047,6 @@ async function runCli(argv = process.argv) {
4642
4047
  cli.parse(argv, { run: true });
4643
4048
  }
4644
4049
 
4645
- export { DEFAULT_REGISTRY_BASE, PromptCancelledError, computeDirectoryHash, concreteInfraTemplate, createCli, detectPackageManager, diProviderTemplate, domainClassTemplate, domainInterfaceTemplate, domainValueObjectTemplate, ensureInterfacePrefix, expressIndexTemplate, fetchModuleManifest, fetchRegistryFile, fetchRegistryIndex, findClosestMatch, findInterfaceFile, findLocalRegistry, findProjectRoot, generateConcreteInfraCode, generateDomain, generateDomainEntityCode, generateFeature, generateHttpHandler, generateHttpHandlerCode, generateInfrastructure, generateInjectable, generateInjectableCode, generateInterface, generateInterfaceCode, generateShared, generateStubCode, generateUseCase, generateUseCaseCode, generateUseCaseTestCode, getAllFiles, getConfiguredFeaturesDir, getConfiguredSharedDir, getEffectiveMode, getMissingNpmPackages, getRegistryBase, getTemplatesDir, handleCancel, handleCreate, handleImport, handleRegistry, hbs, httpHandlerTemplate, injectableInterfaceTemplate, injectableTemplate, installNpmPackages, interfaceTemplate, isValidIdentifier, levenshteinDistance, listDomainEntities, listDomainInterfaces, listExistingFeatures, listExistingShared, listUseCases, loadInterfaceHierarchy, loadMasonConfig, loadTemplate, normalizeRegistryUrl, parseInterfaceMethodsAndImports, printBanner, printGeneratedFiles, promptProperties, removeInterfacePrefix, renderTemplate, renderTemplateFile, resolveFeaturesDir, resolveSharedDir, runCli, runSharedCommand, stubInfraTemplate, synthesizeCrudMethods, toCamelCase, toKebabCase, toPascalCase, toPlural, toSingular, toStubName, updateOrGenerateDiProvider, useCaseTemplate, useCaseTestTemplate, writeFileSafely };
4050
+ export { DEFAULT_REGISTRY_BASE, PromptCancelledError, computeDirectoryHash, concreteInfraTemplate, createCli, detectPackageManager, diProviderTemplate, domainClassTemplate, domainInterfaceTemplate, domainValueObjectTemplate, ensureInterfacePrefix, expressIndexTemplate, fetchModuleManifest, fetchRegistryFile, fetchRegistryIndex, findClosestMatch, findInterfaceFile, findLocalRegistry, findProjectRoot, generateConcreteInfraCode, generateDomain, generateDomainEntityCode, generateFeature, generateHttpHandler, generateHttpHandlerCode, generateInfrastructure, generateInjectable, generateInjectableCode, generateInterface, generateInterfaceCode, generateShared, generateStubCode, generateUseCase, generateUseCaseCode, generateUseCaseTestCode, getAllFiles, getConfiguredFeaturesDir, getConfiguredSharedDir, getEffectiveMode, getMissingNpmPackages, getRegistryBase, getTemplatesDir, handleCancel, handleCreate, handleImport, hbs, httpHandlerTemplate, injectableInterfaceTemplate, injectableTemplate, installNpmPackages, interfaceTemplate, isValidIdentifier, levenshteinDistance, listDomainEntities, listDomainInterfaces, listExistingFeatures, listExistingShared, listUseCases, loadInterfaceHierarchy, loadMasonConfig, loadTemplate, normalizeRegistryUrl, parseInterfaceMethodsAndImports, printBanner, printGeneratedFiles, promptProperties, removeInterfacePrefix, renderTemplate, renderTemplateFile, resolveFeaturesDir, resolveSharedDir, runCli, runSharedCommand, stubInfraTemplate, synthesizeCrudMethods, toCamelCase, toKebabCase, toPascalCase, toPlural, toSingular, toStubName, updateOrGenerateDiProvider, useCaseTemplate, useCaseTestTemplate, writeFileSafely };
4646
4051
  //# sourceMappingURL=index.js.map
4647
4052
  //# sourceMappingURL=index.js.map