@solid-stack/mason 1.0.33 → 1.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +495 -394
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +493 -392
- package/dist/bin.js.map +1 -1
- package/dist/core/lintEngine.d.ts +10 -4
- package/dist/core/lintEngine.d.ts.map +1 -1
- package/dist/index.cjs +526 -393
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +524 -392
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lint.d.ts +7 -1
- package/dist/types/lint.d.ts.map +1 -1
- package/dist/utils/config.d.ts +16 -6
- package/dist/utils/config.d.ts.map +1 -1
- package/package.json +1 -1
- package/schema.json +7 -13
package/dist/bin.cjs
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
var cac = require('cac');
|
|
5
5
|
var p19 = require('@clack/prompts');
|
|
6
6
|
var pc13 = require('picocolors');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
7
|
+
var fs17 = require('fs');
|
|
8
|
+
var path26 = require('path');
|
|
9
9
|
var url = require('url');
|
|
10
10
|
var Handlebars = require('handlebars');
|
|
11
11
|
var child_process = require('child_process');
|
|
@@ -34,14 +34,14 @@ function _interopNamespace(e) {
|
|
|
34
34
|
|
|
35
35
|
var p19__namespace = /*#__PURE__*/_interopNamespace(p19);
|
|
36
36
|
var pc13__default = /*#__PURE__*/_interopDefault(pc13);
|
|
37
|
-
var
|
|
38
|
-
var
|
|
37
|
+
var fs17__default = /*#__PURE__*/_interopDefault(fs17);
|
|
38
|
+
var path26__default = /*#__PURE__*/_interopDefault(path26);
|
|
39
39
|
var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
|
|
40
40
|
|
|
41
41
|
function writeFileSafely(absolutePath, content, options = {}) {
|
|
42
42
|
const projectRoot = options.projectRoot || process.cwd();
|
|
43
|
-
const relPath =
|
|
44
|
-
const existedBefore =
|
|
43
|
+
const relPath = path26__default.default.relative(projectRoot, absolutePath).replace(/\\/g, "/");
|
|
44
|
+
const existedBefore = fs17__default.default.existsSync(absolutePath);
|
|
45
45
|
if (options.dryRun) {
|
|
46
46
|
return {
|
|
47
47
|
relativePath: relPath,
|
|
@@ -60,11 +60,11 @@ function writeFileSafely(absolutePath, content, options = {}) {
|
|
|
60
60
|
existedBefore: true
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
const dir =
|
|
64
|
-
if (!
|
|
65
|
-
|
|
63
|
+
const dir = path26__default.default.dirname(absolutePath);
|
|
64
|
+
if (!fs17__default.default.existsSync(dir)) {
|
|
65
|
+
fs17__default.default.mkdirSync(dir, { recursive: true });
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
fs17__default.default.writeFileSync(absolutePath, content, "utf-8");
|
|
68
68
|
return {
|
|
69
69
|
relativePath: relPath,
|
|
70
70
|
absolutePath,
|
|
@@ -155,17 +155,17 @@ function toStubName(ifaceName) {
|
|
|
155
155
|
return `Stub${base}`;
|
|
156
156
|
}
|
|
157
157
|
function loadMasonConfig(startDir = process.cwd()) {
|
|
158
|
-
let current =
|
|
158
|
+
let current = path26__default.default.resolve(startDir);
|
|
159
159
|
while (true) {
|
|
160
|
-
const configPath =
|
|
161
|
-
if (
|
|
160
|
+
const configPath = path26__default.default.join(current, "mason.config.json");
|
|
161
|
+
if (fs17__default.default.existsSync(configPath)) {
|
|
162
162
|
try {
|
|
163
|
-
return JSON.parse(
|
|
163
|
+
return JSON.parse(fs17__default.default.readFileSync(configPath, "utf-8"));
|
|
164
164
|
} catch {
|
|
165
165
|
return null;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
const parent =
|
|
168
|
+
const parent = path26__default.default.dirname(current);
|
|
169
169
|
if (parent === current) break;
|
|
170
170
|
current = parent;
|
|
171
171
|
}
|
|
@@ -175,70 +175,60 @@ function getEffectiveMode(projectRoot, flags) {
|
|
|
175
175
|
if (flags?.registry) return "registry";
|
|
176
176
|
const config = loadMasonConfig(projectRoot);
|
|
177
177
|
if (config?.mode) return config.mode;
|
|
178
|
-
if (
|
|
178
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "index.json")) && (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "features")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "shared")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/features")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/shared")))) {
|
|
179
179
|
return "registry";
|
|
180
180
|
}
|
|
181
181
|
return "app";
|
|
182
182
|
}
|
|
183
183
|
function getConfiguredFeaturesDir(projectRoot, flags) {
|
|
184
|
-
if (flags?.target) return
|
|
185
|
-
if (flags?.dest) return
|
|
184
|
+
if (flags?.target) return path26__default.default.resolve(projectRoot, flags.target);
|
|
185
|
+
if (flags?.dest) return path26__default.default.resolve(projectRoot, flags.dest);
|
|
186
186
|
const config = loadMasonConfig(projectRoot);
|
|
187
187
|
if (config?.paths?.features) {
|
|
188
|
-
return
|
|
188
|
+
return path26__default.default.resolve(projectRoot, config.paths.features);
|
|
189
189
|
}
|
|
190
190
|
const mode = getEffectiveMode(projectRoot, flags);
|
|
191
191
|
if (mode === "registry") {
|
|
192
|
-
if (
|
|
193
|
-
return
|
|
192
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/features"))) {
|
|
193
|
+
return path26__default.default.join(projectRoot, "src/features");
|
|
194
194
|
}
|
|
195
|
-
return
|
|
195
|
+
return path26__default.default.join(projectRoot, "features");
|
|
196
196
|
}
|
|
197
|
-
if (
|
|
198
|
-
return
|
|
197
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/features"))) {
|
|
198
|
+
return path26__default.default.join(projectRoot, "src/features");
|
|
199
199
|
}
|
|
200
|
-
return
|
|
200
|
+
return path26__default.default.join(projectRoot, "features");
|
|
201
201
|
}
|
|
202
202
|
function getConfiguredSharedDir(projectRoot, flags) {
|
|
203
|
-
if (flags?.target) return
|
|
204
|
-
if (flags?.dest) return
|
|
203
|
+
if (flags?.target) return path26__default.default.resolve(projectRoot, flags.target);
|
|
204
|
+
if (flags?.dest) return path26__default.default.resolve(projectRoot, flags.dest);
|
|
205
205
|
const config = loadMasonConfig(projectRoot);
|
|
206
206
|
if (config?.paths?.shared) {
|
|
207
|
-
return
|
|
207
|
+
return path26__default.default.resolve(projectRoot, config.paths.shared);
|
|
208
208
|
}
|
|
209
209
|
const mode = getEffectiveMode(projectRoot, flags);
|
|
210
210
|
if (mode === "registry") {
|
|
211
|
-
if (
|
|
212
|
-
return
|
|
211
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/shared"))) {
|
|
212
|
+
return path26__default.default.join(projectRoot, "src/shared");
|
|
213
213
|
}
|
|
214
|
-
return
|
|
214
|
+
return path26__default.default.join(projectRoot, "shared");
|
|
215
215
|
}
|
|
216
|
-
if (
|
|
217
|
-
return
|
|
216
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/shared"))) {
|
|
217
|
+
return path26__default.default.join(projectRoot, "src/shared");
|
|
218
218
|
}
|
|
219
|
-
return
|
|
220
|
-
}
|
|
221
|
-
function loadLintConfig(projectRoot) {
|
|
222
|
-
const configPath = path2__default.default.join(projectRoot, "mason-lint.config.json");
|
|
223
|
-
if (fs14__default.default.existsSync(configPath)) {
|
|
224
|
-
try {
|
|
225
|
-
return JSON.parse(fs14__default.default.readFileSync(configPath, "utf-8"));
|
|
226
|
-
} catch {
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return { baseErrorPath: "src/errors/AppError.ts" };
|
|
219
|
+
return path26__default.default.join(projectRoot, "shared");
|
|
230
220
|
}
|
|
231
221
|
|
|
232
222
|
// src/utils/project.ts
|
|
233
223
|
function findProjectRoot(startDir = process.cwd()) {
|
|
234
|
-
let current =
|
|
224
|
+
let current = path26__default.default.resolve(startDir);
|
|
235
225
|
while (true) {
|
|
236
|
-
if (
|
|
226
|
+
if (fs17__default.default.existsSync(path26__default.default.join(current, "package.json"))) {
|
|
237
227
|
return current;
|
|
238
228
|
}
|
|
239
|
-
const parent =
|
|
229
|
+
const parent = path26__default.default.dirname(current);
|
|
240
230
|
if (parent === current) {
|
|
241
|
-
return
|
|
231
|
+
return path26__default.default.resolve(startDir);
|
|
242
232
|
}
|
|
243
233
|
current = parent;
|
|
244
234
|
}
|
|
@@ -251,9 +241,9 @@ function resolveSharedDir(projectRoot, flags) {
|
|
|
251
241
|
}
|
|
252
242
|
function listExistingFeatures(projectRoot) {
|
|
253
243
|
const featuresDir = resolveFeaturesDir(projectRoot);
|
|
254
|
-
if (!
|
|
244
|
+
if (!fs17__default.default.existsSync(featuresDir)) return [];
|
|
255
245
|
try {
|
|
256
|
-
const entries =
|
|
246
|
+
const entries = fs17__default.default.readdirSync(featuresDir, { withFileTypes: true });
|
|
257
247
|
return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
258
248
|
} catch {
|
|
259
249
|
return [];
|
|
@@ -263,14 +253,14 @@ function listDomainInterfaces(projectRoot, featureName) {
|
|
|
263
253
|
const results = [];
|
|
264
254
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
265
255
|
for (const feat of features) {
|
|
266
|
-
const domainDir =
|
|
267
|
-
if (!
|
|
256
|
+
const domainDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
257
|
+
if (!fs17__default.default.existsSync(domainDir)) continue;
|
|
268
258
|
try {
|
|
269
|
-
const files =
|
|
259
|
+
const files = fs17__default.default.readdirSync(domainDir);
|
|
270
260
|
for (const file of files) {
|
|
271
261
|
if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
|
|
272
262
|
const name = file.replace(/\.ts$/, "");
|
|
273
|
-
const fullPath =
|
|
263
|
+
const fullPath = path26__default.default.join(domainDir, file);
|
|
274
264
|
if (/^I[A-Z]/.test(name)) {
|
|
275
265
|
results.push({
|
|
276
266
|
name,
|
|
@@ -279,7 +269,7 @@ function listDomainInterfaces(projectRoot, featureName) {
|
|
|
279
269
|
});
|
|
280
270
|
} else {
|
|
281
271
|
try {
|
|
282
|
-
const content =
|
|
272
|
+
const content = fs17__default.default.readFileSync(fullPath, "utf-8");
|
|
283
273
|
if (/export\s+(?:abstract\s+class|interface)\s+(\w+)/.test(content)) {
|
|
284
274
|
results.push({
|
|
285
275
|
name,
|
|
@@ -301,17 +291,17 @@ function listDomainEntities(projectRoot, featureName) {
|
|
|
301
291
|
const results = [];
|
|
302
292
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
303
293
|
for (const feat of features) {
|
|
304
|
-
const domainDir =
|
|
305
|
-
if (!
|
|
294
|
+
const domainDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
295
|
+
if (!fs17__default.default.existsSync(domainDir)) continue;
|
|
306
296
|
try {
|
|
307
|
-
const files =
|
|
297
|
+
const files = fs17__default.default.readdirSync(domainDir);
|
|
308
298
|
for (const file of files) {
|
|
309
299
|
if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
|
|
310
300
|
const name = file.replace(/\.ts$/, "");
|
|
311
301
|
if (!/^I[A-Z]/.test(name)) {
|
|
312
302
|
results.push({
|
|
313
303
|
name,
|
|
314
|
-
fullPath:
|
|
304
|
+
fullPath: path26__default.default.join(domainDir, file),
|
|
315
305
|
feature: feat
|
|
316
306
|
});
|
|
317
307
|
}
|
|
@@ -326,16 +316,16 @@ function listUseCases(projectRoot, featureName) {
|
|
|
326
316
|
const results = [];
|
|
327
317
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
328
318
|
for (const feat of features) {
|
|
329
|
-
const useCasesDir =
|
|
330
|
-
if (!
|
|
319
|
+
const useCasesDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "useCases");
|
|
320
|
+
if (!fs17__default.default.existsSync(useCasesDir)) continue;
|
|
331
321
|
try {
|
|
332
|
-
const files =
|
|
322
|
+
const files = fs17__default.default.readdirSync(useCasesDir);
|
|
333
323
|
for (const file of files) {
|
|
334
324
|
if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
|
|
335
325
|
const name = file.replace(/\.ts$/, "");
|
|
336
326
|
results.push({
|
|
337
327
|
name,
|
|
338
|
-
fullPath:
|
|
328
|
+
fullPath: path26__default.default.join(useCasesDir, file),
|
|
339
329
|
feature: feat
|
|
340
330
|
});
|
|
341
331
|
}
|
|
@@ -361,33 +351,33 @@ hbs.registerHelper("join", (arr, sep) => {
|
|
|
361
351
|
});
|
|
362
352
|
var cachedTemplatesDir = null;
|
|
363
353
|
function getTemplatesDir() {
|
|
364
|
-
if (cachedTemplatesDir &&
|
|
354
|
+
if (cachedTemplatesDir && fs17__default.default.existsSync(cachedTemplatesDir)) {
|
|
365
355
|
return cachedTemplatesDir;
|
|
366
356
|
}
|
|
367
|
-
const currentDir = typeof __dirname !== "undefined" ? __dirname :
|
|
368
|
-
const cand1 =
|
|
369
|
-
if (
|
|
357
|
+
const currentDir = typeof __dirname !== "undefined" ? __dirname : path26__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bin.cjs', document.baseURI).href))));
|
|
358
|
+
const cand1 = path26__default.default.resolve(currentDir, "../../templates");
|
|
359
|
+
if (fs17__default.default.existsSync(cand1)) {
|
|
370
360
|
cachedTemplatesDir = cand1;
|
|
371
361
|
return cand1;
|
|
372
362
|
}
|
|
373
|
-
const cand2 =
|
|
374
|
-
if (
|
|
363
|
+
const cand2 = path26__default.default.resolve(currentDir, "../templates");
|
|
364
|
+
if (fs17__default.default.existsSync(cand2)) {
|
|
375
365
|
cachedTemplatesDir = cand2;
|
|
376
366
|
return cand2;
|
|
377
367
|
}
|
|
378
|
-
const cand3 =
|
|
379
|
-
if (
|
|
368
|
+
const cand3 = path26__default.default.resolve(currentDir, "templates");
|
|
369
|
+
if (fs17__default.default.existsSync(cand3)) {
|
|
380
370
|
cachedTemplatesDir = cand3;
|
|
381
371
|
return cand3;
|
|
382
372
|
}
|
|
383
373
|
let curr = currentDir;
|
|
384
374
|
while (true) {
|
|
385
|
-
const candTemplates =
|
|
386
|
-
if (
|
|
375
|
+
const candTemplates = path26__default.default.join(curr, "templates");
|
|
376
|
+
if (fs17__default.default.existsSync(candTemplates)) {
|
|
387
377
|
cachedTemplatesDir = candTemplates;
|
|
388
378
|
return candTemplates;
|
|
389
379
|
}
|
|
390
|
-
const parent =
|
|
380
|
+
const parent = path26__default.default.dirname(curr);
|
|
391
381
|
if (parent === curr) break;
|
|
392
382
|
curr = parent;
|
|
393
383
|
}
|
|
@@ -395,8 +385,8 @@ function getTemplatesDir() {
|
|
|
395
385
|
}
|
|
396
386
|
var templateCache = /* @__PURE__ */ new Map();
|
|
397
387
|
function loadTemplate(relativePath) {
|
|
398
|
-
const fullPath =
|
|
399
|
-
return
|
|
388
|
+
const fullPath = path26__default.default.isAbsolute(relativePath) ? relativePath : path26__default.default.join(getTemplatesDir(), relativePath);
|
|
389
|
+
return fs17__default.default.readFileSync(fullPath, "utf-8");
|
|
400
390
|
}
|
|
401
391
|
function renderTemplateFile(relativePath, context) {
|
|
402
392
|
let compiled = templateCache.get(relativePath);
|
|
@@ -483,8 +473,8 @@ function generateDomainEntityCode(name, kind = "interface", properties = []) {
|
|
|
483
473
|
function generateDomain(options) {
|
|
484
474
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
485
475
|
const entityName = toPascalCase(options.name);
|
|
486
|
-
const targetDir = options.targetDir ||
|
|
487
|
-
const filePath =
|
|
476
|
+
const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
|
|
477
|
+
const filePath = path26__default.default.join(targetDir, `${entityName}.ts`);
|
|
488
478
|
const code = generateDomainEntityCode(
|
|
489
479
|
entityName,
|
|
490
480
|
options.kind || "interface",
|
|
@@ -533,8 +523,8 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
|
|
|
533
523
|
function generateInterface(options) {
|
|
534
524
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
535
525
|
const ifaceName = ensureInterfacePrefix(options.name);
|
|
536
|
-
const targetDir = options.targetDir ||
|
|
537
|
-
const filePath =
|
|
526
|
+
const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
|
|
527
|
+
const filePath = path26__default.default.join(targetDir, `${ifaceName}.ts`);
|
|
538
528
|
const code = generateInterfaceCode(
|
|
539
529
|
ifaceName,
|
|
540
530
|
options.kind || "abstractClass",
|
|
@@ -769,7 +759,7 @@ function parseInterfaceMethodsAndImports(content, targetIfaceName) {
|
|
|
769
759
|
};
|
|
770
760
|
}
|
|
771
761
|
function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
|
|
772
|
-
if (customPath &&
|
|
762
|
+
if (customPath && fs17__default.default.existsSync(customPath)) {
|
|
773
763
|
return { filePath: customPath, ifaceName };
|
|
774
764
|
}
|
|
775
765
|
const candidateNames = [
|
|
@@ -779,22 +769,22 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
|
|
|
779
769
|
];
|
|
780
770
|
const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
|
|
781
771
|
for (const feat of features) {
|
|
782
|
-
const domainDir =
|
|
783
|
-
if (!
|
|
772
|
+
const domainDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
773
|
+
if (!fs17__default.default.existsSync(domainDir)) continue;
|
|
784
774
|
for (const cand of candidateNames) {
|
|
785
|
-
const p1 =
|
|
786
|
-
if (
|
|
775
|
+
const p1 = path26__default.default.join(domainDir, `${cand}.ts`);
|
|
776
|
+
if (fs17__default.default.existsSync(p1)) {
|
|
787
777
|
return { filePath: p1, ifaceName: cand, feature: feat };
|
|
788
778
|
}
|
|
789
779
|
}
|
|
790
780
|
}
|
|
791
781
|
for (const cand of candidateNames) {
|
|
792
|
-
const p1 =
|
|
793
|
-
if (
|
|
794
|
-
const p22 =
|
|
795
|
-
if (
|
|
796
|
-
const p32 =
|
|
797
|
-
if (
|
|
782
|
+
const p1 = path26__default.default.join(projectRoot, "domain", `${cand}.ts`);
|
|
783
|
+
if (fs17__default.default.existsSync(p1)) return { filePath: p1, ifaceName: cand };
|
|
784
|
+
const p22 = path26__default.default.join(projectRoot, "src", "domain", `${cand}.ts`);
|
|
785
|
+
if (fs17__default.default.existsSync(p22)) return { filePath: p22, ifaceName: cand };
|
|
786
|
+
const p32 = path26__default.default.join(projectRoot, "interfaces", `${cand}.ts`);
|
|
787
|
+
if (fs17__default.default.existsSync(p32)) return { filePath: p32, ifaceName: cand };
|
|
798
788
|
}
|
|
799
789
|
return null;
|
|
800
790
|
}
|
|
@@ -817,7 +807,7 @@ function loadInterfaceHierarchy(projectRoot, initialIfaceName, featureName, cust
|
|
|
817
807
|
while (currentFile && !visited.has(currentFile)) {
|
|
818
808
|
visited.add(currentFile);
|
|
819
809
|
try {
|
|
820
|
-
const content =
|
|
810
|
+
const content = fs17__default.default.readFileSync(currentFile, "utf-8");
|
|
821
811
|
const parsed = parseInterfaceMethodsAndImports(content, currentName);
|
|
822
812
|
for (const m of parsed.methods) {
|
|
823
813
|
if (!allMethods.some((existing) => existing.name === m.name)) {
|
|
@@ -893,7 +883,7 @@ function generateStubCode(stubClassName, ifaceName, entityName, featureName, met
|
|
|
893
883
|
const entitiesVar = `${entityVar}s`;
|
|
894
884
|
const idKey = `${entityVar}Id`;
|
|
895
885
|
const impPath = ifaceImportPath || `../domain/${ifaceName}.js`;
|
|
896
|
-
const entityImportPath = ifaceImportPath ? `${
|
|
886
|
+
const entityImportPath = ifaceImportPath ? `${path26__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
|
|
897
887
|
const importsByFrom = /* @__PURE__ */ new Map();
|
|
898
888
|
for (const imp of domainImports) {
|
|
899
889
|
if (imp.name === ifaceName || imp.name === baseEntity) continue;
|
|
@@ -942,7 +932,7 @@ function generateConcreteInfraCode(className, ifaceName, dependencies = [], meth
|
|
|
942
932
|
if (baseEntity) {
|
|
943
933
|
finalMethods = synthesizeCrudMethods(baseEntity);
|
|
944
934
|
if (!finalDomainImports.some((imp) => imp.name === baseEntity)) {
|
|
945
|
-
const importPath = ifaceImportPath ? `${
|
|
935
|
+
const importPath = ifaceImportPath ? `${path26__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
|
|
946
936
|
finalDomainImports.push({
|
|
947
937
|
name: baseEntity,
|
|
948
938
|
from: importPath,
|
|
@@ -987,8 +977,8 @@ function generateInfrastructure(options) {
|
|
|
987
977
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
988
978
|
const className = toPascalCase(options.name);
|
|
989
979
|
const isFeatureScope = options.scope !== "global" && Boolean(options.feature);
|
|
990
|
-
const targetDir = options.targetDir || (isFeatureScope ?
|
|
991
|
-
const filePath =
|
|
980
|
+
const targetDir = options.targetDir || (isFeatureScope ? path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path26__default.default.join(projectRoot, "infrastructure"));
|
|
981
|
+
const filePath = path26__default.default.join(targetDir, `${className}.ts`);
|
|
992
982
|
let code;
|
|
993
983
|
if (options.implementsInterface) {
|
|
994
984
|
const rawIfaceName = options.implementsInterface;
|
|
@@ -1002,7 +992,7 @@ function generateInfrastructure(options) {
|
|
|
1002
992
|
const ifaceFilePath = hierarchy.ifaceFilePath;
|
|
1003
993
|
let ifaceImportPath;
|
|
1004
994
|
if (ifaceFilePath) {
|
|
1005
|
-
let rel =
|
|
995
|
+
let rel = path26__default.default.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
|
|
1006
996
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
1007
997
|
ifaceImportPath = rel;
|
|
1008
998
|
} else if (isFeatureScope) {
|
|
@@ -1015,8 +1005,8 @@ function generateInfrastructure(options) {
|
|
|
1015
1005
|
if (new RegExp(`\\b${item.name}\\b`).test(allSignatures)) {
|
|
1016
1006
|
let fromPath;
|
|
1017
1007
|
if (imp.specifier.startsWith(".") && ifaceFilePath) {
|
|
1018
|
-
const absTarget =
|
|
1019
|
-
let rel =
|
|
1008
|
+
const absTarget = path26__default.default.resolve(path26__default.default.dirname(ifaceFilePath), imp.specifier);
|
|
1009
|
+
let rel = path26__default.default.relative(targetDir, absTarget).replace(/\\/g, "/");
|
|
1020
1010
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
1021
1011
|
fromPath = rel;
|
|
1022
1012
|
} else {
|
|
@@ -1203,8 +1193,8 @@ function generateUseCase(options) {
|
|
|
1203
1193
|
const files = [];
|
|
1204
1194
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1205
1195
|
const ucName = toPascalCase(options.name);
|
|
1206
|
-
const targetDir = options.targetDir ||
|
|
1207
|
-
const filePath =
|
|
1196
|
+
const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
|
|
1197
|
+
const filePath = path26__default.default.join(targetDir, `${ucName}.ts`);
|
|
1208
1198
|
const code = generateUseCaseCode(
|
|
1209
1199
|
ucName,
|
|
1210
1200
|
options.dependencies || [],
|
|
@@ -1220,7 +1210,7 @@ function generateUseCase(options) {
|
|
|
1220
1210
|
})
|
|
1221
1211
|
);
|
|
1222
1212
|
if (options.includeTest) {
|
|
1223
|
-
const testPath =
|
|
1213
|
+
const testPath = path26__default.default.join(targetDir, `${ucName}.test.ts`);
|
|
1224
1214
|
const testCode = generateUseCaseTestCode(ucName, options.dependencies || []);
|
|
1225
1215
|
files.push(
|
|
1226
1216
|
writeFileSafely(testPath, testCode, {
|
|
@@ -1288,10 +1278,10 @@ function generateHttpHandler(options) {
|
|
|
1288
1278
|
const files = [];
|
|
1289
1279
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1290
1280
|
const className = toPascalCase(options.name);
|
|
1291
|
-
const pxDir =
|
|
1292
|
-
const handlersDir =
|
|
1293
|
-
const pxIndexPath =
|
|
1294
|
-
if (!
|
|
1281
|
+
const pxDir = path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
|
|
1282
|
+
const handlersDir = path26__default.default.join(pxDir, "handlers");
|
|
1283
|
+
const pxIndexPath = path26__default.default.join(pxDir, "index.ts");
|
|
1284
|
+
if (!fs17__default.default.existsSync(pxIndexPath)) {
|
|
1295
1285
|
const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
|
|
1296
1286
|
const pxIndexContent = renderTemplate(expressIndexTemplate, {
|
|
1297
1287
|
routePath: featurePath
|
|
@@ -1304,7 +1294,7 @@ function generateHttpHandler(options) {
|
|
|
1304
1294
|
})
|
|
1305
1295
|
);
|
|
1306
1296
|
}
|
|
1307
|
-
const handlerFilePath =
|
|
1297
|
+
const handlerFilePath = path26__default.default.join(handlersDir, `${className}.ts`);
|
|
1308
1298
|
const code = generateHttpHandlerCode(
|
|
1309
1299
|
className,
|
|
1310
1300
|
options.method || "get",
|
|
@@ -1325,11 +1315,11 @@ function generateHttpHandler(options) {
|
|
|
1325
1315
|
return files;
|
|
1326
1316
|
}
|
|
1327
1317
|
function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], options = {}) {
|
|
1328
|
-
const providerPath =
|
|
1318
|
+
const providerPath = path26__default.default.join(featureDir, "diProvider.ts");
|
|
1329
1319
|
const pascalFeature = toPascalCase(featureName);
|
|
1330
1320
|
const providerModuleName = `${pascalFeature}Provider`;
|
|
1331
|
-
if (
|
|
1332
|
-
let content =
|
|
1321
|
+
if (fs17__default.default.existsSync(providerPath) && !options.overwrite) {
|
|
1322
|
+
let content = fs17__default.default.readFileSync(providerPath, "utf-8");
|
|
1333
1323
|
content = content.replace(/\n*export\s+const\s+ScaffoldProvider\s*=[^;]+;?/g, "");
|
|
1334
1324
|
for (const b of bindings) {
|
|
1335
1325
|
const ifaceImp = b.ifaceImportPath || `./domain/${b.ifaceName}.js`;
|
|
@@ -1388,7 +1378,7 @@ function generateFeature(options) {
|
|
|
1388
1378
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1389
1379
|
const rawName = options.name.trim();
|
|
1390
1380
|
const featureName = toCamelCase(rawName);
|
|
1391
|
-
const targetDir = options.targetDir ||
|
|
1381
|
+
const targetDir = options.targetDir || path26__default.default.join(resolveFeaturesDir(projectRoot), featureName);
|
|
1392
1382
|
const routePath = options.routePath || `/${featureName}`;
|
|
1393
1383
|
const rawEntities = [];
|
|
1394
1384
|
if (options.entityNames && options.entityNames.length > 0) {
|
|
@@ -1409,7 +1399,7 @@ function generateFeature(options) {
|
|
|
1409
1399
|
const domainFile = generateDomain({
|
|
1410
1400
|
name: ent,
|
|
1411
1401
|
feature: featureName,
|
|
1412
|
-
targetDir:
|
|
1402
|
+
targetDir: path26__default.default.join(targetDir, "domain"),
|
|
1413
1403
|
projectRoot,
|
|
1414
1404
|
dryRun: options.dryRun,
|
|
1415
1405
|
overwrite: options.overwrite,
|
|
@@ -1429,7 +1419,7 @@ function generateFeature(options) {
|
|
|
1429
1419
|
const ifaceFile = generateInterface({
|
|
1430
1420
|
name: ifaceName,
|
|
1431
1421
|
feature: featureName,
|
|
1432
|
-
targetDir:
|
|
1422
|
+
targetDir: path26__default.default.join(targetDir, "domain"),
|
|
1433
1423
|
entityName: ent,
|
|
1434
1424
|
projectRoot,
|
|
1435
1425
|
dryRun: options.dryRun,
|
|
@@ -1446,7 +1436,7 @@ function generateFeature(options) {
|
|
|
1446
1436
|
const stubFile = generateInfrastructure({
|
|
1447
1437
|
name: stubName,
|
|
1448
1438
|
feature: featureName,
|
|
1449
|
-
targetDir:
|
|
1439
|
+
targetDir: path26__default.default.join(targetDir, "infrastructure"),
|
|
1450
1440
|
kind: "stub",
|
|
1451
1441
|
implementsInterface: ifaceName,
|
|
1452
1442
|
entityName: ent,
|
|
@@ -1488,7 +1478,7 @@ function generateFeature(options) {
|
|
|
1488
1478
|
const ucFiles = generateUseCase({
|
|
1489
1479
|
name: ucName,
|
|
1490
1480
|
feature: featureName,
|
|
1491
|
-
targetDir:
|
|
1481
|
+
targetDir: path26__default.default.join(targetDir, "useCases"),
|
|
1492
1482
|
dependencies: options.includeInterface !== false ? [ifaceName] : [],
|
|
1493
1483
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1494
1484
|
outputProperties: [{ name: entVar, type: primaryEntity }],
|
|
@@ -1533,7 +1523,7 @@ function generateFeature(options) {
|
|
|
1533
1523
|
const ucFiles = generateUseCase({
|
|
1534
1524
|
name: ucName,
|
|
1535
1525
|
feature: featureName,
|
|
1536
|
-
targetDir:
|
|
1526
|
+
targetDir: path26__default.default.join(targetDir, "useCases"),
|
|
1537
1527
|
dependencies: deps,
|
|
1538
1528
|
inputProperties: [{ name: entVar, type: ent }],
|
|
1539
1529
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1566,7 +1556,7 @@ function generateFeature(options) {
|
|
|
1566
1556
|
const ucFiles = generateUseCase({
|
|
1567
1557
|
name: ucName,
|
|
1568
1558
|
feature: featureName,
|
|
1569
|
-
targetDir:
|
|
1559
|
+
targetDir: path26__default.default.join(targetDir, "useCases"),
|
|
1570
1560
|
dependencies: deps,
|
|
1571
1561
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1572
1562
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1599,7 +1589,7 @@ function generateFeature(options) {
|
|
|
1599
1589
|
const ucFiles = generateUseCase({
|
|
1600
1590
|
name: ucName,
|
|
1601
1591
|
feature: featureName,
|
|
1602
|
-
targetDir:
|
|
1592
|
+
targetDir: path26__default.default.join(targetDir, "useCases"),
|
|
1603
1593
|
dependencies: deps,
|
|
1604
1594
|
inputProperties: [
|
|
1605
1595
|
{ name: "page", type: "number", optional: true },
|
|
@@ -1643,7 +1633,7 @@ function generateFeature(options) {
|
|
|
1643
1633
|
const ucFiles = generateUseCase({
|
|
1644
1634
|
name: ucName,
|
|
1645
1635
|
feature: featureName,
|
|
1646
|
-
targetDir:
|
|
1636
|
+
targetDir: path26__default.default.join(targetDir, "useCases"),
|
|
1647
1637
|
dependencies: deps,
|
|
1648
1638
|
inputProperties: [{ name: entVar, type: ent }],
|
|
1649
1639
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1676,7 +1666,7 @@ function generateFeature(options) {
|
|
|
1676
1666
|
const ucFiles = generateUseCase({
|
|
1677
1667
|
name: ucName,
|
|
1678
1668
|
feature: featureName,
|
|
1679
|
-
targetDir:
|
|
1669
|
+
targetDir: path26__default.default.join(targetDir, "useCases"),
|
|
1680
1670
|
dependencies: deps,
|
|
1681
1671
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1682
1672
|
outputProperties: [{ name: "success", type: "boolean" }],
|
|
@@ -1713,7 +1703,7 @@ function generateFeature(options) {
|
|
|
1713
1703
|
const ucFiles = generateUseCase({
|
|
1714
1704
|
name: ucName,
|
|
1715
1705
|
feature: featureName,
|
|
1716
|
-
targetDir:
|
|
1706
|
+
targetDir: path26__default.default.join(targetDir, "useCases"),
|
|
1717
1707
|
dependencies: customUc.dependencies || [],
|
|
1718
1708
|
inputProperties: customUc.inputProperties || [],
|
|
1719
1709
|
outputProperties: customUc.outputProperties || [],
|
|
@@ -1745,8 +1735,8 @@ function generateFeature(options) {
|
|
|
1745
1735
|
}
|
|
1746
1736
|
}
|
|
1747
1737
|
if (options.includeExpress !== false) {
|
|
1748
|
-
const pxDir =
|
|
1749
|
-
const pxIndexPath =
|
|
1738
|
+
const pxDir = path26__default.default.join(targetDir, "pxExpress");
|
|
1739
|
+
const pxIndexPath = path26__default.default.join(pxDir, "index.ts");
|
|
1750
1740
|
if (!files.some((f) => f.absolutePath === pxIndexPath)) {
|
|
1751
1741
|
const pxIndexContent = renderTemplate(expressIndexTemplate, { routePath });
|
|
1752
1742
|
files.push(
|
|
@@ -1876,7 +1866,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
1876
1866
|
}
|
|
1877
1867
|
const normalizedName = toCamelCase(name);
|
|
1878
1868
|
const baseFeaturesDir = resolveFeaturesDir(projectRoot, flags);
|
|
1879
|
-
const defaultDir =
|
|
1869
|
+
const defaultDir = path26__default.default.relative(projectRoot, path26__default.default.join(baseFeaturesDir, normalizedName));
|
|
1880
1870
|
let targetDirRel = defaultDir;
|
|
1881
1871
|
if (!flags.yes && !flags.target && !flags.dest) {
|
|
1882
1872
|
targetDirRel = handleCancel(
|
|
@@ -1887,7 +1877,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
1887
1877
|
})
|
|
1888
1878
|
).trim();
|
|
1889
1879
|
}
|
|
1890
|
-
const targetDir = flags.dest ?
|
|
1880
|
+
const targetDir = flags.dest ? path26__default.default.resolve(projectRoot, flags.dest) : flags.target ? path26__default.default.resolve(projectRoot, flags.target) : path26__default.default.resolve(projectRoot, targetDirRel);
|
|
1891
1881
|
let includeExpress = flags.express !== void 0 ? Boolean(flags.express) : true;
|
|
1892
1882
|
let routePath = `/${normalizedName}`;
|
|
1893
1883
|
let includeDomain = true;
|
|
@@ -2129,8 +2119,8 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
2129
2119
|
};
|
|
2130
2120
|
const files = generateFeature(options);
|
|
2131
2121
|
if (isRegistry) {
|
|
2132
|
-
const registryPath =
|
|
2133
|
-
if (!
|
|
2122
|
+
const registryPath = path26__default.default.join(targetDir, "registry.json");
|
|
2123
|
+
if (!fs17__default.default.existsSync(registryPath)) {
|
|
2134
2124
|
const manifest = {
|
|
2135
2125
|
name: toKebabCase(normalizedName),
|
|
2136
2126
|
type: "feature",
|
|
@@ -2156,7 +2146,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
2156
2146
|
printGeneratedFiles(files, options.dryRun);
|
|
2157
2147
|
p19__namespace.outro(
|
|
2158
2148
|
pc13__default.default.green(
|
|
2159
|
-
`\u2713 Feature '${normalizedName}' initialized in ${
|
|
2149
|
+
`\u2713 Feature '${normalizedName}' initialized in ${path26__default.default.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
|
|
2160
2150
|
)
|
|
2161
2151
|
);
|
|
2162
2152
|
}
|
|
@@ -2167,7 +2157,7 @@ function generateShared(options) {
|
|
|
2167
2157
|
const pascalName = toPascalCase(rawName);
|
|
2168
2158
|
const camelName = toCamelCase(rawName);
|
|
2169
2159
|
const kebabName = toKebabCase(rawName);
|
|
2170
|
-
const targetDir = options.targetDir ||
|
|
2160
|
+
const targetDir = options.targetDir || path26__default.default.join(resolveSharedDir(projectRoot), kebabName);
|
|
2171
2161
|
const fileDefs = [];
|
|
2172
2162
|
const facadeContent = `import { MakeInjectable, type DepsType } from "@solid-stack/di";
|
|
2173
2163
|
import { I${pascalName}Engine } from "./ports/I${pascalName}Engine.js";
|
|
@@ -2179,7 +2169,7 @@ export class ${pascalName} {
|
|
|
2179
2169
|
}
|
|
2180
2170
|
`;
|
|
2181
2171
|
fileDefs.push({
|
|
2182
|
-
absolutePath:
|
|
2172
|
+
absolutePath: path26__default.default.join(targetDir, `${pascalName}.ts`),
|
|
2183
2173
|
content: facadeContent
|
|
2184
2174
|
});
|
|
2185
2175
|
const portContent = `export abstract class I${pascalName}Engine {
|
|
@@ -2187,7 +2177,7 @@ export class ${pascalName} {
|
|
|
2187
2177
|
}
|
|
2188
2178
|
`;
|
|
2189
2179
|
fileDefs.push({
|
|
2190
|
-
absolutePath:
|
|
2180
|
+
absolutePath: path26__default.default.join(targetDir, "ports", `I${pascalName}Engine.ts`),
|
|
2191
2181
|
content: portContent
|
|
2192
2182
|
});
|
|
2193
2183
|
const concreteContent = `import { MakeInjectable } from "@solid-stack/di";
|
|
@@ -2199,7 +2189,7 @@ export class Default${pascalName}Engine implements I${pascalName}Engine {
|
|
|
2199
2189
|
}
|
|
2200
2190
|
`;
|
|
2201
2191
|
fileDefs.push({
|
|
2202
|
-
absolutePath:
|
|
2192
|
+
absolutePath: path26__default.default.join(targetDir, "infrastructure", `Default${pascalName}Engine.ts`),
|
|
2203
2193
|
content: concreteContent
|
|
2204
2194
|
});
|
|
2205
2195
|
if (options.includeStub !== false) {
|
|
@@ -2212,7 +2202,7 @@ export class Stub${pascalName}Engine implements I${pascalName}Engine {
|
|
|
2212
2202
|
}
|
|
2213
2203
|
`;
|
|
2214
2204
|
fileDefs.push({
|
|
2215
|
-
absolutePath:
|
|
2205
|
+
absolutePath: path26__default.default.join(targetDir, "infrastructure", `Stub${pascalName}Engine.ts`),
|
|
2216
2206
|
content: stubContent
|
|
2217
2207
|
});
|
|
2218
2208
|
}
|
|
@@ -2227,7 +2217,7 @@ export const diProvider = (c: Container): void => {
|
|
|
2227
2217
|
export default diProvider;
|
|
2228
2218
|
`;
|
|
2229
2219
|
fileDefs.push({
|
|
2230
|
-
absolutePath:
|
|
2220
|
+
absolutePath: path26__default.default.join(targetDir, "diProvider.ts"),
|
|
2231
2221
|
content: providerContent
|
|
2232
2222
|
});
|
|
2233
2223
|
if (options.isRegistry) {
|
|
@@ -2244,7 +2234,7 @@ export default diProvider;
|
|
|
2244
2234
|
files: []
|
|
2245
2235
|
};
|
|
2246
2236
|
fileDefs.push({
|
|
2247
|
-
absolutePath:
|
|
2237
|
+
absolutePath: path26__default.default.join(targetDir, "registry.json"),
|
|
2248
2238
|
content: JSON.stringify(registryManifest, null, 2) + "\n"
|
|
2249
2239
|
});
|
|
2250
2240
|
}
|
|
@@ -2281,7 +2271,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
|
|
|
2281
2271
|
}
|
|
2282
2272
|
const normalizedName = toKebabCase(name);
|
|
2283
2273
|
const baseSharedDir = resolveSharedDir(projectRoot, flags);
|
|
2284
|
-
const defaultDir =
|
|
2274
|
+
const defaultDir = path26__default.default.relative(projectRoot, path26__default.default.join(baseSharedDir, normalizedName));
|
|
2285
2275
|
let targetDirRel = defaultDir;
|
|
2286
2276
|
if (!flags.yes && !flags.target && !flags.dest) {
|
|
2287
2277
|
targetDirRel = handleCancel(
|
|
@@ -2292,7 +2282,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
|
|
|
2292
2282
|
})
|
|
2293
2283
|
).trim();
|
|
2294
2284
|
}
|
|
2295
|
-
const targetDir = flags.dest ?
|
|
2285
|
+
const targetDir = flags.dest ? path26__default.default.resolve(projectRoot, flags.dest) : flags.target ? path26__default.default.resolve(projectRoot, flags.target) : path26__default.default.resolve(projectRoot, targetDirRel);
|
|
2296
2286
|
let description = flags.description || "";
|
|
2297
2287
|
let includeStub = true;
|
|
2298
2288
|
if (!flags.yes) {
|
|
@@ -2326,7 +2316,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
|
|
|
2326
2316
|
printGeneratedFiles(files, Boolean(flags.dryRun));
|
|
2327
2317
|
p19__namespace.outro(
|
|
2328
2318
|
pc13__default.default.green(
|
|
2329
|
-
`\u2713 Shared module '${normalizedName}' initialized in ${
|
|
2319
|
+
`\u2713 Shared module '${normalizedName}' initialized in ${path26__default.default.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
|
|
2330
2320
|
)
|
|
2331
2321
|
);
|
|
2332
2322
|
}
|
|
@@ -2753,7 +2743,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
|
|
|
2753
2743
|
const infraFile = generateInfrastructure(options);
|
|
2754
2744
|
files.push(infraFile);
|
|
2755
2745
|
if (registerInProvider && scope === "feature" && feature && implementsInterface) {
|
|
2756
|
-
const featureDir =
|
|
2746
|
+
const featureDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feature);
|
|
2757
2747
|
const providerFile = updateOrGenerateDiProvider(
|
|
2758
2748
|
featureDir,
|
|
2759
2749
|
feature,
|
|
@@ -2915,7 +2905,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
|
|
|
2915
2905
|
files.push(stubFile);
|
|
2916
2906
|
}
|
|
2917
2907
|
if (registerInProvider && generateStub) {
|
|
2918
|
-
const featureDir =
|
|
2908
|
+
const featureDir = path26__default.default.join(resolveFeaturesDir(projectRoot), feature);
|
|
2919
2909
|
const providerFile = updateOrGenerateDiProvider(
|
|
2920
2910
|
featureDir,
|
|
2921
2911
|
feature,
|
|
@@ -3103,21 +3093,21 @@ function generateInjectable(options) {
|
|
|
3103
3093
|
const className = toPascalCase(options.name);
|
|
3104
3094
|
let targetDir = "";
|
|
3105
3095
|
if (options.customPath) {
|
|
3106
|
-
targetDir =
|
|
3096
|
+
targetDir = path26__default.default.isAbsolute(options.customPath) ? options.customPath : path26__default.default.join(projectRoot, options.customPath);
|
|
3107
3097
|
} else if (options.location === "feature-service" && options.feature) {
|
|
3108
|
-
targetDir =
|
|
3098
|
+
targetDir = path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services");
|
|
3109
3099
|
} else if (options.location === "feature-transformer" && options.feature) {
|
|
3110
|
-
targetDir =
|
|
3100
|
+
targetDir = path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
|
|
3111
3101
|
} else if (options.location === "module") {
|
|
3112
|
-
targetDir =
|
|
3102
|
+
targetDir = path26__default.default.join(projectRoot, "modules", className);
|
|
3113
3103
|
} else {
|
|
3114
|
-
targetDir = options.feature ?
|
|
3104
|
+
targetDir = options.feature ? path26__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path26__default.default.join(projectRoot, "shared", className.toLowerCase());
|
|
3115
3105
|
}
|
|
3116
|
-
const filePath =
|
|
3106
|
+
const filePath = path26__default.default.join(targetDir, `${className}.ts`);
|
|
3117
3107
|
let ifaceName;
|
|
3118
3108
|
if (options.generateInterface) {
|
|
3119
3109
|
ifaceName = `I${className}`;
|
|
3120
|
-
const ifacePath =
|
|
3110
|
+
const ifacePath = path26__default.default.join(targetDir, `${ifaceName}.ts`);
|
|
3121
3111
|
const ifaceContent = renderTemplate(injectableInterfaceTemplate, { ifaceName });
|
|
3122
3112
|
files.push(
|
|
3123
3113
|
writeFileSafely(ifacePath, ifaceContent, {
|
|
@@ -3246,7 +3236,7 @@ async function runEnvInit(flags = {}) {
|
|
|
3246
3236
|
const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
|
|
3247
3237
|
const s = p19__namespace.spinner();
|
|
3248
3238
|
s.start("Scanning for .example environment files...");
|
|
3249
|
-
const files =
|
|
3239
|
+
const files = fs17__default.default.readdirSync(projectRoot);
|
|
3250
3240
|
const exampleFiles = files.filter((file) => file.startsWith(".env") && file.endsWith(".example")).sort();
|
|
3251
3241
|
if (exampleFiles.length === 0) {
|
|
3252
3242
|
s.stop("No .example files found.");
|
|
@@ -3256,11 +3246,11 @@ async function runEnvInit(flags = {}) {
|
|
|
3256
3246
|
s.message(`Found ${exampleFiles.length} template(s). Generating...`);
|
|
3257
3247
|
const generatedFiles = [];
|
|
3258
3248
|
for (const exampleFile of exampleFiles) {
|
|
3259
|
-
const sourcePath =
|
|
3249
|
+
const sourcePath = path26__default.default.join(projectRoot, exampleFile);
|
|
3260
3250
|
const targetFile = exampleFile.replace(/\.example$/, "");
|
|
3261
|
-
const targetPath =
|
|
3251
|
+
const targetPath = path26__default.default.join(projectRoot, targetFile);
|
|
3262
3252
|
let overwrite = flags.overwrite;
|
|
3263
|
-
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY &&
|
|
3253
|
+
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17__default.default.existsSync(targetPath)) {
|
|
3264
3254
|
overwrite = await p19__namespace.confirm({
|
|
3265
3255
|
message: `${targetFile} already exists. Overwrite?`,
|
|
3266
3256
|
initialValue: false
|
|
@@ -3270,7 +3260,7 @@ async function runEnvInit(flags = {}) {
|
|
|
3270
3260
|
process.exit(0);
|
|
3271
3261
|
}
|
|
3272
3262
|
}
|
|
3273
|
-
const content =
|
|
3263
|
+
const content = fs17__default.default.readFileSync(sourcePath, "utf-8");
|
|
3274
3264
|
const genFile = writeFileSafely(targetPath, content, {
|
|
3275
3265
|
projectRoot,
|
|
3276
3266
|
dryRun: Boolean(flags.dryRun),
|
|
@@ -3288,7 +3278,7 @@ var EnvEditor = class {
|
|
|
3288
3278
|
filePath;
|
|
3289
3279
|
constructor(filePath) {
|
|
3290
3280
|
this.filePath = filePath;
|
|
3291
|
-
this.lines =
|
|
3281
|
+
this.lines = fs17__default.default.existsSync(filePath) ? fs17__default.default.readFileSync(filePath, "utf-8").split(/\r?\n/) : [];
|
|
3292
3282
|
}
|
|
3293
3283
|
getLines() {
|
|
3294
3284
|
return [...this.lines];
|
|
@@ -3352,18 +3342,18 @@ var EnvEditor = class {
|
|
|
3352
3342
|
});
|
|
3353
3343
|
}
|
|
3354
3344
|
save() {
|
|
3355
|
-
const dir =
|
|
3356
|
-
if (!
|
|
3357
|
-
|
|
3345
|
+
const dir = path26__default.default.dirname(this.filePath);
|
|
3346
|
+
if (!fs17__default.default.existsSync(dir)) {
|
|
3347
|
+
fs17__default.default.mkdirSync(dir, { recursive: true });
|
|
3358
3348
|
}
|
|
3359
|
-
|
|
3349
|
+
fs17__default.default.writeFileSync(this.filePath, this.lines.join("\n"), "utf-8");
|
|
3360
3350
|
}
|
|
3361
3351
|
};
|
|
3362
3352
|
function discoverEnvironments(projectRoot) {
|
|
3363
|
-
if (!
|
|
3353
|
+
if (!fs17__default.default.existsSync(projectRoot)) {
|
|
3364
3354
|
return ["local", "dev", "prod"];
|
|
3365
3355
|
}
|
|
3366
|
-
const files =
|
|
3356
|
+
const files = fs17__default.default.readdirSync(projectRoot);
|
|
3367
3357
|
const envs = /* @__PURE__ */ new Set();
|
|
3368
3358
|
for (const file of files) {
|
|
3369
3359
|
if (file.startsWith(".env")) {
|
|
@@ -3388,7 +3378,7 @@ async function runEnvInitExamples(flags = {}) {
|
|
|
3388
3378
|
const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
|
|
3389
3379
|
const s = p19__namespace.spinner();
|
|
3390
3380
|
s.start("Scanning for local environment files...");
|
|
3391
|
-
const files =
|
|
3381
|
+
const files = fs17__default.default.readdirSync(projectRoot, { withFileTypes: true });
|
|
3392
3382
|
const envFiles = files.filter((dirent) => dirent.isFile() && dirent.name.startsWith(".env") && !dirent.name.endsWith(".example")).map((dirent) => dirent.name).sort();
|
|
3393
3383
|
if (envFiles.length === 0) {
|
|
3394
3384
|
s.stop("No local .env files found.");
|
|
@@ -3398,11 +3388,11 @@ async function runEnvInitExamples(flags = {}) {
|
|
|
3398
3388
|
s.message(`Found ${envFiles.length} local .env file(s). Generating templates...`);
|
|
3399
3389
|
const generatedFiles = [];
|
|
3400
3390
|
for (const envFile of envFiles) {
|
|
3401
|
-
const sourcePath =
|
|
3391
|
+
const sourcePath = path26__default.default.join(projectRoot, envFile);
|
|
3402
3392
|
const targetFile = `${envFile}.example`;
|
|
3403
|
-
const targetPath =
|
|
3393
|
+
const targetPath = path26__default.default.join(projectRoot, targetFile);
|
|
3404
3394
|
let overwrite = flags.overwrite;
|
|
3405
|
-
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY &&
|
|
3395
|
+
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17__default.default.existsSync(targetPath)) {
|
|
3406
3396
|
overwrite = await p19__namespace.confirm({
|
|
3407
3397
|
message: `${targetFile} already exists. Overwrite with redacted values?`,
|
|
3408
3398
|
initialValue: true
|
|
@@ -3435,12 +3425,12 @@ function isInteractive(flags) {
|
|
|
3435
3425
|
function getAllExistingKeys(projectRoot, envs) {
|
|
3436
3426
|
const keys = /* @__PURE__ */ new Set();
|
|
3437
3427
|
for (const env of envs) {
|
|
3438
|
-
const localPath =
|
|
3439
|
-
const examplePath =
|
|
3440
|
-
if (
|
|
3428
|
+
const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
|
|
3429
|
+
const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
|
|
3430
|
+
if (fs17__default.default.existsSync(localPath)) {
|
|
3441
3431
|
new EnvEditor(localPath).getKeys().forEach((k) => keys.add(k));
|
|
3442
3432
|
}
|
|
3443
|
-
if (
|
|
3433
|
+
if (fs17__default.default.existsSync(examplePath)) {
|
|
3444
3434
|
new EnvEditor(examplePath).getKeys().forEach((k) => keys.add(k));
|
|
3445
3435
|
}
|
|
3446
3436
|
}
|
|
@@ -3512,8 +3502,8 @@ async function runEnvAdd(key, value, flags = {}) {
|
|
|
3512
3502
|
})
|
|
3513
3503
|
);
|
|
3514
3504
|
}
|
|
3515
|
-
const localPath =
|
|
3516
|
-
const examplePath =
|
|
3505
|
+
const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
|
|
3506
|
+
const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
|
|
3517
3507
|
if (flags.dryRun) {
|
|
3518
3508
|
p19__namespace.log.info(
|
|
3519
3509
|
pc13__default.default.cyan(`[DRY RUN] Would set ${targetKey}=${envVal} in ${resolveEnvFilename(env, false)}`)
|
|
@@ -3560,8 +3550,8 @@ async function runEnvUpdate(key, value, flags = {}) {
|
|
|
3560
3550
|
);
|
|
3561
3551
|
}
|
|
3562
3552
|
const envsWithKey = allEnvs.filter((env) => {
|
|
3563
|
-
const localPath =
|
|
3564
|
-
return
|
|
3553
|
+
const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
|
|
3554
|
+
return fs17__default.default.existsSync(localPath) && new EnvEditor(localPath).has(targetKey);
|
|
3565
3555
|
});
|
|
3566
3556
|
let targetEnvs = [];
|
|
3567
3557
|
if (flags.env) {
|
|
@@ -3587,7 +3577,7 @@ async function runEnvUpdate(key, value, flags = {}) {
|
|
|
3587
3577
|
return { key: targetKey, environments: [] };
|
|
3588
3578
|
}
|
|
3589
3579
|
for (const env of targetEnvs) {
|
|
3590
|
-
const localPath =
|
|
3580
|
+
const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
|
|
3591
3581
|
const localEditor = new EnvEditor(localPath);
|
|
3592
3582
|
const currentVal = localEditor.getValue(targetKey);
|
|
3593
3583
|
let newVal = value;
|
|
@@ -3617,7 +3607,7 @@ async function runEnvUpdate(key, value, flags = {}) {
|
|
|
3617
3607
|
} else {
|
|
3618
3608
|
localEditor.set(targetKey, newVal);
|
|
3619
3609
|
localEditor.save();
|
|
3620
|
-
const examplePath =
|
|
3610
|
+
const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
|
|
3621
3611
|
const exampleEditor = new EnvEditor(examplePath);
|
|
3622
3612
|
if (!exampleEditor.has(targetKey)) {
|
|
3623
3613
|
exampleEditor.set(targetKey, "");
|
|
@@ -3653,9 +3643,9 @@ async function runEnvDelete(key, flags = {}) {
|
|
|
3653
3643
|
);
|
|
3654
3644
|
}
|
|
3655
3645
|
const envsWithKey = allEnvs.filter((env) => {
|
|
3656
|
-
const localPath =
|
|
3657
|
-
const examplePath =
|
|
3658
|
-
return
|
|
3646
|
+
const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
|
|
3647
|
+
const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
|
|
3648
|
+
return fs17__default.default.existsSync(localPath) && new EnvEditor(localPath).has(targetKey) || fs17__default.default.existsSync(examplePath) && new EnvEditor(examplePath).has(targetKey);
|
|
3659
3649
|
});
|
|
3660
3650
|
let targetEnvs = [];
|
|
3661
3651
|
if (flags.env) {
|
|
@@ -3693,19 +3683,19 @@ async function runEnvDelete(key, flags = {}) {
|
|
|
3693
3683
|
}
|
|
3694
3684
|
}
|
|
3695
3685
|
for (const env of targetEnvs) {
|
|
3696
|
-
const localPath =
|
|
3697
|
-
const examplePath =
|
|
3686
|
+
const localPath = path26__default.default.join(projectRoot, resolveEnvFilename(env, false));
|
|
3687
|
+
const examplePath = path26__default.default.join(projectRoot, resolveEnvFilename(env, true));
|
|
3698
3688
|
if (flags.dryRun) {
|
|
3699
3689
|
p19__namespace.log.info(
|
|
3700
3690
|
pc13__default.default.cyan(`[DRY RUN] Would delete ${targetKey} from ${resolveEnvFilename(env, false)} and ${resolveEnvFilename(env, true)}`)
|
|
3701
3691
|
);
|
|
3702
3692
|
} else {
|
|
3703
|
-
if (
|
|
3693
|
+
if (fs17__default.default.existsSync(localPath)) {
|
|
3704
3694
|
const localEditor = new EnvEditor(localPath);
|
|
3705
3695
|
localEditor.delete(targetKey);
|
|
3706
3696
|
localEditor.save();
|
|
3707
3697
|
}
|
|
3708
|
-
if (
|
|
3698
|
+
if (fs17__default.default.existsSync(examplePath)) {
|
|
3709
3699
|
const exampleEditor = new EnvEditor(examplePath);
|
|
3710
3700
|
exampleEditor.delete(targetKey);
|
|
3711
3701
|
exampleEditor.save();
|
|
@@ -3730,10 +3720,10 @@ async function runEnvAudit(flags = {}) {
|
|
|
3730
3720
|
for (const env of envs) {
|
|
3731
3721
|
const localFile = resolveEnvFilename(env, false);
|
|
3732
3722
|
const exampleFile = resolveEnvFilename(env, true);
|
|
3733
|
-
const localPath =
|
|
3734
|
-
const examplePath =
|
|
3735
|
-
const localExists =
|
|
3736
|
-
const exampleExists =
|
|
3723
|
+
const localPath = path26__default.default.join(projectRoot, localFile);
|
|
3724
|
+
const examplePath = path26__default.default.join(projectRoot, exampleFile);
|
|
3725
|
+
const localExists = fs17__default.default.existsSync(localPath);
|
|
3726
|
+
const exampleExists = fs17__default.default.existsSync(examplePath);
|
|
3737
3727
|
const localEditor = new EnvEditor(localPath);
|
|
3738
3728
|
const exampleEditor = new EnvEditor(examplePath);
|
|
3739
3729
|
const localKeys = localExists ? localEditor.getKeys() : [];
|
|
@@ -4060,25 +4050,25 @@ function normalizeRegistryUrl(urlOrPath, baseDir) {
|
|
|
4060
4050
|
return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
|
|
4061
4051
|
}
|
|
4062
4052
|
if (baseDir && (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed === "." || trimmed === "..")) {
|
|
4063
|
-
return
|
|
4053
|
+
return path26__default.default.resolve(baseDir, trimmed);
|
|
4064
4054
|
}
|
|
4065
4055
|
return trimmed;
|
|
4066
4056
|
}
|
|
4067
4057
|
function findLocalRegistry(startDir = process.cwd()) {
|
|
4068
|
-
let current =
|
|
4058
|
+
let current = path26__default.default.resolve(startDir);
|
|
4069
4059
|
while (true) {
|
|
4070
|
-
const candidate =
|
|
4071
|
-
if (
|
|
4060
|
+
const candidate = path26__default.default.join(current, "mason-registry");
|
|
4061
|
+
if (fs17__default.default.existsSync(candidate) && fs17__default.default.existsSync(path26__default.default.join(candidate, "index.json"))) {
|
|
4072
4062
|
return candidate;
|
|
4073
4063
|
}
|
|
4074
|
-
const parent =
|
|
4064
|
+
const parent = path26__default.default.dirname(current);
|
|
4075
4065
|
if (parent === current) break;
|
|
4076
4066
|
current = parent;
|
|
4077
4067
|
}
|
|
4078
4068
|
return null;
|
|
4079
4069
|
}
|
|
4080
4070
|
function getRegistryBase(projectRoot, override) {
|
|
4081
|
-
const rootDir = projectRoot ?
|
|
4071
|
+
const rootDir = projectRoot ? path26__default.default.resolve(projectRoot) : process.cwd();
|
|
4082
4072
|
if (override && override.trim()) {
|
|
4083
4073
|
return normalizeRegistryUrl(override.trim(), rootDir);
|
|
4084
4074
|
}
|
|
@@ -4086,30 +4076,30 @@ function getRegistryBase(projectRoot, override) {
|
|
|
4086
4076
|
return normalizeRegistryUrl(process.env.MASON_REGISTRY_URL.trim(), rootDir);
|
|
4087
4077
|
}
|
|
4088
4078
|
const configLocations = [
|
|
4089
|
-
|
|
4090
|
-
|
|
4079
|
+
path26__default.default.join(rootDir, "mason.config.json"),
|
|
4080
|
+
path26__default.default.join(process.cwd(), "mason.config.json")
|
|
4091
4081
|
];
|
|
4092
4082
|
for (const configPath of configLocations) {
|
|
4093
|
-
if (
|
|
4083
|
+
if (fs17__default.default.existsSync(configPath)) {
|
|
4094
4084
|
try {
|
|
4095
|
-
const config = JSON.parse(
|
|
4085
|
+
const config = JSON.parse(fs17__default.default.readFileSync(configPath, "utf-8"));
|
|
4096
4086
|
if (config.registry && typeof config.registry === "string") {
|
|
4097
|
-
return normalizeRegistryUrl(config.registry.trim(),
|
|
4087
|
+
return normalizeRegistryUrl(config.registry.trim(), path26__default.default.dirname(configPath));
|
|
4098
4088
|
}
|
|
4099
4089
|
} catch {
|
|
4100
4090
|
}
|
|
4101
4091
|
}
|
|
4102
4092
|
}
|
|
4103
4093
|
const pkgLocations = [
|
|
4104
|
-
|
|
4105
|
-
|
|
4094
|
+
path26__default.default.join(rootDir, "package.json"),
|
|
4095
|
+
path26__default.default.join(process.cwd(), "package.json")
|
|
4106
4096
|
];
|
|
4107
4097
|
for (const pkgPath of pkgLocations) {
|
|
4108
|
-
if (
|
|
4098
|
+
if (fs17__default.default.existsSync(pkgPath)) {
|
|
4109
4099
|
try {
|
|
4110
|
-
const pkg = JSON.parse(
|
|
4100
|
+
const pkg = JSON.parse(fs17__default.default.readFileSync(pkgPath, "utf-8"));
|
|
4111
4101
|
if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
|
|
4112
|
-
return normalizeRegistryUrl(pkg.mason.registry.trim(),
|
|
4102
|
+
return normalizeRegistryUrl(pkg.mason.registry.trim(), path26__default.default.dirname(pkgPath));
|
|
4113
4103
|
}
|
|
4114
4104
|
} catch {
|
|
4115
4105
|
}
|
|
@@ -4157,16 +4147,16 @@ async function fetchRegistryFile(registryBase, relPath) {
|
|
|
4157
4147
|
if (baseDir.startsWith("file://")) {
|
|
4158
4148
|
baseDir = url.fileURLToPath(baseDir);
|
|
4159
4149
|
}
|
|
4160
|
-
let filePath =
|
|
4161
|
-
if (!
|
|
4162
|
-
const inSrcPath =
|
|
4163
|
-
if (
|
|
4150
|
+
let filePath = path26__default.default.resolve(baseDir, cleanRelPath);
|
|
4151
|
+
if (!fs17__default.default.existsSync(filePath)) {
|
|
4152
|
+
const inSrcPath = path26__default.default.resolve(baseDir, "src", cleanRelPath);
|
|
4153
|
+
if (fs17__default.default.existsSync(inSrcPath)) {
|
|
4164
4154
|
filePath = inSrcPath;
|
|
4165
4155
|
} else {
|
|
4166
4156
|
throw new Error(`Registry file not found at ${filePath}`);
|
|
4167
4157
|
}
|
|
4168
4158
|
}
|
|
4169
|
-
return
|
|
4159
|
+
return fs17__default.default.promises.readFile(filePath, "utf-8");
|
|
4170
4160
|
}
|
|
4171
4161
|
async function fetchRegistryIndex(registryBase) {
|
|
4172
4162
|
const content = await fetchRegistryFile(registryBase, "index.json");
|
|
@@ -4228,19 +4218,19 @@ function findClosestMatch(target, candidates) {
|
|
|
4228
4218
|
return null;
|
|
4229
4219
|
}
|
|
4230
4220
|
function detectPackageManager(projectRoot) {
|
|
4231
|
-
if (
|
|
4232
|
-
if (
|
|
4233
|
-
if (
|
|
4221
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
4222
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
4223
|
+
if (fs17__default.default.existsSync(path26__default.default.join(projectRoot, "bun.lockb")) || fs17__default.default.existsSync(path26__default.default.join(projectRoot, "bun.lock"))) return "bun";
|
|
4234
4224
|
return "npm";
|
|
4235
4225
|
}
|
|
4236
4226
|
function getMissingNpmPackages(projectRoot, requiredPackages) {
|
|
4237
4227
|
if (!requiredPackages || requiredPackages.length === 0) return [];
|
|
4238
|
-
const pkgJsonPath =
|
|
4239
|
-
if (!
|
|
4228
|
+
const pkgJsonPath = path26__default.default.join(projectRoot, "package.json");
|
|
4229
|
+
if (!fs17__default.default.existsSync(pkgJsonPath)) {
|
|
4240
4230
|
return requiredPackages;
|
|
4241
4231
|
}
|
|
4242
4232
|
try {
|
|
4243
|
-
const pkg = JSON.parse(
|
|
4233
|
+
const pkg = JSON.parse(fs17__default.default.readFileSync(pkgJsonPath, "utf-8"));
|
|
4244
4234
|
const installed = /* @__PURE__ */ new Set([
|
|
4245
4235
|
...Object.keys(pkg.dependencies || {}),
|
|
4246
4236
|
...Object.keys(pkg.devDependencies || {}),
|
|
@@ -4279,12 +4269,12 @@ function installNpmPackages(projectRoot, packages, pm) {
|
|
|
4279
4269
|
});
|
|
4280
4270
|
}
|
|
4281
4271
|
function getAllFiles(dir, baseDir = dir) {
|
|
4282
|
-
if (!
|
|
4283
|
-
const entries =
|
|
4272
|
+
if (!fs17__default.default.existsSync(dir)) return [];
|
|
4273
|
+
const entries = fs17__default.default.readdirSync(dir, { withFileTypes: true });
|
|
4284
4274
|
const files = [];
|
|
4285
4275
|
for (const entry of entries) {
|
|
4286
|
-
const fullPath =
|
|
4287
|
-
const relPath =
|
|
4276
|
+
const fullPath = path26__default.default.join(dir, entry.name);
|
|
4277
|
+
const relPath = path26__default.default.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
4288
4278
|
if (entry.isDirectory()) {
|
|
4289
4279
|
if (entry.name === "__tests__" || entry.name.startsWith(".")) {
|
|
4290
4280
|
continue;
|
|
@@ -4300,13 +4290,13 @@ function getAllFiles(dir, baseDir = dir) {
|
|
|
4300
4290
|
return files.sort();
|
|
4301
4291
|
}
|
|
4302
4292
|
function computeDirectoryHash(dirPath, files) {
|
|
4303
|
-
if (!
|
|
4293
|
+
if (!fs17__default.default.existsSync(dirPath)) return "";
|
|
4304
4294
|
const hash = crypto.createHash("sha256");
|
|
4305
4295
|
const fileList = (getAllFiles(dirPath)).sort();
|
|
4306
4296
|
for (const relativePath of fileList) {
|
|
4307
|
-
const absolutePath =
|
|
4308
|
-
if (!
|
|
4309
|
-
const content =
|
|
4297
|
+
const absolutePath = path26__default.default.join(dirPath, relativePath);
|
|
4298
|
+
if (!fs17__default.default.existsSync(absolutePath)) continue;
|
|
4299
|
+
const content = fs17__default.default.readFileSync(absolutePath, "utf8");
|
|
4310
4300
|
const normalizedContent = content.replace(/\r\n/g, "\n");
|
|
4311
4301
|
hash.update(relativePath);
|
|
4312
4302
|
hash.update(normalizedContent);
|
|
@@ -4344,17 +4334,17 @@ function getModuleBaseDir(projectRoot, modType) {
|
|
|
4344
4334
|
return modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
4345
4335
|
}
|
|
4346
4336
|
const folder = modType === "shared" ? "shared" : "features";
|
|
4347
|
-
return
|
|
4337
|
+
return path26__default.default.join(projectRoot, "src", folder);
|
|
4348
4338
|
}
|
|
4349
4339
|
function getExistingModuleDir(projectRoot, modType, modName) {
|
|
4350
4340
|
const folder = modType === "shared" ? "shared" : "features";
|
|
4351
4341
|
const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
4352
|
-
const inConfigured =
|
|
4353
|
-
if (
|
|
4354
|
-
const inSrc =
|
|
4355
|
-
if (
|
|
4356
|
-
const inRoot =
|
|
4357
|
-
if (
|
|
4342
|
+
const inConfigured = path26__default.default.join(configuredDir, modName);
|
|
4343
|
+
if (fs17__default.default.existsSync(inConfigured)) return inConfigured;
|
|
4344
|
+
const inSrc = path26__default.default.join(projectRoot, "src", folder, modName);
|
|
4345
|
+
if (fs17__default.default.existsSync(inSrc)) return inSrc;
|
|
4346
|
+
const inRoot = path26__default.default.join(projectRoot, folder, modName);
|
|
4347
|
+
if (fs17__default.default.existsSync(inRoot)) return inRoot;
|
|
4358
4348
|
return null;
|
|
4359
4349
|
}
|
|
4360
4350
|
function checkModuleExists(projectRoot, modType, modName) {
|
|
@@ -4365,14 +4355,14 @@ function getAvailableLocalModules(projectRoot, modType) {
|
|
|
4365
4355
|
const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
4366
4356
|
const dirs = [
|
|
4367
4357
|
configuredDir,
|
|
4368
|
-
|
|
4369
|
-
|
|
4358
|
+
path26__default.default.join(projectRoot, "src", folder),
|
|
4359
|
+
path26__default.default.join(projectRoot, folder)
|
|
4370
4360
|
];
|
|
4371
4361
|
const set = /* @__PURE__ */ new Set();
|
|
4372
4362
|
for (const dir of dirs) {
|
|
4373
|
-
if (
|
|
4363
|
+
if (fs17__default.default.existsSync(dir)) {
|
|
4374
4364
|
try {
|
|
4375
|
-
const entries =
|
|
4365
|
+
const entries = fs17__default.default.readdirSync(dir, { withFileTypes: true });
|
|
4376
4366
|
for (const e of entries) {
|
|
4377
4367
|
if (e.isDirectory() && !e.name.startsWith(".")) {
|
|
4378
4368
|
set.add(e.name);
|
|
@@ -4574,7 +4564,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4574
4564
|
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${programmaticAlias}/`);
|
|
4575
4565
|
globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${programmaticAlias}`);
|
|
4576
4566
|
const baseDir = getModuleBaseDir(projectRoot, modType);
|
|
4577
|
-
const displayDest =
|
|
4567
|
+
const displayDest = path26__default.default.relative(projectRoot, path26__default.default.join(baseDir, programmaticAlias));
|
|
4578
4568
|
p19__namespace.log.step(`Importing '${registryName}' into '${displayDest}'...`);
|
|
4579
4569
|
resolutions.set(key, {
|
|
4580
4570
|
type: modType,
|
|
@@ -4762,7 +4752,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4762
4752
|
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${newName}/`);
|
|
4763
4753
|
globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${newName}`);
|
|
4764
4754
|
const baseDir = getModuleBaseDir(projectRoot, modType);
|
|
4765
|
-
const displayDest =
|
|
4755
|
+
const displayDest = path26__default.default.relative(projectRoot, path26__default.default.join(baseDir, newName));
|
|
4766
4756
|
p19__namespace.log.step(`Importing '${registryName}' into '${displayDest}'...`);
|
|
4767
4757
|
resolutions.set(key, {
|
|
4768
4758
|
type: modType,
|
|
@@ -4814,7 +4804,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4814
4804
|
continue;
|
|
4815
4805
|
}
|
|
4816
4806
|
const folder = res.type === "shared" ? "shared" : "features";
|
|
4817
|
-
const targetDir =
|
|
4807
|
+
const targetDir = path26__default.default.join(getModuleBaseDir(projectRoot, res.type), res.targetName);
|
|
4818
4808
|
const isOverwrite = Boolean(flags.overwrite || res.action === "overwrite");
|
|
4819
4809
|
if (key !== rootKey) {
|
|
4820
4810
|
p19__namespace.log.step(
|
|
@@ -4824,30 +4814,30 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4824
4814
|
if (res.action === "overwrite" && !flags.dryRun) {
|
|
4825
4815
|
const existingDir = getExistingModuleDir(projectRoot, res.type, res.targetName);
|
|
4826
4816
|
if (existingDir && existingDir !== targetDir) {
|
|
4827
|
-
|
|
4817
|
+
fs17__default.default.rmSync(existingDir, { recursive: true, force: true });
|
|
4828
4818
|
}
|
|
4829
|
-
if (
|
|
4830
|
-
|
|
4819
|
+
if (fs17__default.default.existsSync(targetDir)) {
|
|
4820
|
+
fs17__default.default.rmSync(targetDir, { recursive: true, force: true });
|
|
4831
4821
|
}
|
|
4832
4822
|
}
|
|
4833
4823
|
for (const file of res.manifest.files || []) {
|
|
4834
4824
|
if (file === "registry.json") continue;
|
|
4835
4825
|
if (!includeTests && isTestFile(file)) continue;
|
|
4836
4826
|
const remoteFilePath = `${folder}/${res.registryName}/${file}`;
|
|
4837
|
-
const localFilePath =
|
|
4838
|
-
if (
|
|
4827
|
+
const localFilePath = path26__default.default.join(targetDir, file);
|
|
4828
|
+
if (fs17__default.default.existsSync(localFilePath) && !isOverwrite) {
|
|
4839
4829
|
p19__namespace.log.warn(
|
|
4840
|
-
` \u21B3 Skipping existing file: ${pc13__default.default.dim(
|
|
4830
|
+
` \u21B3 Skipping existing file: ${pc13__default.default.dim(path26__default.default.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
|
|
4841
4831
|
);
|
|
4842
4832
|
continue;
|
|
4843
4833
|
}
|
|
4844
4834
|
let content = await fetchRegistryFile(registryBase, remoteFilePath);
|
|
4845
4835
|
content = rewriteImports(content, globalAliasMap);
|
|
4846
4836
|
if (!flags.dryRun) {
|
|
4847
|
-
|
|
4848
|
-
|
|
4837
|
+
fs17__default.default.mkdirSync(path26__default.default.dirname(localFilePath), { recursive: true });
|
|
4838
|
+
fs17__default.default.writeFileSync(localFilePath, content, "utf-8");
|
|
4849
4839
|
}
|
|
4850
|
-
const displayPath =
|
|
4840
|
+
const displayPath = path26__default.default.relative(projectRoot, localFilePath);
|
|
4851
4841
|
totalWrittenFiles.push(displayPath);
|
|
4852
4842
|
p19__namespace.log.message(` ${pc13__default.default.green("+")} ${displayPath}`);
|
|
4853
4843
|
}
|
|
@@ -4873,7 +4863,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4873
4863
|
} else {
|
|
4874
4864
|
const rootRes = resolutions.get(rootKey);
|
|
4875
4865
|
const baseDir = getModuleBaseDir(projectRoot, type);
|
|
4876
|
-
const displayTarget =
|
|
4866
|
+
const displayTarget = path26__default.default.relative(projectRoot, path26__default.default.join(baseDir, rootRes.targetName));
|
|
4877
4867
|
p19__namespace.log.success(
|
|
4878
4868
|
pc13__default.default.green(
|
|
4879
4869
|
`Successfully imported ${type} '${name}' (${totalWrittenFiles.length} file${totalWrittenFiles.length === 1 ? "" : "s"} placed in ${displayTarget})`
|
|
@@ -4892,19 +4882,19 @@ var DependencyRuleError = class extends Error {
|
|
|
4892
4882
|
}
|
|
4893
4883
|
};
|
|
4894
4884
|
function isTestFile2(filePath, projectRoot) {
|
|
4895
|
-
const norm = (projectRoot ?
|
|
4896
|
-
const base =
|
|
4885
|
+
const norm = (projectRoot ? path26__default.default.relative(projectRoot, filePath) : filePath).replace(/\\/g, "/");
|
|
4886
|
+
const base = path26__default.default.basename(norm);
|
|
4897
4887
|
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);
|
|
4898
4888
|
}
|
|
4899
4889
|
function scanDirFiles(dir, projectRoot) {
|
|
4900
|
-
if (!
|
|
4901
|
-
const entries =
|
|
4890
|
+
if (!fs17__default.default.existsSync(dir)) return [];
|
|
4891
|
+
const entries = fs17__default.default.readdirSync(dir, { withFileTypes: true });
|
|
4902
4892
|
const files = [];
|
|
4903
4893
|
for (const entry of entries) {
|
|
4904
4894
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "__tests__" || entry.name.startsWith(".")) {
|
|
4905
4895
|
continue;
|
|
4906
4896
|
}
|
|
4907
|
-
const fullPath =
|
|
4897
|
+
const fullPath = path26__default.default.join(dir, entry.name);
|
|
4908
4898
|
if (entry.isDirectory()) {
|
|
4909
4899
|
files.push(...scanDirFiles(fullPath, projectRoot));
|
|
4910
4900
|
} else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) && !isTestFile2(fullPath, projectRoot)) {
|
|
@@ -4913,42 +4903,43 @@ function scanDirFiles(dir, projectRoot) {
|
|
|
4913
4903
|
}
|
|
4914
4904
|
return files;
|
|
4915
4905
|
}
|
|
4916
|
-
function
|
|
4917
|
-
const
|
|
4918
|
-
const
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
if (
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4906
|
+
function resolveLintEnvironment(projectRoot) {
|
|
4907
|
+
const config = loadMasonConfig(projectRoot);
|
|
4908
|
+
const resolveDir = (configured, defaultSrc, defaultRoot) => {
|
|
4909
|
+
if (configured !== void 0) {
|
|
4910
|
+
return path26__default.default.resolve(projectRoot, configured);
|
|
4911
|
+
}
|
|
4912
|
+
const srcPath = path26__default.default.join(projectRoot, defaultSrc);
|
|
4913
|
+
if (fs17__default.default.existsSync(srcPath)) return srcPath;
|
|
4914
|
+
const rootPath = path26__default.default.join(projectRoot, defaultRoot);
|
|
4915
|
+
if (fs17__default.default.existsSync(rootPath)) return rootPath;
|
|
4916
|
+
return srcPath;
|
|
4917
|
+
};
|
|
4918
|
+
const featuresBase = resolveDir(config?.paths?.features, "src/features", "features");
|
|
4919
|
+
const sharedBase = resolveDir(config?.paths?.shared, "src/shared", "shared");
|
|
4920
|
+
const errorsBase = resolveDir(config?.paths?.errors, "src/errors", "errors");
|
|
4921
|
+
const defaultBaseErrorRelative = config?.paths?.errors ? path26__default.default.join(config.paths.errors, "AppError.ts") : fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/errors")) ? "src/errors/AppError.ts" : fs17__default.default.existsSync(path26__default.default.join(projectRoot, "errors")) ? "errors/AppError.ts" : "src/errors/AppError.ts";
|
|
4922
|
+
const baseErrorAbs = path26__default.default.resolve(
|
|
4923
|
+
projectRoot,
|
|
4924
|
+
config?.paths?.baseError || defaultBaseErrorRelative
|
|
4925
|
+
);
|
|
4926
|
+
return { featuresBase, sharedBase, errorsBase, baseErrorAbs };
|
|
4927
|
+
}
|
|
4928
|
+
function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
|
|
4929
|
+
if (!sharedBaseAbs || !errorsBaseAbs) {
|
|
4930
|
+
const env = resolveLintEnvironment(featuresBaseAbs);
|
|
4931
|
+
featuresBaseAbs = env.featuresBase;
|
|
4932
|
+
sharedBaseAbs = env.sharedBase;
|
|
4933
|
+
errorsBaseAbs = env.errorsBase;
|
|
4934
|
+
}
|
|
4935
|
+
const normFullPath = path26__default.default.resolve(fullPathAbs);
|
|
4936
|
+
const normErrorsBase = path26__default.default.resolve(errorsBaseAbs);
|
|
4937
|
+
const normSharedBase = path26__default.default.resolve(sharedBaseAbs);
|
|
4938
|
+
const normFeaturesBase = path26__default.default.resolve(featuresBaseAbs);
|
|
4939
|
+
const isUnder = (base, target) => {
|
|
4940
|
+
return target === base || target.startsWith(base + path26__default.default.sep);
|
|
4941
|
+
};
|
|
4942
|
+
if (isUnder(normErrorsBase, normFullPath)) {
|
|
4952
4943
|
return {
|
|
4953
4944
|
moduleType: "error",
|
|
4954
4945
|
moduleName: "global-errors",
|
|
@@ -4956,46 +4947,154 @@ function classifyFile(fullPath, projectRoot) {
|
|
|
4956
4947
|
layer: "domain"
|
|
4957
4948
|
};
|
|
4958
4949
|
}
|
|
4950
|
+
if (isUnder(normSharedBase, normFullPath)) {
|
|
4951
|
+
const rel = path26__default.default.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
|
|
4952
|
+
const parts = rel.split("/").filter(Boolean);
|
|
4953
|
+
if (parts.length >= 1) {
|
|
4954
|
+
const moduleName = parts[0];
|
|
4955
|
+
const subfolder = parts[1];
|
|
4956
|
+
let layer = "root";
|
|
4957
|
+
if (subfolder === "domain" || subfolder === "errors") {
|
|
4958
|
+
layer = "domain";
|
|
4959
|
+
} else if (subfolder === "ports") {
|
|
4960
|
+
layer = "ports";
|
|
4961
|
+
} else if (subfolder === "infrastructure") {
|
|
4962
|
+
layer = "infrastructure";
|
|
4963
|
+
}
|
|
4964
|
+
return { moduleType: "shared", moduleName, feature: moduleName, layer };
|
|
4965
|
+
}
|
|
4966
|
+
}
|
|
4967
|
+
if (isUnder(normFeaturesBase, normFullPath)) {
|
|
4968
|
+
const rel = path26__default.default.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
|
|
4969
|
+
const parts = rel.split("/").filter(Boolean);
|
|
4970
|
+
if (parts.length >= 2) {
|
|
4971
|
+
const moduleName = parts[0];
|
|
4972
|
+
const subfolder = parts[1];
|
|
4973
|
+
let layer;
|
|
4974
|
+
if (subfolder === "domain" || subfolder === "errors") {
|
|
4975
|
+
layer = "domain";
|
|
4976
|
+
} else if (subfolder === "useCases" || subfolder === "usecases") {
|
|
4977
|
+
layer = "useCases";
|
|
4978
|
+
} else if (subfolder === "services") {
|
|
4979
|
+
layer = "services";
|
|
4980
|
+
} else if (subfolder === "infrastructure") {
|
|
4981
|
+
layer = "infrastructure";
|
|
4982
|
+
} else if (subfolder.startsWith("px") || subfolder === "presentation" || subfolder === "handlers" || subfolder === "transformers") {
|
|
4983
|
+
layer = "presentation";
|
|
4984
|
+
}
|
|
4985
|
+
return { moduleType: "feature", moduleName, feature: moduleName, layer };
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4959
4988
|
return {};
|
|
4960
4989
|
}
|
|
4961
|
-
function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
4990
|
+
function classifyTarget(specifier, sourceFileAbs, projectRoot, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
|
|
4962
4991
|
if (specifier === "@solid-stack/di" || specifier.startsWith("@solid-stack/di/")) {
|
|
4963
4992
|
return { isExternal: true, isDiFramework: true };
|
|
4964
4993
|
}
|
|
4965
|
-
if (specifier.startsWith("node:") || [
|
|
4994
|
+
if (specifier.startsWith("node:") || [
|
|
4995
|
+
"crypto",
|
|
4996
|
+
"fs",
|
|
4997
|
+
"path",
|
|
4998
|
+
"http",
|
|
4999
|
+
"https",
|
|
5000
|
+
"url",
|
|
5001
|
+
"os",
|
|
5002
|
+
"child_process",
|
|
5003
|
+
"stream",
|
|
5004
|
+
"express",
|
|
5005
|
+
"cors",
|
|
5006
|
+
"dotenv"
|
|
5007
|
+
].includes(specifier)) {
|
|
4966
5008
|
return { isExternal: true, isDiFramework: false };
|
|
4967
5009
|
}
|
|
4968
|
-
|
|
5010
|
+
if (!featuresBaseAbs || !sharedBaseAbs || !errorsBaseAbs) {
|
|
5011
|
+
const env = resolveLintEnvironment(projectRoot);
|
|
5012
|
+
featuresBaseAbs = featuresBaseAbs || env.featuresBase;
|
|
5013
|
+
sharedBaseAbs = sharedBaseAbs || env.sharedBase;
|
|
5014
|
+
errorsBaseAbs = errorsBaseAbs || env.errorsBase;
|
|
5015
|
+
}
|
|
5016
|
+
const isGlobalConfig = specifier === "@configs" || specifier.startsWith("@configs/") || specifier === "@/configs" || specifier.startsWith("@/configs/") || specifier === "~/configs" || specifier.startsWith("~/configs/") || specifier === "configs" || specifier.startsWith("configs/");
|
|
5017
|
+
let targetAbs = null;
|
|
4969
5018
|
if (specifier.startsWith(".")) {
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
5019
|
+
targetAbs = path26__default.default.resolve(path26__default.default.dirname(sourceFileAbs), specifier);
|
|
5020
|
+
} else {
|
|
5021
|
+
const featRel = path26__default.default.relative(projectRoot, featuresBaseAbs).replace(/\\/g, "/");
|
|
5022
|
+
const sharedRel = path26__default.default.relative(projectRoot, sharedBaseAbs).replace(/\\/g, "/");
|
|
5023
|
+
const errorsRel = path26__default.default.relative(projectRoot, errorsBaseAbs).replace(/\\/g, "/");
|
|
5024
|
+
const featPrefixes = ["features"];
|
|
5025
|
+
if (featRel && featRel !== "." && !featRel.startsWith("..")) {
|
|
5026
|
+
featPrefixes.push(featRel);
|
|
5027
|
+
const b = path26__default.default.basename(featRel);
|
|
5028
|
+
if (!featPrefixes.includes(b)) featPrefixes.push(b);
|
|
5029
|
+
}
|
|
5030
|
+
const sharedPrefixes = ["shared"];
|
|
5031
|
+
if (sharedRel && sharedRel !== "." && !sharedRel.startsWith("..")) {
|
|
5032
|
+
sharedPrefixes.push(sharedRel);
|
|
5033
|
+
const b = path26__default.default.basename(sharedRel);
|
|
5034
|
+
if (!sharedPrefixes.includes(b)) sharedPrefixes.push(b);
|
|
5035
|
+
}
|
|
5036
|
+
const errorsPrefixes = ["errors"];
|
|
5037
|
+
if (errorsRel && errorsRel !== "." && !errorsRel.startsWith("..")) {
|
|
5038
|
+
errorsPrefixes.push(errorsRel);
|
|
5039
|
+
const b = path26__default.default.basename(errorsRel);
|
|
5040
|
+
if (!errorsPrefixes.includes(b)) errorsPrefixes.push(b);
|
|
5041
|
+
}
|
|
5042
|
+
for (const prefix of featPrefixes) {
|
|
5043
|
+
const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
|
|
5044
|
+
const m = specifier.match(aliasRegex);
|
|
5045
|
+
if (m && m[2]) {
|
|
5046
|
+
targetAbs = path26__default.default.resolve(featuresBaseAbs, m[2]);
|
|
5047
|
+
break;
|
|
5048
|
+
}
|
|
5049
|
+
}
|
|
5050
|
+
if (!targetAbs) {
|
|
5051
|
+
for (const prefix of sharedPrefixes) {
|
|
5052
|
+
const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
|
|
5053
|
+
const m = specifier.match(aliasRegex);
|
|
5054
|
+
if (m && m[2]) {
|
|
5055
|
+
targetAbs = path26__default.default.resolve(sharedBaseAbs, m[2]);
|
|
5056
|
+
break;
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
5060
|
+
if (!targetAbs) {
|
|
5061
|
+
for (const prefix of errorsPrefixes) {
|
|
5062
|
+
const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}(?:\\/(.*))?$`);
|
|
5063
|
+
const m = specifier.match(aliasRegex);
|
|
5064
|
+
if (m) {
|
|
5065
|
+
targetAbs = path26__default.default.resolve(errorsBaseAbs, m[2] || "");
|
|
5066
|
+
break;
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
}
|
|
5070
|
+
if (!targetAbs && (specifier.startsWith("@/") || specifier.startsWith("~/"))) {
|
|
5071
|
+
const sub = specifier.slice(2);
|
|
5072
|
+
const srcCandidate = path26__default.default.resolve(projectRoot, "src", sub);
|
|
5073
|
+
const rootCandidate = path26__default.default.resolve(projectRoot, sub);
|
|
5074
|
+
if (fs17__default.default.existsSync(srcCandidate)) {
|
|
5075
|
+
targetAbs = srcCandidate;
|
|
5076
|
+
} else if (fs17__default.default.existsSync(rootCandidate)) {
|
|
5077
|
+
targetAbs = rootCandidate;
|
|
5078
|
+
} else {
|
|
5079
|
+
targetAbs = srcCandidate;
|
|
5080
|
+
}
|
|
5081
|
+
}
|
|
5082
|
+
if (!targetAbs) {
|
|
5083
|
+
const featCandidate = path26__default.default.resolve(featuresBaseAbs, specifier);
|
|
5084
|
+
if (fs17__default.default.existsSync(featCandidate) || fs17__default.default.existsSync(featCandidate + ".ts") || fs17__default.default.existsSync(featCandidate + ".js")) {
|
|
5085
|
+
targetAbs = featCandidate;
|
|
5086
|
+
}
|
|
5087
|
+
}
|
|
4995
5088
|
}
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
5089
|
+
if (!targetAbs) {
|
|
5090
|
+
return { isExternal: true, isDiFramework: false, isGlobalConfig };
|
|
5091
|
+
}
|
|
5092
|
+
const normTarget = path26__default.default.resolve(targetAbs);
|
|
5093
|
+
const srcConfig = path26__default.default.resolve(projectRoot, "src/configs");
|
|
5094
|
+
const rootConfig = path26__default.default.resolve(projectRoot, "configs");
|
|
5095
|
+
const isTargetConfig = isGlobalConfig || normTarget === srcConfig || normTarget.startsWith(srcConfig + path26__default.default.sep) || normTarget === rootConfig || normTarget.startsWith(rootConfig + path26__default.default.sep);
|
|
5096
|
+
const classification = classifyFile(targetAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs);
|
|
5097
|
+
if (classification.moduleType === "error") {
|
|
4999
5098
|
return {
|
|
5000
5099
|
isExternal: false,
|
|
5001
5100
|
isDiFramework: false,
|
|
@@ -5003,33 +5102,19 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
5003
5102
|
isTargetError: true
|
|
5004
5103
|
};
|
|
5005
5104
|
}
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
const
|
|
5009
|
-
const targetSubfolder =
|
|
5010
|
-
const
|
|
5011
|
-
let targetLayer;
|
|
5012
|
-
if (targetSubfolder === "domain" || targetSubfolder === "errors") {
|
|
5013
|
-
targetLayer = "domain";
|
|
5014
|
-
} else if (targetSubfolder === "useCases" || targetSubfolder === "usecases") {
|
|
5015
|
-
targetLayer = "useCases";
|
|
5016
|
-
} else if (targetSubfolder === "services") {
|
|
5017
|
-
targetLayer = "services";
|
|
5018
|
-
} else if (targetSubfolder === "infrastructure") {
|
|
5019
|
-
targetLayer = "infrastructure";
|
|
5020
|
-
} else if (targetSubfolder === "pxExpress" || targetSubfolder === "presentation" || targetSubfolder === "handlers" || targetSubfolder.startsWith("px")) {
|
|
5021
|
-
targetLayer = "presentation";
|
|
5022
|
-
}
|
|
5023
|
-
const basePart = rest ? path2__default.default.basename(rest) : targetSubfolder;
|
|
5024
|
-
const targetFileName = basePart.replace(/\.(js|ts|mjs|cjs)$/, "");
|
|
5105
|
+
if (classification.moduleType === "feature") {
|
|
5106
|
+
const rel = path26__default.default.relative(featuresBaseAbs, targetAbs).replace(/\\/g, "/");
|
|
5107
|
+
const parts = rel.split("/").filter(Boolean);
|
|
5108
|
+
const targetSubfolder = parts[1];
|
|
5109
|
+
const targetFileName = path26__default.default.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
|
|
5025
5110
|
const isTargetPort = /^I[A-Z]/.test(targetFileName);
|
|
5026
5111
|
const isTargetRepo = isTargetPort && targetFileName.includes("Repo");
|
|
5027
|
-
const isTargetError = targetSubfolder === "errors" ||
|
|
5112
|
+
const isTargetError = targetSubfolder === "errors" || rel.includes("/errors/") || targetFileName.endsWith("Error") || targetFileName.endsWith("Errors");
|
|
5028
5113
|
return {
|
|
5029
5114
|
isExternal: false,
|
|
5030
5115
|
isDiFramework: false,
|
|
5031
|
-
targetFeature,
|
|
5032
|
-
targetLayer,
|
|
5116
|
+
targetFeature: classification.moduleName,
|
|
5117
|
+
targetLayer: classification.layer,
|
|
5033
5118
|
targetSubfolder,
|
|
5034
5119
|
targetFileName,
|
|
5035
5120
|
isTargetPort,
|
|
@@ -5037,25 +5122,21 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
5037
5122
|
isTargetError
|
|
5038
5123
|
};
|
|
5039
5124
|
}
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
const
|
|
5043
|
-
const sharedRest = sharedMatch[2] || "";
|
|
5044
|
-
const isSharedRoot = !sharedRest.includes("/");
|
|
5045
|
-
const isSharedPorts = sharedRest.startsWith("ports/") || sharedRest === "ports";
|
|
5046
|
-
const isSharedInfra = sharedRest.startsWith("infrastructure/") || sharedRest === "infrastructure";
|
|
5047
|
-
const isSharedDomain = sharedRest.startsWith("domain/") || sharedRest === "domain";
|
|
5125
|
+
if (classification.moduleType === "shared") {
|
|
5126
|
+
const targetFileName = path26__default.default.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
|
|
5127
|
+
const isTargetError = classification.layer === "domain" && (targetFileName.endsWith("Error") || targetFileName.endsWith("Errors") || targetAbs.includes("/errors/"));
|
|
5048
5128
|
return {
|
|
5049
5129
|
isExternal: false,
|
|
5050
5130
|
isDiFramework: false,
|
|
5051
|
-
targetSharedModule,
|
|
5052
|
-
isSharedRoot,
|
|
5053
|
-
isSharedPorts,
|
|
5054
|
-
isSharedInfra,
|
|
5055
|
-
isSharedDomain
|
|
5131
|
+
targetSharedModule: classification.moduleName,
|
|
5132
|
+
isSharedRoot: classification.layer === "root",
|
|
5133
|
+
isSharedPorts: classification.layer === "ports",
|
|
5134
|
+
isSharedInfra: classification.layer === "infrastructure",
|
|
5135
|
+
isSharedDomain: classification.layer === "domain",
|
|
5136
|
+
isTargetError
|
|
5056
5137
|
};
|
|
5057
5138
|
}
|
|
5058
|
-
return { isExternal: true, isDiFramework: false, isGlobalConfig };
|
|
5139
|
+
return { isExternal: true, isDiFramework: false, isGlobalConfig: isTargetConfig };
|
|
5059
5140
|
}
|
|
5060
5141
|
function extractImportStatements(content) {
|
|
5061
5142
|
const statements = [];
|
|
@@ -5177,22 +5258,50 @@ var FeatureDependencyGraph = class {
|
|
|
5177
5258
|
return dfs(start);
|
|
5178
5259
|
}
|
|
5179
5260
|
};
|
|
5180
|
-
function discoverAllFeatures(
|
|
5181
|
-
const
|
|
5182
|
-
if (!
|
|
5183
|
-
const
|
|
5184
|
-
|
|
5261
|
+
function discoverAllFeatures(featuresBaseAbs, excludeDirs = []) {
|
|
5262
|
+
const base = featuresBaseAbs;
|
|
5263
|
+
if (!fs17__default.default.existsSync(base)) return [];
|
|
5264
|
+
const excludeSet = new Set(excludeDirs.map((d) => path26__default.default.resolve(d)));
|
|
5265
|
+
const entries = fs17__default.default.readdirSync(base, { withFileTypes: true });
|
|
5266
|
+
return entries.filter((e) => {
|
|
5267
|
+
if (!e.isDirectory()) return false;
|
|
5268
|
+
if (e.name.startsWith(".")) return false;
|
|
5269
|
+
if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
|
|
5270
|
+
return false;
|
|
5271
|
+
}
|
|
5272
|
+
const resolved = path26__default.default.resolve(base, e.name);
|
|
5273
|
+
for (const ex of excludeSet) {
|
|
5274
|
+
if (ex === resolved || ex.startsWith(resolved + path26__default.default.sep) || resolved.startsWith(ex + path26__default.default.sep)) {
|
|
5275
|
+
return false;
|
|
5276
|
+
}
|
|
5277
|
+
}
|
|
5278
|
+
return true;
|
|
5279
|
+
}).map((e) => ({
|
|
5185
5280
|
name: e.name,
|
|
5186
|
-
dir:
|
|
5281
|
+
dir: path26__default.default.join(base, e.name)
|
|
5187
5282
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
5188
5283
|
}
|
|
5189
|
-
function discoverAllShared(
|
|
5190
|
-
const
|
|
5191
|
-
if (!
|
|
5192
|
-
const
|
|
5193
|
-
|
|
5284
|
+
function discoverAllShared(sharedBaseAbs, excludeDirs = []) {
|
|
5285
|
+
const base = sharedBaseAbs;
|
|
5286
|
+
if (!fs17__default.default.existsSync(base)) return [];
|
|
5287
|
+
const excludeSet = new Set(excludeDirs.map((d) => path26__default.default.resolve(d)));
|
|
5288
|
+
const entries = fs17__default.default.readdirSync(base, { withFileTypes: true });
|
|
5289
|
+
return entries.filter((e) => {
|
|
5290
|
+
if (!e.isDirectory()) return false;
|
|
5291
|
+
if (e.name.startsWith(".")) return false;
|
|
5292
|
+
if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
|
|
5293
|
+
return false;
|
|
5294
|
+
}
|
|
5295
|
+
const resolved = path26__default.default.resolve(base, e.name);
|
|
5296
|
+
for (const ex of excludeSet) {
|
|
5297
|
+
if (ex === resolved || ex.startsWith(resolved + path26__default.default.sep) || resolved.startsWith(ex + path26__default.default.sep)) {
|
|
5298
|
+
return false;
|
|
5299
|
+
}
|
|
5300
|
+
}
|
|
5301
|
+
return true;
|
|
5302
|
+
}).map((e) => ({
|
|
5194
5303
|
name: e.name,
|
|
5195
|
-
dir:
|
|
5304
|
+
dir: path26__default.default.join(base, e.name)
|
|
5196
5305
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
5197
5306
|
}
|
|
5198
5307
|
function extractClassMethods(content, className) {
|
|
@@ -5348,7 +5457,7 @@ function extractClassMethods(content, className) {
|
|
|
5348
5457
|
return methods;
|
|
5349
5458
|
}
|
|
5350
5459
|
function checkUseCaseShape(featureName, filePath, relativePath, content, addViolation) {
|
|
5351
|
-
const fileName =
|
|
5460
|
+
const fileName = path26__default.default.basename(filePath);
|
|
5352
5461
|
const lines = content.split(/\r?\n/);
|
|
5353
5462
|
const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
|
|
5354
5463
|
if (!classMatch) {
|
|
@@ -5444,7 +5553,7 @@ private ${m.name}(...) { ... }`
|
|
|
5444
5553
|
}
|
|
5445
5554
|
}
|
|
5446
5555
|
function checkServiceShape(featureName, filePath, relativePath, content, addViolation) {
|
|
5447
|
-
const fileName =
|
|
5556
|
+
const fileName = path26__default.default.basename(filePath);
|
|
5448
5557
|
const lines = content.split(/\r?\n/);
|
|
5449
5558
|
const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
|
|
5450
5559
|
if (!classMatch) {
|
|
@@ -5543,40 +5652,32 @@ function lintCodebase(options = {}) {
|
|
|
5543
5652
|
const startTime = Date.now();
|
|
5544
5653
|
const projectRoot = options.projectRoot || findProjectRoot(options.targetDir || process.cwd());
|
|
5545
5654
|
const failFast = !options.complete;
|
|
5546
|
-
const
|
|
5547
|
-
const baseErrorRelative = lintConfig.baseErrorPath || "src/errors/AppError.ts";
|
|
5548
|
-
const baseErrorAbs = path2__default.default.resolve(projectRoot, baseErrorRelative);
|
|
5549
|
-
const featuresBase = resolveFeaturesDir(projectRoot);
|
|
5550
|
-
const sharedBase = resolveSharedDir(projectRoot);
|
|
5551
|
-
let errorsBase = path2__default.default.join(projectRoot, "src/errors");
|
|
5552
|
-
if (!fs14__default.default.existsSync(errorsBase) && fs14__default.default.existsSync(path2__default.default.join(projectRoot, "errors"))) {
|
|
5553
|
-
errorsBase = path2__default.default.join(projectRoot, "errors");
|
|
5554
|
-
}
|
|
5655
|
+
const { featuresBase, sharedBase, errorsBase, baseErrorAbs } = resolveLintEnvironment(projectRoot);
|
|
5555
5656
|
const missingFoundations = [];
|
|
5556
|
-
if (!
|
|
5557
|
-
if (!
|
|
5558
|
-
if (!
|
|
5657
|
+
if (!fs17__default.default.existsSync(featuresBase)) missingFoundations.push("features/");
|
|
5658
|
+
if (!fs17__default.default.existsSync(sharedBase)) missingFoundations.push("shared/");
|
|
5659
|
+
if (!fs17__default.default.existsSync(errorsBase)) missingFoundations.push("errors/");
|
|
5559
5660
|
if (missingFoundations.length > 0) {
|
|
5560
5661
|
throw new DependencyRuleError(
|
|
5561
|
-
`Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every
|
|
5662
|
+
`Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every architecture must contain 'features/', 'shared/', and 'errors/'.`,
|
|
5562
5663
|
[],
|
|
5563
5664
|
true
|
|
5564
5665
|
);
|
|
5565
5666
|
}
|
|
5566
|
-
if (!
|
|
5667
|
+
if (!fs17__default.default.existsSync(baseErrorAbs)) {
|
|
5567
5668
|
throw new DependencyRuleError(
|
|
5568
|
-
`Project Structure Violation: Base error class not found at '${
|
|
5669
|
+
`Project Structure Violation: Base error class not found at '${path26__default.default.relative(projectRoot, baseErrorAbs).replace(/\\/g, "/")}'. Configure paths.baseError in mason.config.json.`,
|
|
5569
5670
|
[],
|
|
5570
5671
|
true
|
|
5571
5672
|
);
|
|
5572
5673
|
}
|
|
5573
|
-
const baseErrorContent =
|
|
5674
|
+
const baseErrorContent = fs17__default.default.readFileSync(baseErrorAbs, "utf-8");
|
|
5574
5675
|
const baseClassMatch = baseErrorContent.match(
|
|
5575
5676
|
/(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
|
|
5576
5677
|
);
|
|
5577
5678
|
const baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
|
|
5578
|
-
const features = discoverAllFeatures(
|
|
5579
|
-
const sharedModules = discoverAllShared(
|
|
5679
|
+
const features = discoverAllFeatures(featuresBase, [sharedBase, errorsBase]);
|
|
5680
|
+
const sharedModules = discoverAllShared(sharedBase, [featuresBase, errorsBase]);
|
|
5580
5681
|
const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
|
|
5581
5682
|
const allModules = [
|
|
5582
5683
|
...features.map((f) => ({ ...f, type: "feature" })),
|
|
@@ -5619,12 +5720,12 @@ Code: ${v.code}`;
|
|
|
5619
5720
|
const allFiles = scanDirFiles(mod.dir, projectRoot);
|
|
5620
5721
|
modResult.scannedFilesCount = allFiles.length;
|
|
5621
5722
|
for (const file of allFiles) {
|
|
5622
|
-
const relPath =
|
|
5623
|
-
const { moduleType, moduleName, layer } = classifyFile(file,
|
|
5723
|
+
const relPath = path26__default.default.relative(projectRoot, file).replace(/\\/g, "/");
|
|
5724
|
+
const { moduleType, moduleName, layer } = classifyFile(file, featuresBase, sharedBase, errorsBase);
|
|
5624
5725
|
if (!layer || !moduleType || !moduleName) continue;
|
|
5625
|
-
const content =
|
|
5726
|
+
const content = fs17__default.default.readFileSync(file, "utf-8");
|
|
5626
5727
|
const statements = extractImportStatements(content);
|
|
5627
|
-
const baseName =
|
|
5728
|
+
const baseName = path26__default.default.basename(file);
|
|
5628
5729
|
const isBarrel = baseName === "index.ts" || baseName === "index.js";
|
|
5629
5730
|
const throwErrorRegex = /\bthrow\s+(?:new\s+)?Error\s*\(/g;
|
|
5630
5731
|
let throwMatch;
|
|
@@ -5643,7 +5744,7 @@ Code: ${v.code}`;
|
|
|
5643
5744
|
code: lineCode,
|
|
5644
5745
|
ruleId: "E3_PLAIN_ERROR_THROW",
|
|
5645
5746
|
severity: "error",
|
|
5646
|
-
advice: `Throwing plain 'Error' is prohibited. You must throw '${baseErrorClassName}' or a
|
|
5747
|
+
advice: `Throwing plain 'Error' is prohibited. You must throw '${baseErrorClassName}' or a custom error class that inherits from it.`,
|
|
5647
5748
|
fixExample: {
|
|
5648
5749
|
bad: lineCode,
|
|
5649
5750
|
good: `throw new ${baseErrorClassName}("Something went wrong");`
|
|
@@ -5651,7 +5752,7 @@ Code: ${v.code}`;
|
|
|
5651
5752
|
});
|
|
5652
5753
|
}
|
|
5653
5754
|
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");
|
|
5654
|
-
const isBaseErrorFile =
|
|
5755
|
+
const isBaseErrorFile = path26__default.default.resolve(file) === path26__default.default.resolve(baseErrorAbs);
|
|
5655
5756
|
if (isErrorFile && !isBaseErrorFile) {
|
|
5656
5757
|
const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
|
|
5657
5758
|
let classMatch;
|
|
@@ -5673,7 +5774,7 @@ Code: ${v.code}`;
|
|
|
5673
5774
|
code: lineCode,
|
|
5674
5775
|
ruleId: "E4_MISSING_INHERITANCE",
|
|
5675
5776
|
severity: "error",
|
|
5676
|
-
advice: `Error class '${className}' must extend '${baseErrorClassName}'
|
|
5777
|
+
advice: `Error class '${className}' must extend '${baseErrorClassName}'.`,
|
|
5677
5778
|
fixExample: {
|
|
5678
5779
|
bad: lineCode,
|
|
5679
5780
|
good: `export class ${className} extends ${baseErrorClassName} { ... }`
|
|
@@ -5690,7 +5791,7 @@ Code: ${v.code}`;
|
|
|
5690
5791
|
code: lineCode,
|
|
5691
5792
|
ruleId: "E5_NATIVE_ERROR_INHERITANCE",
|
|
5692
5793
|
severity: "error",
|
|
5693
|
-
advice: `Error class '${className}' extends
|
|
5794
|
+
advice: `Error class '${className}' extends native 'Error'. It must extend your configured base error class ('${baseErrorClassName}').`,
|
|
5694
5795
|
fixExample: {
|
|
5695
5796
|
bad: lineCode,
|
|
5696
5797
|
good: `export class ${className} extends ${baseErrorClassName} { ... }`
|
|
@@ -5701,7 +5802,7 @@ Code: ${v.code}`;
|
|
|
5701
5802
|
}
|
|
5702
5803
|
if (moduleType === "error") {
|
|
5703
5804
|
for (const stmt of statements) {
|
|
5704
|
-
const target = classifyTarget(stmt.specifier, file, projectRoot);
|
|
5805
|
+
const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
|
|
5705
5806
|
if (target.targetFeature) {
|
|
5706
5807
|
addViolation({
|
|
5707
5808
|
feature: "global-errors",
|
|
@@ -5767,7 +5868,7 @@ Code: ${v.code}`;
|
|
|
5767
5868
|
}
|
|
5768
5869
|
}
|
|
5769
5870
|
for (const stmt of statements) {
|
|
5770
|
-
const target = classifyTarget(stmt.specifier, file, projectRoot);
|
|
5871
|
+
const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
|
|
5771
5872
|
if (target.targetFeature) {
|
|
5772
5873
|
addViolation({
|
|
5773
5874
|
feature: moduleName,
|
|
@@ -5897,7 +5998,7 @@ Code: ${v.code}`;
|
|
|
5897
5998
|
}
|
|
5898
5999
|
}
|
|
5899
6000
|
for (const stmt of statements) {
|
|
5900
|
-
const target = classifyTarget(stmt.specifier, file, projectRoot);
|
|
6001
|
+
const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
|
|
5901
6002
|
if (target.targetFeature && target.targetFeature !== feat.name) {
|
|
5902
6003
|
const evidence = {
|
|
5903
6004
|
fromFeature: feat.name,
|