@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/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import fs17 from 'fs';
|
|
2
|
+
import path26 from 'path';
|
|
3
3
|
import * as p19 from '@clack/prompts';
|
|
4
4
|
import pc14 from 'picocolors';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
@@ -76,8 +76,8 @@ function isValidIdentifier(str) {
|
|
|
76
76
|
}
|
|
77
77
|
function writeFileSafely(absolutePath, content, options = {}) {
|
|
78
78
|
const projectRoot = options.projectRoot || process.cwd();
|
|
79
|
-
const relPath =
|
|
80
|
-
const existedBefore =
|
|
79
|
+
const relPath = path26.relative(projectRoot, absolutePath).replace(/\\/g, "/");
|
|
80
|
+
const existedBefore = fs17.existsSync(absolutePath);
|
|
81
81
|
if (options.dryRun) {
|
|
82
82
|
return {
|
|
83
83
|
relativePath: relPath,
|
|
@@ -96,11 +96,11 @@ function writeFileSafely(absolutePath, content, options = {}) {
|
|
|
96
96
|
existedBefore: true
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
-
const dir =
|
|
100
|
-
if (!
|
|
101
|
-
|
|
99
|
+
const dir = path26.dirname(absolutePath);
|
|
100
|
+
if (!fs17.existsSync(dir)) {
|
|
101
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
fs17.writeFileSync(absolutePath, content, "utf-8");
|
|
104
104
|
return {
|
|
105
105
|
relativePath: relPath,
|
|
106
106
|
absolutePath,
|
|
@@ -127,17 +127,17 @@ function printGeneratedFiles(files, isDryRun = false) {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
function loadMasonConfig(startDir = process.cwd()) {
|
|
130
|
-
let current =
|
|
130
|
+
let current = path26.resolve(startDir);
|
|
131
131
|
while (true) {
|
|
132
|
-
const configPath =
|
|
133
|
-
if (
|
|
132
|
+
const configPath = path26.join(current, "mason.config.json");
|
|
133
|
+
if (fs17.existsSync(configPath)) {
|
|
134
134
|
try {
|
|
135
|
-
return JSON.parse(
|
|
135
|
+
return JSON.parse(fs17.readFileSync(configPath, "utf-8"));
|
|
136
136
|
} catch {
|
|
137
137
|
return null;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
const parent =
|
|
140
|
+
const parent = path26.dirname(current);
|
|
141
141
|
if (parent === current) break;
|
|
142
142
|
current = parent;
|
|
143
143
|
}
|
|
@@ -147,70 +147,91 @@ function getEffectiveMode(projectRoot, flags) {
|
|
|
147
147
|
if (flags?.registry) return "registry";
|
|
148
148
|
const config = loadMasonConfig(projectRoot);
|
|
149
149
|
if (config?.mode) return config.mode;
|
|
150
|
-
if (
|
|
150
|
+
if (fs17.existsSync(path26.join(projectRoot, "index.json")) && (fs17.existsSync(path26.join(projectRoot, "features")) || fs17.existsSync(path26.join(projectRoot, "shared")) || fs17.existsSync(path26.join(projectRoot, "src/features")) || fs17.existsSync(path26.join(projectRoot, "src/shared")))) {
|
|
151
151
|
return "registry";
|
|
152
152
|
}
|
|
153
153
|
return "app";
|
|
154
154
|
}
|
|
155
155
|
function getConfiguredFeaturesDir(projectRoot, flags) {
|
|
156
|
-
if (flags?.target) return
|
|
157
|
-
if (flags?.dest) return
|
|
156
|
+
if (flags?.target) return path26.resolve(projectRoot, flags.target);
|
|
157
|
+
if (flags?.dest) return path26.resolve(projectRoot, flags.dest);
|
|
158
158
|
const config = loadMasonConfig(projectRoot);
|
|
159
159
|
if (config?.paths?.features) {
|
|
160
|
-
return
|
|
160
|
+
return path26.resolve(projectRoot, config.paths.features);
|
|
161
161
|
}
|
|
162
162
|
const mode = getEffectiveMode(projectRoot, flags);
|
|
163
163
|
if (mode === "registry") {
|
|
164
|
-
if (
|
|
165
|
-
return
|
|
164
|
+
if (fs17.existsSync(path26.join(projectRoot, "src/features"))) {
|
|
165
|
+
return path26.join(projectRoot, "src/features");
|
|
166
166
|
}
|
|
167
|
-
return
|
|
167
|
+
return path26.join(projectRoot, "features");
|
|
168
168
|
}
|
|
169
|
-
if (
|
|
170
|
-
return
|
|
169
|
+
if (fs17.existsSync(path26.join(projectRoot, "src/features"))) {
|
|
170
|
+
return path26.join(projectRoot, "src/features");
|
|
171
171
|
}
|
|
172
|
-
return
|
|
172
|
+
return path26.join(projectRoot, "features");
|
|
173
173
|
}
|
|
174
174
|
function getConfiguredSharedDir(projectRoot, flags) {
|
|
175
|
-
if (flags?.target) return
|
|
176
|
-
if (flags?.dest) return
|
|
175
|
+
if (flags?.target) return path26.resolve(projectRoot, flags.target);
|
|
176
|
+
if (flags?.dest) return path26.resolve(projectRoot, flags.dest);
|
|
177
177
|
const config = loadMasonConfig(projectRoot);
|
|
178
178
|
if (config?.paths?.shared) {
|
|
179
|
-
return
|
|
179
|
+
return path26.resolve(projectRoot, config.paths.shared);
|
|
180
180
|
}
|
|
181
181
|
const mode = getEffectiveMode(projectRoot, flags);
|
|
182
182
|
if (mode === "registry") {
|
|
183
|
-
if (
|
|
184
|
-
return
|
|
183
|
+
if (fs17.existsSync(path26.join(projectRoot, "src/shared"))) {
|
|
184
|
+
return path26.join(projectRoot, "src/shared");
|
|
185
185
|
}
|
|
186
|
-
return
|
|
186
|
+
return path26.join(projectRoot, "shared");
|
|
187
187
|
}
|
|
188
|
-
if (
|
|
189
|
-
return
|
|
188
|
+
if (fs17.existsSync(path26.join(projectRoot, "src/shared"))) {
|
|
189
|
+
return path26.join(projectRoot, "src/shared");
|
|
190
190
|
}
|
|
191
|
-
return
|
|
191
|
+
return path26.join(projectRoot, "shared");
|
|
192
192
|
}
|
|
193
193
|
function loadLintConfig(projectRoot) {
|
|
194
|
-
const
|
|
195
|
-
if (
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
194
|
+
const masonConfig = loadMasonConfig(projectRoot);
|
|
195
|
+
if (masonConfig) {
|
|
196
|
+
return {
|
|
197
|
+
baseErrorPath: masonConfig.paths?.baseError,
|
|
198
|
+
paths: masonConfig.paths
|
|
199
|
+
};
|
|
200
200
|
}
|
|
201
|
-
return {
|
|
201
|
+
return {};
|
|
202
|
+
}
|
|
203
|
+
function getResolvedLintPaths(projectRoot, config) {
|
|
204
|
+
const masonConfig = loadMasonConfig(projectRoot);
|
|
205
|
+
const configuredFeatures = config?.paths?.features ?? masonConfig?.paths?.features;
|
|
206
|
+
const configuredShared = config?.paths?.shared ?? masonConfig?.paths?.shared;
|
|
207
|
+
const configuredErrors = config?.paths?.errors ?? masonConfig?.paths?.errors;
|
|
208
|
+
const resolveBase = (configuredPath, defaultSrc, defaultRoot) => {
|
|
209
|
+
if (configuredPath !== void 0) {
|
|
210
|
+
return path26.resolve(projectRoot, configuredPath);
|
|
211
|
+
}
|
|
212
|
+
const srcPath = path26.join(projectRoot, defaultSrc);
|
|
213
|
+
if (fs17.existsSync(srcPath)) return srcPath;
|
|
214
|
+
const rootPath = path26.join(projectRoot, defaultRoot);
|
|
215
|
+
if (fs17.existsSync(rootPath)) return rootPath;
|
|
216
|
+
return srcPath;
|
|
217
|
+
};
|
|
218
|
+
return {
|
|
219
|
+
featuresBase: resolveBase(configuredFeatures, "src/features", "features"),
|
|
220
|
+
sharedBase: resolveBase(configuredShared, "src/shared", "shared"),
|
|
221
|
+
errorsBase: resolveBase(configuredErrors, "src/errors", "errors")
|
|
222
|
+
};
|
|
202
223
|
}
|
|
203
224
|
|
|
204
225
|
// src/utils/project.ts
|
|
205
226
|
function findProjectRoot(startDir = process.cwd()) {
|
|
206
|
-
let current =
|
|
227
|
+
let current = path26.resolve(startDir);
|
|
207
228
|
while (true) {
|
|
208
|
-
if (
|
|
229
|
+
if (fs17.existsSync(path26.join(current, "package.json"))) {
|
|
209
230
|
return current;
|
|
210
231
|
}
|
|
211
|
-
const parent =
|
|
232
|
+
const parent = path26.dirname(current);
|
|
212
233
|
if (parent === current) {
|
|
213
|
-
return
|
|
234
|
+
return path26.resolve(startDir);
|
|
214
235
|
}
|
|
215
236
|
current = parent;
|
|
216
237
|
}
|
|
@@ -223,9 +244,9 @@ function resolveSharedDir(projectRoot, flags) {
|
|
|
223
244
|
}
|
|
224
245
|
function listExistingShared(projectRoot) {
|
|
225
246
|
const sharedDir = resolveSharedDir(projectRoot);
|
|
226
|
-
if (!
|
|
247
|
+
if (!fs17.existsSync(sharedDir)) return [];
|
|
227
248
|
try {
|
|
228
|
-
const entries =
|
|
249
|
+
const entries = fs17.readdirSync(sharedDir, { withFileTypes: true });
|
|
229
250
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
230
251
|
} catch {
|
|
231
252
|
return [];
|
|
@@ -233,9 +254,9 @@ function listExistingShared(projectRoot) {
|
|
|
233
254
|
}
|
|
234
255
|
function listExistingFeatures(projectRoot) {
|
|
235
256
|
const featuresDir = resolveFeaturesDir(projectRoot);
|
|
236
|
-
if (!
|
|
257
|
+
if (!fs17.existsSync(featuresDir)) return [];
|
|
237
258
|
try {
|
|
238
|
-
const entries =
|
|
259
|
+
const entries = fs17.readdirSync(featuresDir, { withFileTypes: true });
|
|
239
260
|
return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
240
261
|
} catch {
|
|
241
262
|
return [];
|
|
@@ -245,14 +266,14 @@ function listDomainInterfaces(projectRoot, featureName) {
|
|
|
245
266
|
const results = [];
|
|
246
267
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
247
268
|
for (const feat of features) {
|
|
248
|
-
const domainDir =
|
|
249
|
-
if (!
|
|
269
|
+
const domainDir = path26.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
270
|
+
if (!fs17.existsSync(domainDir)) continue;
|
|
250
271
|
try {
|
|
251
|
-
const files =
|
|
272
|
+
const files = fs17.readdirSync(domainDir);
|
|
252
273
|
for (const file of files) {
|
|
253
274
|
if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
|
|
254
275
|
const name = file.replace(/\.ts$/, "");
|
|
255
|
-
const fullPath =
|
|
276
|
+
const fullPath = path26.join(domainDir, file);
|
|
256
277
|
if (/^I[A-Z]/.test(name)) {
|
|
257
278
|
results.push({
|
|
258
279
|
name,
|
|
@@ -261,7 +282,7 @@ function listDomainInterfaces(projectRoot, featureName) {
|
|
|
261
282
|
});
|
|
262
283
|
} else {
|
|
263
284
|
try {
|
|
264
|
-
const content =
|
|
285
|
+
const content = fs17.readFileSync(fullPath, "utf-8");
|
|
265
286
|
if (/export\s+(?:abstract\s+class|interface)\s+(\w+)/.test(content)) {
|
|
266
287
|
results.push({
|
|
267
288
|
name,
|
|
@@ -283,17 +304,17 @@ function listDomainEntities(projectRoot, featureName) {
|
|
|
283
304
|
const results = [];
|
|
284
305
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
285
306
|
for (const feat of features) {
|
|
286
|
-
const domainDir =
|
|
287
|
-
if (!
|
|
307
|
+
const domainDir = path26.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
308
|
+
if (!fs17.existsSync(domainDir)) continue;
|
|
288
309
|
try {
|
|
289
|
-
const files =
|
|
310
|
+
const files = fs17.readdirSync(domainDir);
|
|
290
311
|
for (const file of files) {
|
|
291
312
|
if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
|
|
292
313
|
const name = file.replace(/\.ts$/, "");
|
|
293
314
|
if (!/^I[A-Z]/.test(name)) {
|
|
294
315
|
results.push({
|
|
295
316
|
name,
|
|
296
|
-
fullPath:
|
|
317
|
+
fullPath: path26.join(domainDir, file),
|
|
297
318
|
feature: feat
|
|
298
319
|
});
|
|
299
320
|
}
|
|
@@ -308,16 +329,16 @@ function listUseCases(projectRoot, featureName) {
|
|
|
308
329
|
const results = [];
|
|
309
330
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
310
331
|
for (const feat of features) {
|
|
311
|
-
const useCasesDir =
|
|
312
|
-
if (!
|
|
332
|
+
const useCasesDir = path26.join(resolveFeaturesDir(projectRoot), feat, "useCases");
|
|
333
|
+
if (!fs17.existsSync(useCasesDir)) continue;
|
|
313
334
|
try {
|
|
314
|
-
const files =
|
|
335
|
+
const files = fs17.readdirSync(useCasesDir);
|
|
315
336
|
for (const file of files) {
|
|
316
337
|
if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
|
|
317
338
|
const name = file.replace(/\.ts$/, "");
|
|
318
339
|
results.push({
|
|
319
340
|
name,
|
|
320
|
-
fullPath:
|
|
341
|
+
fullPath: path26.join(useCasesDir, file),
|
|
321
342
|
feature: feat
|
|
322
343
|
});
|
|
323
344
|
}
|
|
@@ -429,25 +450,25 @@ function normalizeRegistryUrl(urlOrPath, baseDir) {
|
|
|
429
450
|
return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
|
|
430
451
|
}
|
|
431
452
|
if (baseDir && (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed === "." || trimmed === "..")) {
|
|
432
|
-
return
|
|
453
|
+
return path26.resolve(baseDir, trimmed);
|
|
433
454
|
}
|
|
434
455
|
return trimmed;
|
|
435
456
|
}
|
|
436
457
|
function findLocalRegistry(startDir = process.cwd()) {
|
|
437
|
-
let current =
|
|
458
|
+
let current = path26.resolve(startDir);
|
|
438
459
|
while (true) {
|
|
439
|
-
const candidate =
|
|
440
|
-
if (
|
|
460
|
+
const candidate = path26.join(current, "mason-registry");
|
|
461
|
+
if (fs17.existsSync(candidate) && fs17.existsSync(path26.join(candidate, "index.json"))) {
|
|
441
462
|
return candidate;
|
|
442
463
|
}
|
|
443
|
-
const parent =
|
|
464
|
+
const parent = path26.dirname(current);
|
|
444
465
|
if (parent === current) break;
|
|
445
466
|
current = parent;
|
|
446
467
|
}
|
|
447
468
|
return null;
|
|
448
469
|
}
|
|
449
470
|
function getRegistryBase(projectRoot, override) {
|
|
450
|
-
const rootDir = projectRoot ?
|
|
471
|
+
const rootDir = projectRoot ? path26.resolve(projectRoot) : process.cwd();
|
|
451
472
|
if (override && override.trim()) {
|
|
452
473
|
return normalizeRegistryUrl(override.trim(), rootDir);
|
|
453
474
|
}
|
|
@@ -455,30 +476,30 @@ function getRegistryBase(projectRoot, override) {
|
|
|
455
476
|
return normalizeRegistryUrl(process.env.MASON_REGISTRY_URL.trim(), rootDir);
|
|
456
477
|
}
|
|
457
478
|
const configLocations = [
|
|
458
|
-
|
|
459
|
-
|
|
479
|
+
path26.join(rootDir, "mason.config.json"),
|
|
480
|
+
path26.join(process.cwd(), "mason.config.json")
|
|
460
481
|
];
|
|
461
482
|
for (const configPath of configLocations) {
|
|
462
|
-
if (
|
|
483
|
+
if (fs17.existsSync(configPath)) {
|
|
463
484
|
try {
|
|
464
|
-
const config = JSON.parse(
|
|
485
|
+
const config = JSON.parse(fs17.readFileSync(configPath, "utf-8"));
|
|
465
486
|
if (config.registry && typeof config.registry === "string") {
|
|
466
|
-
return normalizeRegistryUrl(config.registry.trim(),
|
|
487
|
+
return normalizeRegistryUrl(config.registry.trim(), path26.dirname(configPath));
|
|
467
488
|
}
|
|
468
489
|
} catch {
|
|
469
490
|
}
|
|
470
491
|
}
|
|
471
492
|
}
|
|
472
493
|
const pkgLocations = [
|
|
473
|
-
|
|
474
|
-
|
|
494
|
+
path26.join(rootDir, "package.json"),
|
|
495
|
+
path26.join(process.cwd(), "package.json")
|
|
475
496
|
];
|
|
476
497
|
for (const pkgPath of pkgLocations) {
|
|
477
|
-
if (
|
|
498
|
+
if (fs17.existsSync(pkgPath)) {
|
|
478
499
|
try {
|
|
479
|
-
const pkg = JSON.parse(
|
|
500
|
+
const pkg = JSON.parse(fs17.readFileSync(pkgPath, "utf-8"));
|
|
480
501
|
if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
|
|
481
|
-
return normalizeRegistryUrl(pkg.mason.registry.trim(),
|
|
502
|
+
return normalizeRegistryUrl(pkg.mason.registry.trim(), path26.dirname(pkgPath));
|
|
482
503
|
}
|
|
483
504
|
} catch {
|
|
484
505
|
}
|
|
@@ -526,16 +547,16 @@ async function fetchRegistryFile(registryBase, relPath) {
|
|
|
526
547
|
if (baseDir.startsWith("file://")) {
|
|
527
548
|
baseDir = fileURLToPath(baseDir);
|
|
528
549
|
}
|
|
529
|
-
let filePath =
|
|
530
|
-
if (!
|
|
531
|
-
const inSrcPath =
|
|
532
|
-
if (
|
|
550
|
+
let filePath = path26.resolve(baseDir, cleanRelPath);
|
|
551
|
+
if (!fs17.existsSync(filePath)) {
|
|
552
|
+
const inSrcPath = path26.resolve(baseDir, "src", cleanRelPath);
|
|
553
|
+
if (fs17.existsSync(inSrcPath)) {
|
|
533
554
|
filePath = inSrcPath;
|
|
534
555
|
} else {
|
|
535
556
|
throw new Error(`Registry file not found at ${filePath}`);
|
|
536
557
|
}
|
|
537
558
|
}
|
|
538
|
-
return
|
|
559
|
+
return fs17.promises.readFile(filePath, "utf-8");
|
|
539
560
|
}
|
|
540
561
|
async function fetchRegistryIndex(registryBase) {
|
|
541
562
|
const content = await fetchRegistryFile(registryBase, "index.json");
|
|
@@ -597,19 +618,19 @@ function findClosestMatch(target, candidates) {
|
|
|
597
618
|
return null;
|
|
598
619
|
}
|
|
599
620
|
function detectPackageManager(projectRoot) {
|
|
600
|
-
if (
|
|
601
|
-
if (
|
|
602
|
-
if (
|
|
621
|
+
if (fs17.existsSync(path26.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
622
|
+
if (fs17.existsSync(path26.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
623
|
+
if (fs17.existsSync(path26.join(projectRoot, "bun.lockb")) || fs17.existsSync(path26.join(projectRoot, "bun.lock"))) return "bun";
|
|
603
624
|
return "npm";
|
|
604
625
|
}
|
|
605
626
|
function getMissingNpmPackages(projectRoot, requiredPackages) {
|
|
606
627
|
if (!requiredPackages || requiredPackages.length === 0) return [];
|
|
607
|
-
const pkgJsonPath =
|
|
608
|
-
if (!
|
|
628
|
+
const pkgJsonPath = path26.join(projectRoot, "package.json");
|
|
629
|
+
if (!fs17.existsSync(pkgJsonPath)) {
|
|
609
630
|
return requiredPackages;
|
|
610
631
|
}
|
|
611
632
|
try {
|
|
612
|
-
const pkg = JSON.parse(
|
|
633
|
+
const pkg = JSON.parse(fs17.readFileSync(pkgJsonPath, "utf-8"));
|
|
613
634
|
const installed = /* @__PURE__ */ new Set([
|
|
614
635
|
...Object.keys(pkg.dependencies || {}),
|
|
615
636
|
...Object.keys(pkg.devDependencies || {}),
|
|
@@ -648,12 +669,12 @@ function installNpmPackages(projectRoot, packages, pm) {
|
|
|
648
669
|
});
|
|
649
670
|
}
|
|
650
671
|
function getAllFiles(dir, baseDir = dir) {
|
|
651
|
-
if (!
|
|
652
|
-
const entries =
|
|
672
|
+
if (!fs17.existsSync(dir)) return [];
|
|
673
|
+
const entries = fs17.readdirSync(dir, { withFileTypes: true });
|
|
653
674
|
const files = [];
|
|
654
675
|
for (const entry of entries) {
|
|
655
|
-
const fullPath =
|
|
656
|
-
const relPath =
|
|
676
|
+
const fullPath = path26.join(dir, entry.name);
|
|
677
|
+
const relPath = path26.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
657
678
|
if (entry.isDirectory()) {
|
|
658
679
|
if (entry.name === "__tests__" || entry.name.startsWith(".")) {
|
|
659
680
|
continue;
|
|
@@ -669,13 +690,13 @@ function getAllFiles(dir, baseDir = dir) {
|
|
|
669
690
|
return files.sort();
|
|
670
691
|
}
|
|
671
692
|
function computeDirectoryHash(dirPath, files) {
|
|
672
|
-
if (!
|
|
693
|
+
if (!fs17.existsSync(dirPath)) return "";
|
|
673
694
|
const hash = createHash("sha256");
|
|
674
695
|
const fileList = (files ?? getAllFiles(dirPath)).sort();
|
|
675
696
|
for (const relativePath of fileList) {
|
|
676
|
-
const absolutePath =
|
|
677
|
-
if (!
|
|
678
|
-
const content =
|
|
697
|
+
const absolutePath = path26.join(dirPath, relativePath);
|
|
698
|
+
if (!fs17.existsSync(absolutePath)) continue;
|
|
699
|
+
const content = fs17.readFileSync(absolutePath, "utf8");
|
|
679
700
|
const normalizedContent = content.replace(/\r\n/g, "\n");
|
|
680
701
|
hash.update(relativePath);
|
|
681
702
|
hash.update(normalizedContent);
|
|
@@ -698,33 +719,33 @@ hbs.registerHelper("join", (arr, sep) => {
|
|
|
698
719
|
});
|
|
699
720
|
var cachedTemplatesDir = null;
|
|
700
721
|
function getTemplatesDir() {
|
|
701
|
-
if (cachedTemplatesDir &&
|
|
722
|
+
if (cachedTemplatesDir && fs17.existsSync(cachedTemplatesDir)) {
|
|
702
723
|
return cachedTemplatesDir;
|
|
703
724
|
}
|
|
704
|
-
const currentDir = typeof __dirname !== "undefined" ? __dirname :
|
|
705
|
-
const cand1 =
|
|
706
|
-
if (
|
|
725
|
+
const currentDir = typeof __dirname !== "undefined" ? __dirname : path26.dirname(fileURLToPath(import.meta.url));
|
|
726
|
+
const cand1 = path26.resolve(currentDir, "../../templates");
|
|
727
|
+
if (fs17.existsSync(cand1)) {
|
|
707
728
|
cachedTemplatesDir = cand1;
|
|
708
729
|
return cand1;
|
|
709
730
|
}
|
|
710
|
-
const cand2 =
|
|
711
|
-
if (
|
|
731
|
+
const cand2 = path26.resolve(currentDir, "../templates");
|
|
732
|
+
if (fs17.existsSync(cand2)) {
|
|
712
733
|
cachedTemplatesDir = cand2;
|
|
713
734
|
return cand2;
|
|
714
735
|
}
|
|
715
|
-
const cand3 =
|
|
716
|
-
if (
|
|
736
|
+
const cand3 = path26.resolve(currentDir, "templates");
|
|
737
|
+
if (fs17.existsSync(cand3)) {
|
|
717
738
|
cachedTemplatesDir = cand3;
|
|
718
739
|
return cand3;
|
|
719
740
|
}
|
|
720
741
|
let curr = currentDir;
|
|
721
742
|
while (true) {
|
|
722
|
-
const candTemplates =
|
|
723
|
-
if (
|
|
743
|
+
const candTemplates = path26.join(curr, "templates");
|
|
744
|
+
if (fs17.existsSync(candTemplates)) {
|
|
724
745
|
cachedTemplatesDir = candTemplates;
|
|
725
746
|
return candTemplates;
|
|
726
747
|
}
|
|
727
|
-
const parent =
|
|
748
|
+
const parent = path26.dirname(curr);
|
|
728
749
|
if (parent === curr) break;
|
|
729
750
|
curr = parent;
|
|
730
751
|
}
|
|
@@ -732,8 +753,8 @@ function getTemplatesDir() {
|
|
|
732
753
|
}
|
|
733
754
|
var templateCache = /* @__PURE__ */ new Map();
|
|
734
755
|
function loadTemplate(relativePath) {
|
|
735
|
-
const fullPath =
|
|
736
|
-
return
|
|
756
|
+
const fullPath = path26.isAbsolute(relativePath) ? relativePath : path26.join(getTemplatesDir(), relativePath);
|
|
757
|
+
return fs17.readFileSync(fullPath, "utf-8");
|
|
737
758
|
}
|
|
738
759
|
function renderTemplateFile(relativePath, context) {
|
|
739
760
|
let compiled = templateCache.get(relativePath);
|
|
@@ -818,8 +839,8 @@ function generateDomainEntityCode(name, kind = "interface", properties = []) {
|
|
|
818
839
|
function generateDomain(options) {
|
|
819
840
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
820
841
|
const entityName = toPascalCase(options.name);
|
|
821
|
-
const targetDir = options.targetDir ||
|
|
822
|
-
const filePath =
|
|
842
|
+
const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
|
|
843
|
+
const filePath = path26.join(targetDir, `${entityName}.ts`);
|
|
823
844
|
const code = generateDomainEntityCode(
|
|
824
845
|
entityName,
|
|
825
846
|
options.kind || "interface",
|
|
@@ -868,8 +889,8 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
|
|
|
868
889
|
function generateInterface(options) {
|
|
869
890
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
870
891
|
const ifaceName = ensureInterfacePrefix(options.name);
|
|
871
|
-
const targetDir = options.targetDir ||
|
|
872
|
-
const filePath =
|
|
892
|
+
const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
|
|
893
|
+
const filePath = path26.join(targetDir, `${ifaceName}.ts`);
|
|
873
894
|
const code = generateInterfaceCode(
|
|
874
895
|
ifaceName,
|
|
875
896
|
options.kind || "abstractClass",
|
|
@@ -1104,7 +1125,7 @@ function parseInterfaceMethodsAndImports(content, targetIfaceName) {
|
|
|
1104
1125
|
};
|
|
1105
1126
|
}
|
|
1106
1127
|
function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
|
|
1107
|
-
if (customPath &&
|
|
1128
|
+
if (customPath && fs17.existsSync(customPath)) {
|
|
1108
1129
|
return { filePath: customPath, ifaceName };
|
|
1109
1130
|
}
|
|
1110
1131
|
const candidateNames = [
|
|
@@ -1114,22 +1135,22 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
|
|
|
1114
1135
|
];
|
|
1115
1136
|
const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
|
|
1116
1137
|
for (const feat of features) {
|
|
1117
|
-
const domainDir =
|
|
1118
|
-
if (!
|
|
1138
|
+
const domainDir = path26.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
1139
|
+
if (!fs17.existsSync(domainDir)) continue;
|
|
1119
1140
|
for (const cand of candidateNames) {
|
|
1120
|
-
const p1 =
|
|
1121
|
-
if (
|
|
1141
|
+
const p1 = path26.join(domainDir, `${cand}.ts`);
|
|
1142
|
+
if (fs17.existsSync(p1)) {
|
|
1122
1143
|
return { filePath: p1, ifaceName: cand, feature: feat };
|
|
1123
1144
|
}
|
|
1124
1145
|
}
|
|
1125
1146
|
}
|
|
1126
1147
|
for (const cand of candidateNames) {
|
|
1127
|
-
const p1 =
|
|
1128
|
-
if (
|
|
1129
|
-
const p22 =
|
|
1130
|
-
if (
|
|
1131
|
-
const p32 =
|
|
1132
|
-
if (
|
|
1148
|
+
const p1 = path26.join(projectRoot, "domain", `${cand}.ts`);
|
|
1149
|
+
if (fs17.existsSync(p1)) return { filePath: p1, ifaceName: cand };
|
|
1150
|
+
const p22 = path26.join(projectRoot, "src", "domain", `${cand}.ts`);
|
|
1151
|
+
if (fs17.existsSync(p22)) return { filePath: p22, ifaceName: cand };
|
|
1152
|
+
const p32 = path26.join(projectRoot, "interfaces", `${cand}.ts`);
|
|
1153
|
+
if (fs17.existsSync(p32)) return { filePath: p32, ifaceName: cand };
|
|
1133
1154
|
}
|
|
1134
1155
|
return null;
|
|
1135
1156
|
}
|
|
@@ -1152,7 +1173,7 @@ function loadInterfaceHierarchy(projectRoot, initialIfaceName, featureName, cust
|
|
|
1152
1173
|
while (currentFile && !visited.has(currentFile)) {
|
|
1153
1174
|
visited.add(currentFile);
|
|
1154
1175
|
try {
|
|
1155
|
-
const content =
|
|
1176
|
+
const content = fs17.readFileSync(currentFile, "utf-8");
|
|
1156
1177
|
const parsed = parseInterfaceMethodsAndImports(content, currentName);
|
|
1157
1178
|
for (const m of parsed.methods) {
|
|
1158
1179
|
if (!allMethods.some((existing) => existing.name === m.name)) {
|
|
@@ -1228,7 +1249,7 @@ function generateStubCode(stubClassName, ifaceName, entityName, featureName, met
|
|
|
1228
1249
|
const entitiesVar = `${entityVar}s`;
|
|
1229
1250
|
const idKey = `${entityVar}Id`;
|
|
1230
1251
|
const impPath = ifaceImportPath || `../domain/${ifaceName}.js`;
|
|
1231
|
-
const entityImportPath = ifaceImportPath ? `${
|
|
1252
|
+
const entityImportPath = ifaceImportPath ? `${path26.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
|
|
1232
1253
|
const importsByFrom = /* @__PURE__ */ new Map();
|
|
1233
1254
|
for (const imp of domainImports) {
|
|
1234
1255
|
if (imp.name === ifaceName || imp.name === baseEntity) continue;
|
|
@@ -1277,7 +1298,7 @@ function generateConcreteInfraCode(className, ifaceName, dependencies = [], meth
|
|
|
1277
1298
|
if (baseEntity) {
|
|
1278
1299
|
finalMethods = synthesizeCrudMethods(baseEntity);
|
|
1279
1300
|
if (!finalDomainImports.some((imp) => imp.name === baseEntity)) {
|
|
1280
|
-
const importPath = ifaceImportPath ? `${
|
|
1301
|
+
const importPath = ifaceImportPath ? `${path26.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
|
|
1281
1302
|
finalDomainImports.push({
|
|
1282
1303
|
name: baseEntity,
|
|
1283
1304
|
from: importPath,
|
|
@@ -1322,8 +1343,8 @@ function generateInfrastructure(options) {
|
|
|
1322
1343
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1323
1344
|
const className = toPascalCase(options.name);
|
|
1324
1345
|
const isFeatureScope = options.scope !== "global" && Boolean(options.feature);
|
|
1325
|
-
const targetDir = options.targetDir || (isFeatureScope ?
|
|
1326
|
-
const filePath =
|
|
1346
|
+
const targetDir = options.targetDir || (isFeatureScope ? path26.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path26.join(projectRoot, "infrastructure"));
|
|
1347
|
+
const filePath = path26.join(targetDir, `${className}.ts`);
|
|
1327
1348
|
let code;
|
|
1328
1349
|
if (options.implementsInterface) {
|
|
1329
1350
|
const rawIfaceName = options.implementsInterface;
|
|
@@ -1337,7 +1358,7 @@ function generateInfrastructure(options) {
|
|
|
1337
1358
|
const ifaceFilePath = hierarchy.ifaceFilePath;
|
|
1338
1359
|
let ifaceImportPath;
|
|
1339
1360
|
if (ifaceFilePath) {
|
|
1340
|
-
let rel =
|
|
1361
|
+
let rel = path26.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
|
|
1341
1362
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
1342
1363
|
ifaceImportPath = rel;
|
|
1343
1364
|
} else if (isFeatureScope) {
|
|
@@ -1350,8 +1371,8 @@ function generateInfrastructure(options) {
|
|
|
1350
1371
|
if (new RegExp(`\\b${item.name}\\b`).test(allSignatures)) {
|
|
1351
1372
|
let fromPath;
|
|
1352
1373
|
if (imp.specifier.startsWith(".") && ifaceFilePath) {
|
|
1353
|
-
const absTarget =
|
|
1354
|
-
let rel =
|
|
1374
|
+
const absTarget = path26.resolve(path26.dirname(ifaceFilePath), imp.specifier);
|
|
1375
|
+
let rel = path26.relative(targetDir, absTarget).replace(/\\/g, "/");
|
|
1355
1376
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
1356
1377
|
fromPath = rel;
|
|
1357
1378
|
} else {
|
|
@@ -1538,8 +1559,8 @@ function generateUseCase(options) {
|
|
|
1538
1559
|
const files = [];
|
|
1539
1560
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1540
1561
|
const ucName = toPascalCase(options.name);
|
|
1541
|
-
const targetDir = options.targetDir ||
|
|
1542
|
-
const filePath =
|
|
1562
|
+
const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
|
|
1563
|
+
const filePath = path26.join(targetDir, `${ucName}.ts`);
|
|
1543
1564
|
const code = generateUseCaseCode(
|
|
1544
1565
|
ucName,
|
|
1545
1566
|
options.dependencies || [],
|
|
@@ -1555,7 +1576,7 @@ function generateUseCase(options) {
|
|
|
1555
1576
|
})
|
|
1556
1577
|
);
|
|
1557
1578
|
if (options.includeTest) {
|
|
1558
|
-
const testPath =
|
|
1579
|
+
const testPath = path26.join(targetDir, `${ucName}.test.ts`);
|
|
1559
1580
|
const testCode = generateUseCaseTestCode(ucName, options.dependencies || []);
|
|
1560
1581
|
files.push(
|
|
1561
1582
|
writeFileSafely(testPath, testCode, {
|
|
@@ -1623,10 +1644,10 @@ function generateHttpHandler(options) {
|
|
|
1623
1644
|
const files = [];
|
|
1624
1645
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1625
1646
|
const className = toPascalCase(options.name);
|
|
1626
|
-
const pxDir =
|
|
1627
|
-
const handlersDir =
|
|
1628
|
-
const pxIndexPath =
|
|
1629
|
-
if (!
|
|
1647
|
+
const pxDir = path26.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
|
|
1648
|
+
const handlersDir = path26.join(pxDir, "handlers");
|
|
1649
|
+
const pxIndexPath = path26.join(pxDir, "index.ts");
|
|
1650
|
+
if (!fs17.existsSync(pxIndexPath)) {
|
|
1630
1651
|
const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
|
|
1631
1652
|
const pxIndexContent = renderTemplate(expressIndexTemplate, {
|
|
1632
1653
|
routePath: featurePath
|
|
@@ -1639,7 +1660,7 @@ function generateHttpHandler(options) {
|
|
|
1639
1660
|
})
|
|
1640
1661
|
);
|
|
1641
1662
|
}
|
|
1642
|
-
const handlerFilePath =
|
|
1663
|
+
const handlerFilePath = path26.join(handlersDir, `${className}.ts`);
|
|
1643
1664
|
const code = generateHttpHandlerCode(
|
|
1644
1665
|
className,
|
|
1645
1666
|
options.method || "get",
|
|
@@ -1660,11 +1681,11 @@ function generateHttpHandler(options) {
|
|
|
1660
1681
|
return files;
|
|
1661
1682
|
}
|
|
1662
1683
|
function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], options = {}) {
|
|
1663
|
-
const providerPath =
|
|
1684
|
+
const providerPath = path26.join(featureDir, "diProvider.ts");
|
|
1664
1685
|
const pascalFeature = toPascalCase(featureName);
|
|
1665
1686
|
const providerModuleName = `${pascalFeature}Provider`;
|
|
1666
|
-
if (
|
|
1667
|
-
let content =
|
|
1687
|
+
if (fs17.existsSync(providerPath) && !options.overwrite) {
|
|
1688
|
+
let content = fs17.readFileSync(providerPath, "utf-8");
|
|
1668
1689
|
content = content.replace(/\n*export\s+const\s+ScaffoldProvider\s*=[^;]+;?/g, "");
|
|
1669
1690
|
for (const b of bindings) {
|
|
1670
1691
|
const ifaceImp = b.ifaceImportPath || `./domain/${b.ifaceName}.js`;
|
|
@@ -1723,7 +1744,7 @@ function generateFeature(options) {
|
|
|
1723
1744
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1724
1745
|
const rawName = options.name.trim();
|
|
1725
1746
|
const featureName = toCamelCase(rawName);
|
|
1726
|
-
const targetDir = options.targetDir ||
|
|
1747
|
+
const targetDir = options.targetDir || path26.join(resolveFeaturesDir(projectRoot), featureName);
|
|
1727
1748
|
const routePath = options.routePath || `/${featureName}`;
|
|
1728
1749
|
const rawEntities = [];
|
|
1729
1750
|
if (options.entityNames && options.entityNames.length > 0) {
|
|
@@ -1744,7 +1765,7 @@ function generateFeature(options) {
|
|
|
1744
1765
|
const domainFile = generateDomain({
|
|
1745
1766
|
name: ent,
|
|
1746
1767
|
feature: featureName,
|
|
1747
|
-
targetDir:
|
|
1768
|
+
targetDir: path26.join(targetDir, "domain"),
|
|
1748
1769
|
projectRoot,
|
|
1749
1770
|
dryRun: options.dryRun,
|
|
1750
1771
|
overwrite: options.overwrite,
|
|
@@ -1764,7 +1785,7 @@ function generateFeature(options) {
|
|
|
1764
1785
|
const ifaceFile = generateInterface({
|
|
1765
1786
|
name: ifaceName,
|
|
1766
1787
|
feature: featureName,
|
|
1767
|
-
targetDir:
|
|
1788
|
+
targetDir: path26.join(targetDir, "domain"),
|
|
1768
1789
|
entityName: ent,
|
|
1769
1790
|
projectRoot,
|
|
1770
1791
|
dryRun: options.dryRun,
|
|
@@ -1781,7 +1802,7 @@ function generateFeature(options) {
|
|
|
1781
1802
|
const stubFile = generateInfrastructure({
|
|
1782
1803
|
name: stubName,
|
|
1783
1804
|
feature: featureName,
|
|
1784
|
-
targetDir:
|
|
1805
|
+
targetDir: path26.join(targetDir, "infrastructure"),
|
|
1785
1806
|
kind: "stub",
|
|
1786
1807
|
implementsInterface: ifaceName,
|
|
1787
1808
|
entityName: ent,
|
|
@@ -1823,7 +1844,7 @@ function generateFeature(options) {
|
|
|
1823
1844
|
const ucFiles = generateUseCase({
|
|
1824
1845
|
name: ucName,
|
|
1825
1846
|
feature: featureName,
|
|
1826
|
-
targetDir:
|
|
1847
|
+
targetDir: path26.join(targetDir, "useCases"),
|
|
1827
1848
|
dependencies: options.includeInterface !== false ? [ifaceName] : [],
|
|
1828
1849
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1829
1850
|
outputProperties: [{ name: entVar, type: primaryEntity }],
|
|
@@ -1868,7 +1889,7 @@ function generateFeature(options) {
|
|
|
1868
1889
|
const ucFiles = generateUseCase({
|
|
1869
1890
|
name: ucName,
|
|
1870
1891
|
feature: featureName,
|
|
1871
|
-
targetDir:
|
|
1892
|
+
targetDir: path26.join(targetDir, "useCases"),
|
|
1872
1893
|
dependencies: deps,
|
|
1873
1894
|
inputProperties: [{ name: entVar, type: ent }],
|
|
1874
1895
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1901,7 +1922,7 @@ function generateFeature(options) {
|
|
|
1901
1922
|
const ucFiles = generateUseCase({
|
|
1902
1923
|
name: ucName,
|
|
1903
1924
|
feature: featureName,
|
|
1904
|
-
targetDir:
|
|
1925
|
+
targetDir: path26.join(targetDir, "useCases"),
|
|
1905
1926
|
dependencies: deps,
|
|
1906
1927
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1907
1928
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1934,7 +1955,7 @@ function generateFeature(options) {
|
|
|
1934
1955
|
const ucFiles = generateUseCase({
|
|
1935
1956
|
name: ucName,
|
|
1936
1957
|
feature: featureName,
|
|
1937
|
-
targetDir:
|
|
1958
|
+
targetDir: path26.join(targetDir, "useCases"),
|
|
1938
1959
|
dependencies: deps,
|
|
1939
1960
|
inputProperties: [
|
|
1940
1961
|
{ name: "page", type: "number", optional: true },
|
|
@@ -1978,7 +1999,7 @@ function generateFeature(options) {
|
|
|
1978
1999
|
const ucFiles = generateUseCase({
|
|
1979
2000
|
name: ucName,
|
|
1980
2001
|
feature: featureName,
|
|
1981
|
-
targetDir:
|
|
2002
|
+
targetDir: path26.join(targetDir, "useCases"),
|
|
1982
2003
|
dependencies: deps,
|
|
1983
2004
|
inputProperties: [{ name: entVar, type: ent }],
|
|
1984
2005
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -2011,7 +2032,7 @@ function generateFeature(options) {
|
|
|
2011
2032
|
const ucFiles = generateUseCase({
|
|
2012
2033
|
name: ucName,
|
|
2013
2034
|
feature: featureName,
|
|
2014
|
-
targetDir:
|
|
2035
|
+
targetDir: path26.join(targetDir, "useCases"),
|
|
2015
2036
|
dependencies: deps,
|
|
2016
2037
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
2017
2038
|
outputProperties: [{ name: "success", type: "boolean" }],
|
|
@@ -2048,7 +2069,7 @@ function generateFeature(options) {
|
|
|
2048
2069
|
const ucFiles = generateUseCase({
|
|
2049
2070
|
name: ucName,
|
|
2050
2071
|
feature: featureName,
|
|
2051
|
-
targetDir:
|
|
2072
|
+
targetDir: path26.join(targetDir, "useCases"),
|
|
2052
2073
|
dependencies: customUc.dependencies || [],
|
|
2053
2074
|
inputProperties: customUc.inputProperties || [],
|
|
2054
2075
|
outputProperties: customUc.outputProperties || [],
|
|
@@ -2080,8 +2101,8 @@ function generateFeature(options) {
|
|
|
2080
2101
|
}
|
|
2081
2102
|
}
|
|
2082
2103
|
if (options.includeExpress !== false) {
|
|
2083
|
-
const pxDir =
|
|
2084
|
-
const pxIndexPath =
|
|
2104
|
+
const pxDir = path26.join(targetDir, "pxExpress");
|
|
2105
|
+
const pxIndexPath = path26.join(pxDir, "index.ts");
|
|
2085
2106
|
if (!files.some((f) => f.absolutePath === pxIndexPath)) {
|
|
2086
2107
|
const pxIndexContent = renderTemplate(expressIndexTemplate, { routePath });
|
|
2087
2108
|
files.push(
|
|
@@ -2126,7 +2147,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
2126
2147
|
}
|
|
2127
2148
|
const normalizedName = toCamelCase(name);
|
|
2128
2149
|
const baseFeaturesDir = resolveFeaturesDir(projectRoot, flags);
|
|
2129
|
-
const defaultDir =
|
|
2150
|
+
const defaultDir = path26.relative(projectRoot, path26.join(baseFeaturesDir, normalizedName));
|
|
2130
2151
|
let targetDirRel = defaultDir;
|
|
2131
2152
|
if (!flags.yes && !flags.target && !flags.dest) {
|
|
2132
2153
|
targetDirRel = handleCancel(
|
|
@@ -2137,7 +2158,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
2137
2158
|
})
|
|
2138
2159
|
).trim();
|
|
2139
2160
|
}
|
|
2140
|
-
const targetDir = flags.dest ?
|
|
2161
|
+
const targetDir = flags.dest ? path26.resolve(projectRoot, flags.dest) : flags.target ? path26.resolve(projectRoot, flags.target) : path26.resolve(projectRoot, targetDirRel);
|
|
2141
2162
|
let includeExpress = flags.express !== void 0 ? Boolean(flags.express) : true;
|
|
2142
2163
|
let routePath = `/${normalizedName}`;
|
|
2143
2164
|
let includeDomain = true;
|
|
@@ -2379,8 +2400,8 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
2379
2400
|
};
|
|
2380
2401
|
const files = generateFeature(options);
|
|
2381
2402
|
if (isRegistry) {
|
|
2382
|
-
const registryPath =
|
|
2383
|
-
if (!
|
|
2403
|
+
const registryPath = path26.join(targetDir, "registry.json");
|
|
2404
|
+
if (!fs17.existsSync(registryPath)) {
|
|
2384
2405
|
const manifest = {
|
|
2385
2406
|
name: toKebabCase(normalizedName),
|
|
2386
2407
|
type: "feature",
|
|
@@ -2406,7 +2427,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
2406
2427
|
printGeneratedFiles(files, options.dryRun);
|
|
2407
2428
|
p19.outro(
|
|
2408
2429
|
pc14.green(
|
|
2409
|
-
`\u2713 Feature '${normalizedName}' initialized in ${
|
|
2430
|
+
`\u2713 Feature '${normalizedName}' initialized in ${path26.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
|
|
2410
2431
|
)
|
|
2411
2432
|
);
|
|
2412
2433
|
}
|
|
@@ -2417,7 +2438,7 @@ function generateShared(options) {
|
|
|
2417
2438
|
const pascalName = toPascalCase(rawName);
|
|
2418
2439
|
const camelName = toCamelCase(rawName);
|
|
2419
2440
|
const kebabName = toKebabCase(rawName);
|
|
2420
|
-
const targetDir = options.targetDir ||
|
|
2441
|
+
const targetDir = options.targetDir || path26.join(resolveSharedDir(projectRoot), kebabName);
|
|
2421
2442
|
const fileDefs = [];
|
|
2422
2443
|
const facadeContent = `import { MakeInjectable, type DepsType } from "@solid-stack/di";
|
|
2423
2444
|
import { I${pascalName}Engine } from "./ports/I${pascalName}Engine.js";
|
|
@@ -2429,7 +2450,7 @@ export class ${pascalName} {
|
|
|
2429
2450
|
}
|
|
2430
2451
|
`;
|
|
2431
2452
|
fileDefs.push({
|
|
2432
|
-
absolutePath:
|
|
2453
|
+
absolutePath: path26.join(targetDir, `${pascalName}.ts`),
|
|
2433
2454
|
content: facadeContent
|
|
2434
2455
|
});
|
|
2435
2456
|
const portContent = `export abstract class I${pascalName}Engine {
|
|
@@ -2437,7 +2458,7 @@ export class ${pascalName} {
|
|
|
2437
2458
|
}
|
|
2438
2459
|
`;
|
|
2439
2460
|
fileDefs.push({
|
|
2440
|
-
absolutePath:
|
|
2461
|
+
absolutePath: path26.join(targetDir, "ports", `I${pascalName}Engine.ts`),
|
|
2441
2462
|
content: portContent
|
|
2442
2463
|
});
|
|
2443
2464
|
const concreteContent = `import { MakeInjectable } from "@solid-stack/di";
|
|
@@ -2449,7 +2470,7 @@ export class Default${pascalName}Engine implements I${pascalName}Engine {
|
|
|
2449
2470
|
}
|
|
2450
2471
|
`;
|
|
2451
2472
|
fileDefs.push({
|
|
2452
|
-
absolutePath:
|
|
2473
|
+
absolutePath: path26.join(targetDir, "infrastructure", `Default${pascalName}Engine.ts`),
|
|
2453
2474
|
content: concreteContent
|
|
2454
2475
|
});
|
|
2455
2476
|
if (options.includeStub !== false) {
|
|
@@ -2462,7 +2483,7 @@ export class Stub${pascalName}Engine implements I${pascalName}Engine {
|
|
|
2462
2483
|
}
|
|
2463
2484
|
`;
|
|
2464
2485
|
fileDefs.push({
|
|
2465
|
-
absolutePath:
|
|
2486
|
+
absolutePath: path26.join(targetDir, "infrastructure", `Stub${pascalName}Engine.ts`),
|
|
2466
2487
|
content: stubContent
|
|
2467
2488
|
});
|
|
2468
2489
|
}
|
|
@@ -2477,7 +2498,7 @@ export const diProvider = (c: Container): void => {
|
|
|
2477
2498
|
export default diProvider;
|
|
2478
2499
|
`;
|
|
2479
2500
|
fileDefs.push({
|
|
2480
|
-
absolutePath:
|
|
2501
|
+
absolutePath: path26.join(targetDir, "diProvider.ts"),
|
|
2481
2502
|
content: providerContent
|
|
2482
2503
|
});
|
|
2483
2504
|
if (options.isRegistry) {
|
|
@@ -2494,7 +2515,7 @@ export default diProvider;
|
|
|
2494
2515
|
files: []
|
|
2495
2516
|
};
|
|
2496
2517
|
fileDefs.push({
|
|
2497
|
-
absolutePath:
|
|
2518
|
+
absolutePath: path26.join(targetDir, "registry.json"),
|
|
2498
2519
|
content: JSON.stringify(registryManifest, null, 2) + "\n"
|
|
2499
2520
|
});
|
|
2500
2521
|
}
|
|
@@ -2531,7 +2552,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
|
|
|
2531
2552
|
}
|
|
2532
2553
|
const normalizedName = toKebabCase(name);
|
|
2533
2554
|
const baseSharedDir = resolveSharedDir(projectRoot, flags);
|
|
2534
|
-
const defaultDir =
|
|
2555
|
+
const defaultDir = path26.relative(projectRoot, path26.join(baseSharedDir, normalizedName));
|
|
2535
2556
|
let targetDirRel = defaultDir;
|
|
2536
2557
|
if (!flags.yes && !flags.target && !flags.dest) {
|
|
2537
2558
|
targetDirRel = handleCancel(
|
|
@@ -2542,7 +2563,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
|
|
|
2542
2563
|
})
|
|
2543
2564
|
).trim();
|
|
2544
2565
|
}
|
|
2545
|
-
const targetDir = flags.dest ?
|
|
2566
|
+
const targetDir = flags.dest ? path26.resolve(projectRoot, flags.dest) : flags.target ? path26.resolve(projectRoot, flags.target) : path26.resolve(projectRoot, targetDirRel);
|
|
2546
2567
|
let description = flags.description || "";
|
|
2547
2568
|
let includeStub = true;
|
|
2548
2569
|
if (!flags.yes) {
|
|
@@ -2576,7 +2597,7 @@ async function runSharedCommand(sharedNameArg, flags = {}) {
|
|
|
2576
2597
|
printGeneratedFiles(files, Boolean(flags.dryRun));
|
|
2577
2598
|
p19.outro(
|
|
2578
2599
|
pc14.green(
|
|
2579
|
-
`\u2713 Shared module '${normalizedName}' initialized in ${
|
|
2600
|
+
`\u2713 Shared module '${normalizedName}' initialized in ${path26.relative(projectRoot, targetDir)} (uncommitted, unregistered)`
|
|
2580
2601
|
)
|
|
2581
2602
|
);
|
|
2582
2603
|
}
|
|
@@ -3003,7 +3024,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
|
|
|
3003
3024
|
const infraFile = generateInfrastructure(options);
|
|
3004
3025
|
files.push(infraFile);
|
|
3005
3026
|
if (registerInProvider && scope === "feature" && feature && implementsInterface) {
|
|
3006
|
-
const featureDir =
|
|
3027
|
+
const featureDir = path26.join(resolveFeaturesDir(projectRoot), feature);
|
|
3007
3028
|
const providerFile = updateOrGenerateDiProvider(
|
|
3008
3029
|
featureDir,
|
|
3009
3030
|
feature,
|
|
@@ -3165,7 +3186,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
|
|
|
3165
3186
|
files.push(stubFile);
|
|
3166
3187
|
}
|
|
3167
3188
|
if (registerInProvider && generateStub) {
|
|
3168
|
-
const featureDir =
|
|
3189
|
+
const featureDir = path26.join(resolveFeaturesDir(projectRoot), feature);
|
|
3169
3190
|
const providerFile = updateOrGenerateDiProvider(
|
|
3170
3191
|
featureDir,
|
|
3171
3192
|
feature,
|
|
@@ -3353,21 +3374,21 @@ function generateInjectable(options) {
|
|
|
3353
3374
|
const className = toPascalCase(options.name);
|
|
3354
3375
|
let targetDir = "";
|
|
3355
3376
|
if (options.customPath) {
|
|
3356
|
-
targetDir =
|
|
3377
|
+
targetDir = path26.isAbsolute(options.customPath) ? options.customPath : path26.join(projectRoot, options.customPath);
|
|
3357
3378
|
} else if (options.location === "feature-service" && options.feature) {
|
|
3358
|
-
targetDir =
|
|
3379
|
+
targetDir = path26.join(resolveFeaturesDir(projectRoot), options.feature, "services");
|
|
3359
3380
|
} else if (options.location === "feature-transformer" && options.feature) {
|
|
3360
|
-
targetDir =
|
|
3381
|
+
targetDir = path26.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
|
|
3361
3382
|
} else if (options.location === "module") {
|
|
3362
|
-
targetDir =
|
|
3383
|
+
targetDir = path26.join(projectRoot, "modules", className);
|
|
3363
3384
|
} else {
|
|
3364
|
-
targetDir = options.feature ?
|
|
3385
|
+
targetDir = options.feature ? path26.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path26.join(projectRoot, "shared", className.toLowerCase());
|
|
3365
3386
|
}
|
|
3366
|
-
const filePath =
|
|
3387
|
+
const filePath = path26.join(targetDir, `${className}.ts`);
|
|
3367
3388
|
let ifaceName;
|
|
3368
3389
|
if (options.generateInterface) {
|
|
3369
3390
|
ifaceName = `I${className}`;
|
|
3370
|
-
const ifacePath =
|
|
3391
|
+
const ifacePath = path26.join(targetDir, `${ifaceName}.ts`);
|
|
3371
3392
|
const ifaceContent = renderTemplate(injectableInterfaceTemplate, { ifaceName });
|
|
3372
3393
|
files.push(
|
|
3373
3394
|
writeFileSafely(ifacePath, ifaceContent, {
|
|
@@ -3496,7 +3517,7 @@ async function runEnvInit(flags = {}) {
|
|
|
3496
3517
|
const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
|
|
3497
3518
|
const s = p19.spinner();
|
|
3498
3519
|
s.start("Scanning for .example environment files...");
|
|
3499
|
-
const files =
|
|
3520
|
+
const files = fs17.readdirSync(projectRoot);
|
|
3500
3521
|
const exampleFiles = files.filter((file) => file.startsWith(".env") && file.endsWith(".example")).sort();
|
|
3501
3522
|
if (exampleFiles.length === 0) {
|
|
3502
3523
|
s.stop("No .example files found.");
|
|
@@ -3506,11 +3527,11 @@ async function runEnvInit(flags = {}) {
|
|
|
3506
3527
|
s.message(`Found ${exampleFiles.length} template(s). Generating...`);
|
|
3507
3528
|
const generatedFiles = [];
|
|
3508
3529
|
for (const exampleFile of exampleFiles) {
|
|
3509
|
-
const sourcePath =
|
|
3530
|
+
const sourcePath = path26.join(projectRoot, exampleFile);
|
|
3510
3531
|
const targetFile = exampleFile.replace(/\.example$/, "");
|
|
3511
|
-
const targetPath =
|
|
3532
|
+
const targetPath = path26.join(projectRoot, targetFile);
|
|
3512
3533
|
let overwrite = flags.overwrite;
|
|
3513
|
-
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY &&
|
|
3534
|
+
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17.existsSync(targetPath)) {
|
|
3514
3535
|
overwrite = await p19.confirm({
|
|
3515
3536
|
message: `${targetFile} already exists. Overwrite?`,
|
|
3516
3537
|
initialValue: false
|
|
@@ -3520,7 +3541,7 @@ async function runEnvInit(flags = {}) {
|
|
|
3520
3541
|
process.exit(0);
|
|
3521
3542
|
}
|
|
3522
3543
|
}
|
|
3523
|
-
const content =
|
|
3544
|
+
const content = fs17.readFileSync(sourcePath, "utf-8");
|
|
3524
3545
|
const genFile = writeFileSafely(targetPath, content, {
|
|
3525
3546
|
projectRoot,
|
|
3526
3547
|
dryRun: Boolean(flags.dryRun),
|
|
@@ -3539,7 +3560,7 @@ var EnvEditor = class {
|
|
|
3539
3560
|
filePath;
|
|
3540
3561
|
constructor(filePath) {
|
|
3541
3562
|
this.filePath = filePath;
|
|
3542
|
-
this.lines =
|
|
3563
|
+
this.lines = fs17.existsSync(filePath) ? fs17.readFileSync(filePath, "utf-8").split(/\r?\n/) : [];
|
|
3543
3564
|
}
|
|
3544
3565
|
getLines() {
|
|
3545
3566
|
return [...this.lines];
|
|
@@ -3603,18 +3624,18 @@ var EnvEditor = class {
|
|
|
3603
3624
|
});
|
|
3604
3625
|
}
|
|
3605
3626
|
save() {
|
|
3606
|
-
const dir =
|
|
3607
|
-
if (!
|
|
3608
|
-
|
|
3627
|
+
const dir = path26.dirname(this.filePath);
|
|
3628
|
+
if (!fs17.existsSync(dir)) {
|
|
3629
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
3609
3630
|
}
|
|
3610
|
-
|
|
3631
|
+
fs17.writeFileSync(this.filePath, this.lines.join("\n"), "utf-8");
|
|
3611
3632
|
}
|
|
3612
3633
|
};
|
|
3613
3634
|
function discoverEnvironments(projectRoot) {
|
|
3614
|
-
if (!
|
|
3635
|
+
if (!fs17.existsSync(projectRoot)) {
|
|
3615
3636
|
return ["local", "dev", "prod"];
|
|
3616
3637
|
}
|
|
3617
|
-
const files =
|
|
3638
|
+
const files = fs17.readdirSync(projectRoot);
|
|
3618
3639
|
const envs = /* @__PURE__ */ new Set();
|
|
3619
3640
|
for (const file of files) {
|
|
3620
3641
|
if (file.startsWith(".env")) {
|
|
@@ -3639,7 +3660,7 @@ async function runEnvInitExamples(flags = {}) {
|
|
|
3639
3660
|
const projectRoot = flags.cwd || flags.targetDir || findProjectRoot();
|
|
3640
3661
|
const s = p19.spinner();
|
|
3641
3662
|
s.start("Scanning for local environment files...");
|
|
3642
|
-
const files =
|
|
3663
|
+
const files = fs17.readdirSync(projectRoot, { withFileTypes: true });
|
|
3643
3664
|
const envFiles = files.filter((dirent) => dirent.isFile() && dirent.name.startsWith(".env") && !dirent.name.endsWith(".example")).map((dirent) => dirent.name).sort();
|
|
3644
3665
|
if (envFiles.length === 0) {
|
|
3645
3666
|
s.stop("No local .env files found.");
|
|
@@ -3649,11 +3670,11 @@ async function runEnvInitExamples(flags = {}) {
|
|
|
3649
3670
|
s.message(`Found ${envFiles.length} local .env file(s). Generating templates...`);
|
|
3650
3671
|
const generatedFiles = [];
|
|
3651
3672
|
for (const envFile of envFiles) {
|
|
3652
|
-
const sourcePath =
|
|
3673
|
+
const sourcePath = path26.join(projectRoot, envFile);
|
|
3653
3674
|
const targetFile = `${envFile}.example`;
|
|
3654
|
-
const targetPath =
|
|
3675
|
+
const targetPath = path26.join(projectRoot, targetFile);
|
|
3655
3676
|
let overwrite = flags.overwrite;
|
|
3656
|
-
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY &&
|
|
3677
|
+
if (overwrite === void 0 && !flags.dryRun && !flags.yes && !process.env.VITEST && process.stdin.isTTY && fs17.existsSync(targetPath)) {
|
|
3657
3678
|
overwrite = await p19.confirm({
|
|
3658
3679
|
message: `${targetFile} already exists. Overwrite with redacted values?`,
|
|
3659
3680
|
initialValue: true
|
|
@@ -3687,12 +3708,12 @@ function isInteractive(flags) {
|
|
|
3687
3708
|
function getAllExistingKeys(projectRoot, envs) {
|
|
3688
3709
|
const keys = /* @__PURE__ */ new Set();
|
|
3689
3710
|
for (const env of envs) {
|
|
3690
|
-
const localPath =
|
|
3691
|
-
const examplePath =
|
|
3692
|
-
if (
|
|
3711
|
+
const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
|
|
3712
|
+
const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
|
|
3713
|
+
if (fs17.existsSync(localPath)) {
|
|
3693
3714
|
new EnvEditor(localPath).getKeys().forEach((k) => keys.add(k));
|
|
3694
3715
|
}
|
|
3695
|
-
if (
|
|
3716
|
+
if (fs17.existsSync(examplePath)) {
|
|
3696
3717
|
new EnvEditor(examplePath).getKeys().forEach((k) => keys.add(k));
|
|
3697
3718
|
}
|
|
3698
3719
|
}
|
|
@@ -3764,8 +3785,8 @@ async function runEnvAdd(key, value, flags = {}) {
|
|
|
3764
3785
|
})
|
|
3765
3786
|
);
|
|
3766
3787
|
}
|
|
3767
|
-
const localPath =
|
|
3768
|
-
const examplePath =
|
|
3788
|
+
const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
|
|
3789
|
+
const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
|
|
3769
3790
|
if (flags.dryRun) {
|
|
3770
3791
|
p19.log.info(
|
|
3771
3792
|
pc14.cyan(`[DRY RUN] Would set ${targetKey}=${envVal} in ${resolveEnvFilename(env, false)}`)
|
|
@@ -3812,8 +3833,8 @@ async function runEnvUpdate(key, value, flags = {}) {
|
|
|
3812
3833
|
);
|
|
3813
3834
|
}
|
|
3814
3835
|
const envsWithKey = allEnvs.filter((env) => {
|
|
3815
|
-
const localPath =
|
|
3816
|
-
return
|
|
3836
|
+
const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
|
|
3837
|
+
return fs17.existsSync(localPath) && new EnvEditor(localPath).has(targetKey);
|
|
3817
3838
|
});
|
|
3818
3839
|
let targetEnvs = [];
|
|
3819
3840
|
if (flags.env) {
|
|
@@ -3839,7 +3860,7 @@ async function runEnvUpdate(key, value, flags = {}) {
|
|
|
3839
3860
|
return { key: targetKey, environments: [] };
|
|
3840
3861
|
}
|
|
3841
3862
|
for (const env of targetEnvs) {
|
|
3842
|
-
const localPath =
|
|
3863
|
+
const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
|
|
3843
3864
|
const localEditor = new EnvEditor(localPath);
|
|
3844
3865
|
const currentVal = localEditor.getValue(targetKey);
|
|
3845
3866
|
let newVal = value;
|
|
@@ -3869,7 +3890,7 @@ async function runEnvUpdate(key, value, flags = {}) {
|
|
|
3869
3890
|
} else {
|
|
3870
3891
|
localEditor.set(targetKey, newVal);
|
|
3871
3892
|
localEditor.save();
|
|
3872
|
-
const examplePath =
|
|
3893
|
+
const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
|
|
3873
3894
|
const exampleEditor = new EnvEditor(examplePath);
|
|
3874
3895
|
if (!exampleEditor.has(targetKey)) {
|
|
3875
3896
|
exampleEditor.set(targetKey, "");
|
|
@@ -3905,9 +3926,9 @@ async function runEnvDelete(key, flags = {}) {
|
|
|
3905
3926
|
);
|
|
3906
3927
|
}
|
|
3907
3928
|
const envsWithKey = allEnvs.filter((env) => {
|
|
3908
|
-
const localPath =
|
|
3909
|
-
const examplePath =
|
|
3910
|
-
return
|
|
3929
|
+
const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
|
|
3930
|
+
const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
|
|
3931
|
+
return fs17.existsSync(localPath) && new EnvEditor(localPath).has(targetKey) || fs17.existsSync(examplePath) && new EnvEditor(examplePath).has(targetKey);
|
|
3911
3932
|
});
|
|
3912
3933
|
let targetEnvs = [];
|
|
3913
3934
|
if (flags.env) {
|
|
@@ -3945,19 +3966,19 @@ async function runEnvDelete(key, flags = {}) {
|
|
|
3945
3966
|
}
|
|
3946
3967
|
}
|
|
3947
3968
|
for (const env of targetEnvs) {
|
|
3948
|
-
const localPath =
|
|
3949
|
-
const examplePath =
|
|
3969
|
+
const localPath = path26.join(projectRoot, resolveEnvFilename(env, false));
|
|
3970
|
+
const examplePath = path26.join(projectRoot, resolveEnvFilename(env, true));
|
|
3950
3971
|
if (flags.dryRun) {
|
|
3951
3972
|
p19.log.info(
|
|
3952
3973
|
pc14.cyan(`[DRY RUN] Would delete ${targetKey} from ${resolveEnvFilename(env, false)} and ${resolveEnvFilename(env, true)}`)
|
|
3953
3974
|
);
|
|
3954
3975
|
} else {
|
|
3955
|
-
if (
|
|
3976
|
+
if (fs17.existsSync(localPath)) {
|
|
3956
3977
|
const localEditor = new EnvEditor(localPath);
|
|
3957
3978
|
localEditor.delete(targetKey);
|
|
3958
3979
|
localEditor.save();
|
|
3959
3980
|
}
|
|
3960
|
-
if (
|
|
3981
|
+
if (fs17.existsSync(examplePath)) {
|
|
3961
3982
|
const exampleEditor = new EnvEditor(examplePath);
|
|
3962
3983
|
exampleEditor.delete(targetKey);
|
|
3963
3984
|
exampleEditor.save();
|
|
@@ -3982,10 +4003,10 @@ async function runEnvAudit(flags = {}) {
|
|
|
3982
4003
|
for (const env of envs) {
|
|
3983
4004
|
const localFile = resolveEnvFilename(env, false);
|
|
3984
4005
|
const exampleFile = resolveEnvFilename(env, true);
|
|
3985
|
-
const localPath =
|
|
3986
|
-
const examplePath =
|
|
3987
|
-
const localExists =
|
|
3988
|
-
const exampleExists =
|
|
4006
|
+
const localPath = path26.join(projectRoot, localFile);
|
|
4007
|
+
const examplePath = path26.join(projectRoot, exampleFile);
|
|
4008
|
+
const localExists = fs17.existsSync(localPath);
|
|
4009
|
+
const exampleExists = fs17.existsSync(examplePath);
|
|
3989
4010
|
const localEditor = new EnvEditor(localPath);
|
|
3990
4011
|
const exampleEditor = new EnvEditor(examplePath);
|
|
3991
4012
|
const localKeys = localExists ? localEditor.getKeys() : [];
|
|
@@ -4324,17 +4345,17 @@ function getModuleBaseDir(projectRoot, modType) {
|
|
|
4324
4345
|
return modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
4325
4346
|
}
|
|
4326
4347
|
const folder = modType === "shared" ? "shared" : "features";
|
|
4327
|
-
return
|
|
4348
|
+
return path26.join(projectRoot, "src", folder);
|
|
4328
4349
|
}
|
|
4329
4350
|
function getExistingModuleDir(projectRoot, modType, modName) {
|
|
4330
4351
|
const folder = modType === "shared" ? "shared" : "features";
|
|
4331
4352
|
const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
4332
|
-
const inConfigured =
|
|
4333
|
-
if (
|
|
4334
|
-
const inSrc =
|
|
4335
|
-
if (
|
|
4336
|
-
const inRoot =
|
|
4337
|
-
if (
|
|
4353
|
+
const inConfigured = path26.join(configuredDir, modName);
|
|
4354
|
+
if (fs17.existsSync(inConfigured)) return inConfigured;
|
|
4355
|
+
const inSrc = path26.join(projectRoot, "src", folder, modName);
|
|
4356
|
+
if (fs17.existsSync(inSrc)) return inSrc;
|
|
4357
|
+
const inRoot = path26.join(projectRoot, folder, modName);
|
|
4358
|
+
if (fs17.existsSync(inRoot)) return inRoot;
|
|
4338
4359
|
return null;
|
|
4339
4360
|
}
|
|
4340
4361
|
function checkModuleExists(projectRoot, modType, modName) {
|
|
@@ -4345,14 +4366,14 @@ function getAvailableLocalModules(projectRoot, modType) {
|
|
|
4345
4366
|
const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
4346
4367
|
const dirs = [
|
|
4347
4368
|
configuredDir,
|
|
4348
|
-
|
|
4349
|
-
|
|
4369
|
+
path26.join(projectRoot, "src", folder),
|
|
4370
|
+
path26.join(projectRoot, folder)
|
|
4350
4371
|
];
|
|
4351
4372
|
const set = /* @__PURE__ */ new Set();
|
|
4352
4373
|
for (const dir of dirs) {
|
|
4353
|
-
if (
|
|
4374
|
+
if (fs17.existsSync(dir)) {
|
|
4354
4375
|
try {
|
|
4355
|
-
const entries =
|
|
4376
|
+
const entries = fs17.readdirSync(dir, { withFileTypes: true });
|
|
4356
4377
|
for (const e of entries) {
|
|
4357
4378
|
if (e.isDirectory() && !e.name.startsWith(".")) {
|
|
4358
4379
|
set.add(e.name);
|
|
@@ -4554,7 +4575,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4554
4575
|
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${programmaticAlias}/`);
|
|
4555
4576
|
globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${programmaticAlias}`);
|
|
4556
4577
|
const baseDir = getModuleBaseDir(projectRoot, modType);
|
|
4557
|
-
const displayDest =
|
|
4578
|
+
const displayDest = path26.relative(projectRoot, path26.join(baseDir, programmaticAlias));
|
|
4558
4579
|
p19.log.step(`Importing '${registryName}' into '${displayDest}'...`);
|
|
4559
4580
|
resolutions.set(key, {
|
|
4560
4581
|
type: modType,
|
|
@@ -4742,7 +4763,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4742
4763
|
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${newName}/`);
|
|
4743
4764
|
globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${newName}`);
|
|
4744
4765
|
const baseDir = getModuleBaseDir(projectRoot, modType);
|
|
4745
|
-
const displayDest =
|
|
4766
|
+
const displayDest = path26.relative(projectRoot, path26.join(baseDir, newName));
|
|
4746
4767
|
p19.log.step(`Importing '${registryName}' into '${displayDest}'...`);
|
|
4747
4768
|
resolutions.set(key, {
|
|
4748
4769
|
type: modType,
|
|
@@ -4794,7 +4815,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4794
4815
|
continue;
|
|
4795
4816
|
}
|
|
4796
4817
|
const folder = res.type === "shared" ? "shared" : "features";
|
|
4797
|
-
const targetDir =
|
|
4818
|
+
const targetDir = path26.join(getModuleBaseDir(projectRoot, res.type), res.targetName);
|
|
4798
4819
|
const isOverwrite = Boolean(flags.overwrite || res.action === "overwrite");
|
|
4799
4820
|
if (key !== rootKey) {
|
|
4800
4821
|
p19.log.step(
|
|
@@ -4804,30 +4825,30 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4804
4825
|
if (res.action === "overwrite" && !flags.dryRun) {
|
|
4805
4826
|
const existingDir = getExistingModuleDir(projectRoot, res.type, res.targetName);
|
|
4806
4827
|
if (existingDir && existingDir !== targetDir) {
|
|
4807
|
-
|
|
4828
|
+
fs17.rmSync(existingDir, { recursive: true, force: true });
|
|
4808
4829
|
}
|
|
4809
|
-
if (
|
|
4810
|
-
|
|
4830
|
+
if (fs17.existsSync(targetDir)) {
|
|
4831
|
+
fs17.rmSync(targetDir, { recursive: true, force: true });
|
|
4811
4832
|
}
|
|
4812
4833
|
}
|
|
4813
4834
|
for (const file of res.manifest.files || []) {
|
|
4814
4835
|
if (file === "registry.json") continue;
|
|
4815
4836
|
if (!includeTests && isTestFile(file)) continue;
|
|
4816
4837
|
const remoteFilePath = `${folder}/${res.registryName}/${file}`;
|
|
4817
|
-
const localFilePath =
|
|
4818
|
-
if (
|
|
4838
|
+
const localFilePath = path26.join(targetDir, file);
|
|
4839
|
+
if (fs17.existsSync(localFilePath) && !isOverwrite) {
|
|
4819
4840
|
p19.log.warn(
|
|
4820
|
-
` \u21B3 Skipping existing file: ${pc14.dim(
|
|
4841
|
+
` \u21B3 Skipping existing file: ${pc14.dim(path26.relative(projectRoot, localFilePath))} (use --overwrite to replace)`
|
|
4821
4842
|
);
|
|
4822
4843
|
continue;
|
|
4823
4844
|
}
|
|
4824
4845
|
let content = await fetchRegistryFile(registryBase, remoteFilePath);
|
|
4825
4846
|
content = rewriteImports(content, globalAliasMap);
|
|
4826
4847
|
if (!flags.dryRun) {
|
|
4827
|
-
|
|
4828
|
-
|
|
4848
|
+
fs17.mkdirSync(path26.dirname(localFilePath), { recursive: true });
|
|
4849
|
+
fs17.writeFileSync(localFilePath, content, "utf-8");
|
|
4829
4850
|
}
|
|
4830
|
-
const displayPath =
|
|
4851
|
+
const displayPath = path26.relative(projectRoot, localFilePath);
|
|
4831
4852
|
totalWrittenFiles.push(displayPath);
|
|
4832
4853
|
p19.log.message(` ${pc14.green("+")} ${displayPath}`);
|
|
4833
4854
|
}
|
|
@@ -4853,7 +4874,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
4853
4874
|
} else {
|
|
4854
4875
|
const rootRes = resolutions.get(rootKey);
|
|
4855
4876
|
const baseDir = getModuleBaseDir(projectRoot, type);
|
|
4856
|
-
const displayTarget =
|
|
4877
|
+
const displayTarget = path26.relative(projectRoot, path26.join(baseDir, rootRes.targetName));
|
|
4857
4878
|
p19.log.success(
|
|
4858
4879
|
pc14.green(
|
|
4859
4880
|
`Successfully imported ${type} '${name}' (${totalWrittenFiles.length} file${totalWrittenFiles.length === 1 ? "" : "s"} placed in ${displayTarget})`
|
|
@@ -4872,19 +4893,19 @@ var DependencyRuleError = class extends Error {
|
|
|
4872
4893
|
}
|
|
4873
4894
|
};
|
|
4874
4895
|
function isTestFile2(filePath, projectRoot) {
|
|
4875
|
-
const norm = (projectRoot ?
|
|
4876
|
-
const base =
|
|
4896
|
+
const norm = (projectRoot ? path26.relative(projectRoot, filePath) : filePath).replace(/\\/g, "/");
|
|
4897
|
+
const base = path26.basename(norm);
|
|
4877
4898
|
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);
|
|
4878
4899
|
}
|
|
4879
4900
|
function scanDirFiles(dir, projectRoot) {
|
|
4880
|
-
if (!
|
|
4881
|
-
const entries =
|
|
4901
|
+
if (!fs17.existsSync(dir)) return [];
|
|
4902
|
+
const entries = fs17.readdirSync(dir, { withFileTypes: true });
|
|
4882
4903
|
const files = [];
|
|
4883
4904
|
for (const entry of entries) {
|
|
4884
4905
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "__tests__" || entry.name.startsWith(".")) {
|
|
4885
4906
|
continue;
|
|
4886
4907
|
}
|
|
4887
|
-
const fullPath =
|
|
4908
|
+
const fullPath = path26.join(dir, entry.name);
|
|
4888
4909
|
if (entry.isDirectory()) {
|
|
4889
4910
|
files.push(...scanDirFiles(fullPath, projectRoot));
|
|
4890
4911
|
} else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) && !isTestFile2(fullPath, projectRoot)) {
|
|
@@ -4893,42 +4914,43 @@ function scanDirFiles(dir, projectRoot) {
|
|
|
4893
4914
|
}
|
|
4894
4915
|
return files;
|
|
4895
4916
|
}
|
|
4896
|
-
function
|
|
4897
|
-
const
|
|
4898
|
-
const
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
if (
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4917
|
+
function resolveLintEnvironment(projectRoot) {
|
|
4918
|
+
const config = loadMasonConfig(projectRoot);
|
|
4919
|
+
const resolveDir = (configured, defaultSrc, defaultRoot) => {
|
|
4920
|
+
if (configured !== void 0) {
|
|
4921
|
+
return path26.resolve(projectRoot, configured);
|
|
4922
|
+
}
|
|
4923
|
+
const srcPath = path26.join(projectRoot, defaultSrc);
|
|
4924
|
+
if (fs17.existsSync(srcPath)) return srcPath;
|
|
4925
|
+
const rootPath = path26.join(projectRoot, defaultRoot);
|
|
4926
|
+
if (fs17.existsSync(rootPath)) return rootPath;
|
|
4927
|
+
return srcPath;
|
|
4928
|
+
};
|
|
4929
|
+
const featuresBase = resolveDir(config?.paths?.features, "src/features", "features");
|
|
4930
|
+
const sharedBase = resolveDir(config?.paths?.shared, "src/shared", "shared");
|
|
4931
|
+
const errorsBase = resolveDir(config?.paths?.errors, "src/errors", "errors");
|
|
4932
|
+
const defaultBaseErrorRelative = config?.paths?.errors ? path26.join(config.paths.errors, "AppError.ts") : fs17.existsSync(path26.join(projectRoot, "src/errors")) ? "src/errors/AppError.ts" : fs17.existsSync(path26.join(projectRoot, "errors")) ? "errors/AppError.ts" : "src/errors/AppError.ts";
|
|
4933
|
+
const baseErrorAbs = path26.resolve(
|
|
4934
|
+
projectRoot,
|
|
4935
|
+
config?.paths?.baseError || defaultBaseErrorRelative
|
|
4936
|
+
);
|
|
4937
|
+
return { featuresBase, sharedBase, errorsBase, baseErrorAbs };
|
|
4938
|
+
}
|
|
4939
|
+
function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
|
|
4940
|
+
if (!sharedBaseAbs || !errorsBaseAbs) {
|
|
4941
|
+
const env = resolveLintEnvironment(featuresBaseAbs);
|
|
4942
|
+
featuresBaseAbs = env.featuresBase;
|
|
4943
|
+
sharedBaseAbs = env.sharedBase;
|
|
4944
|
+
errorsBaseAbs = env.errorsBase;
|
|
4945
|
+
}
|
|
4946
|
+
const normFullPath = path26.resolve(fullPathAbs);
|
|
4947
|
+
const normErrorsBase = path26.resolve(errorsBaseAbs);
|
|
4948
|
+
const normSharedBase = path26.resolve(sharedBaseAbs);
|
|
4949
|
+
const normFeaturesBase = path26.resolve(featuresBaseAbs);
|
|
4950
|
+
const isUnder = (base, target) => {
|
|
4951
|
+
return target === base || target.startsWith(base + path26.sep);
|
|
4952
|
+
};
|
|
4953
|
+
if (isUnder(normErrorsBase, normFullPath)) {
|
|
4932
4954
|
return {
|
|
4933
4955
|
moduleType: "error",
|
|
4934
4956
|
moduleName: "global-errors",
|
|
@@ -4936,46 +4958,154 @@ function classifyFile(fullPath, projectRoot) {
|
|
|
4936
4958
|
layer: "domain"
|
|
4937
4959
|
};
|
|
4938
4960
|
}
|
|
4961
|
+
if (isUnder(normSharedBase, normFullPath)) {
|
|
4962
|
+
const rel = path26.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
|
|
4963
|
+
const parts = rel.split("/").filter(Boolean);
|
|
4964
|
+
if (parts.length >= 1) {
|
|
4965
|
+
const moduleName = parts[0];
|
|
4966
|
+
const subfolder = parts[1];
|
|
4967
|
+
let layer = "root";
|
|
4968
|
+
if (subfolder === "domain" || subfolder === "errors") {
|
|
4969
|
+
layer = "domain";
|
|
4970
|
+
} else if (subfolder === "ports") {
|
|
4971
|
+
layer = "ports";
|
|
4972
|
+
} else if (subfolder === "infrastructure") {
|
|
4973
|
+
layer = "infrastructure";
|
|
4974
|
+
}
|
|
4975
|
+
return { moduleType: "shared", moduleName, feature: moduleName, layer };
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
if (isUnder(normFeaturesBase, normFullPath)) {
|
|
4979
|
+
const rel = path26.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
|
|
4980
|
+
const parts = rel.split("/").filter(Boolean);
|
|
4981
|
+
if (parts.length >= 2) {
|
|
4982
|
+
const moduleName = parts[0];
|
|
4983
|
+
const subfolder = parts[1];
|
|
4984
|
+
let layer;
|
|
4985
|
+
if (subfolder === "domain" || subfolder === "errors") {
|
|
4986
|
+
layer = "domain";
|
|
4987
|
+
} else if (subfolder === "useCases" || subfolder === "usecases") {
|
|
4988
|
+
layer = "useCases";
|
|
4989
|
+
} else if (subfolder === "services") {
|
|
4990
|
+
layer = "services";
|
|
4991
|
+
} else if (subfolder === "infrastructure") {
|
|
4992
|
+
layer = "infrastructure";
|
|
4993
|
+
} else if (subfolder.startsWith("px") || subfolder === "presentation" || subfolder === "handlers" || subfolder === "transformers") {
|
|
4994
|
+
layer = "presentation";
|
|
4995
|
+
}
|
|
4996
|
+
return { moduleType: "feature", moduleName, feature: moduleName, layer };
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4939
4999
|
return {};
|
|
4940
5000
|
}
|
|
4941
|
-
function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
5001
|
+
function classifyTarget(specifier, sourceFileAbs, projectRoot, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
|
|
4942
5002
|
if (specifier === "@solid-stack/di" || specifier.startsWith("@solid-stack/di/")) {
|
|
4943
5003
|
return { isExternal: true, isDiFramework: true };
|
|
4944
5004
|
}
|
|
4945
|
-
if (specifier.startsWith("node:") || [
|
|
5005
|
+
if (specifier.startsWith("node:") || [
|
|
5006
|
+
"crypto",
|
|
5007
|
+
"fs",
|
|
5008
|
+
"path",
|
|
5009
|
+
"http",
|
|
5010
|
+
"https",
|
|
5011
|
+
"url",
|
|
5012
|
+
"os",
|
|
5013
|
+
"child_process",
|
|
5014
|
+
"stream",
|
|
5015
|
+
"express",
|
|
5016
|
+
"cors",
|
|
5017
|
+
"dotenv"
|
|
5018
|
+
].includes(specifier)) {
|
|
4946
5019
|
return { isExternal: true, isDiFramework: false };
|
|
4947
5020
|
}
|
|
4948
|
-
|
|
5021
|
+
if (!featuresBaseAbs || !sharedBaseAbs || !errorsBaseAbs) {
|
|
5022
|
+
const env = resolveLintEnvironment(projectRoot);
|
|
5023
|
+
featuresBaseAbs = featuresBaseAbs || env.featuresBase;
|
|
5024
|
+
sharedBaseAbs = sharedBaseAbs || env.sharedBase;
|
|
5025
|
+
errorsBaseAbs = errorsBaseAbs || env.errorsBase;
|
|
5026
|
+
}
|
|
5027
|
+
const isGlobalConfig = specifier === "@configs" || specifier.startsWith("@configs/") || specifier === "@/configs" || specifier.startsWith("@/configs/") || specifier === "~/configs" || specifier.startsWith("~/configs/") || specifier === "configs" || specifier.startsWith("configs/");
|
|
5028
|
+
let targetAbs = null;
|
|
4949
5029
|
if (specifier.startsWith(".")) {
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
5030
|
+
targetAbs = path26.resolve(path26.dirname(sourceFileAbs), specifier);
|
|
5031
|
+
} else {
|
|
5032
|
+
const featRel = path26.relative(projectRoot, featuresBaseAbs).replace(/\\/g, "/");
|
|
5033
|
+
const sharedRel = path26.relative(projectRoot, sharedBaseAbs).replace(/\\/g, "/");
|
|
5034
|
+
const errorsRel = path26.relative(projectRoot, errorsBaseAbs).replace(/\\/g, "/");
|
|
5035
|
+
const featPrefixes = ["features"];
|
|
5036
|
+
if (featRel && featRel !== "." && !featRel.startsWith("..")) {
|
|
5037
|
+
featPrefixes.push(featRel);
|
|
5038
|
+
const b = path26.basename(featRel);
|
|
5039
|
+
if (!featPrefixes.includes(b)) featPrefixes.push(b);
|
|
5040
|
+
}
|
|
5041
|
+
const sharedPrefixes = ["shared"];
|
|
5042
|
+
if (sharedRel && sharedRel !== "." && !sharedRel.startsWith("..")) {
|
|
5043
|
+
sharedPrefixes.push(sharedRel);
|
|
5044
|
+
const b = path26.basename(sharedRel);
|
|
5045
|
+
if (!sharedPrefixes.includes(b)) sharedPrefixes.push(b);
|
|
5046
|
+
}
|
|
5047
|
+
const errorsPrefixes = ["errors"];
|
|
5048
|
+
if (errorsRel && errorsRel !== "." && !errorsRel.startsWith("..")) {
|
|
5049
|
+
errorsPrefixes.push(errorsRel);
|
|
5050
|
+
const b = path26.basename(errorsRel);
|
|
5051
|
+
if (!errorsPrefixes.includes(b)) errorsPrefixes.push(b);
|
|
5052
|
+
}
|
|
5053
|
+
for (const prefix of featPrefixes) {
|
|
5054
|
+
const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
|
|
5055
|
+
const m = specifier.match(aliasRegex);
|
|
5056
|
+
if (m && m[2]) {
|
|
5057
|
+
targetAbs = path26.resolve(featuresBaseAbs, m[2]);
|
|
5058
|
+
break;
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5061
|
+
if (!targetAbs) {
|
|
5062
|
+
for (const prefix of sharedPrefixes) {
|
|
5063
|
+
const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}\\/(.*)$`);
|
|
5064
|
+
const m = specifier.match(aliasRegex);
|
|
5065
|
+
if (m && m[2]) {
|
|
5066
|
+
targetAbs = path26.resolve(sharedBaseAbs, m[2]);
|
|
5067
|
+
break;
|
|
5068
|
+
}
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
if (!targetAbs) {
|
|
5072
|
+
for (const prefix of errorsPrefixes) {
|
|
5073
|
+
const aliasRegex = new RegExp(`^([@~]\\/|@)?${prefix}(?:\\/(.*))?$`);
|
|
5074
|
+
const m = specifier.match(aliasRegex);
|
|
5075
|
+
if (m) {
|
|
5076
|
+
targetAbs = path26.resolve(errorsBaseAbs, m[2] || "");
|
|
5077
|
+
break;
|
|
5078
|
+
}
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
if (!targetAbs && (specifier.startsWith("@/") || specifier.startsWith("~/"))) {
|
|
5082
|
+
const sub = specifier.slice(2);
|
|
5083
|
+
const srcCandidate = path26.resolve(projectRoot, "src", sub);
|
|
5084
|
+
const rootCandidate = path26.resolve(projectRoot, sub);
|
|
5085
|
+
if (fs17.existsSync(srcCandidate)) {
|
|
5086
|
+
targetAbs = srcCandidate;
|
|
5087
|
+
} else if (fs17.existsSync(rootCandidate)) {
|
|
5088
|
+
targetAbs = rootCandidate;
|
|
5089
|
+
} else {
|
|
5090
|
+
targetAbs = srcCandidate;
|
|
5091
|
+
}
|
|
5092
|
+
}
|
|
5093
|
+
if (!targetAbs) {
|
|
5094
|
+
const featCandidate = path26.resolve(featuresBaseAbs, specifier);
|
|
5095
|
+
if (fs17.existsSync(featCandidate) || fs17.existsSync(featCandidate + ".ts") || fs17.existsSync(featCandidate + ".js")) {
|
|
5096
|
+
targetAbs = featCandidate;
|
|
5097
|
+
}
|
|
5098
|
+
}
|
|
5099
|
+
}
|
|
5100
|
+
if (!targetAbs) {
|
|
5101
|
+
return { isExternal: true, isDiFramework: false, isGlobalConfig };
|
|
4975
5102
|
}
|
|
4976
|
-
const
|
|
4977
|
-
const
|
|
4978
|
-
|
|
5103
|
+
const normTarget = path26.resolve(targetAbs);
|
|
5104
|
+
const srcConfig = path26.resolve(projectRoot, "src/configs");
|
|
5105
|
+
const rootConfig = path26.resolve(projectRoot, "configs");
|
|
5106
|
+
const isTargetConfig = isGlobalConfig || normTarget === srcConfig || normTarget.startsWith(srcConfig + path26.sep) || normTarget === rootConfig || normTarget.startsWith(rootConfig + path26.sep);
|
|
5107
|
+
const classification = classifyFile(targetAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs);
|
|
5108
|
+
if (classification.moduleType === "error") {
|
|
4979
5109
|
return {
|
|
4980
5110
|
isExternal: false,
|
|
4981
5111
|
isDiFramework: false,
|
|
@@ -4983,33 +5113,19 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
4983
5113
|
isTargetError: true
|
|
4984
5114
|
};
|
|
4985
5115
|
}
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
const
|
|
4989
|
-
const targetSubfolder =
|
|
4990
|
-
const
|
|
4991
|
-
let targetLayer;
|
|
4992
|
-
if (targetSubfolder === "domain" || targetSubfolder === "errors") {
|
|
4993
|
-
targetLayer = "domain";
|
|
4994
|
-
} else if (targetSubfolder === "useCases" || targetSubfolder === "usecases") {
|
|
4995
|
-
targetLayer = "useCases";
|
|
4996
|
-
} else if (targetSubfolder === "services") {
|
|
4997
|
-
targetLayer = "services";
|
|
4998
|
-
} else if (targetSubfolder === "infrastructure") {
|
|
4999
|
-
targetLayer = "infrastructure";
|
|
5000
|
-
} else if (targetSubfolder === "pxExpress" || targetSubfolder === "presentation" || targetSubfolder === "handlers" || targetSubfolder.startsWith("px")) {
|
|
5001
|
-
targetLayer = "presentation";
|
|
5002
|
-
}
|
|
5003
|
-
const basePart = rest ? path2.basename(rest) : targetSubfolder;
|
|
5004
|
-
const targetFileName = basePart.replace(/\.(js|ts|mjs|cjs)$/, "");
|
|
5116
|
+
if (classification.moduleType === "feature") {
|
|
5117
|
+
const rel = path26.relative(featuresBaseAbs, targetAbs).replace(/\\/g, "/");
|
|
5118
|
+
const parts = rel.split("/").filter(Boolean);
|
|
5119
|
+
const targetSubfolder = parts[1];
|
|
5120
|
+
const targetFileName = path26.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
|
|
5005
5121
|
const isTargetPort = /^I[A-Z]/.test(targetFileName);
|
|
5006
5122
|
const isTargetRepo = isTargetPort && targetFileName.includes("Repo");
|
|
5007
|
-
const isTargetError = targetSubfolder === "errors" ||
|
|
5123
|
+
const isTargetError = targetSubfolder === "errors" || rel.includes("/errors/") || targetFileName.endsWith("Error") || targetFileName.endsWith("Errors");
|
|
5008
5124
|
return {
|
|
5009
5125
|
isExternal: false,
|
|
5010
5126
|
isDiFramework: false,
|
|
5011
|
-
targetFeature,
|
|
5012
|
-
targetLayer,
|
|
5127
|
+
targetFeature: classification.moduleName,
|
|
5128
|
+
targetLayer: classification.layer,
|
|
5013
5129
|
targetSubfolder,
|
|
5014
5130
|
targetFileName,
|
|
5015
5131
|
isTargetPort,
|
|
@@ -5017,25 +5133,21 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
5017
5133
|
isTargetError
|
|
5018
5134
|
};
|
|
5019
5135
|
}
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
const
|
|
5023
|
-
const sharedRest = sharedMatch[2] || "";
|
|
5024
|
-
const isSharedRoot = !sharedRest.includes("/");
|
|
5025
|
-
const isSharedPorts = sharedRest.startsWith("ports/") || sharedRest === "ports";
|
|
5026
|
-
const isSharedInfra = sharedRest.startsWith("infrastructure/") || sharedRest === "infrastructure";
|
|
5027
|
-
const isSharedDomain = sharedRest.startsWith("domain/") || sharedRest === "domain";
|
|
5136
|
+
if (classification.moduleType === "shared") {
|
|
5137
|
+
const targetFileName = path26.basename(targetAbs).replace(/\.(js|ts|mjs|cjs)$/, "");
|
|
5138
|
+
const isTargetError = classification.layer === "domain" && (targetFileName.endsWith("Error") || targetFileName.endsWith("Errors") || targetAbs.includes("/errors/"));
|
|
5028
5139
|
return {
|
|
5029
5140
|
isExternal: false,
|
|
5030
5141
|
isDiFramework: false,
|
|
5031
|
-
targetSharedModule,
|
|
5032
|
-
isSharedRoot,
|
|
5033
|
-
isSharedPorts,
|
|
5034
|
-
isSharedInfra,
|
|
5035
|
-
isSharedDomain
|
|
5142
|
+
targetSharedModule: classification.moduleName,
|
|
5143
|
+
isSharedRoot: classification.layer === "root",
|
|
5144
|
+
isSharedPorts: classification.layer === "ports",
|
|
5145
|
+
isSharedInfra: classification.layer === "infrastructure",
|
|
5146
|
+
isSharedDomain: classification.layer === "domain",
|
|
5147
|
+
isTargetError
|
|
5036
5148
|
};
|
|
5037
5149
|
}
|
|
5038
|
-
return { isExternal: true, isDiFramework: false, isGlobalConfig };
|
|
5150
|
+
return { isExternal: true, isDiFramework: false, isGlobalConfig: isTargetConfig };
|
|
5039
5151
|
}
|
|
5040
5152
|
function extractImportStatements(content) {
|
|
5041
5153
|
const statements = [];
|
|
@@ -5157,22 +5269,50 @@ var FeatureDependencyGraph = class {
|
|
|
5157
5269
|
return dfs(start);
|
|
5158
5270
|
}
|
|
5159
5271
|
};
|
|
5160
|
-
function discoverAllFeatures(
|
|
5161
|
-
const
|
|
5162
|
-
if (!
|
|
5163
|
-
const
|
|
5164
|
-
|
|
5272
|
+
function discoverAllFeatures(featuresBaseAbs, excludeDirs = []) {
|
|
5273
|
+
const base = featuresBaseAbs;
|
|
5274
|
+
if (!fs17.existsSync(base)) return [];
|
|
5275
|
+
const excludeSet = new Set(excludeDirs.map((d) => path26.resolve(d)));
|
|
5276
|
+
const entries = fs17.readdirSync(base, { withFileTypes: true });
|
|
5277
|
+
return entries.filter((e) => {
|
|
5278
|
+
if (!e.isDirectory()) return false;
|
|
5279
|
+
if (e.name.startsWith(".")) return false;
|
|
5280
|
+
if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
|
|
5281
|
+
return false;
|
|
5282
|
+
}
|
|
5283
|
+
const resolved = path26.resolve(base, e.name);
|
|
5284
|
+
for (const ex of excludeSet) {
|
|
5285
|
+
if (ex === resolved || ex.startsWith(resolved + path26.sep) || resolved.startsWith(ex + path26.sep)) {
|
|
5286
|
+
return false;
|
|
5287
|
+
}
|
|
5288
|
+
}
|
|
5289
|
+
return true;
|
|
5290
|
+
}).map((e) => ({
|
|
5165
5291
|
name: e.name,
|
|
5166
|
-
dir:
|
|
5292
|
+
dir: path26.join(base, e.name)
|
|
5167
5293
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
5168
5294
|
}
|
|
5169
|
-
function discoverAllShared(
|
|
5170
|
-
const
|
|
5171
|
-
if (!
|
|
5172
|
-
const
|
|
5173
|
-
|
|
5295
|
+
function discoverAllShared(sharedBaseAbs, excludeDirs = []) {
|
|
5296
|
+
const base = sharedBaseAbs;
|
|
5297
|
+
if (!fs17.existsSync(base)) return [];
|
|
5298
|
+
const excludeSet = new Set(excludeDirs.map((d) => path26.resolve(d)));
|
|
5299
|
+
const entries = fs17.readdirSync(base, { withFileTypes: true });
|
|
5300
|
+
return entries.filter((e) => {
|
|
5301
|
+
if (!e.isDirectory()) return false;
|
|
5302
|
+
if (e.name.startsWith(".")) return false;
|
|
5303
|
+
if (["__tests__", "tests", "node_modules", "dist", "coverage", "scratch"].includes(e.name)) {
|
|
5304
|
+
return false;
|
|
5305
|
+
}
|
|
5306
|
+
const resolved = path26.resolve(base, e.name);
|
|
5307
|
+
for (const ex of excludeSet) {
|
|
5308
|
+
if (ex === resolved || ex.startsWith(resolved + path26.sep) || resolved.startsWith(ex + path26.sep)) {
|
|
5309
|
+
return false;
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5312
|
+
return true;
|
|
5313
|
+
}).map((e) => ({
|
|
5174
5314
|
name: e.name,
|
|
5175
|
-
dir:
|
|
5315
|
+
dir: path26.join(base, e.name)
|
|
5176
5316
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
5177
5317
|
}
|
|
5178
5318
|
function extractClassMethods(content, className) {
|
|
@@ -5328,7 +5468,7 @@ function extractClassMethods(content, className) {
|
|
|
5328
5468
|
return methods;
|
|
5329
5469
|
}
|
|
5330
5470
|
function checkUseCaseShape(featureName, filePath, relativePath, content, addViolation) {
|
|
5331
|
-
const fileName =
|
|
5471
|
+
const fileName = path26.basename(filePath);
|
|
5332
5472
|
const lines = content.split(/\r?\n/);
|
|
5333
5473
|
const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
|
|
5334
5474
|
if (!classMatch) {
|
|
@@ -5424,7 +5564,7 @@ private ${m.name}(...) { ... }`
|
|
|
5424
5564
|
}
|
|
5425
5565
|
}
|
|
5426
5566
|
function checkServiceShape(featureName, filePath, relativePath, content, addViolation) {
|
|
5427
|
-
const fileName =
|
|
5567
|
+
const fileName = path26.basename(filePath);
|
|
5428
5568
|
const lines = content.split(/\r?\n/);
|
|
5429
5569
|
const classMatch = content.match(/(?:export\s+(?:default\s+)?)?class\s+([A-Za-z0-9_]+)/);
|
|
5430
5570
|
if (!classMatch) {
|
|
@@ -5523,40 +5663,32 @@ function lintCodebase(options = {}) {
|
|
|
5523
5663
|
const startTime = Date.now();
|
|
5524
5664
|
const projectRoot = options.projectRoot || findProjectRoot(options.targetDir || process.cwd());
|
|
5525
5665
|
const failFast = !options.complete;
|
|
5526
|
-
const
|
|
5527
|
-
const baseErrorRelative = lintConfig.baseErrorPath || "src/errors/AppError.ts";
|
|
5528
|
-
const baseErrorAbs = path2.resolve(projectRoot, baseErrorRelative);
|
|
5529
|
-
const featuresBase = resolveFeaturesDir(projectRoot);
|
|
5530
|
-
const sharedBase = resolveSharedDir(projectRoot);
|
|
5531
|
-
let errorsBase = path2.join(projectRoot, "src/errors");
|
|
5532
|
-
if (!fs4.existsSync(errorsBase) && fs4.existsSync(path2.join(projectRoot, "errors"))) {
|
|
5533
|
-
errorsBase = path2.join(projectRoot, "errors");
|
|
5534
|
-
}
|
|
5666
|
+
const { featuresBase, sharedBase, errorsBase, baseErrorAbs } = resolveLintEnvironment(projectRoot);
|
|
5535
5667
|
const missingFoundations = [];
|
|
5536
|
-
if (!
|
|
5537
|
-
if (!
|
|
5538
|
-
if (!
|
|
5668
|
+
if (!fs17.existsSync(featuresBase)) missingFoundations.push("features/");
|
|
5669
|
+
if (!fs17.existsSync(sharedBase)) missingFoundations.push("shared/");
|
|
5670
|
+
if (!fs17.existsSync(errorsBase)) missingFoundations.push("errors/");
|
|
5539
5671
|
if (missingFoundations.length > 0) {
|
|
5540
5672
|
throw new DependencyRuleError(
|
|
5541
|
-
`Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every
|
|
5673
|
+
`Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every architecture must contain 'features/', 'shared/', and 'errors/'.`,
|
|
5542
5674
|
[],
|
|
5543
5675
|
true
|
|
5544
5676
|
);
|
|
5545
5677
|
}
|
|
5546
|
-
if (!
|
|
5678
|
+
if (!fs17.existsSync(baseErrorAbs)) {
|
|
5547
5679
|
throw new DependencyRuleError(
|
|
5548
|
-
`Project Structure Violation: Base error class not found at '${
|
|
5680
|
+
`Project Structure Violation: Base error class not found at '${path26.relative(projectRoot, baseErrorAbs).replace(/\\/g, "/")}'. Configure paths.baseError in mason.config.json.`,
|
|
5549
5681
|
[],
|
|
5550
5682
|
true
|
|
5551
5683
|
);
|
|
5552
5684
|
}
|
|
5553
|
-
const baseErrorContent =
|
|
5685
|
+
const baseErrorContent = fs17.readFileSync(baseErrorAbs, "utf-8");
|
|
5554
5686
|
const baseClassMatch = baseErrorContent.match(
|
|
5555
5687
|
/(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
|
|
5556
5688
|
);
|
|
5557
5689
|
const baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
|
|
5558
|
-
const features = discoverAllFeatures(
|
|
5559
|
-
const sharedModules = discoverAllShared(
|
|
5690
|
+
const features = discoverAllFeatures(featuresBase, [sharedBase, errorsBase]);
|
|
5691
|
+
const sharedModules = discoverAllShared(sharedBase, [featuresBase, errorsBase]);
|
|
5560
5692
|
const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
|
|
5561
5693
|
const allModules = [
|
|
5562
5694
|
...features.map((f) => ({ ...f, type: "feature" })),
|
|
@@ -5599,12 +5731,12 @@ Code: ${v.code}`;
|
|
|
5599
5731
|
const allFiles = scanDirFiles(mod.dir, projectRoot);
|
|
5600
5732
|
modResult.scannedFilesCount = allFiles.length;
|
|
5601
5733
|
for (const file of allFiles) {
|
|
5602
|
-
const relPath =
|
|
5603
|
-
const { moduleType, moduleName, layer } = classifyFile(file,
|
|
5734
|
+
const relPath = path26.relative(projectRoot, file).replace(/\\/g, "/");
|
|
5735
|
+
const { moduleType, moduleName, layer } = classifyFile(file, featuresBase, sharedBase, errorsBase);
|
|
5604
5736
|
if (!layer || !moduleType || !moduleName) continue;
|
|
5605
|
-
const content =
|
|
5737
|
+
const content = fs17.readFileSync(file, "utf-8");
|
|
5606
5738
|
const statements = extractImportStatements(content);
|
|
5607
|
-
const baseName =
|
|
5739
|
+
const baseName = path26.basename(file);
|
|
5608
5740
|
const isBarrel = baseName === "index.ts" || baseName === "index.js";
|
|
5609
5741
|
const throwErrorRegex = /\bthrow\s+(?:new\s+)?Error\s*\(/g;
|
|
5610
5742
|
let throwMatch;
|
|
@@ -5623,7 +5755,7 @@ Code: ${v.code}`;
|
|
|
5623
5755
|
code: lineCode,
|
|
5624
5756
|
ruleId: "E3_PLAIN_ERROR_THROW",
|
|
5625
5757
|
severity: "error",
|
|
5626
|
-
advice: `Throwing plain 'Error' is prohibited. You must throw '${baseErrorClassName}' or a
|
|
5758
|
+
advice: `Throwing plain 'Error' is prohibited. You must throw '${baseErrorClassName}' or a custom error class that inherits from it.`,
|
|
5627
5759
|
fixExample: {
|
|
5628
5760
|
bad: lineCode,
|
|
5629
5761
|
good: `throw new ${baseErrorClassName}("Something went wrong");`
|
|
@@ -5631,7 +5763,7 @@ Code: ${v.code}`;
|
|
|
5631
5763
|
});
|
|
5632
5764
|
}
|
|
5633
5765
|
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");
|
|
5634
|
-
const isBaseErrorFile =
|
|
5766
|
+
const isBaseErrorFile = path26.resolve(file) === path26.resolve(baseErrorAbs);
|
|
5635
5767
|
if (isErrorFile && !isBaseErrorFile) {
|
|
5636
5768
|
const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
|
|
5637
5769
|
let classMatch;
|
|
@@ -5653,7 +5785,7 @@ Code: ${v.code}`;
|
|
|
5653
5785
|
code: lineCode,
|
|
5654
5786
|
ruleId: "E4_MISSING_INHERITANCE",
|
|
5655
5787
|
severity: "error",
|
|
5656
|
-
advice: `Error class '${className}' must extend '${baseErrorClassName}'
|
|
5788
|
+
advice: `Error class '${className}' must extend '${baseErrorClassName}'.`,
|
|
5657
5789
|
fixExample: {
|
|
5658
5790
|
bad: lineCode,
|
|
5659
5791
|
good: `export class ${className} extends ${baseErrorClassName} { ... }`
|
|
@@ -5670,7 +5802,7 @@ Code: ${v.code}`;
|
|
|
5670
5802
|
code: lineCode,
|
|
5671
5803
|
ruleId: "E5_NATIVE_ERROR_INHERITANCE",
|
|
5672
5804
|
severity: "error",
|
|
5673
|
-
advice: `Error class '${className}' extends
|
|
5805
|
+
advice: `Error class '${className}' extends native 'Error'. It must extend your configured base error class ('${baseErrorClassName}').`,
|
|
5674
5806
|
fixExample: {
|
|
5675
5807
|
bad: lineCode,
|
|
5676
5808
|
good: `export class ${className} extends ${baseErrorClassName} { ... }`
|
|
@@ -5681,7 +5813,7 @@ Code: ${v.code}`;
|
|
|
5681
5813
|
}
|
|
5682
5814
|
if (moduleType === "error") {
|
|
5683
5815
|
for (const stmt of statements) {
|
|
5684
|
-
const target = classifyTarget(stmt.specifier, file, projectRoot);
|
|
5816
|
+
const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
|
|
5685
5817
|
if (target.targetFeature) {
|
|
5686
5818
|
addViolation({
|
|
5687
5819
|
feature: "global-errors",
|
|
@@ -5747,7 +5879,7 @@ Code: ${v.code}`;
|
|
|
5747
5879
|
}
|
|
5748
5880
|
}
|
|
5749
5881
|
for (const stmt of statements) {
|
|
5750
|
-
const target = classifyTarget(stmt.specifier, file, projectRoot);
|
|
5882
|
+
const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
|
|
5751
5883
|
if (target.targetFeature) {
|
|
5752
5884
|
addViolation({
|
|
5753
5885
|
feature: moduleName,
|
|
@@ -5877,7 +6009,7 @@ Code: ${v.code}`;
|
|
|
5877
6009
|
}
|
|
5878
6010
|
}
|
|
5879
6011
|
for (const stmt of statements) {
|
|
5880
|
-
const target = classifyTarget(stmt.specifier, file, projectRoot);
|
|
6012
|
+
const target = classifyTarget(stmt.specifier, file, projectRoot, featuresBase, sharedBase, errorsBase);
|
|
5881
6013
|
if (target.targetFeature && target.targetFeature !== feat.name) {
|
|
5882
6014
|
const evidence = {
|
|
5883
6015
|
fromFeature: feat.name,
|
|
@@ -6743,6 +6875,6 @@ async function runCli(argv = process.argv) {
|
|
|
6743
6875
|
cli.parse(argv, { run: true });
|
|
6744
6876
|
}
|
|
6745
6877
|
|
|
6746
|
-
export { DEFAULT_REGISTRY_BASE, DependencyRuleError, EnvEditor, FeatureDependencyGraph, PromptCancelledError, computeDirectoryHash, concreteInfraTemplate, createCli, detectPackageManager, diProviderTemplate, discoverEnvironments, domainClassTemplate, domainInterfaceTemplate, domainValueObjectTemplate, ensureInterfacePrefix, expressIndexTemplate, fetchModuleManifest, fetchRegistryFile, fetchRegistryIndex, findClosestMatch, findInterfaceFile, findLocalRegistry, findProjectRoot, generateConcreteInfraCode, generateDomain, generateDomainEntityCode, generateFeature, generateHttpHandler, generateHttpHandlerCode, generateInfrastructure, generateInjectable, generateInjectableCode, generateInterface, generateInterfaceCode, generateShared, generateStubCode, generateUseCase, generateUseCaseCode, generateUseCaseTestCode, getAllFiles, getConfiguredFeaturesDir, getConfiguredSharedDir, getEffectiveMode, getMissingNpmPackages, getRegistryBase, getTemplatesDir, handleCancel, handleCreate, handleEnv, handleImport, handleInit, handleLint, hbs, httpHandlerTemplate, injectableInterfaceTemplate, injectableTemplate, installNpmPackages, interfaceTemplate, isValidIdentifier, levenshteinDistance, lintCodebase, listDomainEntities, listDomainInterfaces, listExistingFeatures, listExistingShared, listUseCases, loadInterfaceHierarchy, loadLintConfig, loadMasonConfig, loadTemplate, normalizeRegistryUrl, parseInterfaceMethodsAndImports, printBanner, printGeneratedFiles, promptProperties, removeInterfacePrefix, renderTemplate, renderTemplateFile, resolveEnvFilename, resolveFeaturesDir, resolveSharedDir, runCli, runEnvAdd, runEnvAudit, runEnvCommand, runEnvDelete, runEnvExamplesCommand, runEnvInit, runEnvInitExamples, runEnvMenu, runEnvUpdate, runSharedCommand, stubInfraTemplate, synthesizeCrudMethods, toCamelCase, toKebabCase, toPascalCase, toPlural, toSingular, toStubName, updateOrGenerateDiProvider, useCaseTemplate, useCaseTestTemplate, writeFileSafely };
|
|
6878
|
+
export { DEFAULT_REGISTRY_BASE, DependencyRuleError, EnvEditor, FeatureDependencyGraph, PromptCancelledError, computeDirectoryHash, concreteInfraTemplate, createCli, detectPackageManager, diProviderTemplate, discoverEnvironments, domainClassTemplate, domainInterfaceTemplate, domainValueObjectTemplate, ensureInterfacePrefix, expressIndexTemplate, fetchModuleManifest, fetchRegistryFile, fetchRegistryIndex, findClosestMatch, findInterfaceFile, findLocalRegistry, findProjectRoot, generateConcreteInfraCode, generateDomain, generateDomainEntityCode, generateFeature, generateHttpHandler, generateHttpHandlerCode, generateInfrastructure, generateInjectable, generateInjectableCode, generateInterface, generateInterfaceCode, generateShared, generateStubCode, generateUseCase, generateUseCaseCode, generateUseCaseTestCode, getAllFiles, getConfiguredFeaturesDir, getConfiguredSharedDir, getEffectiveMode, getMissingNpmPackages, getRegistryBase, getResolvedLintPaths, getTemplatesDir, handleCancel, handleCreate, handleEnv, handleImport, handleInit, handleLint, hbs, httpHandlerTemplate, injectableInterfaceTemplate, injectableTemplate, installNpmPackages, interfaceTemplate, isValidIdentifier, levenshteinDistance, lintCodebase, listDomainEntities, listDomainInterfaces, listExistingFeatures, listExistingShared, listUseCases, loadInterfaceHierarchy, loadLintConfig, loadMasonConfig, loadTemplate, normalizeRegistryUrl, parseInterfaceMethodsAndImports, printBanner, printGeneratedFiles, promptProperties, removeInterfacePrefix, renderTemplate, renderTemplateFile, resolveEnvFilename, resolveFeaturesDir, resolveSharedDir, runCli, runEnvAdd, runEnvAudit, runEnvCommand, runEnvDelete, runEnvExamplesCommand, runEnvInit, runEnvInitExamples, runEnvMenu, runEnvUpdate, runSharedCommand, stubInfraTemplate, synthesizeCrudMethods, toCamelCase, toKebabCase, toPascalCase, toPlural, toSingular, toStubName, updateOrGenerateDiProvider, useCaseTemplate, useCaseTestTemplate, writeFileSafely };
|
|
6747
6879
|
//# sourceMappingURL=index.js.map
|
|
6748
6880
|
//# sourceMappingURL=index.js.map
|