@solid-stack/mason 1.0.33 → 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.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import { cac } from 'cac';
3
3
  import * as p19 from '@clack/prompts';
4
4
  import pc13 from 'picocolors';
5
- import fs14 from 'fs';
6
- import path2 from 'path';
5
+ import fs17 from 'fs';
6
+ import path26 from 'path';
7
7
  import { fileURLToPath } from 'url';
8
8
  import Handlebars from 'handlebars';
9
9
  import { execSync } from 'child_process';
@@ -11,8 +11,8 @@ import { createHash } from 'crypto';
11
11
 
12
12
  function writeFileSafely(absolutePath, content, options = {}) {
13
13
  const projectRoot = options.projectRoot || process.cwd();
14
- const relPath = path2.relative(projectRoot, absolutePath).replace(/\\/g, "/");
15
- const existedBefore = fs14.existsSync(absolutePath);
14
+ const relPath = path26.relative(projectRoot, absolutePath).replace(/\\/g, "/");
15
+ const existedBefore = fs17.existsSync(absolutePath);
16
16
  if (options.dryRun) {
17
17
  return {
18
18
  relativePath: relPath,
@@ -31,11 +31,11 @@ function writeFileSafely(absolutePath, content, options = {}) {
31
31
  existedBefore: true
32
32
  };
33
33
  }
34
- const dir = path2.dirname(absolutePath);
35
- if (!fs14.existsSync(dir)) {
36
- fs14.mkdirSync(dir, { recursive: true });
34
+ const dir = path26.dirname(absolutePath);
35
+ if (!fs17.existsSync(dir)) {
36
+ fs17.mkdirSync(dir, { recursive: true });
37
37
  }
38
- fs14.writeFileSync(absolutePath, content, "utf-8");
38
+ fs17.writeFileSync(absolutePath, content, "utf-8");
39
39
  return {
40
40
  relativePath: relPath,
41
41
  absolutePath,
@@ -126,17 +126,17 @@ function toStubName(ifaceName) {
126
126
  return `Stub${base}`;
127
127
  }
128
128
  function loadMasonConfig(startDir = process.cwd()) {
129
- let current = path2.resolve(startDir);
129
+ let current = path26.resolve(startDir);
130
130
  while (true) {
131
- const configPath = path2.join(current, "mason.config.json");
132
- if (fs14.existsSync(configPath)) {
131
+ const configPath = path26.join(current, "mason.config.json");
132
+ if (fs17.existsSync(configPath)) {
133
133
  try {
134
- return JSON.parse(fs14.readFileSync(configPath, "utf-8"));
134
+ return JSON.parse(fs17.readFileSync(configPath, "utf-8"));
135
135
  } catch {
136
136
  return null;
137
137
  }
138
138
  }
139
- const parent = path2.dirname(current);
139
+ const parent = path26.dirname(current);
140
140
  if (parent === current) break;
141
141
  current = parent;
142
142
  }
@@ -146,70 +146,91 @@ function getEffectiveMode(projectRoot, flags) {
146
146
  if (flags?.registry) return "registry";
147
147
  const config = loadMasonConfig(projectRoot);
148
148
  if (config?.mode) return config.mode;
149
- if (fs14.existsSync(path2.join(projectRoot, "index.json")) && (fs14.existsSync(path2.join(projectRoot, "features")) || fs14.existsSync(path2.join(projectRoot, "shared")) || fs14.existsSync(path2.join(projectRoot, "src/features")) || fs14.existsSync(path2.join(projectRoot, "src/shared")))) {
149
+ if (fs17.existsSync(path26.join(projectRoot, "index.json")) && (fs17.existsSync(path26.join(projectRoot, "features")) || fs17.existsSync(path26.join(projectRoot, "shared")) || fs17.existsSync(path26.join(projectRoot, "src/features")) || fs17.existsSync(path26.join(projectRoot, "src/shared")))) {
150
150
  return "registry";
151
151
  }
152
152
  return "app";
153
153
  }
154
154
  function getConfiguredFeaturesDir(projectRoot, flags) {
155
- if (flags?.target) return path2.resolve(projectRoot, flags.target);
156
- if (flags?.dest) return path2.resolve(projectRoot, flags.dest);
155
+ if (flags?.target) return path26.resolve(projectRoot, flags.target);
156
+ if (flags?.dest) return path26.resolve(projectRoot, flags.dest);
157
157
  const config = loadMasonConfig(projectRoot);
158
158
  if (config?.paths?.features) {
159
- return path2.resolve(projectRoot, config.paths.features);
159
+ return path26.resolve(projectRoot, config.paths.features);
160
160
  }
161
161
  const mode = getEffectiveMode(projectRoot, flags);
162
162
  if (mode === "registry") {
163
- if (fs14.existsSync(path2.join(projectRoot, "src/features"))) {
164
- return path2.join(projectRoot, "src/features");
163
+ if (fs17.existsSync(path26.join(projectRoot, "src/features"))) {
164
+ return path26.join(projectRoot, "src/features");
165
165
  }
166
- return path2.join(projectRoot, "features");
166
+ return path26.join(projectRoot, "features");
167
167
  }
168
- if (fs14.existsSync(path2.join(projectRoot, "src/features"))) {
169
- return path2.join(projectRoot, "src/features");
168
+ if (fs17.existsSync(path26.join(projectRoot, "src/features"))) {
169
+ return path26.join(projectRoot, "src/features");
170
170
  }
171
- return path2.join(projectRoot, "features");
171
+ return path26.join(projectRoot, "features");
172
172
  }
173
173
  function getConfiguredSharedDir(projectRoot, flags) {
174
- if (flags?.target) return path2.resolve(projectRoot, flags.target);
175
- if (flags?.dest) return path2.resolve(projectRoot, flags.dest);
174
+ if (flags?.target) return path26.resolve(projectRoot, flags.target);
175
+ if (flags?.dest) return path26.resolve(projectRoot, flags.dest);
176
176
  const config = loadMasonConfig(projectRoot);
177
177
  if (config?.paths?.shared) {
178
- return path2.resolve(projectRoot, config.paths.shared);
178
+ return path26.resolve(projectRoot, config.paths.shared);
179
179
  }
180
180
  const mode = getEffectiveMode(projectRoot, flags);
181
181
  if (mode === "registry") {
182
- if (fs14.existsSync(path2.join(projectRoot, "src/shared"))) {
183
- return path2.join(projectRoot, "src/shared");
182
+ if (fs17.existsSync(path26.join(projectRoot, "src/shared"))) {
183
+ return path26.join(projectRoot, "src/shared");
184
184
  }
185
- return path2.join(projectRoot, "shared");
185
+ return path26.join(projectRoot, "shared");
186
186
  }
187
- if (fs14.existsSync(path2.join(projectRoot, "src/shared"))) {
188
- return path2.join(projectRoot, "src/shared");
187
+ if (fs17.existsSync(path26.join(projectRoot, "src/shared"))) {
188
+ return path26.join(projectRoot, "src/shared");
189
189
  }
190
- return path2.join(projectRoot, "shared");
190
+ return path26.join(projectRoot, "shared");
191
191
  }
192
192
  function loadLintConfig(projectRoot) {
193
- const configPath = path2.join(projectRoot, "mason-lint.config.json");
194
- if (fs14.existsSync(configPath)) {
193
+ const configPath = path26.join(projectRoot, "mason-lint.config.json");
194
+ if (fs17.existsSync(configPath)) {
195
195
  try {
196
- return JSON.parse(fs14.readFileSync(configPath, "utf-8"));
196
+ return JSON.parse(fs17.readFileSync(configPath, "utf-8"));
197
197
  } catch {
198
198
  }
199
199
  }
200
- return { baseErrorPath: "src/errors/AppError.ts" };
200
+ return {};
201
+ }
202
+ function getResolvedLintPaths(projectRoot, config) {
203
+ const masonConfig = loadMasonConfig(projectRoot);
204
+ const configuredFeatures = config.paths?.features ?? masonConfig?.paths?.features;
205
+ const configuredShared = config.paths?.shared ?? masonConfig?.paths?.shared;
206
+ const configuredErrors = config.paths?.errors;
207
+ const resolveBase = (configuredPath, defaultSrc, defaultRoot) => {
208
+ if (configuredPath !== void 0) {
209
+ return path26.resolve(projectRoot, configuredPath);
210
+ }
211
+ const srcPath = path26.join(projectRoot, defaultSrc);
212
+ if (fs17.existsSync(srcPath)) return srcPath;
213
+ const rootPath = path26.join(projectRoot, defaultRoot);
214
+ if (fs17.existsSync(rootPath)) return rootPath;
215
+ return srcPath;
216
+ };
217
+ return {
218
+ featuresBase: resolveBase(configuredFeatures, "src/features", "features"),
219
+ sharedBase: resolveBase(configuredShared, "src/shared", "shared"),
220
+ errorsBase: resolveBase(configuredErrors, "src/errors", "errors")
221
+ };
201
222
  }
202
223
 
203
224
  // src/utils/project.ts
204
225
  function findProjectRoot(startDir = process.cwd()) {
205
- let current = path2.resolve(startDir);
226
+ let current = path26.resolve(startDir);
206
227
  while (true) {
207
- if (fs14.existsSync(path2.join(current, "package.json"))) {
228
+ if (fs17.existsSync(path26.join(current, "package.json"))) {
208
229
  return current;
209
230
  }
210
- const parent = path2.dirname(current);
231
+ const parent = path26.dirname(current);
211
232
  if (parent === current) {
212
- return path2.resolve(startDir);
233
+ return path26.resolve(startDir);
213
234
  }
214
235
  current = parent;
215
236
  }
@@ -222,9 +243,9 @@ function resolveSharedDir(projectRoot, flags) {
222
243
  }
223
244
  function listExistingFeatures(projectRoot) {
224
245
  const featuresDir = resolveFeaturesDir(projectRoot);
225
- if (!fs14.existsSync(featuresDir)) return [];
246
+ if (!fs17.existsSync(featuresDir)) return [];
226
247
  try {
227
- const entries = fs14.readdirSync(featuresDir, { withFileTypes: true });
248
+ const entries = fs17.readdirSync(featuresDir, { withFileTypes: true });
228
249
  return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
229
250
  } catch {
230
251
  return [];
@@ -234,14 +255,14 @@ function listDomainInterfaces(projectRoot, featureName) {
234
255
  const results = [];
235
256
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
236
257
  for (const feat of features) {
237
- const domainDir = path2.join(resolveFeaturesDir(projectRoot), feat, "domain");
238
- if (!fs14.existsSync(domainDir)) continue;
258
+ const domainDir = path26.join(resolveFeaturesDir(projectRoot), feat, "domain");
259
+ if (!fs17.existsSync(domainDir)) continue;
239
260
  try {
240
- const files = fs14.readdirSync(domainDir);
261
+ const files = fs17.readdirSync(domainDir);
241
262
  for (const file of files) {
242
263
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
243
264
  const name = file.replace(/\.ts$/, "");
244
- const fullPath = path2.join(domainDir, file);
265
+ const fullPath = path26.join(domainDir, file);
245
266
  if (/^I[A-Z]/.test(name)) {
246
267
  results.push({
247
268
  name,
@@ -250,7 +271,7 @@ function listDomainInterfaces(projectRoot, featureName) {
250
271
  });
251
272
  } else {
252
273
  try {
253
- const content = fs14.readFileSync(fullPath, "utf-8");
274
+ const content = fs17.readFileSync(fullPath, "utf-8");
254
275
  if (/export\s+(?:abstract\s+class|interface)\s+(\w+)/.test(content)) {
255
276
  results.push({
256
277
  name,
@@ -272,17 +293,17 @@ function listDomainEntities(projectRoot, featureName) {
272
293
  const results = [];
273
294
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
274
295
  for (const feat of features) {
275
- const domainDir = path2.join(resolveFeaturesDir(projectRoot), feat, "domain");
276
- if (!fs14.existsSync(domainDir)) continue;
296
+ const domainDir = path26.join(resolveFeaturesDir(projectRoot), feat, "domain");
297
+ if (!fs17.existsSync(domainDir)) continue;
277
298
  try {
278
- const files = fs14.readdirSync(domainDir);
299
+ const files = fs17.readdirSync(domainDir);
279
300
  for (const file of files) {
280
301
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
281
302
  const name = file.replace(/\.ts$/, "");
282
303
  if (!/^I[A-Z]/.test(name)) {
283
304
  results.push({
284
305
  name,
285
- fullPath: path2.join(domainDir, file),
306
+ fullPath: path26.join(domainDir, file),
286
307
  feature: feat
287
308
  });
288
309
  }
@@ -297,16 +318,16 @@ function listUseCases(projectRoot, featureName) {
297
318
  const results = [];
298
319
  const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
299
320
  for (const feat of features) {
300
- const useCasesDir = path2.join(resolveFeaturesDir(projectRoot), feat, "useCases");
301
- if (!fs14.existsSync(useCasesDir)) continue;
321
+ const useCasesDir = path26.join(resolveFeaturesDir(projectRoot), feat, "useCases");
322
+ if (!fs17.existsSync(useCasesDir)) continue;
302
323
  try {
303
- const files = fs14.readdirSync(useCasesDir);
324
+ const files = fs17.readdirSync(useCasesDir);
304
325
  for (const file of files) {
305
326
  if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
306
327
  const name = file.replace(/\.ts$/, "");
307
328
  results.push({
308
329
  name,
309
- fullPath: path2.join(useCasesDir, file),
330
+ fullPath: path26.join(useCasesDir, file),
310
331
  feature: feat
311
332
  });
312
333
  }
@@ -332,33 +353,33 @@ hbs.registerHelper("join", (arr, sep) => {
332
353
  });
333
354
  var cachedTemplatesDir = null;
334
355
  function getTemplatesDir() {
335
- if (cachedTemplatesDir && fs14.existsSync(cachedTemplatesDir)) {
356
+ if (cachedTemplatesDir && fs17.existsSync(cachedTemplatesDir)) {
336
357
  return cachedTemplatesDir;
337
358
  }
338
- const currentDir = typeof __dirname !== "undefined" ? __dirname : path2.dirname(fileURLToPath(import.meta.url));
339
- const cand1 = path2.resolve(currentDir, "../../templates");
340
- if (fs14.existsSync(cand1)) {
359
+ const currentDir = typeof __dirname !== "undefined" ? __dirname : path26.dirname(fileURLToPath(import.meta.url));
360
+ const cand1 = path26.resolve(currentDir, "../../templates");
361
+ if (fs17.existsSync(cand1)) {
341
362
  cachedTemplatesDir = cand1;
342
363
  return cand1;
343
364
  }
344
- const cand2 = path2.resolve(currentDir, "../templates");
345
- if (fs14.existsSync(cand2)) {
365
+ const cand2 = path26.resolve(currentDir, "../templates");
366
+ if (fs17.existsSync(cand2)) {
346
367
  cachedTemplatesDir = cand2;
347
368
  return cand2;
348
369
  }
349
- const cand3 = path2.resolve(currentDir, "templates");
350
- if (fs14.existsSync(cand3)) {
370
+ const cand3 = path26.resolve(currentDir, "templates");
371
+ if (fs17.existsSync(cand3)) {
351
372
  cachedTemplatesDir = cand3;
352
373
  return cand3;
353
374
  }
354
375
  let curr = currentDir;
355
376
  while (true) {
356
- const candTemplates = path2.join(curr, "templates");
357
- if (fs14.existsSync(candTemplates)) {
377
+ const candTemplates = path26.join(curr, "templates");
378
+ if (fs17.existsSync(candTemplates)) {
358
379
  cachedTemplatesDir = candTemplates;
359
380
  return candTemplates;
360
381
  }
361
- const parent = path2.dirname(curr);
382
+ const parent = path26.dirname(curr);
362
383
  if (parent === curr) break;
363
384
  curr = parent;
364
385
  }
@@ -366,8 +387,8 @@ function getTemplatesDir() {
366
387
  }
367
388
  var templateCache = /* @__PURE__ */ new Map();
368
389
  function loadTemplate(relativePath) {
369
- const fullPath = path2.isAbsolute(relativePath) ? relativePath : path2.join(getTemplatesDir(), relativePath);
370
- return fs14.readFileSync(fullPath, "utf-8");
390
+ const fullPath = path26.isAbsolute(relativePath) ? relativePath : path26.join(getTemplatesDir(), relativePath);
391
+ return fs17.readFileSync(fullPath, "utf-8");
371
392
  }
372
393
  function renderTemplateFile(relativePath, context) {
373
394
  let compiled = templateCache.get(relativePath);
@@ -454,8 +475,8 @@ function generateDomainEntityCode(name, kind = "interface", properties = []) {
454
475
  function generateDomain(options) {
455
476
  const projectRoot = options.projectRoot || findProjectRoot();
456
477
  const entityName = toPascalCase(options.name);
457
- const targetDir = options.targetDir || path2.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
458
- const filePath = path2.join(targetDir, `${entityName}.ts`);
478
+ const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
479
+ const filePath = path26.join(targetDir, `${entityName}.ts`);
459
480
  const code = generateDomainEntityCode(
460
481
  entityName,
461
482
  options.kind || "interface",
@@ -504,8 +525,8 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
504
525
  function generateInterface(options) {
505
526
  const projectRoot = options.projectRoot || findProjectRoot();
506
527
  const ifaceName = ensureInterfacePrefix(options.name);
507
- const targetDir = options.targetDir || path2.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
508
- const filePath = path2.join(targetDir, `${ifaceName}.ts`);
528
+ const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
529
+ const filePath = path26.join(targetDir, `${ifaceName}.ts`);
509
530
  const code = generateInterfaceCode(
510
531
  ifaceName,
511
532
  options.kind || "abstractClass",
@@ -740,7 +761,7 @@ function parseInterfaceMethodsAndImports(content, targetIfaceName) {
740
761
  };
741
762
  }
742
763
  function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
743
- if (customPath && fs14.existsSync(customPath)) {
764
+ if (customPath && fs17.existsSync(customPath)) {
744
765
  return { filePath: customPath, ifaceName };
745
766
  }
746
767
  const candidateNames = [
@@ -750,22 +771,22 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
750
771
  ];
751
772
  const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
752
773
  for (const feat of features) {
753
- const domainDir = path2.join(resolveFeaturesDir(projectRoot), feat, "domain");
754
- if (!fs14.existsSync(domainDir)) continue;
774
+ const domainDir = path26.join(resolveFeaturesDir(projectRoot), feat, "domain");
775
+ if (!fs17.existsSync(domainDir)) continue;
755
776
  for (const cand of candidateNames) {
756
- const p1 = path2.join(domainDir, `${cand}.ts`);
757
- if (fs14.existsSync(p1)) {
777
+ const p1 = path26.join(domainDir, `${cand}.ts`);
778
+ if (fs17.existsSync(p1)) {
758
779
  return { filePath: p1, ifaceName: cand, feature: feat };
759
780
  }
760
781
  }
761
782
  }
762
783
  for (const cand of candidateNames) {
763
- const p1 = path2.join(projectRoot, "domain", `${cand}.ts`);
764
- if (fs14.existsSync(p1)) return { filePath: p1, ifaceName: cand };
765
- const p22 = path2.join(projectRoot, "src", "domain", `${cand}.ts`);
766
- if (fs14.existsSync(p22)) return { filePath: p22, ifaceName: cand };
767
- const p32 = path2.join(projectRoot, "interfaces", `${cand}.ts`);
768
- if (fs14.existsSync(p32)) return { filePath: p32, ifaceName: cand };
784
+ const p1 = path26.join(projectRoot, "domain", `${cand}.ts`);
785
+ if (fs17.existsSync(p1)) return { filePath: p1, ifaceName: cand };
786
+ const p22 = path26.join(projectRoot, "src", "domain", `${cand}.ts`);
787
+ if (fs17.existsSync(p22)) return { filePath: p22, ifaceName: cand };
788
+ const p32 = path26.join(projectRoot, "interfaces", `${cand}.ts`);
789
+ if (fs17.existsSync(p32)) return { filePath: p32, ifaceName: cand };
769
790
  }
770
791
  return null;
771
792
  }
@@ -788,7 +809,7 @@ function loadInterfaceHierarchy(projectRoot, initialIfaceName, featureName, cust
788
809
  while (currentFile && !visited.has(currentFile)) {
789
810
  visited.add(currentFile);
790
811
  try {
791
- const content = fs14.readFileSync(currentFile, "utf-8");
812
+ const content = fs17.readFileSync(currentFile, "utf-8");
792
813
  const parsed = parseInterfaceMethodsAndImports(content, currentName);
793
814
  for (const m of parsed.methods) {
794
815
  if (!allMethods.some((existing) => existing.name === m.name)) {
@@ -864,7 +885,7 @@ function generateStubCode(stubClassName, ifaceName, entityName, featureName, met
864
885
  const entitiesVar = `${entityVar}s`;
865
886
  const idKey = `${entityVar}Id`;
866
887
  const impPath = ifaceImportPath || `../domain/${ifaceName}.js`;
867
- const entityImportPath = ifaceImportPath ? `${path2.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
888
+ const entityImportPath = ifaceImportPath ? `${path26.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
868
889
  const importsByFrom = /* @__PURE__ */ new Map();
869
890
  for (const imp of domainImports) {
870
891
  if (imp.name === ifaceName || imp.name === baseEntity) continue;
@@ -913,7 +934,7 @@ function generateConcreteInfraCode(className, ifaceName, dependencies = [], meth
913
934
  if (baseEntity) {
914
935
  finalMethods = synthesizeCrudMethods(baseEntity);
915
936
  if (!finalDomainImports.some((imp) => imp.name === baseEntity)) {
916
- const importPath = ifaceImportPath ? `${path2.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
937
+ const importPath = ifaceImportPath ? `${path26.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
917
938
  finalDomainImports.push({
918
939
  name: baseEntity,
919
940
  from: importPath,
@@ -958,8 +979,8 @@ function generateInfrastructure(options) {
958
979
  const projectRoot = options.projectRoot || findProjectRoot();
959
980
  const className = toPascalCase(options.name);
960
981
  const isFeatureScope = options.scope !== "global" && Boolean(options.feature);
961
- const targetDir = options.targetDir || (isFeatureScope ? path2.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path2.join(projectRoot, "infrastructure"));
962
- const filePath = path2.join(targetDir, `${className}.ts`);
982
+ const targetDir = options.targetDir || (isFeatureScope ? path26.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path26.join(projectRoot, "infrastructure"));
983
+ const filePath = path26.join(targetDir, `${className}.ts`);
963
984
  let code;
964
985
  if (options.implementsInterface) {
965
986
  const rawIfaceName = options.implementsInterface;
@@ -973,7 +994,7 @@ function generateInfrastructure(options) {
973
994
  const ifaceFilePath = hierarchy.ifaceFilePath;
974
995
  let ifaceImportPath;
975
996
  if (ifaceFilePath) {
976
- let rel = path2.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
997
+ let rel = path26.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
977
998
  if (!rel.startsWith(".")) rel = "./" + rel;
978
999
  ifaceImportPath = rel;
979
1000
  } else if (isFeatureScope) {
@@ -986,8 +1007,8 @@ function generateInfrastructure(options) {
986
1007
  if (new RegExp(`\\b${item.name}\\b`).test(allSignatures)) {
987
1008
  let fromPath;
988
1009
  if (imp.specifier.startsWith(".") && ifaceFilePath) {
989
- const absTarget = path2.resolve(path2.dirname(ifaceFilePath), imp.specifier);
990
- let rel = path2.relative(targetDir, absTarget).replace(/\\/g, "/");
1010
+ const absTarget = path26.resolve(path26.dirname(ifaceFilePath), imp.specifier);
1011
+ let rel = path26.relative(targetDir, absTarget).replace(/\\/g, "/");
991
1012
  if (!rel.startsWith(".")) rel = "./" + rel;
992
1013
  fromPath = rel;
993
1014
  } else {
@@ -1174,8 +1195,8 @@ function generateUseCase(options) {
1174
1195
  const files = [];
1175
1196
  const projectRoot = options.projectRoot || findProjectRoot();
1176
1197
  const ucName = toPascalCase(options.name);
1177
- const targetDir = options.targetDir || path2.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1178
- const filePath = path2.join(targetDir, `${ucName}.ts`);
1198
+ const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
1199
+ const filePath = path26.join(targetDir, `${ucName}.ts`);
1179
1200
  const code = generateUseCaseCode(
1180
1201
  ucName,
1181
1202
  options.dependencies || [],
@@ -1191,7 +1212,7 @@ function generateUseCase(options) {
1191
1212
  })
1192
1213
  );
1193
1214
  if (options.includeTest) {
1194
- const testPath = path2.join(targetDir, `${ucName}.test.ts`);
1215
+ const testPath = path26.join(targetDir, `${ucName}.test.ts`);
1195
1216
  const testCode = generateUseCaseTestCode(ucName, options.dependencies || []);
1196
1217
  files.push(
1197
1218
  writeFileSafely(testPath, testCode, {
@@ -1259,10 +1280,10 @@ function generateHttpHandler(options) {
1259
1280
  const files = [];
1260
1281
  const projectRoot = options.projectRoot || findProjectRoot();
1261
1282
  const className = toPascalCase(options.name);
1262
- const pxDir = path2.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1263
- const handlersDir = path2.join(pxDir, "handlers");
1264
- const pxIndexPath = path2.join(pxDir, "index.ts");
1265
- if (!fs14.existsSync(pxIndexPath)) {
1283
+ const pxDir = path26.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
1284
+ const handlersDir = path26.join(pxDir, "handlers");
1285
+ const pxIndexPath = path26.join(pxDir, "index.ts");
1286
+ if (!fs17.existsSync(pxIndexPath)) {
1266
1287
  const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
1267
1288
  const pxIndexContent = renderTemplate(expressIndexTemplate, {
1268
1289
  routePath: featurePath
@@ -1275,7 +1296,7 @@ function generateHttpHandler(options) {
1275
1296
  })
1276
1297
  );
1277
1298
  }
1278
- const handlerFilePath = path2.join(handlersDir, `${className}.ts`);
1299
+ const handlerFilePath = path26.join(handlersDir, `${className}.ts`);
1279
1300
  const code = generateHttpHandlerCode(
1280
1301
  className,
1281
1302
  options.method || "get",
@@ -1296,11 +1317,11 @@ function generateHttpHandler(options) {
1296
1317
  return files;
1297
1318
  }
1298
1319
  function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], options = {}) {
1299
- const providerPath = path2.join(featureDir, "diProvider.ts");
1320
+ const providerPath = path26.join(featureDir, "diProvider.ts");
1300
1321
  const pascalFeature = toPascalCase(featureName);
1301
1322
  const providerModuleName = `${pascalFeature}Provider`;
1302
- if (fs14.existsSync(providerPath) && !options.overwrite) {
1303
- let content = fs14.readFileSync(providerPath, "utf-8");
1323
+ if (fs17.existsSync(providerPath) && !options.overwrite) {
1324
+ let content = fs17.readFileSync(providerPath, "utf-8");
1304
1325
  content = content.replace(/\n*export\s+const\s+ScaffoldProvider\s*=[^;]+;?/g, "");
1305
1326
  for (const b of bindings) {
1306
1327
  const ifaceImp = b.ifaceImportPath || `./domain/${b.ifaceName}.js`;
@@ -1359,7 +1380,7 @@ function generateFeature(options) {
1359
1380
  const projectRoot = options.projectRoot || findProjectRoot();
1360
1381
  const rawName = options.name.trim();
1361
1382
  const featureName = toCamelCase(rawName);
1362
- const targetDir = options.targetDir || path2.join(resolveFeaturesDir(projectRoot), featureName);
1383
+ const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), featureName);
1363
1384
  const routePath = options.routePath || `/${featureName}`;
1364
1385
  const rawEntities = [];
1365
1386
  if (options.entityNames && options.entityNames.length > 0) {
@@ -1380,7 +1401,7 @@ function generateFeature(options) {
1380
1401
  const domainFile = generateDomain({
1381
1402
  name: ent,
1382
1403
  feature: featureName,
1383
- targetDir: path2.join(targetDir, "domain"),
1404
+ targetDir: path26.join(targetDir, "domain"),
1384
1405
  projectRoot,
1385
1406
  dryRun: options.dryRun,
1386
1407
  overwrite: options.overwrite,
@@ -1400,7 +1421,7 @@ function generateFeature(options) {
1400
1421
  const ifaceFile = generateInterface({
1401
1422
  name: ifaceName,
1402
1423
  feature: featureName,
1403
- targetDir: path2.join(targetDir, "domain"),
1424
+ targetDir: path26.join(targetDir, "domain"),
1404
1425
  entityName: ent,
1405
1426
  projectRoot,
1406
1427
  dryRun: options.dryRun,
@@ -1417,7 +1438,7 @@ function generateFeature(options) {
1417
1438
  const stubFile = generateInfrastructure({
1418
1439
  name: stubName,
1419
1440
  feature: featureName,
1420
- targetDir: path2.join(targetDir, "infrastructure"),
1441
+ targetDir: path26.join(targetDir, "infrastructure"),
1421
1442
  kind: "stub",
1422
1443
  implementsInterface: ifaceName,
1423
1444
  entityName: ent,
@@ -1459,7 +1480,7 @@ function generateFeature(options) {
1459
1480
  const ucFiles = generateUseCase({
1460
1481
  name: ucName,
1461
1482
  feature: featureName,
1462
- targetDir: path2.join(targetDir, "useCases"),
1483
+ targetDir: path26.join(targetDir, "useCases"),
1463
1484
  dependencies: options.includeInterface !== false ? [ifaceName] : [],
1464
1485
  inputProperties: [{ name: idParam, type: "string" }],
1465
1486
  outputProperties: [{ name: entVar, type: primaryEntity }],
@@ -1504,7 +1525,7 @@ function generateFeature(options) {
1504
1525
  const ucFiles = generateUseCase({
1505
1526
  name: ucName,
1506
1527
  feature: featureName,
1507
- targetDir: path2.join(targetDir, "useCases"),
1528
+ targetDir: path26.join(targetDir, "useCases"),
1508
1529
  dependencies: deps,
1509
1530
  inputProperties: [{ name: entVar, type: ent }],
1510
1531
  outputProperties: [{ name: entVar, type: ent }],
@@ -1537,7 +1558,7 @@ function generateFeature(options) {
1537
1558
  const ucFiles = generateUseCase({
1538
1559
  name: ucName,
1539
1560
  feature: featureName,
1540
- targetDir: path2.join(targetDir, "useCases"),
1561
+ targetDir: path26.join(targetDir, "useCases"),
1541
1562
  dependencies: deps,
1542
1563
  inputProperties: [{ name: idParam, type: "string" }],
1543
1564
  outputProperties: [{ name: entVar, type: ent }],
@@ -1570,7 +1591,7 @@ function generateFeature(options) {
1570
1591
  const ucFiles = generateUseCase({
1571
1592
  name: ucName,
1572
1593
  feature: featureName,
1573
- targetDir: path2.join(targetDir, "useCases"),
1594
+ targetDir: path26.join(targetDir, "useCases"),
1574
1595
  dependencies: deps,
1575
1596
  inputProperties: [
1576
1597
  { name: "page", type: "number", optional: true },
@@ -1614,7 +1635,7 @@ function generateFeature(options) {
1614
1635
  const ucFiles = generateUseCase({
1615
1636
  name: ucName,
1616
1637
  feature: featureName,
1617
- targetDir: path2.join(targetDir, "useCases"),
1638
+ targetDir: path26.join(targetDir, "useCases"),
1618
1639
  dependencies: deps,
1619
1640
  inputProperties: [{ name: entVar, type: ent }],
1620
1641
  outputProperties: [{ name: entVar, type: ent }],
@@ -1647,7 +1668,7 @@ function generateFeature(options) {
1647
1668
  const ucFiles = generateUseCase({
1648
1669
  name: ucName,
1649
1670
  feature: featureName,
1650
- targetDir: path2.join(targetDir, "useCases"),
1671
+ targetDir: path26.join(targetDir, "useCases"),
1651
1672
  dependencies: deps,
1652
1673
  inputProperties: [{ name: idParam, type: "string" }],
1653
1674
  outputProperties: [{ name: "success", type: "boolean" }],
@@ -1684,7 +1705,7 @@ function generateFeature(options) {
1684
1705
  const ucFiles = generateUseCase({
1685
1706
  name: ucName,
1686
1707
  feature: featureName,
1687
- targetDir: path2.join(targetDir, "useCases"),
1708
+ targetDir: path26.join(targetDir, "useCases"),
1688
1709
  dependencies: customUc.dependencies || [],
1689
1710
  inputProperties: customUc.inputProperties || [],
1690
1711
  outputProperties: customUc.outputProperties || [],
@@ -1716,8 +1737,8 @@ function generateFeature(options) {
1716
1737
  }
1717
1738
  }
1718
1739
  if (options.includeExpress !== false) {
1719
- const pxDir = path2.join(targetDir, "pxExpress");
1720
- const pxIndexPath = path2.join(pxDir, "index.ts");
1740
+ const pxDir = path26.join(targetDir, "pxExpress");
1741
+ const pxIndexPath = path26.join(pxDir, "index.ts");
1721
1742
  if (!files.some((f) => f.absolutePath === pxIndexPath)) {
1722
1743
  const pxIndexContent = renderTemplate(expressIndexTemplate, { routePath });
1723
1744
  files.push(
@@ -1847,7 +1868,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1847
1868
  }
1848
1869
  const normalizedName = toCamelCase(name);
1849
1870
  const baseFeaturesDir = resolveFeaturesDir(projectRoot, flags);
1850
- const defaultDir = path2.relative(projectRoot, path2.join(baseFeaturesDir, normalizedName));
1871
+ const defaultDir = path26.relative(projectRoot, path26.join(baseFeaturesDir, normalizedName));
1851
1872
  let targetDirRel = defaultDir;
1852
1873
  if (!flags.yes && !flags.target && !flags.dest) {
1853
1874
  targetDirRel = handleCancel(
@@ -1858,7 +1879,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
1858
1879
  })
1859
1880
  ).trim();
1860
1881
  }
1861
- const targetDir = flags.dest ? path2.resolve(projectRoot, flags.dest) : flags.target ? path2.resolve(projectRoot, flags.target) : path2.resolve(projectRoot, targetDirRel);
1882
+ const targetDir = flags.dest ? path26.resolve(projectRoot, flags.dest) : flags.target ? path26.resolve(projectRoot, flags.target) : path26.resolve(projectRoot, targetDirRel);
1862
1883
  let includeExpress = flags.express !== void 0 ? Boolean(flags.express) : true;
1863
1884
  let routePath = `/${normalizedName}`;
1864
1885
  let includeDomain = true;
@@ -2100,8 +2121,8 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2100
2121
  };
2101
2122
  const files = generateFeature(options);
2102
2123
  if (isRegistry) {
2103
- const registryPath = path2.join(targetDir, "registry.json");
2104
- if (!fs14.existsSync(registryPath)) {
2124
+ const registryPath = path26.join(targetDir, "registry.json");
2125
+ if (!fs17.existsSync(registryPath)) {
2105
2126
  const manifest = {
2106
2127
  name: toKebabCase(normalizedName),
2107
2128
  type: "feature",
@@ -2127,7 +2148,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
2127
2148
  printGeneratedFiles(files, options.dryRun);
2128
2149
  p19.outro(
2129
2150
  pc13.green(
2130
- `\u2713 Feature '${normalizedName}' initialized in ${path2.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2151
+ `\u2713 Feature '${normalizedName}' initialized in ${path26.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2131
2152
  )
2132
2153
  );
2133
2154
  }
@@ -2138,7 +2159,7 @@ function generateShared(options) {
2138
2159
  const pascalName = toPascalCase(rawName);
2139
2160
  const camelName = toCamelCase(rawName);
2140
2161
  const kebabName = toKebabCase(rawName);
2141
- const targetDir = options.targetDir || path2.join(resolveSharedDir(projectRoot), kebabName);
2162
+ const targetDir = options.targetDir || path26.join(resolveSharedDir(projectRoot), kebabName);
2142
2163
  const fileDefs = [];
2143
2164
  const facadeContent = `import { MakeInjectable, type DepsType } from "@solid-stack/di";
2144
2165
  import { I${pascalName}Engine } from "./ports/I${pascalName}Engine.js";
@@ -2150,7 +2171,7 @@ export class ${pascalName} {
2150
2171
  }
2151
2172
  `;
2152
2173
  fileDefs.push({
2153
- absolutePath: path2.join(targetDir, `${pascalName}.ts`),
2174
+ absolutePath: path26.join(targetDir, `${pascalName}.ts`),
2154
2175
  content: facadeContent
2155
2176
  });
2156
2177
  const portContent = `export abstract class I${pascalName}Engine {
@@ -2158,7 +2179,7 @@ export class ${pascalName} {
2158
2179
  }
2159
2180
  `;
2160
2181
  fileDefs.push({
2161
- absolutePath: path2.join(targetDir, "ports", `I${pascalName}Engine.ts`),
2182
+ absolutePath: path26.join(targetDir, "ports", `I${pascalName}Engine.ts`),
2162
2183
  content: portContent
2163
2184
  });
2164
2185
  const concreteContent = `import { MakeInjectable } from "@solid-stack/di";
@@ -2170,7 +2191,7 @@ export class Default${pascalName}Engine implements I${pascalName}Engine {
2170
2191
  }
2171
2192
  `;
2172
2193
  fileDefs.push({
2173
- absolutePath: path2.join(targetDir, "infrastructure", `Default${pascalName}Engine.ts`),
2194
+ absolutePath: path26.join(targetDir, "infrastructure", `Default${pascalName}Engine.ts`),
2174
2195
  content: concreteContent
2175
2196
  });
2176
2197
  if (options.includeStub !== false) {
@@ -2183,7 +2204,7 @@ export class Stub${pascalName}Engine implements I${pascalName}Engine {
2183
2204
  }
2184
2205
  `;
2185
2206
  fileDefs.push({
2186
- absolutePath: path2.join(targetDir, "infrastructure", `Stub${pascalName}Engine.ts`),
2207
+ absolutePath: path26.join(targetDir, "infrastructure", `Stub${pascalName}Engine.ts`),
2187
2208
  content: stubContent
2188
2209
  });
2189
2210
  }
@@ -2198,7 +2219,7 @@ export const diProvider = (c: Container): void => {
2198
2219
  export default diProvider;
2199
2220
  `;
2200
2221
  fileDefs.push({
2201
- absolutePath: path2.join(targetDir, "diProvider.ts"),
2222
+ absolutePath: path26.join(targetDir, "diProvider.ts"),
2202
2223
  content: providerContent
2203
2224
  });
2204
2225
  if (options.isRegistry) {
@@ -2215,7 +2236,7 @@ export default diProvider;
2215
2236
  files: []
2216
2237
  };
2217
2238
  fileDefs.push({
2218
- absolutePath: path2.join(targetDir, "registry.json"),
2239
+ absolutePath: path26.join(targetDir, "registry.json"),
2219
2240
  content: JSON.stringify(registryManifest, null, 2) + "\n"
2220
2241
  });
2221
2242
  }
@@ -2252,7 +2273,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2252
2273
  }
2253
2274
  const normalizedName = toKebabCase(name);
2254
2275
  const baseSharedDir = resolveSharedDir(projectRoot, flags);
2255
- const defaultDir = path2.relative(projectRoot, path2.join(baseSharedDir, normalizedName));
2276
+ const defaultDir = path26.relative(projectRoot, path26.join(baseSharedDir, normalizedName));
2256
2277
  let targetDirRel = defaultDir;
2257
2278
  if (!flags.yes && !flags.target && !flags.dest) {
2258
2279
  targetDirRel = handleCancel(
@@ -2263,7 +2284,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2263
2284
  })
2264
2285
  ).trim();
2265
2286
  }
2266
- const targetDir = flags.dest ? path2.resolve(projectRoot, flags.dest) : flags.target ? path2.resolve(projectRoot, flags.target) : path2.resolve(projectRoot, targetDirRel);
2287
+ const targetDir = flags.dest ? path26.resolve(projectRoot, flags.dest) : flags.target ? path26.resolve(projectRoot, flags.target) : path26.resolve(projectRoot, targetDirRel);
2267
2288
  let description = flags.description || "";
2268
2289
  let includeStub = true;
2269
2290
  if (!flags.yes) {
@@ -2297,7 +2318,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
2297
2318
  printGeneratedFiles(files, Boolean(flags.dryRun));
2298
2319
  p19.outro(
2299
2320
  pc13.green(
2300
- `\u2713 Shared module '${normalizedName}' initialized in ${path2.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2321
+ `\u2713 Shared module '${normalizedName}' initialized in ${path26.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
2301
2322
  )
2302
2323
  );
2303
2324
  }
@@ -2724,7 +2745,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
2724
2745
  const infraFile = generateInfrastructure(options);
2725
2746
  files.push(infraFile);
2726
2747
  if (registerInProvider && scope === "feature" && feature && implementsInterface) {
2727
- const featureDir = path2.join(resolveFeaturesDir(projectRoot), feature);
2748
+ const featureDir = path26.join(resolveFeaturesDir(projectRoot), feature);
2728
2749
  const providerFile = updateOrGenerateDiProvider(
2729
2750
  featureDir,
2730
2751
  feature,
@@ -2886,7 +2907,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
2886
2907
  files.push(stubFile);
2887
2908
  }
2888
2909
  if (registerInProvider && generateStub) {
2889
- const featureDir = path2.join(resolveFeaturesDir(projectRoot), feature);
2910
+ const featureDir = path26.join(resolveFeaturesDir(projectRoot), feature);
2890
2911
  const providerFile = updateOrGenerateDiProvider(
2891
2912
  featureDir,
2892
2913
  feature,
@@ -3074,21 +3095,21 @@ function generateInjectable(options) {
3074
3095
  const className = toPascalCase(options.name);
3075
3096
  let targetDir = "";
3076
3097
  if (options.customPath) {
3077
- targetDir = path2.isAbsolute(options.customPath) ? options.customPath : path2.join(projectRoot, options.customPath);
3098
+ targetDir = path26.isAbsolute(options.customPath) ? options.customPath : path26.join(projectRoot, options.customPath);
3078
3099
  } else if (options.location === "feature-service" && options.feature) {
3079
- targetDir = path2.join(resolveFeaturesDir(projectRoot), options.feature, "services");
3100
+ targetDir = path26.join(resolveFeaturesDir(projectRoot), options.feature, "services");
3080
3101
  } else if (options.location === "feature-transformer" && options.feature) {
3081
- targetDir = path2.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
3102
+ targetDir = path26.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
3082
3103
  } else if (options.location === "module") {
3083
- targetDir = path2.join(projectRoot, "modules", className);
3104
+ targetDir = path26.join(projectRoot, "modules", className);
3084
3105
  } else {
3085
- targetDir = options.feature ? path2.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path2.join(projectRoot, "shared", className.toLowerCase());
3106
+ targetDir = options.feature ? path26.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path26.join(projectRoot, "shared", className.toLowerCase());
3086
3107
  }
3087
- const filePath = path2.join(targetDir, `${className}.ts`);
3108
+ const filePath = path26.join(targetDir, `${className}.ts`);
3088
3109
  let ifaceName;
3089
3110
  if (options.generateInterface) {
3090
3111
  ifaceName = `I${className}`;
3091
- const ifacePath = path2.join(targetDir, `${ifaceName}.ts`);
3112
+ const ifacePath = path26.join(targetDir, `${ifaceName}.ts`);
3092
3113
  const ifaceContent = renderTemplate(injectableInterfaceTemplate, { ifaceName });
3093
3114
  files.push(
3094
3115
  writeFileSafely(ifacePath, ifaceContent, {
@@ -3217,7 +3238,7 @@ async function runEnvInit(flags = {}) {
3217
3238
  const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
3218
3239
  const s = p19.spinner();
3219
3240
  s.start("Scanning for .example environment files...");
3220
- const files = fs14.readdirSync(projectRoot);
3241
+ const files = fs17.readdirSync(projectRoot);
3221
3242
  const exampleFiles = files.filter((file) => file.startsWith(".env") && file.endsWith(".example")).sort();
3222
3243
  if (exampleFiles.length === 0) {
3223
3244
  s.stop("No .example files found.");
@@ -3227,11 +3248,11 @@ async function runEnvInit(flags = {}) {
3227
3248
  s.message(`Found ${exampleFiles.length} template(s). Generating...`);
3228
3249
  const generatedFiles = [];
3229
3250
  for (const exampleFile of exampleFiles) {
3230
- const sourcePath = path2.join(projectRoot, exampleFile);
3251
+ const sourcePath = path26.join(projectRoot, exampleFile);
3231
3252
  const targetFile = exampleFile.replace(/\.example$/, "");
3232
- const targetPath = path2.join(projectRoot, targetFile);
3253
+ const targetPath = path26.join(projectRoot, targetFile);
3233
3254
  let overwrite = flags.overwrite;
3234
- if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs14.existsSync(targetPath)) {
3255
+ if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17.existsSync(targetPath)) {
3235
3256
  overwrite = await p19.confirm({
3236
3257
  message: `${targetFile} already exists. Overwrite?`,
3237
3258
  initialValue: false
@@ -3241,7 +3262,7 @@ async function runEnvInit(flags = {}) {
3241
3262
  process.exit(0);
3242
3263
  }
3243
3264
  }
3244
- const content = fs14.readFileSync(sourcePath, "utf-8");
3265
+ const content = fs17.readFileSync(sourcePath, "utf-8");
3245
3266
  const genFile = writeFileSafely(targetPath, content, {
3246
3267
  projectRoot,
3247
3268
  dryRun: Boolean(flags.dryRun),
@@ -3259,7 +3280,7 @@ var EnvEditor = class {
3259
3280
  filePath;
3260
3281
  constructor(filePath) {
3261
3282
  this.filePath = filePath;
3262
- this.lines = fs14.existsSync(filePath) ? fs14.readFileSync(filePath, "utf-8").split(/\r?\n/) : [];
3283
+ this.lines = fs17.existsSync(filePath) ? fs17.readFileSync(filePath, "utf-8").split(/\r?\n/) : [];
3263
3284
  }
3264
3285
  getLines() {
3265
3286
  return [...this.lines];
@@ -3323,18 +3344,18 @@ var EnvEditor = class {
3323
3344
  });
3324
3345
  }
3325
3346
  save() {
3326
- const dir = path2.dirname(this.filePath);
3327
- if (!fs14.existsSync(dir)) {
3328
- fs14.mkdirSync(dir, { recursive: true });
3347
+ const dir = path26.dirname(this.filePath);
3348
+ if (!fs17.existsSync(dir)) {
3349
+ fs17.mkdirSync(dir, { recursive: true });
3329
3350
  }
3330
- fs14.writeFileSync(this.filePath, this.lines.join("\n"), "utf-8");
3351
+ fs17.writeFileSync(this.filePath, this.lines.join("\n"), "utf-8");
3331
3352
  }
3332
3353
  };
3333
3354
  function discoverEnvironments(projectRoot) {
3334
- if (!fs14.existsSync(projectRoot)) {
3355
+ if (!fs17.existsSync(projectRoot)) {
3335
3356
  return ["local", "dev", "prod"];
3336
3357
  }
3337
- const files = fs14.readdirSync(projectRoot);
3358
+ const files = fs17.readdirSync(projectRoot);
3338
3359
  const envs = /* @__PURE__ */ new Set();
3339
3360
  for (const file of files) {
3340
3361
  if (file.startsWith(".env")) {
@@ -3359,7 +3380,7 @@ async function runEnvInitExamples(flags = {}) {
3359
3380
  const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
3360
3381
  const s = p19.spinner();
3361
3382
  s.start("Scanning for local environment files...");
3362
- const files = fs14.readdirSync(projectRoot, { withFileTypes: true });
3383
+ const files = fs17.readdirSync(projectRoot, { withFileTypes: true });
3363
3384
  const envFiles = files.filter((dirent) => dirent.isFile() && dirent.name.startsWith(".env") && !dirent.name.endsWith(".example")).map((dirent) => dirent.name).sort();
3364
3385
  if (envFiles.length === 0) {
3365
3386
  s.stop("No local .env files found.");
@@ -3369,11 +3390,11 @@ async function runEnvInitExamples(flags = {}) {
3369
3390
  s.message(`Found ${envFiles.length} local .env file(s). Generating templates...`);
3370
3391
  const generatedFiles = [];
3371
3392
  for (const envFile of envFiles) {
3372
- const sourcePath = path2.join(projectRoot, envFile);
3393
+ const sourcePath = path26.join(projectRoot, envFile);
3373
3394
  const targetFile = `${envFile}.example`;
3374
- const targetPath = path2.join(projectRoot, targetFile);
3395
+ const targetPath = path26.join(projectRoot, targetFile);
3375
3396
  let overwrite = flags.overwrite;
3376
- if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs14.existsSync(targetPath)) {
3397
+ if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17.existsSync(targetPath)) {
3377
3398
  overwrite = await p19.confirm({
3378
3399
  message: `${targetFile} already exists. Overwrite with redacted values?`,
3379
3400
  initialValue: true
@@ -3406,12 +3427,12 @@ function isInteractive(flags) {
3406
3427
  function getAllExistingKeys(projectRoot, envs) {
3407
3428
  const keys = /* @__PURE__ */ new Set();
3408
3429
  for (const env of envs) {
3409
- const localPath = path2.join(projectRoot, resolveEnvFilename(env, false));
3410
- const examplePath = path2.join(projectRoot, resolveEnvFilename(env, true));
3411
- if (fs14.existsSync(localPath)) {
3430
+ const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
3431
+ const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
3432
+ if (fs17.existsSync(localPath)) {
3412
3433
  new EnvEditor(localPath).getKeys().forEach((k) => keys.add(k));
3413
3434
  }
3414
- if (fs14.existsSync(examplePath)) {
3435
+ if (fs17.existsSync(examplePath)) {
3415
3436
  new EnvEditor(examplePath).getKeys().forEach((k) => keys.add(k));
3416
3437
  }
3417
3438
  }
@@ -3483,8 +3504,8 @@ async function runEnvAdd(key, value, flags = {}) {
3483
3504
  })
3484
3505
  );
3485
3506
  }
3486
- const localPath = path2.join(projectRoot, resolveEnvFilename(env, false));
3487
- const examplePath = path2.join(projectRoot, resolveEnvFilename(env, true));
3507
+ const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
3508
+ const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
3488
3509
  if (flags.dryRun) {
3489
3510
  p19.log.info(
3490
3511
  pc13.cyan(`[DRY RUN] Would set ${targetKey}=${envVal} in ${resolveEnvFilename(env, false)}`)
@@ -3531,8 +3552,8 @@ async function runEnvUpdate(key, value, flags = {}) {
3531
3552
  );
3532
3553
  }
3533
3554
  const envsWithKey = allEnvs.filter((env) => {
3534
- const localPath = path2.join(projectRoot, resolveEnvFilename(env, false));
3535
- return fs14.existsSync(localPath) && new EnvEditor(localPath).has(targetKey);
3555
+ const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
3556
+ return fs17.existsSync(localPath) && new EnvEditor(localPath).has(targetKey);
3536
3557
  });
3537
3558
  let targetEnvs = [];
3538
3559
  if (flags.env) {
@@ -3558,7 +3579,7 @@ async function runEnvUpdate(key, value, flags = {}) {
3558
3579
  return { key: targetKey, environments: [] };
3559
3580
  }
3560
3581
  for (const env of targetEnvs) {
3561
- const localPath = path2.join(projectRoot, resolveEnvFilename(env, false));
3582
+ const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
3562
3583
  const localEditor = new EnvEditor(localPath);
3563
3584
  const currentVal = localEditor.getValue(targetKey);
3564
3585
  let newVal = value;
@@ -3588,7 +3609,7 @@ async function runEnvUpdate(key, value, flags = {}) {
3588
3609
  } else {
3589
3610
  localEditor.set(targetKey, newVal);
3590
3611
  localEditor.save();
3591
- const examplePath = path2.join(projectRoot, resolveEnvFilename(env, true));
3612
+ const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
3592
3613
  const exampleEditor = new EnvEditor(examplePath);
3593
3614
  if (!exampleEditor.has(targetKey)) {
3594
3615
  exampleEditor.set(targetKey, "");
@@ -3624,9 +3645,9 @@ async function runEnvDelete(key, flags = {}) {
3624
3645
  );
3625
3646
  }
3626
3647
  const envsWithKey = allEnvs.filter((env) => {
3627
- const localPath = path2.join(projectRoot, resolveEnvFilename(env, false));
3628
- const examplePath = path2.join(projectRoot, resolveEnvFilename(env, true));
3629
- return fs14.existsSync(localPath) && new EnvEditor(localPath).has(targetKey) || fs14.existsSync(examplePath) && new EnvEditor(examplePath).has(targetKey);
3648
+ const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
3649
+ const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
3650
+ return fs17.existsSync(localPath) && new EnvEditor(localPath).has(targetKey) || fs17.existsSync(examplePath) && new EnvEditor(examplePath).has(targetKey);
3630
3651
  });
3631
3652
  let targetEnvs = [];
3632
3653
  if (flags.env) {
@@ -3664,19 +3685,19 @@ async function runEnvDelete(key, flags = {}) {
3664
3685
  }
3665
3686
  }
3666
3687
  for (const env of targetEnvs) {
3667
- const localPath = path2.join(projectRoot, resolveEnvFilename(env, false));
3668
- const examplePath = path2.join(projectRoot, resolveEnvFilename(env, true));
3688
+ const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
3689
+ const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
3669
3690
  if (flags.dryRun) {
3670
3691
  p19.log.info(
3671
3692
  pc13.cyan(`[DRY RUN] Would delete ${targetKey} from ${resolveEnvFilename(env, false)} and ${resolveEnvFilename(env, true)}`)
3672
3693
  );
3673
3694
  } else {
3674
- if (fs14.existsSync(localPath)) {
3695
+ if (fs17.existsSync(localPath)) {
3675
3696
  const localEditor = new EnvEditor(localPath);
3676
3697
  localEditor.delete(targetKey);
3677
3698
  localEditor.save();
3678
3699
  }
3679
- if (fs14.existsSync(examplePath)) {
3700
+ if (fs17.existsSync(examplePath)) {
3680
3701
  const exampleEditor = new EnvEditor(examplePath);
3681
3702
  exampleEditor.delete(targetKey);
3682
3703
  exampleEditor.save();
@@ -3701,10 +3722,10 @@ async function runEnvAudit(flags = {}) {
3701
3722
  for (const env of envs) {
3702
3723
  const localFile = resolveEnvFilename(env, false);
3703
3724
  const exampleFile = resolveEnvFilename(env, true);
3704
- const localPath = path2.join(projectRoot, localFile);
3705
- const examplePath = path2.join(projectRoot, exampleFile);
3706
- const localExists = fs14.existsSync(localPath);
3707
- const exampleExists = fs14.existsSync(examplePath);
3725
+ const localPath = path26.join(projectRoot, localFile);
3726
+ const examplePath = path26.join(projectRoot, exampleFile);
3727
+ const localExists = fs17.existsSync(localPath);
3728
+ const exampleExists = fs17.existsSync(examplePath);
3708
3729
  const localEditor = new EnvEditor(localPath);
3709
3730
  const exampleEditor = new EnvEditor(examplePath);
3710
3731
  const localKeys = localExists ? localEditor.getKeys() : [];
@@ -4031,25 +4052,25 @@ function normalizeRegistryUrl(urlOrPath, baseDir) {
4031
4052
  return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
4032
4053
  }
4033
4054
  if (baseDir && (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed === "." || trimmed === "..")) {
4034
- return path2.resolve(baseDir, trimmed);
4055
+ return path26.resolve(baseDir, trimmed);
4035
4056
  }
4036
4057
  return trimmed;
4037
4058
  }
4038
4059
  function findLocalRegistry(startDir = process.cwd()) {
4039
- let current = path2.resolve(startDir);
4060
+ let current = path26.resolve(startDir);
4040
4061
  while (true) {
4041
- const candidate = path2.join(current, "mason-registry");
4042
- if (fs14.existsSync(candidate) && fs14.existsSync(path2.join(candidate, "index.json"))) {
4062
+ const candidate = path26.join(current, "mason-registry");
4063
+ if (fs17.existsSync(candidate) && fs17.existsSync(path26.join(candidate, "index.json"))) {
4043
4064
  return candidate;
4044
4065
  }
4045
- const parent = path2.dirname(current);
4066
+ const parent = path26.dirname(current);
4046
4067
  if (parent === current) break;
4047
4068
  current = parent;
4048
4069
  }
4049
4070
  return null;
4050
4071
  }
4051
4072
  function getRegistryBase(projectRoot, override) {
4052
- const rootDir = projectRoot ? path2.resolve(projectRoot) : process.cwd();
4073
+ const rootDir = projectRoot ? path26.resolve(projectRoot) : process.cwd();
4053
4074
  if (override && override.trim()) {
4054
4075
  return normalizeRegistryUrl(override.trim(), rootDir);
4055
4076
  }
@@ -4057,30 +4078,30 @@ function getRegistryBase(projectRoot, override) {
4057
4078
  return normalizeRegistryUrl(process.env.MASON_REGISTRY_URL.trim(), rootDir);
4058
4079
  }
4059
4080
  const configLocations = [
4060
- path2.join(rootDir, "mason.config.json"),
4061
- path2.join(process.cwd(), "mason.config.json")
4081
+ path26.join(rootDir, "mason.config.json"),
4082
+ path26.join(process.cwd(), "mason.config.json")
4062
4083
  ];
4063
4084
  for (const configPath of configLocations) {
4064
- if (fs14.existsSync(configPath)) {
4085
+ if (fs17.existsSync(configPath)) {
4065
4086
  try {
4066
- const config = JSON.parse(fs14.readFileSync(configPath, "utf-8"));
4087
+ const config = JSON.parse(fs17.readFileSync(configPath, "utf-8"));
4067
4088
  if (config.registry && typeof config.registry === "string") {
4068
- return normalizeRegistryUrl(config.registry.trim(), path2.dirname(configPath));
4089
+ return normalizeRegistryUrl(config.registry.trim(), path26.dirname(configPath));
4069
4090
  }
4070
4091
  } catch {
4071
4092
  }
4072
4093
  }
4073
4094
  }
4074
4095
  const pkgLocations = [
4075
- path2.join(rootDir, "package.json"),
4076
- path2.join(process.cwd(), "package.json")
4096
+ path26.join(rootDir, "package.json"),
4097
+ path26.join(process.cwd(), "package.json")
4077
4098
  ];
4078
4099
  for (const pkgPath of pkgLocations) {
4079
- if (fs14.existsSync(pkgPath)) {
4100
+ if (fs17.existsSync(pkgPath)) {
4080
4101
  try {
4081
- const pkg = JSON.parse(fs14.readFileSync(pkgPath, "utf-8"));
4102
+ const pkg = JSON.parse(fs17.readFileSync(pkgPath, "utf-8"));
4082
4103
  if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
4083
- return normalizeRegistryUrl(pkg.mason.registry.trim(), path2.dirname(pkgPath));
4104
+ return normalizeRegistryUrl(pkg.mason.registry.trim(), path26.dirname(pkgPath));
4084
4105
  }
4085
4106
  } catch {
4086
4107
  }
@@ -4128,16 +4149,16 @@ async function fetchRegistryFile(registryBase, relPath) {
4128
4149
  if (baseDir.startsWith("file://")) {
4129
4150
  baseDir = fileURLToPath(baseDir);
4130
4151
  }
4131
- let filePath = path2.resolve(baseDir, cleanRelPath);
4132
- if (!fs14.existsSync(filePath)) {
4133
- const inSrcPath = path2.resolve(baseDir, "src", cleanRelPath);
4134
- if (fs14.existsSync(inSrcPath)) {
4152
+ let filePath = path26.resolve(baseDir, cleanRelPath);
4153
+ if (!fs17.existsSync(filePath)) {
4154
+ const inSrcPath = path26.resolve(baseDir, "src", cleanRelPath);
4155
+ if (fs17.existsSync(inSrcPath)) {
4135
4156
  filePath = inSrcPath;
4136
4157
  } else {
4137
4158
  throw new Error(`Registry file not found at ${filePath}`);
4138
4159
  }
4139
4160
  }
4140
- return fs14.promises.readFile(filePath, "utf-8");
4161
+ return fs17.promises.readFile(filePath, "utf-8");
4141
4162
  }
4142
4163
  async function fetchRegistryIndex(registryBase) {
4143
4164
  const content = await fetchRegistryFile(registryBase, "index.json");
@@ -4199,19 +4220,19 @@ function findClosestMatch(target, candidates) {
4199
4220
  return null;
4200
4221
  }
4201
4222
  function detectPackageManager(projectRoot) {
4202
- if (fs14.existsSync(path2.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
4203
- if (fs14.existsSync(path2.join(projectRoot, "yarn.lock"))) return "yarn";
4204
- if (fs14.existsSync(path2.join(projectRoot, "bun.lockb")) || fs14.existsSync(path2.join(projectRoot, "bun.lock"))) return "bun";
4223
+ if (fs17.existsSync(path26.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
4224
+ if (fs17.existsSync(path26.join(projectRoot, "yarn.lock"))) return "yarn";
4225
+ if (fs17.existsSync(path26.join(projectRoot, "bun.lockb")) || fs17.existsSync(path26.join(projectRoot, "bun.lock"))) return "bun";
4205
4226
  return "npm";
4206
4227
  }
4207
4228
  function getMissingNpmPackages(projectRoot, requiredPackages) {
4208
4229
  if (!requiredPackages || requiredPackages.length === 0) return [];
4209
- const pkgJsonPath = path2.join(projectRoot, "package.json");
4210
- if (!fs14.existsSync(pkgJsonPath)) {
4230
+ const pkgJsonPath = path26.join(projectRoot, "package.json");
4231
+ if (!fs17.existsSync(pkgJsonPath)) {
4211
4232
  return requiredPackages;
4212
4233
  }
4213
4234
  try {
4214
- const pkg = JSON.parse(fs14.readFileSync(pkgJsonPath, "utf-8"));
4235
+ const pkg = JSON.parse(fs17.readFileSync(pkgJsonPath, "utf-8"));
4215
4236
  const installed = /* @__PURE__ */ new Set([
4216
4237
  ...Object.keys(pkg.dependencies || {}),
4217
4238
  ...Object.keys(pkg.devDependencies || {}),
@@ -4250,12 +4271,12 @@ function installNpmPackages(projectRoot, packages, pm) {
4250
4271
  });
4251
4272
  }
4252
4273
  function getAllFiles(dir, baseDir = dir) {
4253
- if (!fs14.existsSync(dir)) return [];
4254
- const entries = fs14.readdirSync(dir, { withFileTypes: true });
4274
+ if (!fs17.existsSync(dir)) return [];
4275
+ const entries = fs17.readdirSync(dir, { withFileTypes: true });
4255
4276
  const files = [];
4256
4277
  for (const entry of entries) {
4257
- const fullPath = path2.join(dir, entry.name);
4258
- const relPath = path2.relative(baseDir, fullPath).replace(/\\/g, "/");
4278
+ const fullPath = path26.join(dir, entry.name);
4279
+ const relPath = path26.relative(baseDir, fullPath).replace(/\\/g, "/");
4259
4280
  if (entry.isDirectory()) {
4260
4281
  if (entry.name === "__tests__" || entry.name.startsWith(".")) {
4261
4282
  continue;
@@ -4271,13 +4292,13 @@ function getAllFiles(dir, baseDir = dir) {
4271
4292
  return files.sort();
4272
4293
  }
4273
4294
  function computeDirectoryHash(dirPath, files) {
4274
- if (!fs14.existsSync(dirPath)) return "";
4295
+ if (!fs17.existsSync(dirPath)) return "";
4275
4296
  const hash = createHash("sha256");
4276
4297
  const fileList = (getAllFiles(dirPath)).sort();
4277
4298
  for (const relativePath of fileList) {
4278
- const absolutePath = path2.join(dirPath, relativePath);
4279
- if (!fs14.existsSync(absolutePath)) continue;
4280
- const content = fs14.readFileSync(absolutePath, "utf8");
4299
+ const absolutePath = path26.join(dirPath, relativePath);
4300
+ if (!fs17.existsSync(absolutePath)) continue;
4301
+ const content = fs17.readFileSync(absolutePath, "utf8");
4281
4302
  const normalizedContent = content.replace(/\r\n/g, "\n");
4282
4303
  hash.update(relativePath);
4283
4304
  hash.update(normalizedContent);
@@ -4315,17 +4336,17 @@ function getModuleBaseDir(projectRoot, modType) {
4315
4336
  return modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
4316
4337
  }
4317
4338
  const folder = modType === "shared" ? "shared" : "features";
4318
- return path2.join(projectRoot, "src", folder);
4339
+ return path26.join(projectRoot, "src", folder);
4319
4340
  }
4320
4341
  function getExistingModuleDir(projectRoot, modType, modName) {
4321
4342
  const folder = modType === "shared" ? "shared" : "features";
4322
4343
  const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
4323
- const inConfigured = path2.join(configuredDir, modName);
4324
- if (fs14.existsSync(inConfigured)) return inConfigured;
4325
- const inSrc = path2.join(projectRoot, "src", folder, modName);
4326
- if (fs14.existsSync(inSrc)) return inSrc;
4327
- const inRoot = path2.join(projectRoot, folder, modName);
4328
- if (fs14.existsSync(inRoot)) return inRoot;
4344
+ const inConfigured = path26.join(configuredDir, modName);
4345
+ if (fs17.existsSync(inConfigured)) return inConfigured;
4346
+ const inSrc = path26.join(projectRoot, "src", folder, modName);
4347
+ if (fs17.existsSync(inSrc)) return inSrc;
4348
+ const inRoot = path26.join(projectRoot, folder, modName);
4349
+ if (fs17.existsSync(inRoot)) return inRoot;
4329
4350
  return null;
4330
4351
  }
4331
4352
  function checkModuleExists(projectRoot, modType, modName) {
@@ -4336,14 +4357,14 @@ function getAvailableLocalModules(projectRoot, modType) {
4336
4357
  const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
4337
4358
  const dirs = [
4338
4359
  configuredDir,
4339
- path2.join(projectRoot, "src", folder),
4340
- path2.join(projectRoot, folder)
4360
+ path26.join(projectRoot, "src", folder),
4361
+ path26.join(projectRoot, folder)
4341
4362
  ];
4342
4363
  const set = /* @__PURE__ */ new Set();
4343
4364
  for (const dir of dirs) {
4344
- if (fs14.existsSync(dir)) {
4365
+ if (fs17.existsSync(dir)) {
4345
4366
  try {
4346
- const entries = fs14.readdirSync(dir, { withFileTypes: true });
4367
+ const entries = fs17.readdirSync(dir, { withFileTypes: true });
4347
4368
  for (const e of entries) {
4348
4369
  if (e.isDirectory() && !e.name.startsWith(".")) {
4349
4370
  set.add(e.name);
@@ -4545,7 +4566,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4545
4566
  globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${programmaticAlias}/`);
4546
4567
  globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${programmaticAlias}`);
4547
4568
  const baseDir = getModuleBaseDir(projectRoot, modType);
4548
- const displayDest = path2.relative(projectRoot, path2.join(baseDir, programmaticAlias));
4569
+ const displayDest = path26.relative(projectRoot, path26.join(baseDir, programmaticAlias));
4549
4570
  p19.log.step(`Importing '${registryName}' into '${displayDest}'...`);
4550
4571
  resolutions.set(key, {
4551
4572
  type: modType,
@@ -4733,7 +4754,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4733
4754
  globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${newName}/`);
4734
4755
  globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${newName}`);
4735
4756
  const baseDir = getModuleBaseDir(projectRoot, modType);
4736
- const displayDest = path2.relative(projectRoot, path2.join(baseDir, newName));
4757
+ const displayDest = path26.relative(projectRoot, path26.join(baseDir, newName));
4737
4758
  p19.log.step(`Importing '${registryName}' into '${displayDest}'...`);
4738
4759
  resolutions.set(key, {
4739
4760
  type: modType,
@@ -4785,7 +4806,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4785
4806
  continue;
4786
4807
  }
4787
4808
  const folder = res.type === "shared" ? "shared" : "features";
4788
- const targetDir = path2.join(getModuleBaseDir(projectRoot, res.type), res.targetName);
4809
+ const targetDir = path26.join(getModuleBaseDir(projectRoot, res.type), res.targetName);
4789
4810
  const isOverwrite = Boolean(flags.overwrite || res.action === "overwrite");
4790
4811
  if (key !== rootKey) {
4791
4812
  p19.log.step(
@@ -4795,30 +4816,30 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4795
4816
  if (res.action === "overwrite" && !flags.dryRun) {
4796
4817
  const existingDir = getExistingModuleDir(projectRoot, res.type, res.targetName);
4797
4818
  if (existingDir && existingDir !== targetDir) {
4798
- fs14.rmSync(existingDir, { recursive: true, force: true });
4819
+ fs17.rmSync(existingDir, { recursive: true, force: true });
4799
4820
  }
4800
- if (fs14.existsSync(targetDir)) {
4801
- fs14.rmSync(targetDir, { recursive: true, force: true });
4821
+ if (fs17.existsSync(targetDir)) {
4822
+ fs17.rmSync(targetDir, { recursive: true, force: true });
4802
4823
  }
4803
4824
  }
4804
4825
  for (const file of res.manifest.files || []) {
4805
4826
  if (file === "registry.json") continue;
4806
4827
  if (!includeTests && isTestFile(file)) continue;
4807
4828
  const remoteFilePath = `${folder}/${res.registryName}/${file}`;
4808
- const localFilePath = path2.join(targetDir, file);
4809
- if (fs14.existsSync(localFilePath) && !isOverwrite) {
4829
+ const localFilePath = path26.join(targetDir, file);
4830
+ if (fs17.existsSync(localFilePath) && !isOverwrite) {
4810
4831
  p19.log.warn(
4811
- ` \u21B3 Skipping existing file: ${pc13.dim(path2.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
4832
+ ` \u21B3 Skipping existing file: ${pc13.dim(path26.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
4812
4833
  );
4813
4834
  continue;
4814
4835
  }
4815
4836
  let content = await fetchRegistryFile(registryBase, remoteFilePath);
4816
4837
  content = rewriteImports(content, globalAliasMap);
4817
4838
  if (!flags.dryRun) {
4818
- fs14.mkdirSync(path2.dirname(localFilePath), { recursive: true });
4819
- fs14.writeFileSync(localFilePath, content, "utf-8");
4839
+ fs17.mkdirSync(path26.dirname(localFilePath), { recursive: true });
4840
+ fs17.writeFileSync(localFilePath, content, "utf-8");
4820
4841
  }
4821
- const displayPath = path2.relative(projectRoot, localFilePath);
4842
+ const displayPath = path26.relative(projectRoot, localFilePath);
4822
4843
  totalWrittenFiles.push(displayPath);
4823
4844
  p19.log.message(` ${pc13.green("+")} ${displayPath}`);
4824
4845
  }
@@ -4844,7 +4865,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
4844
4865
  } else {
4845
4866
  const rootRes = resolutions.get(rootKey);
4846
4867
  const baseDir = getModuleBaseDir(projectRoot, type);
4847
- const displayTarget = path2.relative(projectRoot, path2.join(baseDir, rootRes.targetName));
4868
+ const displayTarget = path26.relative(projectRoot, path26.join(baseDir, rootRes.targetName));
4848
4869
  p19.log.success(
4849
4870
  pc13.green(
4850
4871
  `Successfully imported ${type} '${name}' (${totalWrittenFiles.length} file${totalWrittenFiles.length === 1 ? "" : "s"} placed in ${displayTarget})`
@@ -4863,19 +4884,19 @@ var DependencyRuleError = class extends Error {
4863
4884
  }
4864
4885
  };
4865
4886
  function isTestFile2(filePath, projectRoot) {
4866
- const norm = (projectRoot ? path2.relative(projectRoot, filePath) : filePath).replace(/\\/g, "/");
4867
- const base = path2.basename(norm);
4887
+ const norm = (projectRoot ? path26.relative(projectRoot, filePath) : filePath).replace(/\\/g, "/");
4888
+ const base = path26.basename(norm);
4868
4889
  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);
4869
4890
  }
4870
4891
  function scanDirFiles(dir, projectRoot) {
4871
- if (!fs14.existsSync(dir)) return [];
4872
- const entries = fs14.readdirSync(dir, { withFileTypes: true });
4892
+ if (!fs17.existsSync(dir)) return [];
4893
+ const entries = fs17.readdirSync(dir, { withFileTypes: true });
4873
4894
  const files = [];
4874
4895
  for (const entry of entries) {
4875
4896
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "__tests__" || entry.name.startsWith(".")) {
4876
4897
  continue;
4877
4898
  }
4878
- const fullPath = path2.join(dir, entry.name);
4899
+ const fullPath = path26.join(dir, entry.name);
4879
4900
  if (entry.isDirectory()) {
4880
4901
  files.push(...scanDirFiles(fullPath, projectRoot));
4881
4902
  } else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) && !isTestFile2(fullPath, projectRoot)) {
@@ -4884,42 +4905,19 @@ function scanDirFiles(dir, projectRoot) {
4884
4905
  }
4885
4906
  return files;
4886
4907
  }
4887
- function classifyFile(fullPath, projectRoot) {
4888
- const rel = path2.relative(projectRoot, fullPath).replace(/\\/g, "/");
4889
- const featureMatch = rel.match(/(?:^|\/)(?:src\/)?features\/([^/]+)\/([^/]+)(?:\/.*)?$/);
4890
- if (featureMatch && featureMatch[1] && featureMatch[2]) {
4891
- const feature = featureMatch[1];
4892
- const subfolder = featureMatch[2];
4893
- let layer;
4894
- if (subfolder === "domain" || subfolder === "errors") {
4895
- layer = "domain";
4896
- } else if (subfolder === "useCases" || subfolder === "usecases") {
4897
- layer = "useCases";
4898
- } else if (subfolder === "services") {
4899
- layer = "services";
4900
- } else if (subfolder === "infrastructure") {
4901
- layer = "infrastructure";
4902
- } else if (subfolder === "pxExpress" || subfolder === "presentation" || subfolder === "handlers" || subfolder.startsWith("px")) {
4903
- layer = "presentation";
4904
- }
4905
- return { moduleType: "feature", moduleName: feature, feature, layer };
4906
- }
4907
- const sharedMatch = rel.match(/(?:^|\/)(?:src\/)?shared\/([^/]+)(?:\/(.*))?$/);
4908
- if (sharedMatch && sharedMatch[1]) {
4909
- const moduleName = sharedMatch[1];
4910
- const rest = sharedMatch[2] || "";
4911
- let layer = "root";
4912
- if (rest.startsWith("domain/") || rest === "domain" || rest.startsWith("errors/") || rest === "errors") {
4913
- layer = "domain";
4914
- } else if (rest.startsWith("ports/") || rest === "ports") {
4915
- layer = "ports";
4916
- } else if (rest.startsWith("infrastructure/") || rest === "infrastructure") {
4917
- layer = "infrastructure";
4918
- }
4919
- return { moduleType: "shared", moduleName, feature: moduleName, layer };
4920
- }
4921
- const errorMatch = rel.match(/(?:^|\/)(?:src\/)?errors(?:\/(.*))?$/);
4922
- if (errorMatch) {
4908
+ function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
4909
+ if (!sharedBaseAbs || !errorsBaseAbs) {
4910
+ const paths = getResolvedLintPaths(featuresBaseAbs, loadLintConfig(featuresBaseAbs));
4911
+ featuresBaseAbs = paths.featuresBase;
4912
+ sharedBaseAbs = paths.sharedBase;
4913
+ errorsBaseAbs = paths.errorsBase;
4914
+ }
4915
+ const normFullPath = path26.resolve(fullPathAbs);
4916
+ const normErrorsBase = path26.resolve(errorsBaseAbs);
4917
+ const normSharedBase = path26.resolve(sharedBaseAbs);
4918
+ const normFeaturesBase = path26.resolve(featuresBaseAbs);
4919
+ const relErrors = path26.relative(normErrorsBase, normFullPath).replace(/\\/g, "/");
4920
+ if (!relErrors.startsWith("..") && !path26.isAbsolute(relErrors)) {
4923
4921
  return {
4924
4922
  moduleType: "error",
4925
4923
  moduleName: "global-errors",
@@ -4927,46 +4925,154 @@ function classifyFile(fullPath, projectRoot) {
4927
4925
  layer: "domain"
4928
4926
  };
4929
4927
  }
4928
+ const relShared = path26.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
4929
+ if (!relShared.startsWith("..") && !path26.isAbsolute(relShared)) {
4930
+ const parts = relShared.split("/").filter(Boolean);
4931
+ if (parts.length >= 1) {
4932
+ const moduleName = parts[0];
4933
+ const rest = parts.slice(1).join("/");
4934
+ let layer = "root";
4935
+ if (rest.startsWith("domain/") || rest === "domain" || rest.startsWith("errors/") || rest === "errors") {
4936
+ layer = "domain";
4937
+ } else if (rest.startsWith("ports/") || rest === "ports") {
4938
+ layer = "ports";
4939
+ } else if (rest.startsWith("infrastructure/") || rest === "infrastructure") {
4940
+ layer = "infrastructure";
4941
+ }
4942
+ return { moduleType: "shared", moduleName, feature: moduleName, layer };
4943
+ }
4944
+ }
4945
+ const relFeatures = path26.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
4946
+ if (!relFeatures.startsWith("..") && !path26.isAbsolute(relFeatures)) {
4947
+ const parts = relFeatures.split("/").filter(Boolean);
4948
+ if (parts.length >= 2) {
4949
+ const moduleName = parts[0];
4950
+ const subfolder = parts[1];
4951
+ let layer;
4952
+ if (subfolder === "domain" || subfolder === "errors") {
4953
+ layer = "domain";
4954
+ } else if (subfolder === "useCases" || subfolder === "usecases") {
4955
+ layer = "useCases";
4956
+ } else if (subfolder === "services") {
4957
+ layer = "services";
4958
+ } else if (subfolder === "infrastructure") {
4959
+ layer = "infrastructure";
4960
+ } else if (subfolder === "pxExpress" || subfolder === "presentation" || subfolder === "handlers" || subfolder.startsWith("px")) {
4961
+ layer = "presentation";
4962
+ }
4963
+ return { moduleType: "feature", moduleName, feature: moduleName, layer };
4964
+ }
4965
+ }
4930
4966
  return {};
4931
4967
  }
4932
- function classifyTarget(specifier, sourceFileAbs, projectRoot) {
4968
+ function classifyTarget(specifier, sourceFileAbs, projectRoot, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
4933
4969
  if (specifier === "@solid-stack/di" || specifier.startsWith("@solid-stack/di/")) {
4934
4970
  return { isExternal: true, isDiFramework: true };
4935
4971
  }
4936
- if (specifier.startsWith("node:") || ["crypto", "fs", "path", "http", "https", "url", "os", "child_process", "stream", "express", "cors", "dotenv"].includes(specifier)) {
4972
+ if (specifier.startsWith("node:") || [
4973
+ "crypto",
4974
+ "fs",
4975
+ "path",
4976
+ "http",
4977
+ "https",
4978
+ "url",
4979
+ "os",
4980
+ "child_process",
4981
+ "stream",
4982
+ "express",
4983
+ "cors",
4984
+ "dotenv"
4985
+ ].includes(specifier)) {
4937
4986
  return { isExternal: true, isDiFramework: false };
4938
4987
  }
4939
- let resolvedRel = null;
4988
+ if (!featuresBaseAbs || !sharedBaseAbs || !errorsBaseAbs) {
4989
+ const paths = getResolvedLintPaths(projectRoot, loadLintConfig(projectRoot));
4990
+ featuresBaseAbs = featuresBaseAbs || paths.featuresBase;
4991
+ sharedBaseAbs = sharedBaseAbs || paths.sharedBase;
4992
+ errorsBaseAbs = errorsBaseAbs || paths.errorsBase;
4993
+ }
4994
+ const isGlobalConfig = specifier === "@configs" || specifier.startsWith("@configs/") || specifier === "@/configs" || specifier.startsWith("@/configs/") || specifier === "~/configs" || specifier.startsWith("~/configs/") || specifier === "configs" || specifier.startsWith("configs/");
4995
+ let targetAbs = null;
4940
4996
  if (specifier.startsWith(".")) {
4941
- const abs = path2.resolve(path2.dirname(sourceFileAbs), specifier);
4942
- resolvedRel = path2.relative(projectRoot, abs).replace(/\\/g, "/");
4943
- } else if (specifier.startsWith("@/features/") || specifier.startsWith("~/features/")) {
4944
- resolvedRel = specifier.replace(/^[@~]\//, "src/");
4945
- } else if (specifier.startsWith("@features/")) {
4946
- resolvedRel = "src/" + specifier.slice(1);
4947
- } else if (specifier.startsWith("@/shared/") || specifier.startsWith("~/shared/")) {
4948
- resolvedRel = specifier.replace(/^[@~]\//, "src/");
4949
- } else if (specifier.startsWith("@shared/")) {
4950
- resolvedRel = "src/" + specifier.slice(1);
4951
- } else if (specifier.startsWith("@/configs/") || specifier.startsWith("~/configs/") || specifier === "@/configs" || specifier === "~/configs") {
4952
- resolvedRel = specifier.replace(/^[@~]\//, "src/");
4953
- } else if (specifier === "@configs" || specifier.startsWith("@configs/")) {
4954
- resolvedRel = "src/" + specifier.slice(1);
4955
- } else if (specifier.startsWith("@/errors/") || specifier.startsWith("~/errors/") || specifier === "@/errors" || specifier === "~/errors") {
4956
- resolvedRel = specifier.replace(/^[@~]\//, "src/");
4957
- } else if (specifier === "@errors" || specifier.startsWith("@errors/")) {
4958
- resolvedRel = "src/" + specifier.slice(1);
4959
- } else if (specifier.startsWith("@/") || specifier.startsWith("~/")) {
4960
- resolvedRel = "src/" + specifier.slice(2);
4961
- } else if (specifier.startsWith("features/") || specifier.startsWith("shared/") || specifier.startsWith("configs/") || specifier === "configs" || specifier.startsWith("errors/") || specifier === "errors") {
4962
- resolvedRel = specifier;
4963
- }
4964
- if (!resolvedRel) {
4965
- return { isExternal: true, isDiFramework: false };
4997
+ targetAbs = path26.resolve(path26.dirname(sourceFileAbs), specifier);
4998
+ } else {
4999
+ const featRel = path26.relative(projectRoot, featuresBaseAbs).replace(/\\/g, "/");
5000
+ const sharedRel = path26.relative(projectRoot, sharedBaseAbs).replace(/\\/g, "/");
5001
+ const errorsRel = path26.relative(projectRoot, errorsBaseAbs).replace(/\\/g, "/");
5002
+ const featPrefixes = ["features"];
5003
+ if (featRel && featRel !== "." && !featRel.startsWith("..")) {
5004
+ featPrefixes.push(featRel);
5005
+ const b = path26.basename(featRel);
5006
+ if (!featPrefixes.includes(b)) featPrefixes.push(b);
5007
+ }
5008
+ const sharedPrefixes = ["shared"];
5009
+ if (sharedRel && sharedRel !== "." && !sharedRel.startsWith("..")) {
5010
+ sharedPrefixes.push(sharedRel);
5011
+ const b = path26.basename(sharedRel);
5012
+ if (!sharedPrefixes.includes(b)) sharedPrefixes.push(b);
5013
+ }
5014
+ const errorsPrefixes = ["errors"];
5015
+ if (errorsRel && errorsRel !== "." && !errorsRel.startsWith("..")) {
5016
+ errorsPrefixes.push(errorsRel);
5017
+ const b = path26.basename(errorsRel);
5018
+ if (!errorsPrefixes.includes(b)) errorsPrefixes.push(b);
5019
+ }
5020
+ for (const prefix of featPrefixes) {
5021
+ const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
5022
+ const m = specifier.match(aliasRegex);
5023
+ if (m && m[2]) {
5024
+ targetAbs = path26.resolve(featuresBaseAbs, m[2]);
5025
+ break;
5026
+ }
5027
+ }
5028
+ if (!targetAbs) {
5029
+ for (const prefix of sharedPrefixes) {
5030
+ const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
5031
+ const m = specifier.match(aliasRegex);
5032
+ if (m && m[2]) {
5033
+ targetAbs = path26.resolve(sharedBaseAbs, m[2]);
5034
+ break;
5035
+ }
5036
+ }
5037
+ }
5038
+ if (!targetAbs) {
5039
+ for (const prefix of errorsPrefixes) {
5040
+ const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}(?:\\/(.*))?$`);
5041
+ const m = specifier.match(aliasRegex);
5042
+ if (m) {
5043
+ targetAbs = path26.resolve(errorsBaseAbs, m[2] || "");
5044
+ break;
5045
+ }
5046
+ }
5047
+ }
5048
+ if (!targetAbs && (specifier.startsWith("@/") || specifier.startsWith("~/"))) {
5049
+ const sub = specifier.slice(2);
5050
+ const srcCandidate = path26.resolve(projectRoot, "src", sub);
5051
+ const rootCandidate = path26.resolve(projectRoot, sub);
5052
+ if (fs17.existsSync(srcCandidate)) {
5053
+ targetAbs = srcCandidate;
5054
+ } else if (fs17.existsSync(rootCandidate)) {
5055
+ targetAbs = rootCandidate;
5056
+ } else {
5057
+ targetAbs = srcCandidate;
5058
+ }
5059
+ }
5060
+ if (!targetAbs) {
5061
+ const featCandidate = path26.resolve(featuresBaseAbs, specifier);
5062
+ if (fs17.existsSync(featCandidate) || fs17.existsSync(featCandidate + ".ts") || fs17.existsSync(featCandidate + ".js")) {
5063
+ targetAbs = featCandidate;
5064
+ }
5065
+ }
5066
+ }
5067
+ if (!targetAbs) {
5068
+ return { isExternal: true, isDiFramework: false, isGlobalConfig };
4966
5069
  }
4967
- const isGlobalConfig = resolvedRel.startsWith("src/configs/") || resolvedRel === "src/configs" || resolvedRel.startsWith("configs/") || resolvedRel === "configs";
4968
- const isGlobalError = resolvedRel.startsWith("src/errors/") || resolvedRel === "src/errors" || resolvedRel.startsWith("errors/") || resolvedRel === "errors";
4969
- if (isGlobalError) {
5070
+ const normTarget = path26.resolve(targetAbs);
5071
+ const srcConfig = path26.resolve(projectRoot, "src/configs");
5072
+ const rootConfig = path26.resolve(projectRoot, "configs");
5073
+ const isTargetConfig = isGlobalConfig || normTarget === srcConfig || normTarget.startsWith(srcConfig + path26.sep) || normTarget === rootConfig || normTarget.startsWith(rootConfig + path26.sep);
5074
+ const classification = classifyFile(targetAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs);
5075
+ if (classification.moduleType === "error") {
4970
5076
  return {
4971
5077
  isExternal: false,
4972
5078
  isDiFramework: false,
@@ -4974,33 +5080,19 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
4974
5080
  isTargetError: true
4975
5081
  };
4976
5082
  }
4977
- const featMatch = resolvedRel.match(/(?:^|\/)(?:src\/)?features\/([^/]+)\/([^/]+)(?:\/(.*))?$/);
4978
- if (featMatch && featMatch[1] && featMatch[2]) {
4979
- const targetFeature = featMatch[1];
4980
- const targetSubfolder = featMatch[2];
4981
- const rest = featMatch[3] || "";
4982
- let targetLayer;
4983
- if (targetSubfolder === "domain" || targetSubfolder === "errors") {
4984
- targetLayer = "domain";
4985
- } else if (targetSubfolder === "useCases" || targetSubfolder === "usecases") {
4986
- targetLayer = "useCases";
4987
- } else if (targetSubfolder === "services") {
4988
- targetLayer = "services";
4989
- } else if (targetSubfolder === "infrastructure") {
4990
- targetLayer = "infrastructure";
4991
- } else if (targetSubfolder === "pxExpress" || targetSubfolder === "presentation" || targetSubfolder === "handlers" || targetSubfolder.startsWith("px")) {
4992
- targetLayer = "presentation";
4993
- }
4994
- const basePart = rest ? path2.basename(rest) : targetSubfolder;
4995
- const targetFileName = basePart.replace(/\.(js|ts|mjs|cjs)$/, "");
5083
+ if (classification.moduleType === "feature") {
5084
+ const rel = path26.relative(featuresBaseAbs, targetAbs).replace(/\\/g, "/");
5085
+ const parts = rel.split("/").filter(Boolean);
5086
+ const targetSubfolder = parts[1];
5087
+ const targetFileName = path26.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
4996
5088
  const isTargetPort = /^I[A-Z]/.test(targetFileName);
4997
5089
  const isTargetRepo = isTargetPort && targetFileName.includes("Repo");
4998
- const isTargetError = targetSubfolder === "errors" || rest.startsWith("errors/") || rest.includes("/errors/") || targetFileName.endsWith("Error") || targetFileName.endsWith("Errors");
5090
+ const isTargetError = targetSubfolder === "errors" || rel.includes("/errors/") || targetFileName.endsWith("Error") || targetFileName.endsWith("Errors");
4999
5091
  return {
5000
5092
  isExternal: false,
5001
5093
  isDiFramework: false,
5002
- targetFeature,
5003
- targetLayer,
5094
+ targetFeature: classification.moduleName,
5095
+ targetLayer: classification.layer,
5004
5096
  targetSubfolder,
5005
5097
  targetFileName,
5006
5098
  isTargetPort,
@@ -5008,25 +5100,21 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
5008
5100
  isTargetError
5009
5101
  };
5010
5102
  }
5011
- const sharedMatch = resolvedRel.match(/(?:^|\/)(?:src\/)?shared\/([^/]+)(?:\/(.*))?$/);
5012
- if (sharedMatch) {
5013
- const targetSharedModule = sharedMatch[1];
5014
- const sharedRest = sharedMatch[2] || "";
5015
- const isSharedRoot = !sharedRest.includes("/");
5016
- const isSharedPorts = sharedRest.startsWith("ports/") || sharedRest === "ports";
5017
- const isSharedInfra = sharedRest.startsWith("infrastructure/") || sharedRest === "infrastructure";
5018
- const isSharedDomain = sharedRest.startsWith("domain/") || sharedRest === "domain";
5103
+ if (classification.moduleType === "shared") {
5104
+ const targetFileName = path26.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
5105
+ const isTargetError = classification.layer === "domain" && (targetFileName.endsWith("Error") || targetFileName.endsWith("Errors") || targetAbs.includes("/errors/"));
5019
5106
  return {
5020
5107
  isExternal: false,
5021
5108
  isDiFramework: false,
5022
- targetSharedModule,
5023
- isSharedRoot,
5024
- isSharedPorts,
5025
- isSharedInfra,
5026
- isSharedDomain
5109
+ targetSharedModule: classification.moduleName,
5110
+ isSharedRoot: classification.layer === "root",
5111
+ isSharedPorts: classification.layer === "ports",
5112
+ isSharedInfra: classification.layer === "infrastructure",
5113
+ isSharedDomain: classification.layer === "domain",
5114
+ isTargetError
5027
5115
  };
5028
5116
  }
5029
- return { isExternal: true, isDiFramework: false, isGlobalConfig };
5117
+ return { isExternal: true, isDiFramework: false, isGlobalConfig: isTargetConfig };
5030
5118
  }
5031
5119
  function extractImportStatements(content) {
5032
5120
  const statements = [];
@@ -5148,22 +5236,50 @@ var FeatureDependencyGraph = class {
5148
5236
  return dfs(start);
5149
5237
  }
5150
5238
  };
5151
- function discoverAllFeatures(projectRoot) {
5152
- const featuresBase = resolveFeaturesDir(projectRoot);
5153
- if (!fs14.existsSync(featuresBase)) return [];
5154
- const entries = fs14.readdirSync(featuresBase, { withFileTypes: true });
5155
- return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "__tests__" && e.name !== "tests").map((e) => ({
5239
+ function discoverAllFeatures(featuresBaseAbs, excludeDirs = []) {
5240
+ const base = featuresBaseAbs;
5241
+ if (!fs17.existsSync(base)) return [];
5242
+ const excludeSet = new Set(excludeDirs.map((d) => path26.resolve(d)));
5243
+ const entries = fs17.readdirSync(base, { withFileTypes: true });
5244
+ return entries.filter((e) => {
5245
+ if (!e.isDirectory()) return false;
5246
+ if (e.name.startsWith(".")) return false;
5247
+ if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
5248
+ return false;
5249
+ }
5250
+ const resolved = path26.resolve(base, e.name);
5251
+ for (const ex of excludeSet) {
5252
+ if (ex === resolved || ex.startsWith(resolved + path26.sep) || resolved.startsWith(ex + path26.sep)) {
5253
+ return false;
5254
+ }
5255
+ }
5256
+ return true;
5257
+ }).map((e) => ({
5156
5258
  name: e.name,
5157
- dir: path2.join(featuresBase, e.name)
5259
+ dir: path26.join(base, e.name)
5158
5260
  })).sort((a, b) => a.name.localeCompare(b.name));
5159
5261
  }
5160
- function discoverAllShared(projectRoot) {
5161
- const sharedBase = resolveSharedDir(projectRoot);
5162
- if (!fs14.existsSync(sharedBase)) return [];
5163
- const entries = fs14.readdirSync(sharedBase, { withFileTypes: true });
5164
- return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "__tests__" && e.name !== "tests").map((e) => ({
5262
+ function discoverAllShared(sharedBaseAbs, excludeDirs = []) {
5263
+ const base = sharedBaseAbs;
5264
+ if (!fs17.existsSync(base)) return [];
5265
+ const excludeSet = new Set(excludeDirs.map((d) => path26.resolve(d)));
5266
+ const entries = fs17.readdirSync(base, { withFileTypes: true });
5267
+ return entries.filter((e) => {
5268
+ if (!e.isDirectory()) return false;
5269
+ if (e.name.startsWith(".")) return false;
5270
+ if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
5271
+ return false;
5272
+ }
5273
+ const resolved = path26.resolve(base, e.name);
5274
+ for (const ex of excludeSet) {
5275
+ if (ex === resolved || ex.startsWith(resolved + path26.sep) || resolved.startsWith(ex + path26.sep)) {
5276
+ return false;
5277
+ }
5278
+ }
5279
+ return true;
5280
+ }).map((e) => ({
5165
5281
  name: e.name,
5166
- dir: path2.join(sharedBase, e.name)
5282
+ dir: path26.join(base, e.name)
5167
5283
  })).sort((a, b) => a.name.localeCompare(b.name));
5168
5284
  }
5169
5285
  function extractClassMethods(content, className) {
@@ -5319,7 +5435,7 @@ function extractClassMethods(content, className) {
5319
5435
  return methods;
5320
5436
  }
5321
5437
  function checkUseCaseShape(featureName, filePath, relativePath, content, addViolation) {
5322
- const fileName = path2.basename(filePath);
5438
+ const fileName = path26.basename(filePath);
5323
5439
  const lines = content.split(/\r?\n/);
5324
5440
  const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
5325
5441
  if (!classMatch) {
@@ -5415,7 +5531,7 @@ private ${m.name}(...) { ... }`
5415
5531
  }
5416
5532
  }
5417
5533
  function checkServiceShape(featureName, filePath, relativePath, content, addViolation) {
5418
- const fileName = path2.basename(filePath);
5534
+ const fileName = path26.basename(filePath);
5419
5535
  const lines = content.split(/\r?\n/);
5420
5536
  const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
5421
5537
  if (!classMatch) {
@@ -5515,18 +5631,11 @@ function lintCodebase(options = {}) {
5515
5631
  const projectRoot = options.projectRoot || findProjectRoot(options.targetDir || process.cwd());
5516
5632
  const failFast = !options.complete;
5517
5633
  const lintConfig = loadLintConfig(projectRoot);
5518
- const baseErrorRelative = lintConfig.baseErrorPath || "src/errors/AppError.ts";
5519
- const baseErrorAbs = path2.resolve(projectRoot, baseErrorRelative);
5520
- const featuresBase = resolveFeaturesDir(projectRoot);
5521
- const sharedBase = resolveSharedDir(projectRoot);
5522
- let errorsBase = path2.join(projectRoot, "src/errors");
5523
- if (!fs14.existsSync(errorsBase) && fs14.existsSync(path2.join(projectRoot, "errors"))) {
5524
- errorsBase = path2.join(projectRoot, "errors");
5525
- }
5634
+ const { featuresBase, sharedBase, errorsBase } = getResolvedLintPaths(projectRoot, lintConfig);
5526
5635
  const missingFoundations = [];
5527
- if (!fs14.existsSync(featuresBase)) missingFoundations.push("features/");
5528
- if (!fs14.existsSync(sharedBase)) missingFoundations.push("shared/");
5529
- if (!fs14.existsSync(errorsBase)) missingFoundations.push("errors/");
5636
+ if (!fs17.existsSync(featuresBase)) missingFoundations.push("features/");
5637
+ if (!fs17.existsSync(sharedBase)) missingFoundations.push("shared/");
5638
+ if (!fs17.existsSync(errorsBase)) missingFoundations.push("errors/");
5530
5639
  if (missingFoundations.length > 0) {
5531
5640
  throw new DependencyRuleError(
5532
5641
  `Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every project must contain 'features/', 'shared/', and 'errors/'.`,
@@ -5534,20 +5643,22 @@ function lintCodebase(options = {}) {
5534
5643
  true
5535
5644
  );
5536
5645
  }
5537
- if (!fs14.existsSync(baseErrorAbs)) {
5646
+ const baseErrorRelative = lintConfig.baseErrorPath || path26.relative(projectRoot, path26.join(errorsBase, "AppError.ts")).replace(/\\/g, "/");
5647
+ const baseErrorAbs = path26.resolve(projectRoot, baseErrorRelative);
5648
+ if (!fs17.existsSync(baseErrorAbs)) {
5538
5649
  throw new DependencyRuleError(
5539
5650
  `Project Structure Violation: Base error class not found at '${baseErrorRelative}'. Create this file or update 'baseErrorPath' in mason-lint.config.json.`,
5540
5651
  [],
5541
5652
  true
5542
5653
  );
5543
5654
  }
5544
- const baseErrorContent = fs14.readFileSync(baseErrorAbs, "utf-8");
5655
+ const baseErrorContent = fs17.readFileSync(baseErrorAbs, "utf-8");
5545
5656
  const baseClassMatch = baseErrorContent.match(
5546
5657
  /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
5547
5658
  );
5548
5659
  const baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
5549
- const features = discoverAllFeatures(projectRoot);
5550
- const sharedModules = discoverAllShared(projectRoot);
5660
+ const features = discoverAllFeatures(featuresBase, [sharedBase, errorsBase]);
5661
+ const sharedModules = discoverAllShared(sharedBase, [featuresBase, errorsBase]);
5551
5662
  const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
5552
5663
  const allModules = [
5553
5664
  ...features.map((f) => ({ ...f, type: "feature" })),
@@ -5590,12 +5701,12 @@ Code: ${v.code}`;
5590
5701
  const allFiles = scanDirFiles(mod.dir, projectRoot);
5591
5702
  modResult.scannedFilesCount = allFiles.length;
5592
5703
  for (const file of allFiles) {
5593
- const relPath = path2.relative(projectRoot, file).replace(/\\/g, "/");
5594
- const { moduleType, moduleName, layer } = classifyFile(file, projectRoot);
5704
+ const relPath = path26.relative(projectRoot, file).replace(/\\/g, "/");
5705
+ const { moduleType, moduleName, layer } = classifyFile(file, featuresBase, sharedBase, errorsBase);
5595
5706
  if (!layer || !moduleType || !moduleName) continue;
5596
- const content = fs14.readFileSync(file, "utf-8");
5707
+ const content = fs17.readFileSync(file, "utf-8");
5597
5708
  const statements = extractImportStatements(content);
5598
- const baseName = path2.basename(file);
5709
+ const baseName = path26.basename(file);
5599
5710
  const isBarrel = baseName === "index.ts" || baseName === "index.js";
5600
5711
  const throwErrorRegex = /\bthrow\s+(?:new\s+)?Error\s*\(/g;
5601
5712
  let throwMatch;
@@ -5622,7 +5733,7 @@ Code: ${v.code}`;
5622
5733
  });
5623
5734
  }
5624
5735
  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");
5625
- const isBaseErrorFile = path2.resolve(file) === path2.resolve(baseErrorAbs);
5736
+ const isBaseErrorFile = path26.resolve(file) === path26.resolve(baseErrorAbs);
5626
5737
  if (isErrorFile && !isBaseErrorFile) {
5627
5738
  const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
5628
5739
  let classMatch;
@@ -5672,7 +5783,7 @@ Code: ${v.code}`;
5672
5783
  }
5673
5784
  if (moduleType === "error") {
5674
5785
  for (const stmt of statements) {
5675
- const target = classifyTarget(stmt.specifier, file, projectRoot);
5786
+ const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
5676
5787
  if (target.targetFeature) {
5677
5788
  addViolation({
5678
5789
  feature: "global-errors",
@@ -5738,7 +5849,7 @@ Code: ${v.code}`;
5738
5849
  }
5739
5850
  }
5740
5851
  for (const stmt of statements) {
5741
- const target = classifyTarget(stmt.specifier, file, projectRoot);
5852
+ const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
5742
5853
  if (target.targetFeature) {
5743
5854
  addViolation({
5744
5855
  feature: moduleName,
@@ -5868,7 +5979,7 @@ Code: ${v.code}`;
5868
5979
  }
5869
5980
  }
5870
5981
  for (const stmt of statements) {
5871
- const target = classifyTarget(stmt.specifier, file, projectRoot);
5982
+ const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
5872
5983
  if (target.targetFeature && target.targetFeature !== feat.name) {
5873
5984
  const evidence = {
5874
5985
  fromFeature: feat.name,