@solid-stack/mason 1.0.32 → 1.0.34

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/bin.cjs CHANGED
@@ -4,8 +4,8 @@
4
4
  var cac = require('cac');
5
5
  var p19 = require('@clack/prompts');
6
6
  var pc13 = require('picocolors');
7
- var fs14 = require('fs');
8
- var path2 = require('path');
7
+ var fs17 = require('fs');
8
+ var path26 = require('path');
9
9
  var url = require('url');
10
10
  var Handlebars = require('handlebars');
11
11
  var child_process = require('child_process');
@@ -34,14 +34,14 @@ function _interopNamespace(e) {
34
34
 
35
35
  var p19__namespace = /*#__PURE__*/_interopNamespace(p19);
36
36
  var pc13__default = /*#__PURE__*/_interopDefault(pc13);
37
- var fs14__default = /*#__PURE__*/_interopDefault(fs14);
38
- var path2__default = /*#__PURE__*/_interopDefault(path2);
37
+ var fs17__default = /*#__PURE__*/_interopDefault(fs17);
38
+ var path26__default = /*#__PURE__*/_interopDefault(path26);
39
39
  var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
40
40
 
41
41
  function writeFileSafely(absolutePath, content, options = {}) {
42
42
  const projectRoot = options.projectRoot || process.cwd();
43
- const relPath = path2__default.default.relative(projectRoot, absolutePath).replace(/\\/g, "/");
44
- const existedBefore = fs14__default.default.existsSync(absolutePath);
43
+ const relPath = path26__default.default.relative(projectRoot, absolutePath).replace(/\\/g, "/");
44
+ const existedBefore = fs17__default.default.existsSync(absolutePath);
45
45
  if (options.dryRun) {
46
46
  return {
47
47
  relativePath: relPath,
@@ -60,11 +60,11 @@ function writeFileSafely(absolutePath, content, options = {}) {
60
60
  existedBefore: true
61
61
  };
62
62
  }
63
- const dir = path2__default.default.dirname(absolutePath);
64
- if (!fs14__default.default.existsSync(dir)) {
65
- fs14__default.default.mkdirSync(dir, { recursive: true });
63
+ const dir = path26__default.default.dirname(absolutePath);
64
+ if (!fs17__default.default.existsSync(dir)) {
65
+ fs17__default.default.mkdirSync(dir, { recursive: true });
66
66
  }
67
- fs14__default.default.writeFileSync(absolutePath, content, "utf-8");
67
+ fs17__default.default.writeFileSync(absolutePath, content, "utf-8");
68
68
  return {
69
69
  relativePath: relPath,
70
70
  absolutePath,
@@ -155,17 +155,17 @@ function toStubName(ifaceName) {
155
155
  return `Stub${base}`;
156
156
  }
157
157
  function loadMasonConfig(startDir = process.cwd()) {
158
- let current = path2__default.default.resolve(startDir);
158
+ let current = path26__default.default.resolve(startDir);
159
159
  while (true) {
160
- const configPath = path2__default.default.join(current, "mason.config.json");
161
- if (fs14__default.default.existsSync(configPath)) {
160
+ const configPath = path26__default.default.join(current, "mason.config.json");
161
+ if (fs17__default.default.existsSync(configPath)) {
162
162
  try {
163
- return JSON.parse(fs14__default.default.readFileSync(configPath, "utf-8"));
163
+ return JSON.parse(fs17__default.default.readFileSync(configPath, "utf-8"));
164
164
  } catch {
165
165
  return null;
166
166
  }
167
167
  }
168
- const parent = path2__default.default.dirname(current);
168
+ const parent = path26__default.default.dirname(current);
169
169
  if (parent === current) break;
170
170
  current = parent;
171
171
  }
@@ -175,60 +175,91 @@ function getEffectiveMode(projectRoot, flags) {
175
175
  if (flags?.registry) return "registry";
176
176
  const config = loadMasonConfig(projectRoot);
177
177
  if (config?.mode) return config.mode;
178
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "index.json")) && (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "features")) || fs14__default.default.existsSync(path2__default.default.join(projectRoot, "shared")) || fs14__default.default.existsSync(path2__default.default.join(projectRoot, "src/features")) || fs14__default.default.existsSync(path2__default.default.join(projectRoot, "src/shared")))) {
178
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "index.json")) && (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "features")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "shared")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/features")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/shared")))) {
179
179
  return "registry";
180
180
  }
181
181
  return "app";
182
182
  }
183
183
  function getConfiguredFeaturesDir(projectRoot, flags) {
184
- if (flags?.target) return path2__default.default.resolve(projectRoot, flags.target);
185
- if (flags?.dest) return path2__default.default.resolve(projectRoot, flags.dest);
184
+ if (flags?.target) return path26__default.default.resolve(projectRoot, flags.target);
185
+ if (flags?.dest) return path26__default.default.resolve(projectRoot, flags.dest);
186
186
  const config = loadMasonConfig(projectRoot);
187
187
  if (config?.paths?.features) {
188
- return path2__default.default.resolve(projectRoot, config.paths.features);
188
+ return path26__default.default.resolve(projectRoot, config.paths.features);
189
189
  }
190
190
  const mode = getEffectiveMode(projectRoot, flags);
191
191
  if (mode === "registry") {
192
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "src/features"))) {
193
- return path2__default.default.join(projectRoot, "src/features");
192
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/features"))) {
193
+ return path26__default.default.join(projectRoot, "src/features");
194
194
  }
195
- return path2__default.default.join(projectRoot, "features");
195
+ return path26__default.default.join(projectRoot, "features");
196
196
  }
197
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "src/features"))) {
198
- return path2__default.default.join(projectRoot, "src/features");
197
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/features"))) {
198
+ return path26__default.default.join(projectRoot, "src/features");
199
199
  }
200
- return path2__default.default.join(projectRoot, "features");
200
+ return path26__default.default.join(projectRoot, "features");
201
201
  }
202
202
  function getConfiguredSharedDir(projectRoot, flags) {
203
- if (flags?.target) return path2__default.default.resolve(projectRoot, flags.target);
204
- if (flags?.dest) return path2__default.default.resolve(projectRoot, flags.dest);
203
+ if (flags?.target) return path26__default.default.resolve(projectRoot, flags.target);
204
+ if (flags?.dest) return path26__default.default.resolve(projectRoot, flags.dest);
205
205
  const config = loadMasonConfig(projectRoot);
206
206
  if (config?.paths?.shared) {
207
- return path2__default.default.resolve(projectRoot, config.paths.shared);
207
+ return path26__default.default.resolve(projectRoot, config.paths.shared);
208
208
  }
209
209
  const mode = getEffectiveMode(projectRoot, flags);
210
210
  if (mode === "registry") {
211
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "src/shared"))) {
212
- return path2__default.default.join(projectRoot, "src/shared");
211
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/shared"))) {
212
+ return path26__default.default.join(projectRoot, "src/shared");
213
213
  }
214
- return path2__default.default.join(projectRoot, "shared");
214
+ return path26__default.default.join(projectRoot, "shared");
215
215
  }
216
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "src/shared"))) {
217
- return path2__default.default.join(projectRoot, "src/shared");
216
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/shared"))) {
217
+ return path26__default.default.join(projectRoot, "src/shared");
218
218
  }
219
- return path2__default.default.join(projectRoot, "shared");
219
+ return path26__default.default.join(projectRoot, "shared");
220
+ }
221
+ function loadLintConfig(projectRoot) {
222
+ const configPath = path26__default.default.join(projectRoot, "mason-lint.config.json");
223
+ if (fs17__default.default.existsSync(configPath)) {
224
+ try {
225
+ return JSON.parse(fs17__default.default.readFileSync(configPath, "utf-8"));
226
+ } catch {
227
+ }
228
+ }
229
+ return {};
230
+ }
231
+ function getResolvedLintPaths(projectRoot, config) {
232
+ const masonConfig = loadMasonConfig(projectRoot);
233
+ const configuredFeatures = config.paths?.features ?? masonConfig?.paths?.features;
234
+ const configuredShared = config.paths?.shared ?? masonConfig?.paths?.shared;
235
+ const configuredErrors = config.paths?.errors;
236
+ const resolveBase = (configuredPath, defaultSrc, defaultRoot) => {
237
+ if (configuredPath !== void 0) {
238
+ return path26__default.default.resolve(projectRoot, configuredPath);
239
+ }
240
+ const srcPath = path26__default.default.join(projectRoot, defaultSrc);
241
+ if (fs17__default.default.existsSync(srcPath)) return srcPath;
242
+ const rootPath = path26__default.default.join(projectRoot, defaultRoot);
243
+ if (fs17__default.default.existsSync(rootPath)) return rootPath;
244
+ return srcPath;
245
+ };
246
+ return {
247
+ featuresBase: resolveBase(configuredFeatures, "src/features", "features"),
248
+ sharedBase: resolveBase(configuredShared, "src/shared", "shared"),
249
+ errorsBase: resolveBase(configuredErrors, "src/errors", "errors")
250
+ };
220
251
  }
221
252
 
222
253
  // src/utils/project.ts
223
254
  function findProjectRoot(startDir = process.cwd()) {
224
- let current = path2__default.default.resolve(startDir);
255
+ let current = path26__default.default.resolve(startDir);
225
256
  while (true) {
226
- if (fs14__default.default.existsSync(path2__default.default.join(current, "package.json"))) {
257
+ if (fs17__default.default.existsSync(path26__default.default.join(current, "package.json"))) {
227
258
  return current;
228
259
  }
229
- const parent = path2__default.default.dirname(current);
260
+ const parent = path26__default.default.dirname(current);
230
261
  if (parent === current) {
231
- return path2__default.default.resolve(startDir);
262
+ return path26__default.default.resolve(startDir);
232
263
  }
233
264
  current = parent;
234
265
  }
@@ -241,9 +272,9 @@ function resolveSharedDir(projectRoot, flags) {
241
272
  }
242
273
  function listExistingFeatures(projectRoot) {
243
274
  const featuresDir = resolveFeaturesDir(projectRoot);
244
- if (!fs14__default.default.existsSync(featuresDir)) return [];
275
+ if (!fs17__default.default.existsSync(featuresDir)) return [];
245
276
  try {
246
- const entries = fs14__default.default.readdirSync(featuresDir, { withFileTypes: true });
277
+ const entries = fs17__default.default.readdirSync(featuresDir, { withFileTypes: true });
247
278
  return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
248
279
  } catch {
249
280
  return [];
@@ -253,14 +284,14 @@ function listDomainInterfaces(projectRoot, featureName) {
253
284
  const results = [];
254
285
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
255
286
  for (const feat of features) {
256
- const domainDir = path2__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
257
- if (!fs14__default.default.existsSync(domainDir)) continue;
287
+ const domainDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
288
+ if (!fs17__default.default.existsSync(domainDir)) continue;
258
289
  try {
259
- const files = fs14__default.default.readdirSync(domainDir);
290
+ const files = fs17__default.default.readdirSync(domainDir);
260
291
  for (const file of files) {
261
292
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
262
293
  const name = file.replace(/\.ts$/, "");
263
- const fullPath = path2__default.default.join(domainDir, file);
294
+ const fullPath = path26__default.default.join(domainDir, file);
264
295
  if (/^I[A-Z]/.test(name)) {
265
296
  results.push({
266
297
  name,
@@ -269,7 +300,7 @@ function listDomainInterfaces(projectRoot, featureName) {
269
300
  });
270
301
  } else {
271
302
  try {
272
- const content = fs14__default.default.readFileSync(fullPath, "utf-8");
303
+ const content = fs17__default.default.readFileSync(fullPath, "utf-8");
273
304
  if (/export\s+(?:abstract\s+class|interface)\s+(\w+)/.test(content)) {
274
305
  results.push({
275
306
  name,
@@ -291,17 +322,17 @@ function listDomainEntities(projectRoot, featureName) {
291
322
  const results = [];
292
323
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
293
324
  for (const feat of features) {
294
- const domainDir = path2__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
295
- if (!fs14__default.default.existsSync(domainDir)) continue;
325
+ const domainDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
326
+ if (!fs17__default.default.existsSync(domainDir)) continue;
296
327
  try {
297
- const files = fs14__default.default.readdirSync(domainDir);
328
+ const files = fs17__default.default.readdirSync(domainDir);
298
329
  for (const file of files) {
299
330
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
300
331
  const name = file.replace(/\.ts$/, "");
301
332
  if (!/^I[A-Z]/.test(name)) {
302
333
  results.push({
303
334
  name,
304
- fullPath: path2__default.default.join(domainDir, file),
335
+ fullPath: path26__default.default.join(domainDir, file),
305
336
  feature: feat
306
337
  });
307
338
  }
@@ -316,16 +347,16 @@ function listUseCases(projectRoot, featureName) {
316
347
  const results = [];
317
348
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
318
349
  for (const feat of features) {
319
- const useCasesDir = path2__default.default.join(resolveFeaturesDir(projectRoot), feat, "useCases");
320
- if (!fs14__default.default.existsSync(useCasesDir)) continue;
350
+ const useCasesDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "useCases");
351
+ if (!fs17__default.default.existsSync(useCasesDir)) continue;
321
352
  try {
322
- const files = fs14__default.default.readdirSync(useCasesDir);
353
+ const files = fs17__default.default.readdirSync(useCasesDir);
323
354
  for (const file of files) {
324
355
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
325
356
  const name = file.replace(/\.ts$/, "");
326
357
  results.push({
327
358
  name,
328
- fullPath: path2__default.default.join(useCasesDir, file),
359
+ fullPath: path26__default.default.join(useCasesDir, file),
329
360
  feature: feat
330
361
  });
331
362
  }
@@ -351,33 +382,33 @@ hbs.registerHelper("join", (arr, sep) => {
351
382
  });
352
383
  var cachedTemplatesDir = null;
353
384
  function getTemplatesDir() {
354
- if (cachedTemplatesDir && fs14__default.default.existsSync(cachedTemplatesDir)) {
385
+ if (cachedTemplatesDir && fs17__default.default.existsSync(cachedTemplatesDir)) {
355
386
  return cachedTemplatesDir;
356
387
  }
357
- const currentDir = typeof __dirname !== "undefined" ? __dirname : path2__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bin.cjs', document.baseURI).href))));
358
- const cand1 = path2__default.default.resolve(currentDir, "../../templates");
359
- if (fs14__default.default.existsSync(cand1)) {
388
+ const currentDir = typeof __dirname !== "undefined" ? __dirname : path26__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bin.cjs', document.baseURI).href))));
389
+ const cand1 = path26__default.default.resolve(currentDir, "../../templates");
390
+ if (fs17__default.default.existsSync(cand1)) {
360
391
  cachedTemplatesDir = cand1;
361
392
  return cand1;
362
393
  }
363
- const cand2 = path2__default.default.resolve(currentDir, "../templates");
364
- if (fs14__default.default.existsSync(cand2)) {
394
+ const cand2 = path26__default.default.resolve(currentDir, "../templates");
395
+ if (fs17__default.default.existsSync(cand2)) {
365
396
  cachedTemplatesDir = cand2;
366
397
  return cand2;
367
398
  }
368
- const cand3 = path2__default.default.resolve(currentDir, "templates");
369
- if (fs14__default.default.existsSync(cand3)) {
399
+ const cand3 = path26__default.default.resolve(currentDir, "templates");
400
+ if (fs17__default.default.existsSync(cand3)) {
370
401
  cachedTemplatesDir = cand3;
371
402
  return cand3;
372
403
  }
373
404
  let curr = currentDir;
374
405
  while (true) {
375
- const candTemplates = path2__default.default.join(curr, "templates");
376
- if (fs14__default.default.existsSync(candTemplates)) {
406
+ const candTemplates = path26__default.default.join(curr, "templates");
407
+ if (fs17__default.default.existsSync(candTemplates)) {
377
408
  cachedTemplatesDir = candTemplates;
378
409
  return candTemplates;
379
410
  }
380
- const parent = path2__default.default.dirname(curr);
411
+ const parent = path26__default.default.dirname(curr);
381
412
  if (parent === curr) break;
382
413
  curr = parent;
383
414
  }
@@ -385,8 +416,8 @@ function getTemplatesDir() {
385
416
  }
386
417
  var templateCache = /* @__PURE__ */ new Map();
387
418
  function loadTemplate(relativePath) {
388
- const fullPath = path2__default.default.isAbsolute(relativePath) ? relativePath : path2__default.default.join(getTemplatesDir(), relativePath);
389
- return fs14__default.default.readFileSync(fullPath, "utf-8");
419
+ const fullPath = path26__default.default.isAbsolute(relativePath) ? relativePath : path26__default.default.join(getTemplatesDir(), relativePath);
420
+ return fs17__default.default.readFileSync(fullPath, "utf-8");
390
421
  }
391
422
  function renderTemplateFile(relativePath, context) {
392
423
  let compiled = templateCache.get(relativePath);
@@ -473,8 +504,8 @@ function generateDomainEntityCode(name, kind = "interface", properties = []) {
473
504
  function generateDomain(options) {
474
505
  const projectRoot = options.projectRoot || findProjectRoot();
475
506
  const entityName = toPascalCase(options.name);
476
- const targetDir = options.targetDir || path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
477
- const filePath = path2__default.default.join(targetDir, `${entityName}.ts`);
507
+ const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
508
+ const filePath = path26__default.default.join(targetDir, `${entityName}.ts`);
478
509
  const code = generateDomainEntityCode(
479
510
  entityName,
480
511
  options.kind || "interface",
@@ -523,8 +554,8 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
523
554
  function generateInterface(options) {
524
555
  const projectRoot = options.projectRoot || findProjectRoot();
525
556
  const ifaceName = ensureInterfacePrefix(options.name);
526
- const targetDir = options.targetDir || path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
527
- const filePath = path2__default.default.join(targetDir, `${ifaceName}.ts`);
557
+ const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
558
+ const filePath = path26__default.default.join(targetDir, `${ifaceName}.ts`);
528
559
  const code = generateInterfaceCode(
529
560
  ifaceName,
530
561
  options.kind || "abstractClass",
@@ -759,7 +790,7 @@ function parseInterfaceMethodsAndImports(content, targetIfaceName) {
759
790
  };
760
791
  }
761
792
  function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
762
- if (customPath && fs14__default.default.existsSync(customPath)) {
793
+ if (customPath && fs17__default.default.existsSync(customPath)) {
763
794
  return { filePath: customPath, ifaceName };
764
795
  }
765
796
  const candidateNames = [
@@ -769,22 +800,22 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
769
800
  ];
770
801
  const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
771
802
  for (const feat of features) {
772
- const domainDir = path2__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
773
- if (!fs14__default.default.existsSync(domainDir)) continue;
803
+ const domainDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
804
+ if (!fs17__default.default.existsSync(domainDir)) continue;
774
805
  for (const cand of candidateNames) {
775
- const p1 = path2__default.default.join(domainDir, `${cand}.ts`);
776
- if (fs14__default.default.existsSync(p1)) {
806
+ const p1 = path26__default.default.join(domainDir, `${cand}.ts`);
807
+ if (fs17__default.default.existsSync(p1)) {
777
808
  return { filePath: p1, ifaceName: cand, feature: feat };
778
809
  }
779
810
  }
780
811
  }
781
812
  for (const cand of candidateNames) {
782
- const p1 = path2__default.default.join(projectRoot, "domain", `${cand}.ts`);
783
- if (fs14__default.default.existsSync(p1)) return { filePath: p1, ifaceName: cand };
784
- const p22 = path2__default.default.join(projectRoot, "src", "domain", `${cand}.ts`);
785
- if (fs14__default.default.existsSync(p22)) return { filePath: p22, ifaceName: cand };
786
- const p32 = path2__default.default.join(projectRoot, "interfaces", `${cand}.ts`);
787
- if (fs14__default.default.existsSync(p32)) return { filePath: p32, ifaceName: cand };
813
+ const p1 = path26__default.default.join(projectRoot, "domain", `${cand}.ts`);
814
+ if (fs17__default.default.existsSync(p1)) return { filePath: p1, ifaceName: cand };
815
+ const p22 = path26__default.default.join(projectRoot, "src", "domain", `${cand}.ts`);
816
+ if (fs17__default.default.existsSync(p22)) return { filePath: p22, ifaceName: cand };
817
+ const p32 = path26__default.default.join(projectRoot, "interfaces", `${cand}.ts`);
818
+ if (fs17__default.default.existsSync(p32)) return { filePath: p32, ifaceName: cand };
788
819
  }
789
820
  return null;
790
821
  }
@@ -807,7 +838,7 @@ function loadInterfaceHierarchy(projectRoot, initialIfaceName, featureName, cust
807
838
  while (currentFile && !visited.has(currentFile)) {
808
839
  visited.add(currentFile);
809
840
  try {
810
- const content = fs14__default.default.readFileSync(currentFile, "utf-8");
841
+ const content = fs17__default.default.readFileSync(currentFile, "utf-8");
811
842
  const parsed = parseInterfaceMethodsAndImports(content, currentName);
812
843
  for (const m of parsed.methods) {
813
844
  if (!allMethods.some((existing) => existing.name === m.name)) {
@@ -883,7 +914,7 @@ function generateStubCode(stubClassName, ifaceName, entityName, featureName, met
883
914
  const entitiesVar = `${entityVar}s`;
884
915
  const idKey = `${entityVar}Id`;
885
916
  const impPath = ifaceImportPath || `../domain/${ifaceName}.js`;
886
- const entityImportPath = ifaceImportPath ? `${path2__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
917
+ const entityImportPath = ifaceImportPath ? `${path26__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
887
918
  const importsByFrom = /* @__PURE__ */ new Map();
888
919
  for (const imp of domainImports) {
889
920
  if (imp.name === ifaceName || imp.name === baseEntity) continue;
@@ -932,7 +963,7 @@ function generateConcreteInfraCode(className, ifaceName, dependencies = [], meth
932
963
  if (baseEntity) {
933
964
  finalMethods = synthesizeCrudMethods(baseEntity);
934
965
  if (!finalDomainImports.some((imp) => imp.name === baseEntity)) {
935
- const importPath = ifaceImportPath ? `${path2__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
966
+ const importPath = ifaceImportPath ? `${path26__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
936
967
  finalDomainImports.push({
937
968
  name: baseEntity,
938
969
  from: importPath,
@@ -977,8 +1008,8 @@ function generateInfrastructure(options) {
977
1008
  const projectRoot = options.projectRoot || findProjectRoot();
978
1009
  const className = toPascalCase(options.name);
979
1010
  const isFeatureScope = options.scope !== "global" && Boolean(options.feature);
980
- const targetDir = options.targetDir || (isFeatureScope ? path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path2__default.default.join(projectRoot, "infrastructure"));
981
- const filePath = path2__default.default.join(targetDir, `${className}.ts`);
1011
+ const targetDir = options.targetDir || (isFeatureScope ? path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path26__default.default.join(projectRoot, "infrastructure"));
1012
+ const filePath = path26__default.default.join(targetDir, `${className}.ts`);
982
1013
  let code;
983
1014
  if (options.implementsInterface) {
984
1015
  const rawIfaceName = options.implementsInterface;
@@ -992,7 +1023,7 @@ function generateInfrastructure(options) {
992
1023
  const ifaceFilePath = hierarchy.ifaceFilePath;
993
1024
  let ifaceImportPath;
994
1025
  if (ifaceFilePath) {
995
- let rel = path2__default.default.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
1026
+ let rel = path26__default.default.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
996
1027
  if (!rel.startsWith(".")) rel = "./" + rel;
997
1028
  ifaceImportPath = rel;
998
1029
  } else if (isFeatureScope) {
@@ -1005,8 +1036,8 @@ function generateInfrastructure(options) {
1005
1036
  if (new RegExp(`\\b${item.name}\\b`).test(allSignatures)) {
1006
1037
  let fromPath;
1007
1038
  if (imp.specifier.startsWith(".") && ifaceFilePath) {
1008
- const absTarget = path2__default.default.resolve(path2__default.default.dirname(ifaceFilePath), imp.specifier);
1009
- let rel = path2__default.default.relative(targetDir, absTarget).replace(/\\/g, "/");
1039
+ const absTarget = path26__default.default.resolve(path26__default.default.dirname(ifaceFilePath), imp.specifier);
1040
+ let rel = path26__default.default.relative(targetDir, absTarget).replace(/\\/g, "/");
1010
1041
  if (!rel.startsWith(".")) rel = "./" + rel;
1011
1042
  fromPath = rel;
1012
1043
  } else {
@@ -1193,8 +1224,8 @@ function generateUseCase(options) {
1193
1224
  const files = [];
1194
1225
  const projectRoot = options.projectRoot || findProjectRoot();
1195
1226
  const ucName = toPascalCase(options.name);
1196
- const targetDir = options.targetDir || path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1197
- const filePath = path2__default.default.join(targetDir, `${ucName}.ts`);
1227
+ const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1228
+ const filePath = path26__default.default.join(targetDir, `${ucName}.ts`);
1198
1229
  const code = generateUseCaseCode(
1199
1230
  ucName,
1200
1231
  options.dependencies || [],
@@ -1210,7 +1241,7 @@ function generateUseCase(options) {
1210
1241
  })
1211
1242
  );
1212
1243
  if (options.includeTest) {
1213
- const testPath = path2__default.default.join(targetDir, `${ucName}.test.ts`);
1244
+ const testPath = path26__default.default.join(targetDir, `${ucName}.test.ts`);
1214
1245
  const testCode = generateUseCaseTestCode(ucName, options.dependencies || []);
1215
1246
  files.push(
1216
1247
  writeFileSafely(testPath, testCode, {
@@ -1278,10 +1309,10 @@ function generateHttpHandler(options) {
1278
1309
  const files = [];
1279
1310
  const projectRoot = options.projectRoot || findProjectRoot();
1280
1311
  const className = toPascalCase(options.name);
1281
- const pxDir = path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1282
- const handlersDir = path2__default.default.join(pxDir, "handlers");
1283
- const pxIndexPath = path2__default.default.join(pxDir, "index.ts");
1284
- if (!fs14__default.default.existsSync(pxIndexPath)) {
1312
+ const pxDir = path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1313
+ const handlersDir = path26__default.default.join(pxDir, "handlers");
1314
+ const pxIndexPath = path26__default.default.join(pxDir, "index.ts");
1315
+ if (!fs17__default.default.existsSync(pxIndexPath)) {
1285
1316
  const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
1286
1317
  const pxIndexContent = renderTemplate(expressIndexTemplate, {
1287
1318
  routePath: featurePath
@@ -1294,7 +1325,7 @@ function generateHttpHandler(options) {
1294
1325
  })
1295
1326
  );
1296
1327
  }
1297
- const handlerFilePath = path2__default.default.join(handlersDir, `${className}.ts`);
1328
+ const handlerFilePath = path26__default.default.join(handlersDir, `${className}.ts`);
1298
1329
  const code = generateHttpHandlerCode(
1299
1330
  className,
1300
1331
  options.method || "get",
@@ -1315,11 +1346,11 @@ function generateHttpHandler(options) {
1315
1346
  return files;
1316
1347
  }
1317
1348
  function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], options = {}) {
1318
- const providerPath = path2__default.default.join(featureDir, "diProvider.ts");
1349
+ const providerPath = path26__default.default.join(featureDir, "diProvider.ts");
1319
1350
  const pascalFeature = toPascalCase(featureName);
1320
1351
  const providerModuleName = `${pascalFeature}Provider`;
1321
- if (fs14__default.default.existsSync(providerPath) && !options.overwrite) {
1322
- let content = fs14__default.default.readFileSync(providerPath, "utf-8");
1352
+ if (fs17__default.default.existsSync(providerPath) && !options.overwrite) {
1353
+ let content = fs17__default.default.readFileSync(providerPath, "utf-8");
1323
1354
  content = content.replace(/\n*export\s+const\s+ScaffoldProvider\s*=[^;]+;?/g, "");
1324
1355
  for (const b of bindings) {
1325
1356
  const ifaceImp = b.ifaceImportPath || `./domain/${b.ifaceName}.js`;
@@ -1378,7 +1409,7 @@ function generateFeature(options) {
1378
1409
  const projectRoot = options.projectRoot || findProjectRoot();
1379
1410
  const rawName = options.name.trim();
1380
1411
  const featureName = toCamelCase(rawName);
1381
- const targetDir = options.targetDir || path2__default.default.join(resolveFeaturesDir(projectRoot), featureName);
1412
+ const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), featureName);
1382
1413
  const routePath = options.routePath || `/${featureName}`;
1383
1414
  const rawEntities = [];
1384
1415
  if (options.entityNames && options.entityNames.length > 0) {
@@ -1399,7 +1430,7 @@ function generateFeature(options) {
1399
1430
  const domainFile = generateDomain({
1400
1431
  name: ent,
1401
1432
  feature: featureName,
1402
- targetDir: path2__default.default.join(targetDir, "domain"),
1433
+ targetDir: path26__default.default.join(targetDir, "domain"),
1403
1434
  projectRoot,
1404
1435
  dryRun: options.dryRun,
1405
1436
  overwrite: options.overwrite,
@@ -1419,7 +1450,7 @@ function generateFeature(options) {
1419
1450
  const ifaceFile = generateInterface({
1420
1451
  name: ifaceName,
1421
1452
  feature: featureName,
1422
- targetDir: path2__default.default.join(targetDir, "domain"),
1453
+ targetDir: path26__default.default.join(targetDir, "domain"),
1423
1454
  entityName: ent,
1424
1455
  projectRoot,
1425
1456
  dryRun: options.dryRun,
@@ -1436,7 +1467,7 @@ function generateFeature(options) {
1436
1467
  const stubFile = generateInfrastructure({
1437
1468
  name: stubName,
1438
1469
  feature: featureName,
1439
- targetDir: path2__default.default.join(targetDir, "infrastructure"),
1470
+ targetDir: path26__default.default.join(targetDir, "infrastructure"),
1440
1471
  kind: "stub",
1441
1472
  implementsInterface: ifaceName,
1442
1473
  entityName: ent,
@@ -1478,7 +1509,7 @@ function generateFeature(options) {
1478
1509
  const ucFiles = generateUseCase({
1479
1510
  name: ucName,
1480
1511
  feature: featureName,
1481
- targetDir: path2__default.default.join(targetDir, "useCases"),
1512
+ targetDir: path26__default.default.join(targetDir, "useCases"),
1482
1513
  dependencies: options.includeInterface !== false ? [ifaceName] : [],
1483
1514
  inputProperties: [{ name: idParam, type: "string" }],
1484
1515
  outputProperties: [{ name: entVar, type: primaryEntity }],
@@ -1523,7 +1554,7 @@ function generateFeature(options) {
1523
1554
  const ucFiles = generateUseCase({
1524
1555
  name: ucName,
1525
1556
  feature: featureName,
1526
- targetDir: path2__default.default.join(targetDir, "useCases"),
1557
+ targetDir: path26__default.default.join(targetDir, "useCases"),
1527
1558
  dependencies: deps,
1528
1559
  inputProperties: [{ name: entVar, type: ent }],
1529
1560
  outputProperties: [{ name: entVar, type: ent }],
@@ -1556,7 +1587,7 @@ function generateFeature(options) {
1556
1587
  const ucFiles = generateUseCase({
1557
1588
  name: ucName,
1558
1589
  feature: featureName,
1559
- targetDir: path2__default.default.join(targetDir, "useCases"),
1590
+ targetDir: path26__default.default.join(targetDir, "useCases"),
1560
1591
  dependencies: deps,
1561
1592
  inputProperties: [{ name: idParam, type: "string" }],
1562
1593
  outputProperties: [{ name: entVar, type: ent }],
@@ -1589,7 +1620,7 @@ function generateFeature(options) {
1589
1620
  const ucFiles = generateUseCase({
1590
1621
  name: ucName,
1591
1622
  feature: featureName,
1592
- targetDir: path2__default.default.join(targetDir, "useCases"),
1623
+ targetDir: path26__default.default.join(targetDir, "useCases"),
1593
1624
  dependencies: deps,
1594
1625
  inputProperties: [
1595
1626
  { name: "page", type: "number", optional: true },
@@ -1633,7 +1664,7 @@ function generateFeature(options) {
1633
1664
  const ucFiles = generateUseCase({
1634
1665
  name: ucName,
1635
1666
  feature: featureName,
1636
- targetDir: path2__default.default.join(targetDir, "useCases"),
1667
+ targetDir: path26__default.default.join(targetDir, "useCases"),
1637
1668
  dependencies: deps,
1638
1669
  inputProperties: [{ name: entVar, type: ent }],
1639
1670
  outputProperties: [{ name: entVar, type: ent }],
@@ -1666,7 +1697,7 @@ function generateFeature(options) {
1666
1697
  const ucFiles = generateUseCase({
1667
1698
  name: ucName,
1668
1699
  feature: featureName,
1669
- targetDir: path2__default.default.join(targetDir, "useCases"),
1700
+ targetDir: path26__default.default.join(targetDir, "useCases"),
1670
1701
  dependencies: deps,
1671
1702
  inputProperties: [{ name: idParam, type: "string" }],
1672
1703
  outputProperties: [{ name: "success", type: "boolean" }],
@@ -1703,7 +1734,7 @@ function generateFeature(options) {
1703
1734
  const ucFiles = generateUseCase({
1704
1735
  name: ucName,
1705
1736
  feature: featureName,
1706
- targetDir: path2__default.default.join(targetDir, "useCases"),
1737
+ targetDir: path26__default.default.join(targetDir, "useCases"),
1707
1738
  dependencies: customUc.dependencies || [],
1708
1739
  inputProperties: customUc.inputProperties || [],
1709
1740
  outputProperties: customUc.outputProperties || [],
@@ -1735,8 +1766,8 @@ function generateFeature(options) {
1735
1766
  }
1736
1767
  }
1737
1768
  if (options.includeExpress !== false) {
1738
- const pxDir = path2__default.default.join(targetDir, "pxExpress");
1739
- const pxIndexPath = path2__default.default.join(pxDir, "index.ts");
1769
+ const pxDir = path26__default.default.join(targetDir, "pxExpress");
1770
+ const pxIndexPath = path26__default.default.join(pxDir, "index.ts");
1740
1771
  if (!files.some((f) => f.absolutePath === pxIndexPath)) {
1741
1772
  const pxIndexContent = renderTemplate(expressIndexTemplate, { routePath });
1742
1773
  files.push(
@@ -1866,7 +1897,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1866
1897
  }
1867
1898
  const normalizedName = toCamelCase(name);
1868
1899
  const baseFeaturesDir = resolveFeaturesDir(projectRoot, flags);
1869
- const defaultDir = path2__default.default.relative(projectRoot, path2__default.default.join(baseFeaturesDir, normalizedName));
1900
+ const defaultDir = path26__default.default.relative(projectRoot, path26__default.default.join(baseFeaturesDir, normalizedName));
1870
1901
  let targetDirRel = defaultDir;
1871
1902
  if (!flags.yes && !flags.target && !flags.dest) {
1872
1903
  targetDirRel = handleCancel(
@@ -1877,7 +1908,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1877
1908
  })
1878
1909
  ).trim();
1879
1910
  }
1880
- const targetDir = flags.dest ? path2__default.default.resolve(projectRoot, flags.dest) : flags.target ? path2__default.default.resolve(projectRoot, flags.target) : path2__default.default.resolve(projectRoot, targetDirRel);
1911
+ const targetDir = flags.dest ? path26__default.default.resolve(projectRoot, flags.dest) : flags.target ? path26__default.default.resolve(projectRoot, flags.target) : path26__default.default.resolve(projectRoot, targetDirRel);
1881
1912
  let includeExpress = flags.express !== void 0 ? Boolean(flags.express) : true;
1882
1913
  let routePath = `/${normalizedName}`;
1883
1914
  let includeDomain = true;
@@ -2119,8 +2150,8 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2119
2150
  };
2120
2151
  const files = generateFeature(options);
2121
2152
  if (isRegistry) {
2122
- const registryPath = path2__default.default.join(targetDir, "registry.json");
2123
- if (!fs14__default.default.existsSync(registryPath)) {
2153
+ const registryPath = path26__default.default.join(targetDir, "registry.json");
2154
+ if (!fs17__default.default.existsSync(registryPath)) {
2124
2155
  const manifest = {
2125
2156
  name: toKebabCase(normalizedName),
2126
2157
  type: "feature",
@@ -2146,7 +2177,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2146
2177
  printGeneratedFiles(files, options.dryRun);
2147
2178
  p19__namespace.outro(
2148
2179
  pc13__default.default.green(
2149
- `\u2713 Feature '${normalizedName}' initialized in ${path2__default.default.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2180
+ `\u2713 Feature '${normalizedName}' initialized in ${path26__default.default.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2150
2181
  )
2151
2182
  );
2152
2183
  }
@@ -2157,7 +2188,7 @@ function generateShared(options) {
2157
2188
  const pascalName = toPascalCase(rawName);
2158
2189
  const camelName = toCamelCase(rawName);
2159
2190
  const kebabName = toKebabCase(rawName);
2160
- const targetDir = options.targetDir || path2__default.default.join(resolveSharedDir(projectRoot), kebabName);
2191
+ const targetDir = options.targetDir || path26__default.default.join(resolveSharedDir(projectRoot), kebabName);
2161
2192
  const fileDefs = [];
2162
2193
  const facadeContent = `import { MakeInjectable, type DepsType } from "@solid-stack/di";
2163
2194
  import { I${pascalName}Engine } from "./ports/I${pascalName}Engine.js";
@@ -2169,7 +2200,7 @@ export class ${pascalName} {
2169
2200
  }
2170
2201
  `;
2171
2202
  fileDefs.push({
2172
- absolutePath: path2__default.default.join(targetDir, `${pascalName}.ts`),
2203
+ absolutePath: path26__default.default.join(targetDir, `${pascalName}.ts`),
2173
2204
  content: facadeContent
2174
2205
  });
2175
2206
  const portContent = `export abstract class I${pascalName}Engine {
@@ -2177,7 +2208,7 @@ export class ${pascalName} {
2177
2208
  }
2178
2209
  `;
2179
2210
  fileDefs.push({
2180
- absolutePath: path2__default.default.join(targetDir, "ports", `I${pascalName}Engine.ts`),
2211
+ absolutePath: path26__default.default.join(targetDir, "ports", `I${pascalName}Engine.ts`),
2181
2212
  content: portContent
2182
2213
  });
2183
2214
  const concreteContent = `import { MakeInjectable } from "@solid-stack/di";
@@ -2189,7 +2220,7 @@ export class Default${pascalName}Engine implements I${pascalName}Engine {
2189
2220
  }
2190
2221
  `;
2191
2222
  fileDefs.push({
2192
- absolutePath: path2__default.default.join(targetDir, "infrastructure", `Default${pascalName}Engine.ts`),
2223
+ absolutePath: path26__default.default.join(targetDir, "infrastructure", `Default${pascalName}Engine.ts`),
2193
2224
  content: concreteContent
2194
2225
  });
2195
2226
  if (options.includeStub !== false) {
@@ -2202,7 +2233,7 @@ export class Stub${pascalName}Engine implements I${pascalName}Engine {
2202
2233
  }
2203
2234
  `;
2204
2235
  fileDefs.push({
2205
- absolutePath: path2__default.default.join(targetDir, "infrastructure", `Stub${pascalName}Engine.ts`),
2236
+ absolutePath: path26__default.default.join(targetDir, "infrastructure", `Stub${pascalName}Engine.ts`),
2206
2237
  content: stubContent
2207
2238
  });
2208
2239
  }
@@ -2217,7 +2248,7 @@ export const diProvider = (c: Container): void => {
2217
2248
  export default diProvider;
2218
2249
  `;
2219
2250
  fileDefs.push({
2220
- absolutePath: path2__default.default.join(targetDir, "diProvider.ts"),
2251
+ absolutePath: path26__default.default.join(targetDir, "diProvider.ts"),
2221
2252
  content: providerContent
2222
2253
  });
2223
2254
  if (options.isRegistry) {
@@ -2234,7 +2265,7 @@ export default diProvider;
2234
2265
  files: []
2235
2266
  };
2236
2267
  fileDefs.push({
2237
- absolutePath: path2__default.default.join(targetDir, "registry.json"),
2268
+ absolutePath: path26__default.default.join(targetDir, "registry.json"),
2238
2269
  content: JSON.stringify(registryManifest, null, 2) + "\n"
2239
2270
  });
2240
2271
  }
@@ -2271,7 +2302,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2271
2302
  }
2272
2303
  const normalizedName = toKebabCase(name);
2273
2304
  const baseSharedDir = resolveSharedDir(projectRoot, flags);
2274
- const defaultDir = path2__default.default.relative(projectRoot, path2__default.default.join(baseSharedDir, normalizedName));
2305
+ const defaultDir = path26__default.default.relative(projectRoot, path26__default.default.join(baseSharedDir, normalizedName));
2275
2306
  let targetDirRel = defaultDir;
2276
2307
  if (!flags.yes && !flags.target && !flags.dest) {
2277
2308
  targetDirRel = handleCancel(
@@ -2282,7 +2313,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2282
2313
  })
2283
2314
  ).trim();
2284
2315
  }
2285
- const targetDir = flags.dest ? path2__default.default.resolve(projectRoot, flags.dest) : flags.target ? path2__default.default.resolve(projectRoot, flags.target) : path2__default.default.resolve(projectRoot, targetDirRel);
2316
+ const targetDir = flags.dest ? path26__default.default.resolve(projectRoot, flags.dest) : flags.target ? path26__default.default.resolve(projectRoot, flags.target) : path26__default.default.resolve(projectRoot, targetDirRel);
2286
2317
  let description = flags.description || "";
2287
2318
  let includeStub = true;
2288
2319
  if (!flags.yes) {
@@ -2316,7 +2347,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2316
2347
  printGeneratedFiles(files, Boolean(flags.dryRun));
2317
2348
  p19__namespace.outro(
2318
2349
  pc13__default.default.green(
2319
- `\u2713 Shared module '${normalizedName}' initialized in ${path2__default.default.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2350
+ `\u2713 Shared module '${normalizedName}' initialized in ${path26__default.default.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2320
2351
  )
2321
2352
  );
2322
2353
  }
@@ -2743,7 +2774,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2743
2774
  const infraFile = generateInfrastructure(options);
2744
2775
  files.push(infraFile);
2745
2776
  if (registerInProvider && scope === "feature" && feature && implementsInterface) {
2746
- const featureDir = path2__default.default.join(resolveFeaturesDir(projectRoot), feature);
2777
+ const featureDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feature);
2747
2778
  const providerFile = updateOrGenerateDiProvider(
2748
2779
  featureDir,
2749
2780
  feature,
@@ -2905,7 +2936,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
2905
2936
  files.push(stubFile);
2906
2937
  }
2907
2938
  if (registerInProvider && generateStub) {
2908
- const featureDir = path2__default.default.join(resolveFeaturesDir(projectRoot), feature);
2939
+ const featureDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feature);
2909
2940
  const providerFile = updateOrGenerateDiProvider(
2910
2941
  featureDir,
2911
2942
  feature,
@@ -3093,21 +3124,21 @@ function generateInjectable(options) {
3093
3124
  const className = toPascalCase(options.name);
3094
3125
  let targetDir = "";
3095
3126
  if (options.customPath) {
3096
- targetDir = path2__default.default.isAbsolute(options.customPath) ? options.customPath : path2__default.default.join(projectRoot, options.customPath);
3127
+ targetDir = path26__default.default.isAbsolute(options.customPath) ? options.customPath : path26__default.default.join(projectRoot, options.customPath);
3097
3128
  } else if (options.location === "feature-service" && options.feature) {
3098
- targetDir = path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services");
3129
+ targetDir = path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services");
3099
3130
  } else if (options.location === "feature-transformer" && options.feature) {
3100
- targetDir = path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
3131
+ targetDir = path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
3101
3132
  } else if (options.location === "module") {
3102
- targetDir = path2__default.default.join(projectRoot, "modules", className);
3133
+ targetDir = path26__default.default.join(projectRoot, "modules", className);
3103
3134
  } else {
3104
- targetDir = options.feature ? path2__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path2__default.default.join(projectRoot, "shared", className.toLowerCase());
3135
+ targetDir = options.feature ? path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path26__default.default.join(projectRoot, "shared", className.toLowerCase());
3105
3136
  }
3106
- const filePath = path2__default.default.join(targetDir, `${className}.ts`);
3137
+ const filePath = path26__default.default.join(targetDir, `${className}.ts`);
3107
3138
  let ifaceName;
3108
3139
  if (options.generateInterface) {
3109
3140
  ifaceName = `I${className}`;
3110
- const ifacePath = path2__default.default.join(targetDir, `${ifaceName}.ts`);
3141
+ const ifacePath = path26__default.default.join(targetDir, `${ifaceName}.ts`);
3111
3142
  const ifaceContent = renderTemplate(injectableInterfaceTemplate, { ifaceName });
3112
3143
  files.push(
3113
3144
  writeFileSafely(ifacePath, ifaceContent, {
@@ -3236,7 +3267,7 @@ async function runEnvInit(flags = {}) {
3236
3267
  const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
3237
3268
  const s = p19__namespace.spinner();
3238
3269
  s.start("Scanning for .example environment files...");
3239
- const files = fs14__default.default.readdirSync(projectRoot);
3270
+ const files = fs17__default.default.readdirSync(projectRoot);
3240
3271
  const exampleFiles = files.filter((file) => file.startsWith(".env") && file.endsWith(".example")).sort();
3241
3272
  if (exampleFiles.length === 0) {
3242
3273
  s.stop("No .example files found.");
@@ -3246,11 +3277,11 @@ async function runEnvInit(flags = {}) {
3246
3277
  s.message(`Found ${exampleFiles.length} template(s). Generating...`);
3247
3278
  const generatedFiles = [];
3248
3279
  for (const exampleFile of exampleFiles) {
3249
- const sourcePath = path2__default.default.join(projectRoot, exampleFile);
3280
+ const sourcePath = path26__default.default.join(projectRoot, exampleFile);
3250
3281
  const targetFile = exampleFile.replace(/\.example$/, "");
3251
- const targetPath = path2__default.default.join(projectRoot, targetFile);
3282
+ const targetPath = path26__default.default.join(projectRoot, targetFile);
3252
3283
  let overwrite = flags.overwrite;
3253
- if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs14__default.default.existsSync(targetPath)) {
3284
+ if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17__default.default.existsSync(targetPath)) {
3254
3285
  overwrite = await p19__namespace.confirm({
3255
3286
  message: `${targetFile} already exists. Overwrite?`,
3256
3287
  initialValue: false
@@ -3260,7 +3291,7 @@ async function runEnvInit(flags = {}) {
3260
3291
  process.exit(0);
3261
3292
  }
3262
3293
  }
3263
- const content = fs14__default.default.readFileSync(sourcePath, "utf-8");
3294
+ const content = fs17__default.default.readFileSync(sourcePath, "utf-8");
3264
3295
  const genFile = writeFileSafely(targetPath, content, {
3265
3296
  projectRoot,
3266
3297
  dryRun: Boolean(flags.dryRun),
@@ -3278,7 +3309,7 @@ var EnvEditor = class {
3278
3309
  filePath;
3279
3310
  constructor(filePath) {
3280
3311
  this.filePath = filePath;
3281
- this.lines = fs14__default.default.existsSync(filePath) ? fs14__default.default.readFileSync(filePath, "utf-8").split(/\r?\n/) : [];
3312
+ this.lines = fs17__default.default.existsSync(filePath) ? fs17__default.default.readFileSync(filePath, "utf-8").split(/\r?\n/) : [];
3282
3313
  }
3283
3314
  getLines() {
3284
3315
  return [...this.lines];
@@ -3342,18 +3373,18 @@ var EnvEditor = class {
3342
3373
  });
3343
3374
  }
3344
3375
  save() {
3345
- const dir = path2__default.default.dirname(this.filePath);
3346
- if (!fs14__default.default.existsSync(dir)) {
3347
- fs14__default.default.mkdirSync(dir, { recursive: true });
3376
+ const dir = path26__default.default.dirname(this.filePath);
3377
+ if (!fs17__default.default.existsSync(dir)) {
3378
+ fs17__default.default.mkdirSync(dir, { recursive: true });
3348
3379
  }
3349
- fs14__default.default.writeFileSync(this.filePath, this.lines.join("\n"), "utf-8");
3380
+ fs17__default.default.writeFileSync(this.filePath, this.lines.join("\n"), "utf-8");
3350
3381
  }
3351
3382
  };
3352
3383
  function discoverEnvironments(projectRoot) {
3353
- if (!fs14__default.default.existsSync(projectRoot)) {
3384
+ if (!fs17__default.default.existsSync(projectRoot)) {
3354
3385
  return ["local", "dev", "prod"];
3355
3386
  }
3356
- const files = fs14__default.default.readdirSync(projectRoot);
3387
+ const files = fs17__default.default.readdirSync(projectRoot);
3357
3388
  const envs = /* @__PURE__ */ new Set();
3358
3389
  for (const file of files) {
3359
3390
  if (file.startsWith(".env")) {
@@ -3378,7 +3409,7 @@ async function runEnvInitExamples(flags = {}) {
3378
3409
  const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
3379
3410
  const s = p19__namespace.spinner();
3380
3411
  s.start("Scanning for local environment files...");
3381
- const files = fs14__default.default.readdirSync(projectRoot, { withFileTypes: true });
3412
+ const files = fs17__default.default.readdirSync(projectRoot, { withFileTypes: true });
3382
3413
  const envFiles = files.filter((dirent) => dirent.isFile() && dirent.name.startsWith(".env") && !dirent.name.endsWith(".example")).map((dirent) => dirent.name).sort();
3383
3414
  if (envFiles.length === 0) {
3384
3415
  s.stop("No local .env files found.");
@@ -3388,11 +3419,11 @@ async function runEnvInitExamples(flags = {}) {
3388
3419
  s.message(`Found ${envFiles.length} local .env file(s). Generating templates...`);
3389
3420
  const generatedFiles = [];
3390
3421
  for (const envFile of envFiles) {
3391
- const sourcePath = path2__default.default.join(projectRoot, envFile);
3422
+ const sourcePath = path26__default.default.join(projectRoot, envFile);
3392
3423
  const targetFile = `${envFile}.example`;
3393
- const targetPath = path2__default.default.join(projectRoot, targetFile);
3424
+ const targetPath = path26__default.default.join(projectRoot, targetFile);
3394
3425
  let overwrite = flags.overwrite;
3395
- if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs14__default.default.existsSync(targetPath)) {
3426
+ if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17__default.default.existsSync(targetPath)) {
3396
3427
  overwrite = await p19__namespace.confirm({
3397
3428
  message: `${targetFile} already exists. Overwrite with redacted values?`,
3398
3429
  initialValue: true
@@ -3425,12 +3456,12 @@ function isInteractive(flags) {
3425
3456
  function getAllExistingKeys(projectRoot, envs) {
3426
3457
  const keys = /* @__PURE__ */ new Set();
3427
3458
  for (const env of envs) {
3428
- const localPath = path2__default.default.join(projectRoot, resolveEnvFilename(env, false));
3429
- const examplePath = path2__default.default.join(projectRoot, resolveEnvFilename(env, true));
3430
- if (fs14__default.default.existsSync(localPath)) {
3459
+ const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
3460
+ const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
3461
+ if (fs17__default.default.existsSync(localPath)) {
3431
3462
  new EnvEditor(localPath).getKeys().forEach((k) => keys.add(k));
3432
3463
  }
3433
- if (fs14__default.default.existsSync(examplePath)) {
3464
+ if (fs17__default.default.existsSync(examplePath)) {
3434
3465
  new EnvEditor(examplePath).getKeys().forEach((k) => keys.add(k));
3435
3466
  }
3436
3467
  }
@@ -3502,8 +3533,8 @@ async function runEnvAdd(key, value, flags = {}) {
3502
3533
  })
3503
3534
  );
3504
3535
  }
3505
- const localPath = path2__default.default.join(projectRoot, resolveEnvFilename(env, false));
3506
- const examplePath = path2__default.default.join(projectRoot, resolveEnvFilename(env, true));
3536
+ const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
3537
+ const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
3507
3538
  if (flags.dryRun) {
3508
3539
  p19__namespace.log.info(
3509
3540
  pc13__default.default.cyan(`[DRY RUN] Would set ${targetKey}=${envVal} in ${resolveEnvFilename(env, false)}`)
@@ -3550,8 +3581,8 @@ async function runEnvUpdate(key, value, flags = {}) {
3550
3581
  );
3551
3582
  }
3552
3583
  const envsWithKey = allEnvs.filter((env) => {
3553
- const localPath = path2__default.default.join(projectRoot, resolveEnvFilename(env, false));
3554
- return fs14__default.default.existsSync(localPath) && new EnvEditor(localPath).has(targetKey);
3584
+ const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
3585
+ return fs17__default.default.existsSync(localPath) && new EnvEditor(localPath).has(targetKey);
3555
3586
  });
3556
3587
  let targetEnvs = [];
3557
3588
  if (flags.env) {
@@ -3577,7 +3608,7 @@ async function runEnvUpdate(key, value, flags = {}) {
3577
3608
  return { key: targetKey, environments: [] };
3578
3609
  }
3579
3610
  for (const env of targetEnvs) {
3580
- const localPath = path2__default.default.join(projectRoot, resolveEnvFilename(env, false));
3611
+ const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
3581
3612
  const localEditor = new EnvEditor(localPath);
3582
3613
  const currentVal = localEditor.getValue(targetKey);
3583
3614
  let newVal = value;
@@ -3607,7 +3638,7 @@ async function runEnvUpdate(key, value, flags = {}) {
3607
3638
  } else {
3608
3639
  localEditor.set(targetKey, newVal);
3609
3640
  localEditor.save();
3610
- const examplePath = path2__default.default.join(projectRoot, resolveEnvFilename(env, true));
3641
+ const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
3611
3642
  const exampleEditor = new EnvEditor(examplePath);
3612
3643
  if (!exampleEditor.has(targetKey)) {
3613
3644
  exampleEditor.set(targetKey, "");
@@ -3643,9 +3674,9 @@ async function runEnvDelete(key, flags = {}) {
3643
3674
  );
3644
3675
  }
3645
3676
  const envsWithKey = allEnvs.filter((env) => {
3646
- const localPath = path2__default.default.join(projectRoot, resolveEnvFilename(env, false));
3647
- const examplePath = path2__default.default.join(projectRoot, resolveEnvFilename(env, true));
3648
- return fs14__default.default.existsSync(localPath) && new EnvEditor(localPath).has(targetKey) || fs14__default.default.existsSync(examplePath) && new EnvEditor(examplePath).has(targetKey);
3677
+ const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
3678
+ const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
3679
+ return fs17__default.default.existsSync(localPath) && new EnvEditor(localPath).has(targetKey) || fs17__default.default.existsSync(examplePath) && new EnvEditor(examplePath).has(targetKey);
3649
3680
  });
3650
3681
  let targetEnvs = [];
3651
3682
  if (flags.env) {
@@ -3683,19 +3714,19 @@ async function runEnvDelete(key, flags = {}) {
3683
3714
  }
3684
3715
  }
3685
3716
  for (const env of targetEnvs) {
3686
- const localPath = path2__default.default.join(projectRoot, resolveEnvFilename(env, false));
3687
- const examplePath = path2__default.default.join(projectRoot, resolveEnvFilename(env, true));
3717
+ const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
3718
+ const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
3688
3719
  if (flags.dryRun) {
3689
3720
  p19__namespace.log.info(
3690
3721
  pc13__default.default.cyan(`[DRY RUN] Would delete ${targetKey} from ${resolveEnvFilename(env, false)} and ${resolveEnvFilename(env, true)}`)
3691
3722
  );
3692
3723
  } else {
3693
- if (fs14__default.default.existsSync(localPath)) {
3724
+ if (fs17__default.default.existsSync(localPath)) {
3694
3725
  const localEditor = new EnvEditor(localPath);
3695
3726
  localEditor.delete(targetKey);
3696
3727
  localEditor.save();
3697
3728
  }
3698
- if (fs14__default.default.existsSync(examplePath)) {
3729
+ if (fs17__default.default.existsSync(examplePath)) {
3699
3730
  const exampleEditor = new EnvEditor(examplePath);
3700
3731
  exampleEditor.delete(targetKey);
3701
3732
  exampleEditor.save();
@@ -3720,10 +3751,10 @@ async function runEnvAudit(flags = {}) {
3720
3751
  for (const env of envs) {
3721
3752
  const localFile = resolveEnvFilename(env, false);
3722
3753
  const exampleFile = resolveEnvFilename(env, true);
3723
- const localPath = path2__default.default.join(projectRoot, localFile);
3724
- const examplePath = path2__default.default.join(projectRoot, exampleFile);
3725
- const localExists = fs14__default.default.existsSync(localPath);
3726
- const exampleExists = fs14__default.default.existsSync(examplePath);
3754
+ const localPath = path26__default.default.join(projectRoot, localFile);
3755
+ const examplePath = path26__default.default.join(projectRoot, exampleFile);
3756
+ const localExists = fs17__default.default.existsSync(localPath);
3757
+ const exampleExists = fs17__default.default.existsSync(examplePath);
3727
3758
  const localEditor = new EnvEditor(localPath);
3728
3759
  const exampleEditor = new EnvEditor(examplePath);
3729
3760
  const localKeys = localExists ? localEditor.getKeys() : [];
@@ -4050,25 +4081,25 @@ function normalizeRegistryUrl(urlOrPath, baseDir) {
4050
4081
  return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
4051
4082
  }
4052
4083
  if (baseDir && (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed === "." || trimmed === "..")) {
4053
- return path2__default.default.resolve(baseDir, trimmed);
4084
+ return path26__default.default.resolve(baseDir, trimmed);
4054
4085
  }
4055
4086
  return trimmed;
4056
4087
  }
4057
4088
  function findLocalRegistry(startDir = process.cwd()) {
4058
- let current = path2__default.default.resolve(startDir);
4089
+ let current = path26__default.default.resolve(startDir);
4059
4090
  while (true) {
4060
- const candidate = path2__default.default.join(current, "mason-registry");
4061
- if (fs14__default.default.existsSync(candidate) && fs14__default.default.existsSync(path2__default.default.join(candidate, "index.json"))) {
4091
+ const candidate = path26__default.default.join(current, "mason-registry");
4092
+ if (fs17__default.default.existsSync(candidate) && fs17__default.default.existsSync(path26__default.default.join(candidate, "index.json"))) {
4062
4093
  return candidate;
4063
4094
  }
4064
- const parent = path2__default.default.dirname(current);
4095
+ const parent = path26__default.default.dirname(current);
4065
4096
  if (parent === current) break;
4066
4097
  current = parent;
4067
4098
  }
4068
4099
  return null;
4069
4100
  }
4070
4101
  function getRegistryBase(projectRoot, override) {
4071
- const rootDir = projectRoot ? path2__default.default.resolve(projectRoot) : process.cwd();
4102
+ const rootDir = projectRoot ? path26__default.default.resolve(projectRoot) : process.cwd();
4072
4103
  if (override && override.trim()) {
4073
4104
  return normalizeRegistryUrl(override.trim(), rootDir);
4074
4105
  }
@@ -4076,30 +4107,30 @@ function getRegistryBase(projectRoot, override) {
4076
4107
  return normalizeRegistryUrl(process.env.MASON_REGISTRY_URL.trim(), rootDir);
4077
4108
  }
4078
4109
  const configLocations = [
4079
- path2__default.default.join(rootDir, "mason.config.json"),
4080
- path2__default.default.join(process.cwd(), "mason.config.json")
4110
+ path26__default.default.join(rootDir, "mason.config.json"),
4111
+ path26__default.default.join(process.cwd(), "mason.config.json")
4081
4112
  ];
4082
4113
  for (const configPath of configLocations) {
4083
- if (fs14__default.default.existsSync(configPath)) {
4114
+ if (fs17__default.default.existsSync(configPath)) {
4084
4115
  try {
4085
- const config = JSON.parse(fs14__default.default.readFileSync(configPath, "utf-8"));
4116
+ const config = JSON.parse(fs17__default.default.readFileSync(configPath, "utf-8"));
4086
4117
  if (config.registry && typeof config.registry === "string") {
4087
- return normalizeRegistryUrl(config.registry.trim(), path2__default.default.dirname(configPath));
4118
+ return normalizeRegistryUrl(config.registry.trim(), path26__default.default.dirname(configPath));
4088
4119
  }
4089
4120
  } catch {
4090
4121
  }
4091
4122
  }
4092
4123
  }
4093
4124
  const pkgLocations = [
4094
- path2__default.default.join(rootDir, "package.json"),
4095
- path2__default.default.join(process.cwd(), "package.json")
4125
+ path26__default.default.join(rootDir, "package.json"),
4126
+ path26__default.default.join(process.cwd(), "package.json")
4096
4127
  ];
4097
4128
  for (const pkgPath of pkgLocations) {
4098
- if (fs14__default.default.existsSync(pkgPath)) {
4129
+ if (fs17__default.default.existsSync(pkgPath)) {
4099
4130
  try {
4100
- const pkg = JSON.parse(fs14__default.default.readFileSync(pkgPath, "utf-8"));
4131
+ const pkg = JSON.parse(fs17__default.default.readFileSync(pkgPath, "utf-8"));
4101
4132
  if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
4102
- return normalizeRegistryUrl(pkg.mason.registry.trim(), path2__default.default.dirname(pkgPath));
4133
+ return normalizeRegistryUrl(pkg.mason.registry.trim(), path26__default.default.dirname(pkgPath));
4103
4134
  }
4104
4135
  } catch {
4105
4136
  }
@@ -4147,16 +4178,16 @@ async function fetchRegistryFile(registryBase, relPath) {
4147
4178
  if (baseDir.startsWith("file://")) {
4148
4179
  baseDir = url.fileURLToPath(baseDir);
4149
4180
  }
4150
- let filePath = path2__default.default.resolve(baseDir, cleanRelPath);
4151
- if (!fs14__default.default.existsSync(filePath)) {
4152
- const inSrcPath = path2__default.default.resolve(baseDir, "src", cleanRelPath);
4153
- if (fs14__default.default.existsSync(inSrcPath)) {
4181
+ let filePath = path26__default.default.resolve(baseDir, cleanRelPath);
4182
+ if (!fs17__default.default.existsSync(filePath)) {
4183
+ const inSrcPath = path26__default.default.resolve(baseDir, "src", cleanRelPath);
4184
+ if (fs17__default.default.existsSync(inSrcPath)) {
4154
4185
  filePath = inSrcPath;
4155
4186
  } else {
4156
4187
  throw new Error(`Registry file not found at ${filePath}`);
4157
4188
  }
4158
4189
  }
4159
- return fs14__default.default.promises.readFile(filePath, "utf-8");
4190
+ return fs17__default.default.promises.readFile(filePath, "utf-8");
4160
4191
  }
4161
4192
  async function fetchRegistryIndex(registryBase) {
4162
4193
  const content = await fetchRegistryFile(registryBase, "index.json");
@@ -4218,19 +4249,19 @@ function findClosestMatch(target, candidates) {
4218
4249
  return null;
4219
4250
  }
4220
4251
  function detectPackageManager(projectRoot) {
4221
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
4222
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "yarn.lock"))) return "yarn";
4223
- if (fs14__default.default.existsSync(path2__default.default.join(projectRoot, "bun.lockb")) || fs14__default.default.existsSync(path2__default.default.join(projectRoot, "bun.lock"))) return "bun";
4252
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
4253
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "yarn.lock"))) return "yarn";
4254
+ if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "bun.lockb")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "bun.lock"))) return "bun";
4224
4255
  return "npm";
4225
4256
  }
4226
4257
  function getMissingNpmPackages(projectRoot, requiredPackages) {
4227
4258
  if (!requiredPackages || requiredPackages.length === 0) return [];
4228
- const pkgJsonPath = path2__default.default.join(projectRoot, "package.json");
4229
- if (!fs14__default.default.existsSync(pkgJsonPath)) {
4259
+ const pkgJsonPath = path26__default.default.join(projectRoot, "package.json");
4260
+ if (!fs17__default.default.existsSync(pkgJsonPath)) {
4230
4261
  return requiredPackages;
4231
4262
  }
4232
4263
  try {
4233
- const pkg = JSON.parse(fs14__default.default.readFileSync(pkgJsonPath, "utf-8"));
4264
+ const pkg = JSON.parse(fs17__default.default.readFileSync(pkgJsonPath, "utf-8"));
4234
4265
  const installed = /* @__PURE__ */ new Set([
4235
4266
  ...Object.keys(pkg.dependencies || {}),
4236
4267
  ...Object.keys(pkg.devDependencies || {}),
@@ -4269,12 +4300,12 @@ function installNpmPackages(projectRoot, packages, pm) {
4269
4300
  });
4270
4301
  }
4271
4302
  function getAllFiles(dir, baseDir = dir) {
4272
- if (!fs14__default.default.existsSync(dir)) return [];
4273
- const entries = fs14__default.default.readdirSync(dir, { withFileTypes: true });
4303
+ if (!fs17__default.default.existsSync(dir)) return [];
4304
+ const entries = fs17__default.default.readdirSync(dir, { withFileTypes: true });
4274
4305
  const files = [];
4275
4306
  for (const entry of entries) {
4276
- const fullPath = path2__default.default.join(dir, entry.name);
4277
- const relPath = path2__default.default.relative(baseDir, fullPath).replace(/\\/g, "/");
4307
+ const fullPath = path26__default.default.join(dir, entry.name);
4308
+ const relPath = path26__default.default.relative(baseDir, fullPath).replace(/\\/g, "/");
4278
4309
  if (entry.isDirectory()) {
4279
4310
  if (entry.name === "__tests__" || entry.name.startsWith(".")) {
4280
4311
  continue;
@@ -4290,13 +4321,13 @@ function getAllFiles(dir, baseDir = dir) {
4290
4321
  return files.sort();
4291
4322
  }
4292
4323
  function computeDirectoryHash(dirPath, files) {
4293
- if (!fs14__default.default.existsSync(dirPath)) return "";
4324
+ if (!fs17__default.default.existsSync(dirPath)) return "";
4294
4325
  const hash = crypto.createHash("sha256");
4295
4326
  const fileList = (getAllFiles(dirPath)).sort();
4296
4327
  for (const relativePath of fileList) {
4297
- const absolutePath = path2__default.default.join(dirPath, relativePath);
4298
- if (!fs14__default.default.existsSync(absolutePath)) continue;
4299
- const content = fs14__default.default.readFileSync(absolutePath, "utf8");
4328
+ const absolutePath = path26__default.default.join(dirPath, relativePath);
4329
+ if (!fs17__default.default.existsSync(absolutePath)) continue;
4330
+ const content = fs17__default.default.readFileSync(absolutePath, "utf8");
4300
4331
  const normalizedContent = content.replace(/\r\n/g, "\n");
4301
4332
  hash.update(relativePath);
4302
4333
  hash.update(normalizedContent);
@@ -4334,17 +4365,17 @@ function getModuleBaseDir(projectRoot, modType) {
4334
4365
  return modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
4335
4366
  }
4336
4367
  const folder = modType === "shared" ? "shared" : "features";
4337
- return path2__default.default.join(projectRoot, "src", folder);
4368
+ return path26__default.default.join(projectRoot, "src", folder);
4338
4369
  }
4339
4370
  function getExistingModuleDir(projectRoot, modType, modName) {
4340
4371
  const folder = modType === "shared" ? "shared" : "features";
4341
4372
  const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
4342
- const inConfigured = path2__default.default.join(configuredDir, modName);
4343
- if (fs14__default.default.existsSync(inConfigured)) return inConfigured;
4344
- const inSrc = path2__default.default.join(projectRoot, "src", folder, modName);
4345
- if (fs14__default.default.existsSync(inSrc)) return inSrc;
4346
- const inRoot = path2__default.default.join(projectRoot, folder, modName);
4347
- if (fs14__default.default.existsSync(inRoot)) return inRoot;
4373
+ const inConfigured = path26__default.default.join(configuredDir, modName);
4374
+ if (fs17__default.default.existsSync(inConfigured)) return inConfigured;
4375
+ const inSrc = path26__default.default.join(projectRoot, "src", folder, modName);
4376
+ if (fs17__default.default.existsSync(inSrc)) return inSrc;
4377
+ const inRoot = path26__default.default.join(projectRoot, folder, modName);
4378
+ if (fs17__default.default.existsSync(inRoot)) return inRoot;
4348
4379
  return null;
4349
4380
  }
4350
4381
  function checkModuleExists(projectRoot, modType, modName) {
@@ -4355,14 +4386,14 @@ function getAvailableLocalModules(projectRoot, modType) {
4355
4386
  const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
4356
4387
  const dirs = [
4357
4388
  configuredDir,
4358
- path2__default.default.join(projectRoot, "src", folder),
4359
- path2__default.default.join(projectRoot, folder)
4389
+ path26__default.default.join(projectRoot, "src", folder),
4390
+ path26__default.default.join(projectRoot, folder)
4360
4391
  ];
4361
4392
  const set = /* @__PURE__ */ new Set();
4362
4393
  for (const dir of dirs) {
4363
- if (fs14__default.default.existsSync(dir)) {
4394
+ if (fs17__default.default.existsSync(dir)) {
4364
4395
  try {
4365
- const entries = fs14__default.default.readdirSync(dir, { withFileTypes: true });
4396
+ const entries = fs17__default.default.readdirSync(dir, { withFileTypes: true });
4366
4397
  for (const e of entries) {
4367
4398
  if (e.isDirectory() && !e.name.startsWith(".")) {
4368
4399
  set.add(e.name);
@@ -4564,7 +4595,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4564
4595
  globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${programmaticAlias}/`);
4565
4596
  globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${programmaticAlias}`);
4566
4597
  const baseDir = getModuleBaseDir(projectRoot, modType);
4567
- const displayDest = path2__default.default.relative(projectRoot, path2__default.default.join(baseDir, programmaticAlias));
4598
+ const displayDest = path26__default.default.relative(projectRoot, path26__default.default.join(baseDir, programmaticAlias));
4568
4599
  p19__namespace.log.step(`Importing '${registryName}' into '${displayDest}'...`);
4569
4600
  resolutions.set(key, {
4570
4601
  type: modType,
@@ -4752,7 +4783,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4752
4783
  globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${newName}/`);
4753
4784
  globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${newName}`);
4754
4785
  const baseDir = getModuleBaseDir(projectRoot, modType);
4755
- const displayDest = path2__default.default.relative(projectRoot, path2__default.default.join(baseDir, newName));
4786
+ const displayDest = path26__default.default.relative(projectRoot, path26__default.default.join(baseDir, newName));
4756
4787
  p19__namespace.log.step(`Importing '${registryName}' into '${displayDest}'...`);
4757
4788
  resolutions.set(key, {
4758
4789
  type: modType,
@@ -4804,7 +4835,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4804
4835
  continue;
4805
4836
  }
4806
4837
  const folder = res.type === "shared" ? "shared" : "features";
4807
- const targetDir = path2__default.default.join(getModuleBaseDir(projectRoot, res.type), res.targetName);
4838
+ const targetDir = path26__default.default.join(getModuleBaseDir(projectRoot, res.type), res.targetName);
4808
4839
  const isOverwrite = Boolean(flags.overwrite || res.action === "overwrite");
4809
4840
  if (key !== rootKey) {
4810
4841
  p19__namespace.log.step(
@@ -4814,30 +4845,30 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4814
4845
  if (res.action === "overwrite" && !flags.dryRun) {
4815
4846
  const existingDir = getExistingModuleDir(projectRoot, res.type, res.targetName);
4816
4847
  if (existingDir && existingDir !== targetDir) {
4817
- fs14__default.default.rmSync(existingDir, { recursive: true, force: true });
4848
+ fs17__default.default.rmSync(existingDir, { recursive: true, force: true });
4818
4849
  }
4819
- if (fs14__default.default.existsSync(targetDir)) {
4820
- fs14__default.default.rmSync(targetDir, { recursive: true, force: true });
4850
+ if (fs17__default.default.existsSync(targetDir)) {
4851
+ fs17__default.default.rmSync(targetDir, { recursive: true, force: true });
4821
4852
  }
4822
4853
  }
4823
4854
  for (const file of res.manifest.files || []) {
4824
4855
  if (file === "registry.json") continue;
4825
4856
  if (!includeTests && isTestFile(file)) continue;
4826
4857
  const remoteFilePath = `${folder}/${res.registryName}/${file}`;
4827
- const localFilePath = path2__default.default.join(targetDir, file);
4828
- if (fs14__default.default.existsSync(localFilePath) && !isOverwrite) {
4858
+ const localFilePath = path26__default.default.join(targetDir, file);
4859
+ if (fs17__default.default.existsSync(localFilePath) && !isOverwrite) {
4829
4860
  p19__namespace.log.warn(
4830
- ` \u21B3 Skipping existing file: ${pc13__default.default.dim(path2__default.default.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
4861
+ ` \u21B3 Skipping existing file: ${pc13__default.default.dim(path26__default.default.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
4831
4862
  );
4832
4863
  continue;
4833
4864
  }
4834
4865
  let content = await fetchRegistryFile(registryBase, remoteFilePath);
4835
4866
  content = rewriteImports(content, globalAliasMap);
4836
4867
  if (!flags.dryRun) {
4837
- fs14__default.default.mkdirSync(path2__default.default.dirname(localFilePath), { recursive: true });
4838
- fs14__default.default.writeFileSync(localFilePath, content, "utf-8");
4868
+ fs17__default.default.mkdirSync(path26__default.default.dirname(localFilePath), { recursive: true });
4869
+ fs17__default.default.writeFileSync(localFilePath, content, "utf-8");
4839
4870
  }
4840
- const displayPath = path2__default.default.relative(projectRoot, localFilePath);
4871
+ const displayPath = path26__default.default.relative(projectRoot, localFilePath);
4841
4872
  totalWrittenFiles.push(displayPath);
4842
4873
  p19__namespace.log.message(` ${pc13__default.default.green("+")} ${displayPath}`);
4843
4874
  }
@@ -4863,7 +4894,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4863
4894
  } else {
4864
4895
  const rootRes = resolutions.get(rootKey);
4865
4896
  const baseDir = getModuleBaseDir(projectRoot, type);
4866
- const displayTarget = path2__default.default.relative(projectRoot, path2__default.default.join(baseDir, rootRes.targetName));
4897
+ const displayTarget = path26__default.default.relative(projectRoot, path26__default.default.join(baseDir, rootRes.targetName));
4867
4898
  p19__namespace.log.success(
4868
4899
  pc13__default.default.green(
4869
4900
  `Successfully imported ${type} '${name}' (${totalWrittenFiles.length} file${totalWrittenFiles.length === 1 ? "" : "s"} placed in ${displayTarget})`
@@ -4882,19 +4913,19 @@ var DependencyRuleError = class extends Error {
4882
4913
  }
4883
4914
  };
4884
4915
  function isTestFile2(filePath, projectRoot) {
4885
- const norm = (projectRoot ? path2__default.default.relative(projectRoot, filePath) : filePath).replace(/\\/g, "/");
4886
- const base = path2__default.default.basename(norm);
4916
+ const norm = (projectRoot ? path26__default.default.relative(projectRoot, filePath) : filePath).replace(/\\/g, "/");
4917
+ const base = path26__default.default.basename(norm);
4887
4918
  return base.endsWith(".test.ts") || base.endsWith(".test.js") || base.endsWith(".spec.ts") || base.endsWith(".spec.js") || base.endsWith(".d.ts") || norm.includes("/__tests__/") || norm.startsWith("__tests__/") || /(?:^|\/)tests?\//.test(norm);
4888
4919
  }
4889
4920
  function scanDirFiles(dir, projectRoot) {
4890
- if (!fs14__default.default.existsSync(dir)) return [];
4891
- const entries = fs14__default.default.readdirSync(dir, { withFileTypes: true });
4921
+ if (!fs17__default.default.existsSync(dir)) return [];
4922
+ const entries = fs17__default.default.readdirSync(dir, { withFileTypes: true });
4892
4923
  const files = [];
4893
4924
  for (const entry of entries) {
4894
4925
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "__tests__" || entry.name.startsWith(".")) {
4895
4926
  continue;
4896
4927
  }
4897
- const fullPath = path2__default.default.join(dir, entry.name);
4928
+ const fullPath = path26__default.default.join(dir, entry.name);
4898
4929
  if (entry.isDirectory()) {
4899
4930
  files.push(...scanDirFiles(fullPath, projectRoot));
4900
4931
  } else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) && !isTestFile2(fullPath, projectRoot)) {
@@ -4903,101 +4934,194 @@ function scanDirFiles(dir, projectRoot) {
4903
4934
  }
4904
4935
  return files;
4905
4936
  }
4906
- function classifyFile(fullPath, projectRoot) {
4907
- const rel = path2__default.default.relative(projectRoot, fullPath).replace(/\\/g, "/");
4908
- const featureMatch = rel.match(/(?:^|\/)(?:src\/)?features\/([^/]+)\/([^/]+)(?:\/.*)?$/);
4909
- if (featureMatch && featureMatch[1] && featureMatch[2]) {
4910
- const feature = featureMatch[1];
4911
- const subfolder = featureMatch[2];
4912
- let layer;
4913
- if (subfolder === "domain" || subfolder === "errors") {
4914
- layer = "domain";
4915
- } else if (subfolder === "useCases" || subfolder === "usecases") {
4916
- layer = "useCases";
4917
- } else if (subfolder === "services") {
4918
- layer = "services";
4919
- } else if (subfolder === "infrastructure") {
4920
- layer = "infrastructure";
4921
- } else if (subfolder === "pxExpress" || subfolder === "presentation" || subfolder === "handlers" || subfolder.startsWith("px")) {
4922
- layer = "presentation";
4923
- }
4924
- return { moduleType: "feature", moduleName: feature, feature, layer };
4925
- }
4926
- const sharedMatch = rel.match(/(?:^|\/)(?:src\/)?shared\/([^/]+)(?:\/(.*))?$/);
4927
- if (sharedMatch && sharedMatch[1]) {
4928
- const moduleName = sharedMatch[1];
4929
- const rest = sharedMatch[2] || "";
4930
- let layer = "root";
4931
- if (rest.startsWith("domain/") || rest === "domain" || rest.startsWith("errors/") || rest === "errors") {
4932
- layer = "domain";
4933
- } else if (rest.startsWith("ports/") || rest === "ports") {
4934
- layer = "ports";
4935
- } else if (rest.startsWith("infrastructure/") || rest === "infrastructure") {
4936
- layer = "infrastructure";
4937
- }
4938
- return { moduleType: "shared", moduleName, feature: moduleName, layer };
4937
+ function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
4938
+ if (!sharedBaseAbs || !errorsBaseAbs) {
4939
+ const paths = getResolvedLintPaths(featuresBaseAbs, loadLintConfig(featuresBaseAbs));
4940
+ featuresBaseAbs = paths.featuresBase;
4941
+ sharedBaseAbs = paths.sharedBase;
4942
+ errorsBaseAbs = paths.errorsBase;
4943
+ }
4944
+ const normFullPath = path26__default.default.resolve(fullPathAbs);
4945
+ const normErrorsBase = path26__default.default.resolve(errorsBaseAbs);
4946
+ const normSharedBase = path26__default.default.resolve(sharedBaseAbs);
4947
+ const normFeaturesBase = path26__default.default.resolve(featuresBaseAbs);
4948
+ const relErrors = path26__default.default.relative(normErrorsBase, normFullPath).replace(/\\/g, "/");
4949
+ if (!relErrors.startsWith("..") && !path26__default.default.isAbsolute(relErrors)) {
4950
+ return {
4951
+ moduleType: "error",
4952
+ moduleName: "global-errors",
4953
+ feature: "global-errors",
4954
+ layer: "domain"
4955
+ };
4956
+ }
4957
+ const relShared = path26__default.default.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
4958
+ if (!relShared.startsWith("..") && !path26__default.default.isAbsolute(relShared)) {
4959
+ const parts = relShared.split("/").filter(Boolean);
4960
+ if (parts.length >= 1) {
4961
+ const moduleName = parts[0];
4962
+ const rest = parts.slice(1).join("/");
4963
+ let layer = "root";
4964
+ if (rest.startsWith("domain/") || rest === "domain" || rest.startsWith("errors/") || rest === "errors") {
4965
+ layer = "domain";
4966
+ } else if (rest.startsWith("ports/") || rest === "ports") {
4967
+ layer = "ports";
4968
+ } else if (rest.startsWith("infrastructure/") || rest === "infrastructure") {
4969
+ layer = "infrastructure";
4970
+ }
4971
+ return { moduleType: "shared", moduleName, feature: moduleName, layer };
4972
+ }
4973
+ }
4974
+ const relFeatures = path26__default.default.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
4975
+ if (!relFeatures.startsWith("..") && !path26__default.default.isAbsolute(relFeatures)) {
4976
+ const parts = relFeatures.split("/").filter(Boolean);
4977
+ if (parts.length >= 2) {
4978
+ const moduleName = parts[0];
4979
+ const subfolder = parts[1];
4980
+ let layer;
4981
+ if (subfolder === "domain" || subfolder === "errors") {
4982
+ layer = "domain";
4983
+ } else if (subfolder === "useCases" || subfolder === "usecases") {
4984
+ layer = "useCases";
4985
+ } else if (subfolder === "services") {
4986
+ layer = "services";
4987
+ } else if (subfolder === "infrastructure") {
4988
+ layer = "infrastructure";
4989
+ } else if (subfolder === "pxExpress" || subfolder === "presentation" || subfolder === "handlers" || subfolder.startsWith("px")) {
4990
+ layer = "presentation";
4991
+ }
4992
+ return { moduleType: "feature", moduleName, feature: moduleName, layer };
4993
+ }
4939
4994
  }
4940
4995
  return {};
4941
4996
  }
4942
- function classifyTarget(specifier, sourceFileAbs, projectRoot) {
4997
+ function classifyTarget(specifier, sourceFileAbs, projectRoot, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
4943
4998
  if (specifier === "@solid-stack/di" || specifier.startsWith("@solid-stack/di/")) {
4944
4999
  return { isExternal: true, isDiFramework: true };
4945
5000
  }
4946
- if (specifier.startsWith("node:") || ["crypto", "fs", "path", "http", "https", "url", "os", "child_process", "stream", "express", "cors", "dotenv"].includes(specifier)) {
5001
+ if (specifier.startsWith("node:") || [
5002
+ "crypto",
5003
+ "fs",
5004
+ "path",
5005
+ "http",
5006
+ "https",
5007
+ "url",
5008
+ "os",
5009
+ "child_process",
5010
+ "stream",
5011
+ "express",
5012
+ "cors",
5013
+ "dotenv"
5014
+ ].includes(specifier)) {
4947
5015
  return { isExternal: true, isDiFramework: false };
4948
5016
  }
4949
- let resolvedRel = null;
5017
+ if (!featuresBaseAbs || !sharedBaseAbs || !errorsBaseAbs) {
5018
+ const paths = getResolvedLintPaths(projectRoot, loadLintConfig(projectRoot));
5019
+ featuresBaseAbs = featuresBaseAbs || paths.featuresBase;
5020
+ sharedBaseAbs = sharedBaseAbs || paths.sharedBase;
5021
+ errorsBaseAbs = errorsBaseAbs || paths.errorsBase;
5022
+ }
5023
+ const isGlobalConfig = specifier === "@configs" || specifier.startsWith("@configs/") || specifier === "@/configs" || specifier.startsWith("@/configs/") || specifier === "~/configs" || specifier.startsWith("~/configs/") || specifier === "configs" || specifier.startsWith("configs/");
5024
+ let targetAbs = null;
4950
5025
  if (specifier.startsWith(".")) {
4951
- const abs = path2__default.default.resolve(path2__default.default.dirname(sourceFileAbs), specifier);
4952
- resolvedRel = path2__default.default.relative(projectRoot, abs).replace(/\\/g, "/");
4953
- } else if (specifier.startsWith("@/features/") || specifier.startsWith("~/features/")) {
4954
- resolvedRel = specifier.replace(/^[@~]\//, "src/");
4955
- } else if (specifier.startsWith("@features/")) {
4956
- resolvedRel = "src/" + specifier.slice(1);
4957
- } else if (specifier.startsWith("@/shared/") || specifier.startsWith("~/shared/")) {
4958
- resolvedRel = specifier.replace(/^[@~]\//, "src/");
4959
- } else if (specifier.startsWith("@shared/")) {
4960
- resolvedRel = "src/" + specifier.slice(1);
4961
- } else if (specifier.startsWith("@/configs/") || specifier.startsWith("~/configs/") || specifier === "@/configs" || specifier === "~/configs") {
4962
- resolvedRel = specifier.replace(/^[@~]\//, "src/");
4963
- } else if (specifier === "@configs" || specifier.startsWith("@configs/")) {
4964
- resolvedRel = "src/" + specifier.slice(1);
4965
- } else if (specifier.startsWith("@/") || specifier.startsWith("~/")) {
4966
- resolvedRel = "src/" + specifier.slice(2);
4967
- } else if (specifier.startsWith("features/") || specifier.startsWith("shared/") || specifier.startsWith("configs/") || specifier === "configs") {
4968
- resolvedRel = specifier;
4969
- }
4970
- if (!resolvedRel) {
4971
- return { isExternal: true, isDiFramework: false };
5026
+ targetAbs = path26__default.default.resolve(path26__default.default.dirname(sourceFileAbs), specifier);
5027
+ } else {
5028
+ const featRel = path26__default.default.relative(projectRoot, featuresBaseAbs).replace(/\\/g, "/");
5029
+ const sharedRel = path26__default.default.relative(projectRoot, sharedBaseAbs).replace(/\\/g, "/");
5030
+ const errorsRel = path26__default.default.relative(projectRoot, errorsBaseAbs).replace(/\\/g, "/");
5031
+ const featPrefixes = ["features"];
5032
+ if (featRel && featRel !== "." && !featRel.startsWith("..")) {
5033
+ featPrefixes.push(featRel);
5034
+ const b = path26__default.default.basename(featRel);
5035
+ if (!featPrefixes.includes(b)) featPrefixes.push(b);
5036
+ }
5037
+ const sharedPrefixes = ["shared"];
5038
+ if (sharedRel && sharedRel !== "." && !sharedRel.startsWith("..")) {
5039
+ sharedPrefixes.push(sharedRel);
5040
+ const b = path26__default.default.basename(sharedRel);
5041
+ if (!sharedPrefixes.includes(b)) sharedPrefixes.push(b);
5042
+ }
5043
+ const errorsPrefixes = ["errors"];
5044
+ if (errorsRel && errorsRel !== "." && !errorsRel.startsWith("..")) {
5045
+ errorsPrefixes.push(errorsRel);
5046
+ const b = path26__default.default.basename(errorsRel);
5047
+ if (!errorsPrefixes.includes(b)) errorsPrefixes.push(b);
5048
+ }
5049
+ for (const prefix of featPrefixes) {
5050
+ const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
5051
+ const m = specifier.match(aliasRegex);
5052
+ if (m && m[2]) {
5053
+ targetAbs = path26__default.default.resolve(featuresBaseAbs, m[2]);
5054
+ break;
5055
+ }
5056
+ }
5057
+ if (!targetAbs) {
5058
+ for (const prefix of sharedPrefixes) {
5059
+ const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
5060
+ const m = specifier.match(aliasRegex);
5061
+ if (m && m[2]) {
5062
+ targetAbs = path26__default.default.resolve(sharedBaseAbs, m[2]);
5063
+ break;
5064
+ }
5065
+ }
5066
+ }
5067
+ if (!targetAbs) {
5068
+ for (const prefix of errorsPrefixes) {
5069
+ const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}(?:\\/(.*))?$`);
5070
+ const m = specifier.match(aliasRegex);
5071
+ if (m) {
5072
+ targetAbs = path26__default.default.resolve(errorsBaseAbs, m[2] || "");
5073
+ break;
5074
+ }
5075
+ }
5076
+ }
5077
+ if (!targetAbs && (specifier.startsWith("@/") || specifier.startsWith("~/"))) {
5078
+ const sub = specifier.slice(2);
5079
+ const srcCandidate = path26__default.default.resolve(projectRoot, "src", sub);
5080
+ const rootCandidate = path26__default.default.resolve(projectRoot, sub);
5081
+ if (fs17__default.default.existsSync(srcCandidate)) {
5082
+ targetAbs = srcCandidate;
5083
+ } else if (fs17__default.default.existsSync(rootCandidate)) {
5084
+ targetAbs = rootCandidate;
5085
+ } else {
5086
+ targetAbs = srcCandidate;
5087
+ }
5088
+ }
5089
+ if (!targetAbs) {
5090
+ const featCandidate = path26__default.default.resolve(featuresBaseAbs, specifier);
5091
+ if (fs17__default.default.existsSync(featCandidate) || fs17__default.default.existsSync(featCandidate + ".ts") || fs17__default.default.existsSync(featCandidate + ".js")) {
5092
+ targetAbs = featCandidate;
5093
+ }
5094
+ }
5095
+ }
5096
+ if (!targetAbs) {
5097
+ return { isExternal: true, isDiFramework: false, isGlobalConfig };
5098
+ }
5099
+ const normTarget = path26__default.default.resolve(targetAbs);
5100
+ const srcConfig = path26__default.default.resolve(projectRoot, "src/configs");
5101
+ const rootConfig = path26__default.default.resolve(projectRoot, "configs");
5102
+ const isTargetConfig = isGlobalConfig || normTarget === srcConfig || normTarget.startsWith(srcConfig + path26__default.default.sep) || normTarget === rootConfig || normTarget.startsWith(rootConfig + path26__default.default.sep);
5103
+ const classification = classifyFile(targetAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs);
5104
+ if (classification.moduleType === "error") {
5105
+ return {
5106
+ isExternal: false,
5107
+ isDiFramework: false,
5108
+ isGlobalError: true,
5109
+ isTargetError: true
5110
+ };
4972
5111
  }
4973
- const isGlobalConfig = resolvedRel.startsWith("src/configs/") || resolvedRel === "src/configs" || resolvedRel.startsWith("configs/") || resolvedRel === "configs";
4974
- const featMatch = resolvedRel.match(/(?:^|\/)(?:src\/)?features\/([^/]+)\/([^/]+)(?:\/(.*))?$/);
4975
- if (featMatch && featMatch[1] && featMatch[2]) {
4976
- const targetFeature = featMatch[1];
4977
- const targetSubfolder = featMatch[2];
4978
- const rest = featMatch[3] || "";
4979
- let targetLayer;
4980
- if (targetSubfolder === "domain" || targetSubfolder === "errors") {
4981
- targetLayer = "domain";
4982
- } else if (targetSubfolder === "useCases" || targetSubfolder === "usecases") {
4983
- targetLayer = "useCases";
4984
- } else if (targetSubfolder === "services") {
4985
- targetLayer = "services";
4986
- } else if (targetSubfolder === "infrastructure") {
4987
- targetLayer = "infrastructure";
4988
- } else if (targetSubfolder === "pxExpress" || targetSubfolder === "presentation" || targetSubfolder === "handlers" || targetSubfolder.startsWith("px")) {
4989
- targetLayer = "presentation";
4990
- }
4991
- const basePart = rest ? path2__default.default.basename(rest) : targetSubfolder;
4992
- const targetFileName = basePart.replace(/\.(js|ts|mjs|cjs)$/, "");
5112
+ if (classification.moduleType === "feature") {
5113
+ const rel = path26__default.default.relative(featuresBaseAbs, targetAbs).replace(/\\/g, "/");
5114
+ const parts = rel.split("/").filter(Boolean);
5115
+ const targetSubfolder = parts[1];
5116
+ const targetFileName = path26__default.default.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
4993
5117
  const isTargetPort = /^I[A-Z]/.test(targetFileName);
4994
5118
  const isTargetRepo = isTargetPort && targetFileName.includes("Repo");
4995
- const isTargetError = targetSubfolder === "errors" || rest.startsWith("errors/") || rest.includes("/errors/") || targetFileName.endsWith("Error") || targetFileName.endsWith("Errors");
5119
+ const isTargetError = targetSubfolder === "errors" || rel.includes("/errors/") || targetFileName.endsWith("Error") || targetFileName.endsWith("Errors");
4996
5120
  return {
4997
5121
  isExternal: false,
4998
5122
  isDiFramework: false,
4999
- targetFeature,
5000
- targetLayer,
5123
+ targetFeature: classification.moduleName,
5124
+ targetLayer: classification.layer,
5001
5125
  targetSubfolder,
5002
5126
  targetFileName,
5003
5127
  isTargetPort,
@@ -5005,25 +5129,21 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
5005
5129
  isTargetError
5006
5130
  };
5007
5131
  }
5008
- const sharedMatch = resolvedRel.match(/(?:^|\/)(?:src\/)?shared\/([^/]+)(?:\/(.*))?$/);
5009
- if (sharedMatch) {
5010
- const targetSharedModule = sharedMatch[1];
5011
- const sharedRest = sharedMatch[2] || "";
5012
- const isSharedRoot = !sharedRest.includes("/");
5013
- const isSharedPorts = sharedRest.startsWith("ports/") || sharedRest === "ports";
5014
- const isSharedInfra = sharedRest.startsWith("infrastructure/") || sharedRest === "infrastructure";
5015
- const isSharedDomain = sharedRest.startsWith("domain/") || sharedRest === "domain";
5132
+ if (classification.moduleType === "shared") {
5133
+ const targetFileName = path26__default.default.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
5134
+ const isTargetError = classification.layer === "domain" && (targetFileName.endsWith("Error") || targetFileName.endsWith("Errors") || targetAbs.includes("/errors/"));
5016
5135
  return {
5017
5136
  isExternal: false,
5018
5137
  isDiFramework: false,
5019
- targetSharedModule,
5020
- isSharedRoot,
5021
- isSharedPorts,
5022
- isSharedInfra,
5023
- isSharedDomain
5138
+ targetSharedModule: classification.moduleName,
5139
+ isSharedRoot: classification.layer === "root",
5140
+ isSharedPorts: classification.layer === "ports",
5141
+ isSharedInfra: classification.layer === "infrastructure",
5142
+ isSharedDomain: classification.layer === "domain",
5143
+ isTargetError
5024
5144
  };
5025
5145
  }
5026
- return { isExternal: true, isDiFramework: false, isGlobalConfig };
5146
+ return { isExternal: true, isDiFramework: false, isGlobalConfig: isTargetConfig };
5027
5147
  }
5028
5148
  function extractImportStatements(content) {
5029
5149
  const statements = [];
@@ -5145,22 +5265,50 @@ var FeatureDependencyGraph = class {
5145
5265
  return dfs(start);
5146
5266
  }
5147
5267
  };
5148
- function discoverAllFeatures(projectRoot) {
5149
- const featuresBase = resolveFeaturesDir(projectRoot);
5150
- if (!fs14__default.default.existsSync(featuresBase)) return [];
5151
- const entries = fs14__default.default.readdirSync(featuresBase, { withFileTypes: true });
5152
- return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "__tests__" && e.name !== "tests").map((e) => ({
5268
+ function discoverAllFeatures(featuresBaseAbs, excludeDirs = []) {
5269
+ const base = featuresBaseAbs;
5270
+ if (!fs17__default.default.existsSync(base)) return [];
5271
+ const excludeSet = new Set(excludeDirs.map((d) => path26__default.default.resolve(d)));
5272
+ const entries = fs17__default.default.readdirSync(base, { withFileTypes: true });
5273
+ return entries.filter((e) => {
5274
+ if (!e.isDirectory()) return false;
5275
+ if (e.name.startsWith(".")) return false;
5276
+ if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
5277
+ return false;
5278
+ }
5279
+ const resolved = path26__default.default.resolve(base, e.name);
5280
+ for (const ex of excludeSet) {
5281
+ if (ex === resolved || ex.startsWith(resolved + path26__default.default.sep) || resolved.startsWith(ex + path26__default.default.sep)) {
5282
+ return false;
5283
+ }
5284
+ }
5285
+ return true;
5286
+ }).map((e) => ({
5153
5287
  name: e.name,
5154
- dir: path2__default.default.join(featuresBase, e.name)
5288
+ dir: path26__default.default.join(base, e.name)
5155
5289
  })).sort((a, b) => a.name.localeCompare(b.name));
5156
5290
  }
5157
- function discoverAllShared(projectRoot) {
5158
- const sharedBase = resolveSharedDir(projectRoot);
5159
- if (!fs14__default.default.existsSync(sharedBase)) return [];
5160
- const entries = fs14__default.default.readdirSync(sharedBase, { withFileTypes: true });
5161
- return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "__tests__" && e.name !== "tests").map((e) => ({
5291
+ function discoverAllShared(sharedBaseAbs, excludeDirs = []) {
5292
+ const base = sharedBaseAbs;
5293
+ if (!fs17__default.default.existsSync(base)) return [];
5294
+ const excludeSet = new Set(excludeDirs.map((d) => path26__default.default.resolve(d)));
5295
+ const entries = fs17__default.default.readdirSync(base, { withFileTypes: true });
5296
+ return entries.filter((e) => {
5297
+ if (!e.isDirectory()) return false;
5298
+ if (e.name.startsWith(".")) return false;
5299
+ if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
5300
+ return false;
5301
+ }
5302
+ const resolved = path26__default.default.resolve(base, e.name);
5303
+ for (const ex of excludeSet) {
5304
+ if (ex === resolved || ex.startsWith(resolved + path26__default.default.sep) || resolved.startsWith(ex + path26__default.default.sep)) {
5305
+ return false;
5306
+ }
5307
+ }
5308
+ return true;
5309
+ }).map((e) => ({
5162
5310
  name: e.name,
5163
- dir: path2__default.default.join(sharedBase, e.name)
5311
+ dir: path26__default.default.join(base, e.name)
5164
5312
  })).sort((a, b) => a.name.localeCompare(b.name));
5165
5313
  }
5166
5314
  function extractClassMethods(content, className) {
@@ -5316,7 +5464,7 @@ function extractClassMethods(content, className) {
5316
5464
  return methods;
5317
5465
  }
5318
5466
  function checkUseCaseShape(featureName, filePath, relativePath, content, addViolation) {
5319
- const fileName = path2__default.default.basename(filePath);
5467
+ const fileName = path26__default.default.basename(filePath);
5320
5468
  const lines = content.split(/\r?\n/);
5321
5469
  const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
5322
5470
  if (!classMatch) {
@@ -5412,7 +5560,7 @@ private ${m.name}(...) { ... }`
5412
5560
  }
5413
5561
  }
5414
5562
  function checkServiceShape(featureName, filePath, relativePath, content, addViolation) {
5415
- const fileName = path2__default.default.basename(filePath);
5563
+ const fileName = path26__default.default.basename(filePath);
5416
5564
  const lines = content.split(/\r?\n/);
5417
5565
  const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
5418
5566
  if (!classMatch) {
@@ -5511,11 +5659,40 @@ function lintCodebase(options = {}) {
5511
5659
  const startTime = Date.now();
5512
5660
  const projectRoot = options.projectRoot || findProjectRoot(options.targetDir || process.cwd());
5513
5661
  const failFast = !options.complete;
5514
- const features = discoverAllFeatures(projectRoot);
5515
- const sharedModules = discoverAllShared(projectRoot);
5662
+ const lintConfig = loadLintConfig(projectRoot);
5663
+ const { featuresBase, sharedBase, errorsBase } = getResolvedLintPaths(projectRoot, lintConfig);
5664
+ const missingFoundations = [];
5665
+ if (!fs17__default.default.existsSync(featuresBase)) missingFoundations.push("features/");
5666
+ if (!fs17__default.default.existsSync(sharedBase)) missingFoundations.push("shared/");
5667
+ if (!fs17__default.default.existsSync(errorsBase)) missingFoundations.push("errors/");
5668
+ if (missingFoundations.length > 0) {
5669
+ throw new DependencyRuleError(
5670
+ `Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every project must contain 'features/', 'shared/', and 'errors/'.`,
5671
+ [],
5672
+ true
5673
+ );
5674
+ }
5675
+ const baseErrorRelative = lintConfig.baseErrorPath || path26__default.default.relative(projectRoot, path26__default.default.join(errorsBase, "AppError.ts")).replace(/\\/g, "/");
5676
+ const baseErrorAbs = path26__default.default.resolve(projectRoot, baseErrorRelative);
5677
+ if (!fs17__default.default.existsSync(baseErrorAbs)) {
5678
+ throw new DependencyRuleError(
5679
+ `Project Structure Violation: Base error class not found at '${baseErrorRelative}'. Create this file or update 'baseErrorPath' in mason-lint.config.json.`,
5680
+ [],
5681
+ true
5682
+ );
5683
+ }
5684
+ const baseErrorContent = fs17__default.default.readFileSync(baseErrorAbs, "utf-8");
5685
+ const baseClassMatch = baseErrorContent.match(
5686
+ /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
5687
+ );
5688
+ const baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
5689
+ const features = discoverAllFeatures(featuresBase, [sharedBase, errorsBase]);
5690
+ const sharedModules = discoverAllShared(sharedBase, [featuresBase, errorsBase]);
5691
+ const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
5516
5692
  const allModules = [
5517
5693
  ...features.map((f) => ({ ...f, type: "feature" })),
5518
- ...sharedModules.map((s) => ({ ...s, type: "shared" }))
5694
+ ...sharedModules.map((s) => ({ ...s, type: "shared" })),
5695
+ errorModule
5519
5696
  ];
5520
5697
  const graph = new FeatureDependencyGraph();
5521
5698
  const allViolations = [];
@@ -5545,7 +5722,7 @@ Code: ${v.code}`;
5545
5722
  scannedFilesCount: 0,
5546
5723
  passed: true,
5547
5724
  violations: [],
5548
- layersChecked: mod.type === "feature" ? ["domain", "useCases", "services", "infrastructure", "presentation"] : ["domain", "ports", "infrastructure", "root"]
5725
+ layersChecked: mod.type === "feature" ? ["domain", "useCases", "services", "infrastructure", "presentation"] : mod.type === "shared" ? ["domain", "ports", "infrastructure", "root"] : ["domain"]
5549
5726
  });
5550
5727
  }
5551
5728
  for (const mod of allModules) {
@@ -5553,13 +5730,128 @@ Code: ${v.code}`;
5553
5730
  const allFiles = scanDirFiles(mod.dir, projectRoot);
5554
5731
  modResult.scannedFilesCount = allFiles.length;
5555
5732
  for (const file of allFiles) {
5556
- const relPath = path2__default.default.relative(projectRoot, file).replace(/\\/g, "/");
5557
- const { moduleType, moduleName, layer } = classifyFile(file, projectRoot);
5733
+ const relPath = path26__default.default.relative(projectRoot, file).replace(/\\/g, "/");
5734
+ const { moduleType, moduleName, layer } = classifyFile(file, featuresBase, sharedBase, errorsBase);
5558
5735
  if (!layer || !moduleType || !moduleName) continue;
5559
- const content = fs14__default.default.readFileSync(file, "utf-8");
5736
+ const content = fs17__default.default.readFileSync(file, "utf-8");
5560
5737
  const statements = extractImportStatements(content);
5561
- const baseName = path2__default.default.basename(file);
5738
+ const baseName = path26__default.default.basename(file);
5562
5739
  const isBarrel = baseName === "index.ts" || baseName === "index.js";
5740
+ const throwErrorRegex = /\bthrow\s+(?:new\s+)?Error\s*\(/g;
5741
+ let throwMatch;
5742
+ while ((throwMatch = throwErrorRegex.exec(content)) !== null) {
5743
+ const charIndex = throwMatch.index;
5744
+ const lineNum = content.substring(0, charIndex).split("\n").length;
5745
+ const lineCode = content.split(/\r?\n/)[lineNum - 1]?.trim() || throwMatch[0];
5746
+ if (lineCode.startsWith("//")) continue;
5747
+ addViolation({
5748
+ feature: moduleName,
5749
+ layer,
5750
+ file,
5751
+ relativePath: relPath,
5752
+ line: lineNum,
5753
+ category: "Plain Error Throw Violation",
5754
+ code: lineCode,
5755
+ ruleId: "E3_PLAIN_ERROR_THROW",
5756
+ severity: "error",
5757
+ advice: `Throwing plain 'Error' is prohibited. You must throw '${baseErrorClassName}' or a domain-specific error class that inherits from it.`,
5758
+ fixExample: {
5759
+ bad: lineCode,
5760
+ good: `throw new ${baseErrorClassName}("Something went wrong");`
5761
+ }
5762
+ });
5763
+ }
5764
+ const isErrorFile = relPath.includes("/errors/") || relPath.startsWith("errors/") || relPath.startsWith("src/errors/") || moduleType === "error" || baseName.endsWith("Error.ts") || baseName.endsWith("Errors.ts") || baseName.endsWith("Error.js") || baseName.endsWith("Errors.js");
5765
+ const isBaseErrorFile = path26__default.default.resolve(file) === path26__default.default.resolve(baseErrorAbs);
5766
+ if (isErrorFile && !isBaseErrorFile) {
5767
+ const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
5768
+ let classMatch;
5769
+ while ((classMatch = classRegex.exec(content)) !== null) {
5770
+ const className = classMatch[1];
5771
+ const extendsName = classMatch[2];
5772
+ const charIndex = classMatch.index;
5773
+ const lineNum = content.substring(0, charIndex).split("\n").length;
5774
+ const lineCode = content.split(/\r?\n/)[lineNum - 1]?.trim() || classMatch[0];
5775
+ if (lineCode.startsWith("//")) continue;
5776
+ if (!extendsName) {
5777
+ addViolation({
5778
+ feature: moduleName,
5779
+ layer,
5780
+ file,
5781
+ relativePath: relPath,
5782
+ line: lineNum,
5783
+ category: "Error Inheritance Violation",
5784
+ code: lineCode,
5785
+ ruleId: "E4_MISSING_INHERITANCE",
5786
+ severity: "error",
5787
+ advice: `Error class '${className}' must extend '${baseErrorClassName}' (or another class that derives from it).`,
5788
+ fixExample: {
5789
+ bad: lineCode,
5790
+ good: `export class ${className} extends ${baseErrorClassName} { ... }`
5791
+ }
5792
+ });
5793
+ } else if (extendsName === "Error") {
5794
+ addViolation({
5795
+ feature: moduleName,
5796
+ layer,
5797
+ file,
5798
+ relativePath: relPath,
5799
+ line: lineNum,
5800
+ category: "Error Inheritance Violation",
5801
+ code: lineCode,
5802
+ ruleId: "E5_NATIVE_ERROR_INHERITANCE",
5803
+ severity: "error",
5804
+ advice: `Error class '${className}' extends the native 'Error'. It must extend your base error class ('${baseErrorClassName}').`,
5805
+ fixExample: {
5806
+ bad: lineCode,
5807
+ good: `export class ${className} extends ${baseErrorClassName} { ... }`
5808
+ }
5809
+ });
5810
+ }
5811
+ }
5812
+ }
5813
+ if (moduleType === "error") {
5814
+ for (const stmt of statements) {
5815
+ const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
5816
+ if (target.targetFeature) {
5817
+ addViolation({
5818
+ feature: "global-errors",
5819
+ layer: "domain",
5820
+ file,
5821
+ relativePath: relPath,
5822
+ line: stmt.line,
5823
+ category: "Global Error Purity Violation",
5824
+ code: stmt.rawCode,
5825
+ ruleId: "E1_FEATURE_DEPENDENCY",
5826
+ severity: "error",
5827
+ advice: `Global errors must not depend on features ('${target.targetFeature}'). Global errors represent pure domain or system states.`,
5828
+ fixExample: {
5829
+ bad: stmt.rawCode,
5830
+ good: "// Global errors must not reference specific features. Keep error types pure."
5831
+ }
5832
+ });
5833
+ }
5834
+ if (target.targetSharedModule && !target.isSharedDomain) {
5835
+ addViolation({
5836
+ feature: "global-errors",
5837
+ layer: "domain",
5838
+ file,
5839
+ relativePath: relPath,
5840
+ line: stmt.line,
5841
+ category: "Global Error Purity Violation",
5842
+ code: stmt.rawCode,
5843
+ ruleId: "E2_SHARED_NON_DOMAIN",
5844
+ severity: "error",
5845
+ advice: `Global errors can only depend on shared domain elements (e.g., value objects). They cannot depend on shared ports or infrastructure.`,
5846
+ fixExample: {
5847
+ bad: stmt.rawCode,
5848
+ good: "// Depend only on pure domain types from shared modules."
5849
+ }
5850
+ });
5851
+ }
5852
+ }
5853
+ continue;
5854
+ }
5563
5855
  if (moduleType === "shared") {
5564
5856
  if (layer === "domain") {
5565
5857
  const lines = content.split(/\r?\n/);
@@ -5586,7 +5878,7 @@ Code: ${v.code}`;
5586
5878
  }
5587
5879
  }
5588
5880
  for (const stmt of statements) {
5589
- const target = classifyTarget(stmt.specifier, file, projectRoot);
5881
+ const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
5590
5882
  if (target.targetFeature) {
5591
5883
  addViolation({
5592
5884
  feature: moduleName,
@@ -5716,7 +6008,7 @@ Code: ${v.code}`;
5716
6008
  }
5717
6009
  }
5718
6010
  for (const stmt of statements) {
5719
- const target = classifyTarget(stmt.specifier, file, projectRoot);
6011
+ const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
5720
6012
  if (target.targetFeature && target.targetFeature !== feat.name) {
5721
6013
  const evidence = {
5722
6014
  fromFeature: feat.name,