@solid-stack/mason 1.0.11 → 1.0.12

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,5 +1,5 @@
1
1
  import fs3 from 'fs';
2
- import path7 from 'path';
2
+ import path3 from 'path';
3
3
  import * as p4 from '@clack/prompts';
4
4
  import pc13 from 'picocolors';
5
5
  import { fileURLToPath } from 'url';
@@ -75,7 +75,7 @@ function isValidIdentifier(str) {
75
75
  }
76
76
  function writeFileSafely(absolutePath, content, options = {}) {
77
77
  const projectRoot = options.projectRoot || process.cwd();
78
- const relPath = path7.relative(projectRoot, absolutePath).replace(/\\/g, "/");
78
+ const relPath = path3.relative(projectRoot, absolutePath).replace(/\\/g, "/");
79
79
  const existedBefore = fs3.existsSync(absolutePath);
80
80
  if (options.dryRun) {
81
81
  return {
@@ -95,7 +95,7 @@ function writeFileSafely(absolutePath, content, options = {}) {
95
95
  existedBefore: true
96
96
  };
97
97
  }
98
- const dir = path7.dirname(absolutePath);
98
+ const dir = path3.dirname(absolutePath);
99
99
  if (!fs3.existsSync(dir)) {
100
100
  fs3.mkdirSync(dir, { recursive: true });
101
101
  }
@@ -126,20 +126,20 @@ function printGeneratedFiles(files, isDryRun = false) {
126
126
  }
127
127
  }
128
128
  function findProjectRoot(startDir = process.cwd()) {
129
- let current = path7.resolve(startDir);
129
+ let current = path3.resolve(startDir);
130
130
  while (true) {
131
- if (fs3.existsSync(path7.join(current, "package.json"))) {
131
+ if (fs3.existsSync(path3.join(current, "package.json"))) {
132
132
  return current;
133
133
  }
134
- const parent = path7.dirname(current);
134
+ const parent = path3.dirname(current);
135
135
  if (parent === current) {
136
- return path7.resolve(startDir);
136
+ return path3.resolve(startDir);
137
137
  }
138
138
  current = parent;
139
139
  }
140
140
  }
141
141
  function resolveFeaturesDir(projectRoot) {
142
- return path7.join(projectRoot, "features");
142
+ return path3.join(projectRoot, "features");
143
143
  }
144
144
  function listExistingFeatures(projectRoot) {
145
145
  const featuresDir = resolveFeaturesDir(projectRoot);
@@ -155,14 +155,14 @@ function listDomainInterfaces(projectRoot, featureName) {
155
155
  const results = [];
156
156
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
157
157
  for (const feat of features) {
158
- const domainDir = path7.join(resolveFeaturesDir(projectRoot), feat, "domain");
158
+ const domainDir = path3.join(resolveFeaturesDir(projectRoot), feat, "domain");
159
159
  if (!fs3.existsSync(domainDir)) continue;
160
160
  try {
161
161
  const files = fs3.readdirSync(domainDir);
162
162
  for (const file of files) {
163
163
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
164
164
  const name = file.replace(/\.ts$/, "");
165
- const fullPath = path7.join(domainDir, file);
165
+ const fullPath = path3.join(domainDir, file);
166
166
  if (/^I[A-Z]/.test(name)) {
167
167
  results.push({
168
168
  name,
@@ -193,7 +193,7 @@ function listDomainEntities(projectRoot, featureName) {
193
193
  const results = [];
194
194
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
195
195
  for (const feat of features) {
196
- const domainDir = path7.join(resolveFeaturesDir(projectRoot), feat, "domain");
196
+ const domainDir = path3.join(resolveFeaturesDir(projectRoot), feat, "domain");
197
197
  if (!fs3.existsSync(domainDir)) continue;
198
198
  try {
199
199
  const files = fs3.readdirSync(domainDir);
@@ -203,7 +203,7 @@ function listDomainEntities(projectRoot, featureName) {
203
203
  if (!/^I[A-Z]/.test(name)) {
204
204
  results.push({
205
205
  name,
206
- fullPath: path7.join(domainDir, file),
206
+ fullPath: path3.join(domainDir, file),
207
207
  feature: feat
208
208
  });
209
209
  }
@@ -218,7 +218,7 @@ function listUseCases(projectRoot, featureName) {
218
218
  const results = [];
219
219
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
220
220
  for (const feat of features) {
221
- const useCasesDir = path7.join(resolveFeaturesDir(projectRoot), feat, "useCases");
221
+ const useCasesDir = path3.join(resolveFeaturesDir(projectRoot), feat, "useCases");
222
222
  if (!fs3.existsSync(useCasesDir)) continue;
223
223
  try {
224
224
  const files = fs3.readdirSync(useCasesDir);
@@ -227,7 +227,7 @@ function listUseCases(projectRoot, featureName) {
227
227
  const name = file.replace(/\.ts$/, "");
228
228
  results.push({
229
229
  name,
230
- fullPath: path7.join(useCasesDir, file),
230
+ fullPath: path3.join(useCasesDir, file),
231
231
  feature: feat
232
232
  });
233
233
  }
@@ -323,40 +323,105 @@ async function promptProperties(options = {}) {
323
323
  return properties;
324
324
  }
325
325
  var DEFAULT_REGISTRY_BASE = "https://raw.githubusercontent.com/solid-stack-digital/mason-registry/main";
326
+ function normalizeRegistryUrl(urlOrPath, baseDir) {
327
+ let trimmed = urlOrPath.trim();
328
+ const gitSshRegex = /^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
329
+ const sshMatch = trimmed.match(gitSshRegex);
330
+ if (sshMatch && sshMatch[1] && sshMatch[2]) {
331
+ return `https://raw.githubusercontent.com/${sshMatch[1]}/${sshMatch[2]}/main`;
332
+ }
333
+ const githubWebRegex = /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^/]+))?\/?$/;
334
+ const webMatch = trimmed.match(githubWebRegex);
335
+ if (webMatch && webMatch[1] && webMatch[2]) {
336
+ const owner = webMatch[1];
337
+ const repo = webMatch[2];
338
+ const branch = webMatch[3] || "main";
339
+ return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
340
+ }
341
+ if (baseDir && (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed === "." || trimmed === "..")) {
342
+ return path3.resolve(baseDir, trimmed);
343
+ }
344
+ return trimmed;
345
+ }
346
+ function findLocalRegistry(startDir = process.cwd()) {
347
+ let current = path3.resolve(startDir);
348
+ while (true) {
349
+ const candidate = path3.join(current, "mason-registry");
350
+ if (fs3.existsSync(candidate) && fs3.existsSync(path3.join(candidate, "index.json"))) {
351
+ return candidate;
352
+ }
353
+ const parent = path3.dirname(current);
354
+ if (parent === current) break;
355
+ current = parent;
356
+ }
357
+ return null;
358
+ }
326
359
  function getRegistryBase(projectRoot, override) {
360
+ const rootDir = projectRoot ? path3.resolve(projectRoot) : process.cwd();
327
361
  if (override && override.trim()) {
328
- return override.trim();
362
+ return normalizeRegistryUrl(override.trim(), rootDir);
329
363
  }
330
364
  if (process.env.MASON_REGISTRY_URL && process.env.MASON_REGISTRY_URL.trim()) {
331
- return process.env.MASON_REGISTRY_URL.trim();
365
+ return normalizeRegistryUrl(process.env.MASON_REGISTRY_URL.trim(), rootDir);
332
366
  }
333
- if (projectRoot) {
334
- const configPath = path7.join(projectRoot, "mason.config.json");
367
+ const configLocations = [
368
+ path3.join(rootDir, "mason.config.json"),
369
+ path3.join(process.cwd(), "mason.config.json")
370
+ ];
371
+ for (const configPath of configLocations) {
335
372
  if (fs3.existsSync(configPath)) {
336
373
  try {
337
374
  const config = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
338
375
  if (config.registry && typeof config.registry === "string") {
339
- return config.registry.trim();
376
+ return normalizeRegistryUrl(config.registry.trim(), path3.dirname(configPath));
340
377
  }
341
378
  } catch {
342
379
  }
343
380
  }
344
381
  }
345
- if (projectRoot) {
346
- const siblingRegistry = path7.resolve(projectRoot, "../mason-registry");
347
- if (fs3.existsSync(siblingRegistry) && fs3.existsSync(path7.join(siblingRegistry, "index.json"))) {
348
- return siblingRegistry;
382
+ const pkgLocations = [
383
+ path3.join(rootDir, "package.json"),
384
+ path3.join(process.cwd(), "package.json")
385
+ ];
386
+ for (const pkgPath of pkgLocations) {
387
+ if (fs3.existsSync(pkgPath)) {
388
+ try {
389
+ const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
390
+ if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
391
+ return normalizeRegistryUrl(pkg.mason.registry.trim(), path3.dirname(pkgPath));
392
+ }
393
+ } catch {
394
+ }
349
395
  }
350
396
  }
397
+ const localRegistry = findLocalRegistry(rootDir);
398
+ if (localRegistry) {
399
+ return localRegistry;
400
+ }
351
401
  return DEFAULT_REGISTRY_BASE;
352
402
  }
353
403
  async function fetchRegistryFile(registryBase, relPath) {
354
404
  const cleanRelPath = relPath.replace(/^\/+/, "");
355
405
  if (registryBase.startsWith("http://") || registryBase.startsWith("https://")) {
356
406
  const url = `${registryBase.replace(/\/+$/, "")}/${cleanRelPath}`;
357
- const res = await fetch(url);
407
+ const headers = {};
408
+ const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
409
+ if (token) {
410
+ headers["Authorization"] = `Bearer ${token}`;
411
+ }
412
+ const res = await fetch(url, { headers });
358
413
  if (!res.ok) {
359
- throw new Error(`Failed to fetch ${cleanRelPath} from ${url} (HTTP ${res.status}: ${res.statusText})`);
414
+ let extraHint = "";
415
+ if (res.status === 404) {
416
+ extraHint = `
417
+ Possible reasons:
418
+ \u2022 If using a private GitHub repository, ensure GITHUB_TOKEN is set in your environment.
419
+ \u2022 If your registry has not yet been pushed to GitHub, point to your local directory:
420
+ - CLI flag: mason import ... --registry /path/to/mason-registry
421
+ - Environment: export MASON_REGISTRY_URL=/path/to/mason-registry
422
+ - Config file: Create mason.config.json with { "registry": "/path/to/mason-registry" }`;
423
+ }
424
+ throw new Error(`Failed to fetch ${cleanRelPath} from ${url} (HTTP ${res.status}: ${res.statusText})${extraHint}`);
360
425
  }
361
426
  return await res.text();
362
427
  }
@@ -364,7 +429,7 @@ async function fetchRegistryFile(registryBase, relPath) {
364
429
  if (baseDir.startsWith("file://")) {
365
430
  baseDir = fileURLToPath(baseDir);
366
431
  }
367
- const filePath = path7.resolve(baseDir, cleanRelPath);
432
+ const filePath = path3.resolve(baseDir, cleanRelPath);
368
433
  if (!fs3.existsSync(filePath)) {
369
434
  throw new Error(`Registry file not found at ${filePath}`);
370
435
  }
@@ -430,14 +495,14 @@ function findClosestMatch(target, candidates) {
430
495
  return null;
431
496
  }
432
497
  function detectPackageManager(projectRoot) {
433
- if (fs3.existsSync(path7.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
434
- if (fs3.existsSync(path7.join(projectRoot, "yarn.lock"))) return "yarn";
435
- if (fs3.existsSync(path7.join(projectRoot, "bun.lockb")) || fs3.existsSync(path7.join(projectRoot, "bun.lock"))) return "bun";
498
+ if (fs3.existsSync(path3.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
499
+ if (fs3.existsSync(path3.join(projectRoot, "yarn.lock"))) return "yarn";
500
+ if (fs3.existsSync(path3.join(projectRoot, "bun.lockb")) || fs3.existsSync(path3.join(projectRoot, "bun.lock"))) return "bun";
436
501
  return "npm";
437
502
  }
438
503
  function getMissingNpmPackages(projectRoot, requiredPackages) {
439
504
  if (!requiredPackages || requiredPackages.length === 0) return [];
440
- const pkgJsonPath = path7.join(projectRoot, "package.json");
505
+ const pkgJsonPath = path3.join(projectRoot, "package.json");
441
506
  if (!fs3.existsSync(pkgJsonPath)) {
442
507
  return requiredPackages;
443
508
  }
@@ -499,30 +564,30 @@ function getTemplatesDir() {
499
564
  if (cachedTemplatesDir && fs3.existsSync(cachedTemplatesDir)) {
500
565
  return cachedTemplatesDir;
501
566
  }
502
- const currentDir = typeof __dirname !== "undefined" ? __dirname : path7.dirname(fileURLToPath(import.meta.url));
503
- const cand1 = path7.resolve(currentDir, "../../templates");
567
+ const currentDir = typeof __dirname !== "undefined" ? __dirname : path3.dirname(fileURLToPath(import.meta.url));
568
+ const cand1 = path3.resolve(currentDir, "../../templates");
504
569
  if (fs3.existsSync(cand1)) {
505
570
  cachedTemplatesDir = cand1;
506
571
  return cand1;
507
572
  }
508
- const cand2 = path7.resolve(currentDir, "../templates");
573
+ const cand2 = path3.resolve(currentDir, "../templates");
509
574
  if (fs3.existsSync(cand2)) {
510
575
  cachedTemplatesDir = cand2;
511
576
  return cand2;
512
577
  }
513
- const cand3 = path7.resolve(currentDir, "templates");
578
+ const cand3 = path3.resolve(currentDir, "templates");
514
579
  if (fs3.existsSync(cand3)) {
515
580
  cachedTemplatesDir = cand3;
516
581
  return cand3;
517
582
  }
518
583
  let curr = currentDir;
519
584
  while (true) {
520
- const candTemplates = path7.join(curr, "templates");
585
+ const candTemplates = path3.join(curr, "templates");
521
586
  if (fs3.existsSync(candTemplates)) {
522
587
  cachedTemplatesDir = candTemplates;
523
588
  return candTemplates;
524
589
  }
525
- const parent = path7.dirname(curr);
590
+ const parent = path3.dirname(curr);
526
591
  if (parent === curr) break;
527
592
  curr = parent;
528
593
  }
@@ -530,7 +595,7 @@ function getTemplatesDir() {
530
595
  }
531
596
  var templateCache = /* @__PURE__ */ new Map();
532
597
  function loadTemplate(relativePath) {
533
- const fullPath = path7.isAbsolute(relativePath) ? relativePath : path7.join(getTemplatesDir(), relativePath);
598
+ const fullPath = path3.isAbsolute(relativePath) ? relativePath : path3.join(getTemplatesDir(), relativePath);
534
599
  return fs3.readFileSync(fullPath, "utf-8");
535
600
  }
536
601
  function renderTemplateFile(relativePath, context) {
@@ -616,8 +681,8 @@ function generateDomainEntityCode(name, kind = "interface", properties = []) {
616
681
  function generateDomain(options) {
617
682
  const projectRoot = options.projectRoot || findProjectRoot();
618
683
  const entityName = toPascalCase(options.name);
619
- const targetDir = options.targetDir || path7.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
620
- const filePath = path7.join(targetDir, `${entityName}.ts`);
684
+ const targetDir = options.targetDir || path3.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
685
+ const filePath = path3.join(targetDir, `${entityName}.ts`);
621
686
  const code = generateDomainEntityCode(
622
687
  entityName,
623
688
  options.kind || "interface",
@@ -666,8 +731,8 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
666
731
  function generateInterface(options) {
667
732
  const projectRoot = options.projectRoot || findProjectRoot();
668
733
  const ifaceName = ensureInterfacePrefix(options.name);
669
- const targetDir = options.targetDir || path7.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
670
- const filePath = path7.join(targetDir, `${ifaceName}.ts`);
734
+ const targetDir = options.targetDir || path3.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
735
+ const filePath = path3.join(targetDir, `${ifaceName}.ts`);
671
736
  const code = generateInterfaceCode(
672
737
  ifaceName,
673
738
  options.kind || "abstractClass",
@@ -912,21 +977,21 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
912
977
  ];
913
978
  const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
914
979
  for (const feat of features) {
915
- const domainDir = path7.join(resolveFeaturesDir(projectRoot), feat, "domain");
980
+ const domainDir = path3.join(resolveFeaturesDir(projectRoot), feat, "domain");
916
981
  if (!fs3.existsSync(domainDir)) continue;
917
982
  for (const cand of candidateNames) {
918
- const p1 = path7.join(domainDir, `${cand}.ts`);
983
+ const p1 = path3.join(domainDir, `${cand}.ts`);
919
984
  if (fs3.existsSync(p1)) {
920
985
  return { filePath: p1, ifaceName: cand, feature: feat };
921
986
  }
922
987
  }
923
988
  }
924
989
  for (const cand of candidateNames) {
925
- const p1 = path7.join(projectRoot, "domain", `${cand}.ts`);
990
+ const p1 = path3.join(projectRoot, "domain", `${cand}.ts`);
926
991
  if (fs3.existsSync(p1)) return { filePath: p1, ifaceName: cand };
927
- const p22 = path7.join(projectRoot, "src", "domain", `${cand}.ts`);
992
+ const p22 = path3.join(projectRoot, "src", "domain", `${cand}.ts`);
928
993
  if (fs3.existsSync(p22)) return { filePath: p22, ifaceName: cand };
929
- const p32 = path7.join(projectRoot, "interfaces", `${cand}.ts`);
994
+ const p32 = path3.join(projectRoot, "interfaces", `${cand}.ts`);
930
995
  if (fs3.existsSync(p32)) return { filePath: p32, ifaceName: cand };
931
996
  }
932
997
  return null;
@@ -1026,7 +1091,7 @@ function generateStubCode(stubClassName, ifaceName, entityName, featureName, met
1026
1091
  const entitiesVar = `${entityVar}s`;
1027
1092
  const idKey = `${entityVar}Id`;
1028
1093
  const impPath = ifaceImportPath || `../domain/${ifaceName}.js`;
1029
- const entityImportPath = ifaceImportPath ? `${path7.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1094
+ const entityImportPath = ifaceImportPath ? `${path3.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1030
1095
  const importsByFrom = /* @__PURE__ */ new Map();
1031
1096
  for (const imp of domainImports) {
1032
1097
  if (imp.name === ifaceName || imp.name === baseEntity) continue;
@@ -1075,7 +1140,7 @@ function generateConcreteInfraCode(className, ifaceName, dependencies = [], meth
1075
1140
  if (baseEntity) {
1076
1141
  finalMethods = synthesizeCrudMethods(baseEntity);
1077
1142
  if (!finalDomainImports.some((imp) => imp.name === baseEntity)) {
1078
- const importPath = ifaceImportPath ? `${path7.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1143
+ const importPath = ifaceImportPath ? `${path3.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1079
1144
  finalDomainImports.push({
1080
1145
  name: baseEntity,
1081
1146
  from: importPath,
@@ -1120,8 +1185,8 @@ function generateInfrastructure(options) {
1120
1185
  const projectRoot = options.projectRoot || findProjectRoot();
1121
1186
  const className = toPascalCase(options.name);
1122
1187
  const isFeatureScope = options.scope !== "global" && Boolean(options.feature);
1123
- const targetDir = options.targetDir || (isFeatureScope ? path7.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path7.join(projectRoot, "infrastructure"));
1124
- const filePath = path7.join(targetDir, `${className}.ts`);
1188
+ const targetDir = options.targetDir || (isFeatureScope ? path3.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path3.join(projectRoot, "infrastructure"));
1189
+ const filePath = path3.join(targetDir, `${className}.ts`);
1125
1190
  let code;
1126
1191
  if (options.implementsInterface) {
1127
1192
  const rawIfaceName = options.implementsInterface;
@@ -1135,7 +1200,7 @@ function generateInfrastructure(options) {
1135
1200
  const ifaceFilePath = hierarchy.ifaceFilePath;
1136
1201
  let ifaceImportPath;
1137
1202
  if (ifaceFilePath) {
1138
- let rel = path7.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
1203
+ let rel = path3.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
1139
1204
  if (!rel.startsWith(".")) rel = "./" + rel;
1140
1205
  ifaceImportPath = rel;
1141
1206
  } else if (isFeatureScope) {
@@ -1148,8 +1213,8 @@ function generateInfrastructure(options) {
1148
1213
  if (new RegExp(`\\b${item.name}\\b`).test(allSignatures)) {
1149
1214
  let fromPath;
1150
1215
  if (imp.specifier.startsWith(".") && ifaceFilePath) {
1151
- const absTarget = path7.resolve(path7.dirname(ifaceFilePath), imp.specifier);
1152
- let rel = path7.relative(targetDir, absTarget).replace(/\\/g, "/");
1216
+ const absTarget = path3.resolve(path3.dirname(ifaceFilePath), imp.specifier);
1217
+ let rel = path3.relative(targetDir, absTarget).replace(/\\/g, "/");
1153
1218
  if (!rel.startsWith(".")) rel = "./" + rel;
1154
1219
  fromPath = rel;
1155
1220
  } else {
@@ -1336,8 +1401,8 @@ function generateUseCase(options) {
1336
1401
  const files = [];
1337
1402
  const projectRoot = options.projectRoot || findProjectRoot();
1338
1403
  const ucName = toPascalCase(options.name);
1339
- const targetDir = options.targetDir || path7.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1340
- const filePath = path7.join(targetDir, `${ucName}.ts`);
1404
+ const targetDir = options.targetDir || path3.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1405
+ const filePath = path3.join(targetDir, `${ucName}.ts`);
1341
1406
  const code = generateUseCaseCode(
1342
1407
  ucName,
1343
1408
  options.dependencies || [],
@@ -1353,7 +1418,7 @@ function generateUseCase(options) {
1353
1418
  })
1354
1419
  );
1355
1420
  if (options.includeTest) {
1356
- const testPath = path7.join(targetDir, `${ucName}.test.ts`);
1421
+ const testPath = path3.join(targetDir, `${ucName}.test.ts`);
1357
1422
  const testCode = generateUseCaseTestCode(ucName, options.dependencies || []);
1358
1423
  files.push(
1359
1424
  writeFileSafely(testPath, testCode, {
@@ -1421,9 +1486,9 @@ function generateHttpHandler(options) {
1421
1486
  const files = [];
1422
1487
  const projectRoot = options.projectRoot || findProjectRoot();
1423
1488
  const className = toPascalCase(options.name);
1424
- const pxDir = path7.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1425
- const handlersDir = path7.join(pxDir, "handlers");
1426
- const pxIndexPath = path7.join(pxDir, "index.ts");
1489
+ const pxDir = path3.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1490
+ const handlersDir = path3.join(pxDir, "handlers");
1491
+ const pxIndexPath = path3.join(pxDir, "index.ts");
1427
1492
  if (!fs3.existsSync(pxIndexPath)) {
1428
1493
  const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
1429
1494
  const pxIndexContent = renderTemplate(expressIndexTemplate, {
@@ -1437,7 +1502,7 @@ function generateHttpHandler(options) {
1437
1502
  })
1438
1503
  );
1439
1504
  }
1440
- const handlerFilePath = path7.join(handlersDir, `${className}.ts`);
1505
+ const handlerFilePath = path3.join(handlersDir, `${className}.ts`);
1441
1506
  const code = generateHttpHandlerCode(
1442
1507
  className,
1443
1508
  options.method || "get",
@@ -1458,7 +1523,7 @@ function generateHttpHandler(options) {
1458
1523
  return files;
1459
1524
  }
1460
1525
  function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], options = {}) {
1461
- const providerPath = path7.join(featureDir, "diProvider.ts");
1526
+ const providerPath = path3.join(featureDir, "diProvider.ts");
1462
1527
  const pascalFeature = toPascalCase(featureName);
1463
1528
  const providerModuleName = `${pascalFeature}Provider`;
1464
1529
  if (fs3.existsSync(providerPath) && !options.overwrite) {
@@ -1521,7 +1586,7 @@ function generateFeature(options) {
1521
1586
  const projectRoot = options.projectRoot || findProjectRoot();
1522
1587
  const rawName = options.name.trim();
1523
1588
  const featureName = toCamelCase(rawName);
1524
- const targetDir = options.targetDir || path7.join(resolveFeaturesDir(projectRoot), featureName);
1589
+ const targetDir = options.targetDir || path3.join(resolveFeaturesDir(projectRoot), featureName);
1525
1590
  const routePath = options.routePath || `/${featureName}`;
1526
1591
  const rawEntities = [];
1527
1592
  if (options.entityNames && options.entityNames.length > 0) {
@@ -1542,7 +1607,7 @@ function generateFeature(options) {
1542
1607
  const domainFile = generateDomain({
1543
1608
  name: ent,
1544
1609
  feature: featureName,
1545
- targetDir: path7.join(targetDir, "domain"),
1610
+ targetDir: path3.join(targetDir, "domain"),
1546
1611
  projectRoot,
1547
1612
  dryRun: options.dryRun,
1548
1613
  overwrite: options.overwrite,
@@ -1562,7 +1627,7 @@ function generateFeature(options) {
1562
1627
  const ifaceFile = generateInterface({
1563
1628
  name: ifaceName,
1564
1629
  feature: featureName,
1565
- targetDir: path7.join(targetDir, "domain"),
1630
+ targetDir: path3.join(targetDir, "domain"),
1566
1631
  entityName: ent,
1567
1632
  projectRoot,
1568
1633
  dryRun: options.dryRun,
@@ -1579,7 +1644,7 @@ function generateFeature(options) {
1579
1644
  const stubFile = generateInfrastructure({
1580
1645
  name: stubName,
1581
1646
  feature: featureName,
1582
- targetDir: path7.join(targetDir, "infrastructure"),
1647
+ targetDir: path3.join(targetDir, "infrastructure"),
1583
1648
  kind: "stub",
1584
1649
  implementsInterface: ifaceName,
1585
1650
  entityName: ent,
@@ -1621,7 +1686,7 @@ function generateFeature(options) {
1621
1686
  const ucFiles = generateUseCase({
1622
1687
  name: ucName,
1623
1688
  feature: featureName,
1624
- targetDir: path7.join(targetDir, "useCases"),
1689
+ targetDir: path3.join(targetDir, "useCases"),
1625
1690
  dependencies: options.includeInterface !== false ? [ifaceName] : [],
1626
1691
  inputProperties: [{ name: idParam, type: "string" }],
1627
1692
  outputProperties: [{ name: entVar, type: primaryEntity }],
@@ -1666,7 +1731,7 @@ function generateFeature(options) {
1666
1731
  const ucFiles = generateUseCase({
1667
1732
  name: ucName,
1668
1733
  feature: featureName,
1669
- targetDir: path7.join(targetDir, "useCases"),
1734
+ targetDir: path3.join(targetDir, "useCases"),
1670
1735
  dependencies: deps,
1671
1736
  inputProperties: [{ name: entVar, type: ent }],
1672
1737
  outputProperties: [{ name: entVar, type: ent }],
@@ -1699,7 +1764,7 @@ function generateFeature(options) {
1699
1764
  const ucFiles = generateUseCase({
1700
1765
  name: ucName,
1701
1766
  feature: featureName,
1702
- targetDir: path7.join(targetDir, "useCases"),
1767
+ targetDir: path3.join(targetDir, "useCases"),
1703
1768
  dependencies: deps,
1704
1769
  inputProperties: [{ name: idParam, type: "string" }],
1705
1770
  outputProperties: [{ name: entVar, type: ent }],
@@ -1732,7 +1797,7 @@ function generateFeature(options) {
1732
1797
  const ucFiles = generateUseCase({
1733
1798
  name: ucName,
1734
1799
  feature: featureName,
1735
- targetDir: path7.join(targetDir, "useCases"),
1800
+ targetDir: path3.join(targetDir, "useCases"),
1736
1801
  dependencies: deps,
1737
1802
  inputProperties: [
1738
1803
  { name: "page", type: "number", optional: true },
@@ -1776,7 +1841,7 @@ function generateFeature(options) {
1776
1841
  const ucFiles = generateUseCase({
1777
1842
  name: ucName,
1778
1843
  feature: featureName,
1779
- targetDir: path7.join(targetDir, "useCases"),
1844
+ targetDir: path3.join(targetDir, "useCases"),
1780
1845
  dependencies: deps,
1781
1846
  inputProperties: [{ name: entVar, type: ent }],
1782
1847
  outputProperties: [{ name: entVar, type: ent }],
@@ -1809,7 +1874,7 @@ function generateFeature(options) {
1809
1874
  const ucFiles = generateUseCase({
1810
1875
  name: ucName,
1811
1876
  feature: featureName,
1812
- targetDir: path7.join(targetDir, "useCases"),
1877
+ targetDir: path3.join(targetDir, "useCases"),
1813
1878
  dependencies: deps,
1814
1879
  inputProperties: [{ name: idParam, type: "string" }],
1815
1880
  outputProperties: [{ name: "success", type: "boolean" }],
@@ -1846,7 +1911,7 @@ function generateFeature(options) {
1846
1911
  const ucFiles = generateUseCase({
1847
1912
  name: ucName,
1848
1913
  feature: featureName,
1849
- targetDir: path7.join(targetDir, "useCases"),
1914
+ targetDir: path3.join(targetDir, "useCases"),
1850
1915
  dependencies: customUc.dependencies || [],
1851
1916
  inputProperties: customUc.inputProperties || [],
1852
1917
  outputProperties: customUc.outputProperties || [],
@@ -1878,8 +1943,8 @@ function generateFeature(options) {
1878
1943
  }
1879
1944
  }
1880
1945
  if (options.includeExpress !== false) {
1881
- const pxDir = path7.join(targetDir, "pxExpress");
1882
- const pxIndexPath = path7.join(pxDir, "index.ts");
1946
+ const pxDir = path3.join(targetDir, "pxExpress");
1947
+ const pxIndexPath = path3.join(pxDir, "index.ts");
1883
1948
  if (!files.some((f) => f.absolutePath === pxIndexPath)) {
1884
1949
  const pxIndexContent = renderTemplate(expressIndexTemplate, { routePath });
1885
1950
  files.push(
@@ -1922,7 +1987,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1922
1987
  ).trim();
1923
1988
  }
1924
1989
  const normalizedName = toCamelCase(name);
1925
- const defaultDir = path7.relative(projectRoot, path7.join(resolveFeaturesDir(projectRoot), normalizedName));
1990
+ const defaultDir = path3.relative(projectRoot, path3.join(resolveFeaturesDir(projectRoot), normalizedName));
1926
1991
  let targetDirRel = defaultDir;
1927
1992
  if (!flags.yes && !flags.target) {
1928
1993
  targetDirRel = handleCancel(
@@ -1933,7 +1998,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1933
1998
  })
1934
1999
  ).trim();
1935
2000
  }
1936
- const targetDir = flags.target ? path7.resolve(projectRoot, flags.target) : path7.resolve(projectRoot, targetDirRel);
2001
+ const targetDir = flags.target ? path3.resolve(projectRoot, flags.target) : path3.resolve(projectRoot, targetDirRel);
1937
2002
  let includeExpress = flags.express !== void 0 ? Boolean(flags.express) : true;
1938
2003
  let routePath = `/${normalizedName}`;
1939
2004
  let includeDomain = true;
@@ -2601,7 +2666,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2601
2666
  const infraFile = generateInfrastructure(options);
2602
2667
  files.push(infraFile);
2603
2668
  if (registerInProvider && scope === "feature" && feature && implementsInterface) {
2604
- const featureDir = path7.join(resolveFeaturesDir(projectRoot), feature);
2669
+ const featureDir = path3.join(resolveFeaturesDir(projectRoot), feature);
2605
2670
  const providerFile = updateOrGenerateDiProvider(
2606
2671
  featureDir,
2607
2672
  feature,
@@ -2763,7 +2828,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
2763
2828
  files.push(stubFile);
2764
2829
  }
2765
2830
  if (registerInProvider && generateStub) {
2766
- const featureDir = path7.join(resolveFeaturesDir(projectRoot), feature);
2831
+ const featureDir = path3.join(resolveFeaturesDir(projectRoot), feature);
2767
2832
  const providerFile = updateOrGenerateDiProvider(
2768
2833
  featureDir,
2769
2834
  feature,
@@ -2951,21 +3016,21 @@ function generateInjectable(options) {
2951
3016
  const className = toPascalCase(options.name);
2952
3017
  let targetDir = "";
2953
3018
  if (options.customPath) {
2954
- targetDir = path7.isAbsolute(options.customPath) ? options.customPath : path7.join(projectRoot, options.customPath);
3019
+ targetDir = path3.isAbsolute(options.customPath) ? options.customPath : path3.join(projectRoot, options.customPath);
2955
3020
  } else if (options.location === "feature-service" && options.feature) {
2956
- targetDir = path7.join(resolveFeaturesDir(projectRoot), options.feature, "services");
3021
+ targetDir = path3.join(resolveFeaturesDir(projectRoot), options.feature, "services");
2957
3022
  } else if (options.location === "feature-transformer" && options.feature) {
2958
- targetDir = path7.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
3023
+ targetDir = path3.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
2959
3024
  } else if (options.location === "module") {
2960
- targetDir = path7.join(projectRoot, "modules", className);
3025
+ targetDir = path3.join(projectRoot, "modules", className);
2961
3026
  } else {
2962
- targetDir = options.feature ? path7.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path7.join(projectRoot, "shared", className.toLowerCase());
3027
+ targetDir = options.feature ? path3.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path3.join(projectRoot, "shared", className.toLowerCase());
2963
3028
  }
2964
- const filePath = path7.join(targetDir, `${className}.ts`);
3029
+ const filePath = path3.join(targetDir, `${className}.ts`);
2965
3030
  let ifaceName;
2966
3031
  if (options.generateInterface) {
2967
3032
  ifaceName = `I${className}`;
2968
- const ifacePath = path7.join(targetDir, `${ifaceName}.ts`);
3033
+ const ifacePath = path3.join(targetDir, `${ifaceName}.ts`);
2969
3034
  const ifaceContent = renderTemplate(injectableInterfaceTemplate, { ifaceName });
2970
3035
  files.push(
2971
3036
  writeFileSafely(ifacePath, ifaceContent, {
@@ -3280,7 +3345,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3280
3345
  }
3281
3346
  const sharedDeps = manifest.dependencies?.shared || [];
3282
3347
  for (const dep of sharedDeps) {
3283
- const depPath = path7.join(projectRoot, "src", "shared", dep);
3348
+ const depPath = path3.join(projectRoot, "src", "shared", dep);
3284
3349
  if (!fs3.existsSync(depPath) && !importedModules.has(`shared:${dep}`)) {
3285
3350
  p4.log.info(` \u21B3 Resolving required shared dependency: ${pc13.cyan(dep)}`);
3286
3351
  await importModuleRecursive("shared", dep);
@@ -3288,7 +3353,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3288
3353
  }
3289
3354
  const featureDeps = manifest.dependencies?.features || [];
3290
3355
  for (const dep of featureDeps) {
3291
- const depPath = path7.join(projectRoot, "src", "features", dep);
3356
+ const depPath = path3.join(projectRoot, "src", "features", dep);
3292
3357
  if (!fs3.existsSync(depPath) && !importedModules.has(`feature:${dep}`)) {
3293
3358
  p4.log.info(` \u21B3 Resolving required feature dependency: ${pc13.cyan(dep)}`);
3294
3359
  await importModuleRecursive("feature", dep);
@@ -3298,21 +3363,21 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3298
3363
  requiredNpmPackages.add(pkg);
3299
3364
  }
3300
3365
  const folder = modType === "shared" ? "shared" : "features";
3301
- const targetDir = path7.join(projectRoot, "src", folder, modName);
3366
+ const targetDir = path3.join(projectRoot, "src", folder, modName);
3302
3367
  for (const file of manifest.files || []) {
3303
3368
  if (file === "registry.json") continue;
3304
3369
  const remoteFilePath = `${folder}/${modName}/${file}`;
3305
- const localFilePath = path7.join(targetDir, file);
3370
+ const localFilePath = path3.join(targetDir, file);
3306
3371
  if (fs3.existsSync(localFilePath) && !flags.overwrite) {
3307
- p4.log.warn(` \u21B3 Skipping existing file: ${pc13.dim(path7.relative(projectRoot, localFilePath))} (use --overwrite to replace)`);
3372
+ p4.log.warn(` \u21B3 Skipping existing file: ${pc13.dim(path3.relative(projectRoot, localFilePath))} (use --overwrite to replace)`);
3308
3373
  continue;
3309
3374
  }
3310
3375
  const content = await fetchRegistryFile(registryBase, remoteFilePath);
3311
3376
  if (!flags.dryRun) {
3312
- fs3.mkdirSync(path7.dirname(localFilePath), { recursive: true });
3377
+ fs3.mkdirSync(path3.dirname(localFilePath), { recursive: true });
3313
3378
  fs3.writeFileSync(localFilePath, content, "utf-8");
3314
3379
  }
3315
- const displayPath = path7.relative(projectRoot, localFilePath);
3380
+ const displayPath = path3.relative(projectRoot, localFilePath);
3316
3381
  totalWrittenFiles.push(displayPath);
3317
3382
  p4.log.message(` ${pc13.green("+")} ${displayPath}`);
3318
3383
  }
@@ -3439,6 +3504,6 @@ async function runCli(argv = process.argv) {
3439
3504
  cli.parse(argv, { run: true });
3440
3505
  }
3441
3506
 
3442
- export { DEFAULT_REGISTRY_BASE, PromptCancelledError, concreteInfraTemplate, createCli, detectPackageManager, diProviderTemplate, domainClassTemplate, domainInterfaceTemplate, domainValueObjectTemplate, ensureInterfacePrefix, expressIndexTemplate, fetchModuleManifest, fetchRegistryFile, fetchRegistryIndex, findClosestMatch, findInterfaceFile, findProjectRoot, generateConcreteInfraCode, generateDomain, generateDomainEntityCode, generateFeature, generateHttpHandler, generateHttpHandlerCode, generateInfrastructure, generateInjectable, generateInjectableCode, generateInterface, generateInterfaceCode, generateStubCode, generateUseCase, generateUseCaseCode, generateUseCaseTestCode, getMissingNpmPackages, getRegistryBase, getTemplatesDir, handleCancel, handleCreate, handleImport, hbs, httpHandlerTemplate, injectableInterfaceTemplate, injectableTemplate, installNpmPackages, interfaceTemplate, isValidIdentifier, levenshteinDistance, listDomainEntities, listDomainInterfaces, listExistingFeatures, listUseCases, loadInterfaceHierarchy, loadTemplate, parseInterfaceMethodsAndImports, printBanner, printGeneratedFiles, promptProperties, removeInterfacePrefix, renderTemplate, renderTemplateFile, resolveFeaturesDir, runCli, stubInfraTemplate, synthesizeCrudMethods, toCamelCase, toKebabCase, toPascalCase, toPlural, toSingular, toStubName, updateOrGenerateDiProvider, useCaseTemplate, useCaseTestTemplate, writeFileSafely };
3507
+ export { DEFAULT_REGISTRY_BASE, PromptCancelledError, 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, generateStubCode, generateUseCase, generateUseCaseCode, generateUseCaseTestCode, getMissingNpmPackages, getRegistryBase, getTemplatesDir, handleCancel, handleCreate, handleImport, hbs, httpHandlerTemplate, injectableInterfaceTemplate, injectableTemplate, installNpmPackages, interfaceTemplate, isValidIdentifier, levenshteinDistance, listDomainEntities, listDomainInterfaces, listExistingFeatures, listUseCases, loadInterfaceHierarchy, loadTemplate, normalizeRegistryUrl, parseInterfaceMethodsAndImports, printBanner, printGeneratedFiles, promptProperties, removeInterfacePrefix, renderTemplate, renderTemplateFile, resolveFeaturesDir, runCli, stubInfraTemplate, synthesizeCrudMethods, toCamelCase, toKebabCase, toPascalCase, toPlural, toSingular, toStubName, updateOrGenerateDiProvider, useCaseTemplate, useCaseTestTemplate, writeFileSafely };
3443
3508
  //# sourceMappingURL=index.js.map
3444
3509
  //# sourceMappingURL=index.js.map