@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.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var fs3 = require('fs');
4
- var path7 = require('path');
4
+ var path3 = require('path');
5
5
  var p4 = require('@clack/prompts');
6
6
  var pc13 = require('picocolors');
7
7
  var url = require('url');
@@ -31,7 +31,7 @@ function _interopNamespace(e) {
31
31
  }
32
32
 
33
33
  var fs3__default = /*#__PURE__*/_interopDefault(fs3);
34
- var path7__default = /*#__PURE__*/_interopDefault(path7);
34
+ var path3__default = /*#__PURE__*/_interopDefault(path3);
35
35
  var p4__namespace = /*#__PURE__*/_interopNamespace(p4);
36
36
  var pc13__default = /*#__PURE__*/_interopDefault(pc13);
37
37
  var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
@@ -104,7 +104,7 @@ function isValidIdentifier(str) {
104
104
  }
105
105
  function writeFileSafely(absolutePath, content, options = {}) {
106
106
  const projectRoot = options.projectRoot || process.cwd();
107
- const relPath = path7__default.default.relative(projectRoot, absolutePath).replace(/\\/g, "/");
107
+ const relPath = path3__default.default.relative(projectRoot, absolutePath).replace(/\\/g, "/");
108
108
  const existedBefore = fs3__default.default.existsSync(absolutePath);
109
109
  if (options.dryRun) {
110
110
  return {
@@ -124,7 +124,7 @@ function writeFileSafely(absolutePath, content, options = {}) {
124
124
  existedBefore: true
125
125
  };
126
126
  }
127
- const dir = path7__default.default.dirname(absolutePath);
127
+ const dir = path3__default.default.dirname(absolutePath);
128
128
  if (!fs3__default.default.existsSync(dir)) {
129
129
  fs3__default.default.mkdirSync(dir, { recursive: true });
130
130
  }
@@ -155,20 +155,20 @@ function printGeneratedFiles(files, isDryRun = false) {
155
155
  }
156
156
  }
157
157
  function findProjectRoot(startDir = process.cwd()) {
158
- let current = path7__default.default.resolve(startDir);
158
+ let current = path3__default.default.resolve(startDir);
159
159
  while (true) {
160
- if (fs3__default.default.existsSync(path7__default.default.join(current, "package.json"))) {
160
+ if (fs3__default.default.existsSync(path3__default.default.join(current, "package.json"))) {
161
161
  return current;
162
162
  }
163
- const parent = path7__default.default.dirname(current);
163
+ const parent = path3__default.default.dirname(current);
164
164
  if (parent === current) {
165
- return path7__default.default.resolve(startDir);
165
+ return path3__default.default.resolve(startDir);
166
166
  }
167
167
  current = parent;
168
168
  }
169
169
  }
170
170
  function resolveFeaturesDir(projectRoot) {
171
- return path7__default.default.join(projectRoot, "features");
171
+ return path3__default.default.join(projectRoot, "features");
172
172
  }
173
173
  function listExistingFeatures(projectRoot) {
174
174
  const featuresDir = resolveFeaturesDir(projectRoot);
@@ -184,14 +184,14 @@ function listDomainInterfaces(projectRoot, featureName) {
184
184
  const results = [];
185
185
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
186
186
  for (const feat of features) {
187
- const domainDir = path7__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
187
+ const domainDir = path3__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
188
188
  if (!fs3__default.default.existsSync(domainDir)) continue;
189
189
  try {
190
190
  const files = fs3__default.default.readdirSync(domainDir);
191
191
  for (const file of files) {
192
192
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
193
193
  const name = file.replace(/\.ts$/, "");
194
- const fullPath = path7__default.default.join(domainDir, file);
194
+ const fullPath = path3__default.default.join(domainDir, file);
195
195
  if (/^I[A-Z]/.test(name)) {
196
196
  results.push({
197
197
  name,
@@ -222,7 +222,7 @@ function listDomainEntities(projectRoot, featureName) {
222
222
  const results = [];
223
223
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
224
224
  for (const feat of features) {
225
- const domainDir = path7__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
225
+ const domainDir = path3__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
226
226
  if (!fs3__default.default.existsSync(domainDir)) continue;
227
227
  try {
228
228
  const files = fs3__default.default.readdirSync(domainDir);
@@ -232,7 +232,7 @@ function listDomainEntities(projectRoot, featureName) {
232
232
  if (!/^I[A-Z]/.test(name)) {
233
233
  results.push({
234
234
  name,
235
- fullPath: path7__default.default.join(domainDir, file),
235
+ fullPath: path3__default.default.join(domainDir, file),
236
236
  feature: feat
237
237
  });
238
238
  }
@@ -247,7 +247,7 @@ function listUseCases(projectRoot, featureName) {
247
247
  const results = [];
248
248
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
249
249
  for (const feat of features) {
250
- const useCasesDir = path7__default.default.join(resolveFeaturesDir(projectRoot), feat, "useCases");
250
+ const useCasesDir = path3__default.default.join(resolveFeaturesDir(projectRoot), feat, "useCases");
251
251
  if (!fs3__default.default.existsSync(useCasesDir)) continue;
252
252
  try {
253
253
  const files = fs3__default.default.readdirSync(useCasesDir);
@@ -256,7 +256,7 @@ function listUseCases(projectRoot, featureName) {
256
256
  const name = file.replace(/\.ts$/, "");
257
257
  results.push({
258
258
  name,
259
- fullPath: path7__default.default.join(useCasesDir, file),
259
+ fullPath: path3__default.default.join(useCasesDir, file),
260
260
  feature: feat
261
261
  });
262
262
  }
@@ -352,40 +352,105 @@ async function promptProperties(options = {}) {
352
352
  return properties;
353
353
  }
354
354
  var DEFAULT_REGISTRY_BASE = "https://raw.githubusercontent.com/solid-stack-digital/mason-registry/main";
355
+ function normalizeRegistryUrl(urlOrPath, baseDir) {
356
+ let trimmed = urlOrPath.trim();
357
+ const gitSshRegex = /^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
358
+ const sshMatch = trimmed.match(gitSshRegex);
359
+ if (sshMatch && sshMatch[1] && sshMatch[2]) {
360
+ return `https://raw.githubusercontent.com/${sshMatch[1]}/${sshMatch[2]}/main`;
361
+ }
362
+ const githubWebRegex = /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^/]+))?\/?$/;
363
+ const webMatch = trimmed.match(githubWebRegex);
364
+ if (webMatch && webMatch[1] && webMatch[2]) {
365
+ const owner = webMatch[1];
366
+ const repo = webMatch[2];
367
+ const branch = webMatch[3] || "main";
368
+ return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
369
+ }
370
+ if (baseDir && (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed === "." || trimmed === "..")) {
371
+ return path3__default.default.resolve(baseDir, trimmed);
372
+ }
373
+ return trimmed;
374
+ }
375
+ function findLocalRegistry(startDir = process.cwd()) {
376
+ let current = path3__default.default.resolve(startDir);
377
+ while (true) {
378
+ const candidate = path3__default.default.join(current, "mason-registry");
379
+ if (fs3__default.default.existsSync(candidate) && fs3__default.default.existsSync(path3__default.default.join(candidate, "index.json"))) {
380
+ return candidate;
381
+ }
382
+ const parent = path3__default.default.dirname(current);
383
+ if (parent === current) break;
384
+ current = parent;
385
+ }
386
+ return null;
387
+ }
355
388
  function getRegistryBase(projectRoot, override) {
389
+ const rootDir = projectRoot ? path3__default.default.resolve(projectRoot) : process.cwd();
356
390
  if (override && override.trim()) {
357
- return override.trim();
391
+ return normalizeRegistryUrl(override.trim(), rootDir);
358
392
  }
359
393
  if (process.env.MASON_REGISTRY_URL && process.env.MASON_REGISTRY_URL.trim()) {
360
- return process.env.MASON_REGISTRY_URL.trim();
394
+ return normalizeRegistryUrl(process.env.MASON_REGISTRY_URL.trim(), rootDir);
361
395
  }
362
- if (projectRoot) {
363
- const configPath = path7__default.default.join(projectRoot, "mason.config.json");
396
+ const configLocations = [
397
+ path3__default.default.join(rootDir, "mason.config.json"),
398
+ path3__default.default.join(process.cwd(), "mason.config.json")
399
+ ];
400
+ for (const configPath of configLocations) {
364
401
  if (fs3__default.default.existsSync(configPath)) {
365
402
  try {
366
403
  const config = JSON.parse(fs3__default.default.readFileSync(configPath, "utf-8"));
367
404
  if (config.registry && typeof config.registry === "string") {
368
- return config.registry.trim();
405
+ return normalizeRegistryUrl(config.registry.trim(), path3__default.default.dirname(configPath));
369
406
  }
370
407
  } catch {
371
408
  }
372
409
  }
373
410
  }
374
- if (projectRoot) {
375
- const siblingRegistry = path7__default.default.resolve(projectRoot, "../mason-registry");
376
- if (fs3__default.default.existsSync(siblingRegistry) && fs3__default.default.existsSync(path7__default.default.join(siblingRegistry, "index.json"))) {
377
- return siblingRegistry;
411
+ const pkgLocations = [
412
+ path3__default.default.join(rootDir, "package.json"),
413
+ path3__default.default.join(process.cwd(), "package.json")
414
+ ];
415
+ for (const pkgPath of pkgLocations) {
416
+ if (fs3__default.default.existsSync(pkgPath)) {
417
+ try {
418
+ const pkg = JSON.parse(fs3__default.default.readFileSync(pkgPath, "utf-8"));
419
+ if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
420
+ return normalizeRegistryUrl(pkg.mason.registry.trim(), path3__default.default.dirname(pkgPath));
421
+ }
422
+ } catch {
423
+ }
378
424
  }
379
425
  }
426
+ const localRegistry = findLocalRegistry(rootDir);
427
+ if (localRegistry) {
428
+ return localRegistry;
429
+ }
380
430
  return DEFAULT_REGISTRY_BASE;
381
431
  }
382
432
  async function fetchRegistryFile(registryBase, relPath) {
383
433
  const cleanRelPath = relPath.replace(/^\/+/, "");
384
434
  if (registryBase.startsWith("http://") || registryBase.startsWith("https://")) {
385
435
  const url = `${registryBase.replace(/\/+$/, "")}/${cleanRelPath}`;
386
- const res = await fetch(url);
436
+ const headers = {};
437
+ const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
438
+ if (token) {
439
+ headers["Authorization"] = `Bearer ${token}`;
440
+ }
441
+ const res = await fetch(url, { headers });
387
442
  if (!res.ok) {
388
- throw new Error(`Failed to fetch ${cleanRelPath} from ${url} (HTTP ${res.status}: ${res.statusText})`);
443
+ let extraHint = "";
444
+ if (res.status === 404) {
445
+ extraHint = `
446
+ Possible reasons:
447
+ \u2022 If using a private GitHub repository, ensure GITHUB_TOKEN is set in your environment.
448
+ \u2022 If your registry has not yet been pushed to GitHub, point to your local directory:
449
+ - CLI flag: mason import ... --registry /path/to/mason-registry
450
+ - Environment: export MASON_REGISTRY_URL=/path/to/mason-registry
451
+ - Config file: Create mason.config.json with { "registry": "/path/to/mason-registry" }`;
452
+ }
453
+ throw new Error(`Failed to fetch ${cleanRelPath} from ${url} (HTTP ${res.status}: ${res.statusText})${extraHint}`);
389
454
  }
390
455
  return await res.text();
391
456
  }
@@ -393,7 +458,7 @@ async function fetchRegistryFile(registryBase, relPath) {
393
458
  if (baseDir.startsWith("file://")) {
394
459
  baseDir = url.fileURLToPath(baseDir);
395
460
  }
396
- const filePath = path7__default.default.resolve(baseDir, cleanRelPath);
461
+ const filePath = path3__default.default.resolve(baseDir, cleanRelPath);
397
462
  if (!fs3__default.default.existsSync(filePath)) {
398
463
  throw new Error(`Registry file not found at ${filePath}`);
399
464
  }
@@ -459,14 +524,14 @@ function findClosestMatch(target, candidates) {
459
524
  return null;
460
525
  }
461
526
  function detectPackageManager(projectRoot) {
462
- if (fs3__default.default.existsSync(path7__default.default.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
463
- if (fs3__default.default.existsSync(path7__default.default.join(projectRoot, "yarn.lock"))) return "yarn";
464
- if (fs3__default.default.existsSync(path7__default.default.join(projectRoot, "bun.lockb")) || fs3__default.default.existsSync(path7__default.default.join(projectRoot, "bun.lock"))) return "bun";
527
+ if (fs3__default.default.existsSync(path3__default.default.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
528
+ if (fs3__default.default.existsSync(path3__default.default.join(projectRoot, "yarn.lock"))) return "yarn";
529
+ if (fs3__default.default.existsSync(path3__default.default.join(projectRoot, "bun.lockb")) || fs3__default.default.existsSync(path3__default.default.join(projectRoot, "bun.lock"))) return "bun";
465
530
  return "npm";
466
531
  }
467
532
  function getMissingNpmPackages(projectRoot, requiredPackages) {
468
533
  if (!requiredPackages || requiredPackages.length === 0) return [];
469
- const pkgJsonPath = path7__default.default.join(projectRoot, "package.json");
534
+ const pkgJsonPath = path3__default.default.join(projectRoot, "package.json");
470
535
  if (!fs3__default.default.existsSync(pkgJsonPath)) {
471
536
  return requiredPackages;
472
537
  }
@@ -528,30 +593,30 @@ function getTemplatesDir() {
528
593
  if (cachedTemplatesDir && fs3__default.default.existsSync(cachedTemplatesDir)) {
529
594
  return cachedTemplatesDir;
530
595
  }
531
- const currentDir = typeof __dirname !== "undefined" ? __dirname : path7__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
532
- const cand1 = path7__default.default.resolve(currentDir, "../../templates");
596
+ const currentDir = typeof __dirname !== "undefined" ? __dirname : path3__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
597
+ const cand1 = path3__default.default.resolve(currentDir, "../../templates");
533
598
  if (fs3__default.default.existsSync(cand1)) {
534
599
  cachedTemplatesDir = cand1;
535
600
  return cand1;
536
601
  }
537
- const cand2 = path7__default.default.resolve(currentDir, "../templates");
602
+ const cand2 = path3__default.default.resolve(currentDir, "../templates");
538
603
  if (fs3__default.default.existsSync(cand2)) {
539
604
  cachedTemplatesDir = cand2;
540
605
  return cand2;
541
606
  }
542
- const cand3 = path7__default.default.resolve(currentDir, "templates");
607
+ const cand3 = path3__default.default.resolve(currentDir, "templates");
543
608
  if (fs3__default.default.existsSync(cand3)) {
544
609
  cachedTemplatesDir = cand3;
545
610
  return cand3;
546
611
  }
547
612
  let curr = currentDir;
548
613
  while (true) {
549
- const candTemplates = path7__default.default.join(curr, "templates");
614
+ const candTemplates = path3__default.default.join(curr, "templates");
550
615
  if (fs3__default.default.existsSync(candTemplates)) {
551
616
  cachedTemplatesDir = candTemplates;
552
617
  return candTemplates;
553
618
  }
554
- const parent = path7__default.default.dirname(curr);
619
+ const parent = path3__default.default.dirname(curr);
555
620
  if (parent === curr) break;
556
621
  curr = parent;
557
622
  }
@@ -559,7 +624,7 @@ function getTemplatesDir() {
559
624
  }
560
625
  var templateCache = /* @__PURE__ */ new Map();
561
626
  function loadTemplate(relativePath) {
562
- const fullPath = path7__default.default.isAbsolute(relativePath) ? relativePath : path7__default.default.join(getTemplatesDir(), relativePath);
627
+ const fullPath = path3__default.default.isAbsolute(relativePath) ? relativePath : path3__default.default.join(getTemplatesDir(), relativePath);
563
628
  return fs3__default.default.readFileSync(fullPath, "utf-8");
564
629
  }
565
630
  function renderTemplateFile(relativePath, context) {
@@ -645,8 +710,8 @@ function generateDomainEntityCode(name, kind = "interface", properties = []) {
645
710
  function generateDomain(options) {
646
711
  const projectRoot = options.projectRoot || findProjectRoot();
647
712
  const entityName = toPascalCase(options.name);
648
- const targetDir = options.targetDir || path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
649
- const filePath = path7__default.default.join(targetDir, `${entityName}.ts`);
713
+ const targetDir = options.targetDir || path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
714
+ const filePath = path3__default.default.join(targetDir, `${entityName}.ts`);
650
715
  const code = generateDomainEntityCode(
651
716
  entityName,
652
717
  options.kind || "interface",
@@ -695,8 +760,8 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
695
760
  function generateInterface(options) {
696
761
  const projectRoot = options.projectRoot || findProjectRoot();
697
762
  const ifaceName = ensureInterfacePrefix(options.name);
698
- const targetDir = options.targetDir || path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
699
- const filePath = path7__default.default.join(targetDir, `${ifaceName}.ts`);
763
+ const targetDir = options.targetDir || path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
764
+ const filePath = path3__default.default.join(targetDir, `${ifaceName}.ts`);
700
765
  const code = generateInterfaceCode(
701
766
  ifaceName,
702
767
  options.kind || "abstractClass",
@@ -941,21 +1006,21 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
941
1006
  ];
942
1007
  const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
943
1008
  for (const feat of features) {
944
- const domainDir = path7__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
1009
+ const domainDir = path3__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
945
1010
  if (!fs3__default.default.existsSync(domainDir)) continue;
946
1011
  for (const cand of candidateNames) {
947
- const p1 = path7__default.default.join(domainDir, `${cand}.ts`);
1012
+ const p1 = path3__default.default.join(domainDir, `${cand}.ts`);
948
1013
  if (fs3__default.default.existsSync(p1)) {
949
1014
  return { filePath: p1, ifaceName: cand, feature: feat };
950
1015
  }
951
1016
  }
952
1017
  }
953
1018
  for (const cand of candidateNames) {
954
- const p1 = path7__default.default.join(projectRoot, "domain", `${cand}.ts`);
1019
+ const p1 = path3__default.default.join(projectRoot, "domain", `${cand}.ts`);
955
1020
  if (fs3__default.default.existsSync(p1)) return { filePath: p1, ifaceName: cand };
956
- const p22 = path7__default.default.join(projectRoot, "src", "domain", `${cand}.ts`);
1021
+ const p22 = path3__default.default.join(projectRoot, "src", "domain", `${cand}.ts`);
957
1022
  if (fs3__default.default.existsSync(p22)) return { filePath: p22, ifaceName: cand };
958
- const p32 = path7__default.default.join(projectRoot, "interfaces", `${cand}.ts`);
1023
+ const p32 = path3__default.default.join(projectRoot, "interfaces", `${cand}.ts`);
959
1024
  if (fs3__default.default.existsSync(p32)) return { filePath: p32, ifaceName: cand };
960
1025
  }
961
1026
  return null;
@@ -1055,7 +1120,7 @@ function generateStubCode(stubClassName, ifaceName, entityName, featureName, met
1055
1120
  const entitiesVar = `${entityVar}s`;
1056
1121
  const idKey = `${entityVar}Id`;
1057
1122
  const impPath = ifaceImportPath || `../domain/${ifaceName}.js`;
1058
- const entityImportPath = ifaceImportPath ? `${path7__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1123
+ const entityImportPath = ifaceImportPath ? `${path3__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1059
1124
  const importsByFrom = /* @__PURE__ */ new Map();
1060
1125
  for (const imp of domainImports) {
1061
1126
  if (imp.name === ifaceName || imp.name === baseEntity) continue;
@@ -1104,7 +1169,7 @@ function generateConcreteInfraCode(className, ifaceName, dependencies = [], meth
1104
1169
  if (baseEntity) {
1105
1170
  finalMethods = synthesizeCrudMethods(baseEntity);
1106
1171
  if (!finalDomainImports.some((imp) => imp.name === baseEntity)) {
1107
- const importPath = ifaceImportPath ? `${path7__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1172
+ const importPath = ifaceImportPath ? `${path3__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
1108
1173
  finalDomainImports.push({
1109
1174
  name: baseEntity,
1110
1175
  from: importPath,
@@ -1149,8 +1214,8 @@ function generateInfrastructure(options) {
1149
1214
  const projectRoot = options.projectRoot || findProjectRoot();
1150
1215
  const className = toPascalCase(options.name);
1151
1216
  const isFeatureScope = options.scope !== "global" && Boolean(options.feature);
1152
- const targetDir = options.targetDir || (isFeatureScope ? path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path7__default.default.join(projectRoot, "infrastructure"));
1153
- const filePath = path7__default.default.join(targetDir, `${className}.ts`);
1217
+ const targetDir = options.targetDir || (isFeatureScope ? path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path3__default.default.join(projectRoot, "infrastructure"));
1218
+ const filePath = path3__default.default.join(targetDir, `${className}.ts`);
1154
1219
  let code;
1155
1220
  if (options.implementsInterface) {
1156
1221
  const rawIfaceName = options.implementsInterface;
@@ -1164,7 +1229,7 @@ function generateInfrastructure(options) {
1164
1229
  const ifaceFilePath = hierarchy.ifaceFilePath;
1165
1230
  let ifaceImportPath;
1166
1231
  if (ifaceFilePath) {
1167
- let rel = path7__default.default.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
1232
+ let rel = path3__default.default.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
1168
1233
  if (!rel.startsWith(".")) rel = "./" + rel;
1169
1234
  ifaceImportPath = rel;
1170
1235
  } else if (isFeatureScope) {
@@ -1177,8 +1242,8 @@ function generateInfrastructure(options) {
1177
1242
  if (new RegExp(`\\b${item.name}\\b`).test(allSignatures)) {
1178
1243
  let fromPath;
1179
1244
  if (imp.specifier.startsWith(".") && ifaceFilePath) {
1180
- const absTarget = path7__default.default.resolve(path7__default.default.dirname(ifaceFilePath), imp.specifier);
1181
- let rel = path7__default.default.relative(targetDir, absTarget).replace(/\\/g, "/");
1245
+ const absTarget = path3__default.default.resolve(path3__default.default.dirname(ifaceFilePath), imp.specifier);
1246
+ let rel = path3__default.default.relative(targetDir, absTarget).replace(/\\/g, "/");
1182
1247
  if (!rel.startsWith(".")) rel = "./" + rel;
1183
1248
  fromPath = rel;
1184
1249
  } else {
@@ -1365,8 +1430,8 @@ function generateUseCase(options) {
1365
1430
  const files = [];
1366
1431
  const projectRoot = options.projectRoot || findProjectRoot();
1367
1432
  const ucName = toPascalCase(options.name);
1368
- const targetDir = options.targetDir || path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1369
- const filePath = path7__default.default.join(targetDir, `${ucName}.ts`);
1433
+ const targetDir = options.targetDir || path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1434
+ const filePath = path3__default.default.join(targetDir, `${ucName}.ts`);
1370
1435
  const code = generateUseCaseCode(
1371
1436
  ucName,
1372
1437
  options.dependencies || [],
@@ -1382,7 +1447,7 @@ function generateUseCase(options) {
1382
1447
  })
1383
1448
  );
1384
1449
  if (options.includeTest) {
1385
- const testPath = path7__default.default.join(targetDir, `${ucName}.test.ts`);
1450
+ const testPath = path3__default.default.join(targetDir, `${ucName}.test.ts`);
1386
1451
  const testCode = generateUseCaseTestCode(ucName, options.dependencies || []);
1387
1452
  files.push(
1388
1453
  writeFileSafely(testPath, testCode, {
@@ -1450,9 +1515,9 @@ function generateHttpHandler(options) {
1450
1515
  const files = [];
1451
1516
  const projectRoot = options.projectRoot || findProjectRoot();
1452
1517
  const className = toPascalCase(options.name);
1453
- const pxDir = path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1454
- const handlersDir = path7__default.default.join(pxDir, "handlers");
1455
- const pxIndexPath = path7__default.default.join(pxDir, "index.ts");
1518
+ const pxDir = path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1519
+ const handlersDir = path3__default.default.join(pxDir, "handlers");
1520
+ const pxIndexPath = path3__default.default.join(pxDir, "index.ts");
1456
1521
  if (!fs3__default.default.existsSync(pxIndexPath)) {
1457
1522
  const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
1458
1523
  const pxIndexContent = renderTemplate(expressIndexTemplate, {
@@ -1466,7 +1531,7 @@ function generateHttpHandler(options) {
1466
1531
  })
1467
1532
  );
1468
1533
  }
1469
- const handlerFilePath = path7__default.default.join(handlersDir, `${className}.ts`);
1534
+ const handlerFilePath = path3__default.default.join(handlersDir, `${className}.ts`);
1470
1535
  const code = generateHttpHandlerCode(
1471
1536
  className,
1472
1537
  options.method || "get",
@@ -1487,7 +1552,7 @@ function generateHttpHandler(options) {
1487
1552
  return files;
1488
1553
  }
1489
1554
  function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], options = {}) {
1490
- const providerPath = path7__default.default.join(featureDir, "diProvider.ts");
1555
+ const providerPath = path3__default.default.join(featureDir, "diProvider.ts");
1491
1556
  const pascalFeature = toPascalCase(featureName);
1492
1557
  const providerModuleName = `${pascalFeature}Provider`;
1493
1558
  if (fs3__default.default.existsSync(providerPath) && !options.overwrite) {
@@ -1550,7 +1615,7 @@ function generateFeature(options) {
1550
1615
  const projectRoot = options.projectRoot || findProjectRoot();
1551
1616
  const rawName = options.name.trim();
1552
1617
  const featureName = toCamelCase(rawName);
1553
- const targetDir = options.targetDir || path7__default.default.join(resolveFeaturesDir(projectRoot), featureName);
1618
+ const targetDir = options.targetDir || path3__default.default.join(resolveFeaturesDir(projectRoot), featureName);
1554
1619
  const routePath = options.routePath || `/${featureName}`;
1555
1620
  const rawEntities = [];
1556
1621
  if (options.entityNames && options.entityNames.length > 0) {
@@ -1571,7 +1636,7 @@ function generateFeature(options) {
1571
1636
  const domainFile = generateDomain({
1572
1637
  name: ent,
1573
1638
  feature: featureName,
1574
- targetDir: path7__default.default.join(targetDir, "domain"),
1639
+ targetDir: path3__default.default.join(targetDir, "domain"),
1575
1640
  projectRoot,
1576
1641
  dryRun: options.dryRun,
1577
1642
  overwrite: options.overwrite,
@@ -1591,7 +1656,7 @@ function generateFeature(options) {
1591
1656
  const ifaceFile = generateInterface({
1592
1657
  name: ifaceName,
1593
1658
  feature: featureName,
1594
- targetDir: path7__default.default.join(targetDir, "domain"),
1659
+ targetDir: path3__default.default.join(targetDir, "domain"),
1595
1660
  entityName: ent,
1596
1661
  projectRoot,
1597
1662
  dryRun: options.dryRun,
@@ -1608,7 +1673,7 @@ function generateFeature(options) {
1608
1673
  const stubFile = generateInfrastructure({
1609
1674
  name: stubName,
1610
1675
  feature: featureName,
1611
- targetDir: path7__default.default.join(targetDir, "infrastructure"),
1676
+ targetDir: path3__default.default.join(targetDir, "infrastructure"),
1612
1677
  kind: "stub",
1613
1678
  implementsInterface: ifaceName,
1614
1679
  entityName: ent,
@@ -1650,7 +1715,7 @@ function generateFeature(options) {
1650
1715
  const ucFiles = generateUseCase({
1651
1716
  name: ucName,
1652
1717
  feature: featureName,
1653
- targetDir: path7__default.default.join(targetDir, "useCases"),
1718
+ targetDir: path3__default.default.join(targetDir, "useCases"),
1654
1719
  dependencies: options.includeInterface !== false ? [ifaceName] : [],
1655
1720
  inputProperties: [{ name: idParam, type: "string" }],
1656
1721
  outputProperties: [{ name: entVar, type: primaryEntity }],
@@ -1695,7 +1760,7 @@ function generateFeature(options) {
1695
1760
  const ucFiles = generateUseCase({
1696
1761
  name: ucName,
1697
1762
  feature: featureName,
1698
- targetDir: path7__default.default.join(targetDir, "useCases"),
1763
+ targetDir: path3__default.default.join(targetDir, "useCases"),
1699
1764
  dependencies: deps,
1700
1765
  inputProperties: [{ name: entVar, type: ent }],
1701
1766
  outputProperties: [{ name: entVar, type: ent }],
@@ -1728,7 +1793,7 @@ function generateFeature(options) {
1728
1793
  const ucFiles = generateUseCase({
1729
1794
  name: ucName,
1730
1795
  feature: featureName,
1731
- targetDir: path7__default.default.join(targetDir, "useCases"),
1796
+ targetDir: path3__default.default.join(targetDir, "useCases"),
1732
1797
  dependencies: deps,
1733
1798
  inputProperties: [{ name: idParam, type: "string" }],
1734
1799
  outputProperties: [{ name: entVar, type: ent }],
@@ -1761,7 +1826,7 @@ function generateFeature(options) {
1761
1826
  const ucFiles = generateUseCase({
1762
1827
  name: ucName,
1763
1828
  feature: featureName,
1764
- targetDir: path7__default.default.join(targetDir, "useCases"),
1829
+ targetDir: path3__default.default.join(targetDir, "useCases"),
1765
1830
  dependencies: deps,
1766
1831
  inputProperties: [
1767
1832
  { name: "page", type: "number", optional: true },
@@ -1805,7 +1870,7 @@ function generateFeature(options) {
1805
1870
  const ucFiles = generateUseCase({
1806
1871
  name: ucName,
1807
1872
  feature: featureName,
1808
- targetDir: path7__default.default.join(targetDir, "useCases"),
1873
+ targetDir: path3__default.default.join(targetDir, "useCases"),
1809
1874
  dependencies: deps,
1810
1875
  inputProperties: [{ name: entVar, type: ent }],
1811
1876
  outputProperties: [{ name: entVar, type: ent }],
@@ -1838,7 +1903,7 @@ function generateFeature(options) {
1838
1903
  const ucFiles = generateUseCase({
1839
1904
  name: ucName,
1840
1905
  feature: featureName,
1841
- targetDir: path7__default.default.join(targetDir, "useCases"),
1906
+ targetDir: path3__default.default.join(targetDir, "useCases"),
1842
1907
  dependencies: deps,
1843
1908
  inputProperties: [{ name: idParam, type: "string" }],
1844
1909
  outputProperties: [{ name: "success", type: "boolean" }],
@@ -1875,7 +1940,7 @@ function generateFeature(options) {
1875
1940
  const ucFiles = generateUseCase({
1876
1941
  name: ucName,
1877
1942
  feature: featureName,
1878
- targetDir: path7__default.default.join(targetDir, "useCases"),
1943
+ targetDir: path3__default.default.join(targetDir, "useCases"),
1879
1944
  dependencies: customUc.dependencies || [],
1880
1945
  inputProperties: customUc.inputProperties || [],
1881
1946
  outputProperties: customUc.outputProperties || [],
@@ -1907,8 +1972,8 @@ function generateFeature(options) {
1907
1972
  }
1908
1973
  }
1909
1974
  if (options.includeExpress !== false) {
1910
- const pxDir = path7__default.default.join(targetDir, "pxExpress");
1911
- const pxIndexPath = path7__default.default.join(pxDir, "index.ts");
1975
+ const pxDir = path3__default.default.join(targetDir, "pxExpress");
1976
+ const pxIndexPath = path3__default.default.join(pxDir, "index.ts");
1912
1977
  if (!files.some((f) => f.absolutePath === pxIndexPath)) {
1913
1978
  const pxIndexContent = renderTemplate(expressIndexTemplate, { routePath });
1914
1979
  files.push(
@@ -1951,7 +2016,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1951
2016
  ).trim();
1952
2017
  }
1953
2018
  const normalizedName = toCamelCase(name);
1954
- const defaultDir = path7__default.default.relative(projectRoot, path7__default.default.join(resolveFeaturesDir(projectRoot), normalizedName));
2019
+ const defaultDir = path3__default.default.relative(projectRoot, path3__default.default.join(resolveFeaturesDir(projectRoot), normalizedName));
1955
2020
  let targetDirRel = defaultDir;
1956
2021
  if (!flags.yes && !flags.target) {
1957
2022
  targetDirRel = handleCancel(
@@ -1962,7 +2027,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1962
2027
  })
1963
2028
  ).trim();
1964
2029
  }
1965
- const targetDir = flags.target ? path7__default.default.resolve(projectRoot, flags.target) : path7__default.default.resolve(projectRoot, targetDirRel);
2030
+ const targetDir = flags.target ? path3__default.default.resolve(projectRoot, flags.target) : path3__default.default.resolve(projectRoot, targetDirRel);
1966
2031
  let includeExpress = flags.express !== void 0 ? Boolean(flags.express) : true;
1967
2032
  let routePath = `/${normalizedName}`;
1968
2033
  let includeDomain = true;
@@ -2630,7 +2695,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2630
2695
  const infraFile = generateInfrastructure(options);
2631
2696
  files.push(infraFile);
2632
2697
  if (registerInProvider && scope === "feature" && feature && implementsInterface) {
2633
- const featureDir = path7__default.default.join(resolveFeaturesDir(projectRoot), feature);
2698
+ const featureDir = path3__default.default.join(resolveFeaturesDir(projectRoot), feature);
2634
2699
  const providerFile = updateOrGenerateDiProvider(
2635
2700
  featureDir,
2636
2701
  feature,
@@ -2792,7 +2857,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
2792
2857
  files.push(stubFile);
2793
2858
  }
2794
2859
  if (registerInProvider && generateStub) {
2795
- const featureDir = path7__default.default.join(resolveFeaturesDir(projectRoot), feature);
2860
+ const featureDir = path3__default.default.join(resolveFeaturesDir(projectRoot), feature);
2796
2861
  const providerFile = updateOrGenerateDiProvider(
2797
2862
  featureDir,
2798
2863
  feature,
@@ -2980,21 +3045,21 @@ function generateInjectable(options) {
2980
3045
  const className = toPascalCase(options.name);
2981
3046
  let targetDir = "";
2982
3047
  if (options.customPath) {
2983
- targetDir = path7__default.default.isAbsolute(options.customPath) ? options.customPath : path7__default.default.join(projectRoot, options.customPath);
3048
+ targetDir = path3__default.default.isAbsolute(options.customPath) ? options.customPath : path3__default.default.join(projectRoot, options.customPath);
2984
3049
  } else if (options.location === "feature-service" && options.feature) {
2985
- targetDir = path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services");
3050
+ targetDir = path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services");
2986
3051
  } else if (options.location === "feature-transformer" && options.feature) {
2987
- targetDir = path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
3052
+ targetDir = path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
2988
3053
  } else if (options.location === "module") {
2989
- targetDir = path7__default.default.join(projectRoot, "modules", className);
3054
+ targetDir = path3__default.default.join(projectRoot, "modules", className);
2990
3055
  } else {
2991
- targetDir = options.feature ? path7__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path7__default.default.join(projectRoot, "shared", className.toLowerCase());
3056
+ targetDir = options.feature ? path3__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path3__default.default.join(projectRoot, "shared", className.toLowerCase());
2992
3057
  }
2993
- const filePath = path7__default.default.join(targetDir, `${className}.ts`);
3058
+ const filePath = path3__default.default.join(targetDir, `${className}.ts`);
2994
3059
  let ifaceName;
2995
3060
  if (options.generateInterface) {
2996
3061
  ifaceName = `I${className}`;
2997
- const ifacePath = path7__default.default.join(targetDir, `${ifaceName}.ts`);
3062
+ const ifacePath = path3__default.default.join(targetDir, `${ifaceName}.ts`);
2998
3063
  const ifaceContent = renderTemplate(injectableInterfaceTemplate, { ifaceName });
2999
3064
  files.push(
3000
3065
  writeFileSafely(ifacePath, ifaceContent, {
@@ -3309,7 +3374,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3309
3374
  }
3310
3375
  const sharedDeps = manifest.dependencies?.shared || [];
3311
3376
  for (const dep of sharedDeps) {
3312
- const depPath = path7__default.default.join(projectRoot, "src", "shared", dep);
3377
+ const depPath = path3__default.default.join(projectRoot, "src", "shared", dep);
3313
3378
  if (!fs3__default.default.existsSync(depPath) && !importedModules.has(`shared:${dep}`)) {
3314
3379
  p4__namespace.log.info(` \u21B3 Resolving required shared dependency: ${pc13__default.default.cyan(dep)}`);
3315
3380
  await importModuleRecursive("shared", dep);
@@ -3317,7 +3382,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3317
3382
  }
3318
3383
  const featureDeps = manifest.dependencies?.features || [];
3319
3384
  for (const dep of featureDeps) {
3320
- const depPath = path7__default.default.join(projectRoot, "src", "features", dep);
3385
+ const depPath = path3__default.default.join(projectRoot, "src", "features", dep);
3321
3386
  if (!fs3__default.default.existsSync(depPath) && !importedModules.has(`feature:${dep}`)) {
3322
3387
  p4__namespace.log.info(` \u21B3 Resolving required feature dependency: ${pc13__default.default.cyan(dep)}`);
3323
3388
  await importModuleRecursive("feature", dep);
@@ -3327,21 +3392,21 @@ async function handleImport(typeArg, nameArg, flags = {}) {
3327
3392
  requiredNpmPackages.add(pkg);
3328
3393
  }
3329
3394
  const folder = modType === "shared" ? "shared" : "features";
3330
- const targetDir = path7__default.default.join(projectRoot, "src", folder, modName);
3395
+ const targetDir = path3__default.default.join(projectRoot, "src", folder, modName);
3331
3396
  for (const file of manifest.files || []) {
3332
3397
  if (file === "registry.json") continue;
3333
3398
  const remoteFilePath = `${folder}/${modName}/${file}`;
3334
- const localFilePath = path7__default.default.join(targetDir, file);
3399
+ const localFilePath = path3__default.default.join(targetDir, file);
3335
3400
  if (fs3__default.default.existsSync(localFilePath) && !flags.overwrite) {
3336
- p4__namespace.log.warn(` \u21B3 Skipping existing file: ${pc13__default.default.dim(path7__default.default.relative(projectRoot, localFilePath))} (use --overwrite to replace)`);
3401
+ p4__namespace.log.warn(` \u21B3 Skipping existing file: ${pc13__default.default.dim(path3__default.default.relative(projectRoot, localFilePath))} (use --overwrite to replace)`);
3337
3402
  continue;
3338
3403
  }
3339
3404
  const content = await fetchRegistryFile(registryBase, remoteFilePath);
3340
3405
  if (!flags.dryRun) {
3341
- fs3__default.default.mkdirSync(path7__default.default.dirname(localFilePath), { recursive: true });
3406
+ fs3__default.default.mkdirSync(path3__default.default.dirname(localFilePath), { recursive: true });
3342
3407
  fs3__default.default.writeFileSync(localFilePath, content, "utf-8");
3343
3408
  }
3344
- const displayPath = path7__default.default.relative(projectRoot, localFilePath);
3409
+ const displayPath = path3__default.default.relative(projectRoot, localFilePath);
3345
3410
  totalWrittenFiles.push(displayPath);
3346
3411
  p4__namespace.log.message(` ${pc13__default.default.green("+")} ${displayPath}`);
3347
3412
  }
@@ -3484,6 +3549,7 @@ exports.fetchRegistryFile = fetchRegistryFile;
3484
3549
  exports.fetchRegistryIndex = fetchRegistryIndex;
3485
3550
  exports.findClosestMatch = findClosestMatch;
3486
3551
  exports.findInterfaceFile = findInterfaceFile;
3552
+ exports.findLocalRegistry = findLocalRegistry;
3487
3553
  exports.findProjectRoot = findProjectRoot;
3488
3554
  exports.generateConcreteInfraCode = generateConcreteInfraCode;
3489
3555
  exports.generateDomain = generateDomain;
@@ -3520,6 +3586,7 @@ exports.listExistingFeatures = listExistingFeatures;
3520
3586
  exports.listUseCases = listUseCases;
3521
3587
  exports.loadInterfaceHierarchy = loadInterfaceHierarchy;
3522
3588
  exports.loadTemplate = loadTemplate;
3589
+ exports.normalizeRegistryUrl = normalizeRegistryUrl;
3523
3590
  exports.parseInterfaceMethodsAndImports = parseInterfaceMethodsAndImports;
3524
3591
  exports.printBanner = printBanner;
3525
3592
  exports.printGeneratedFiles = printGeneratedFiles;