@solid-stack/mason 1.0.11 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +158 -93
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +157 -92
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +160 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +158 -93
- package/dist/index.js.map +1 -1
- package/dist/utils/registry.d.ts +18 -0
- package/dist/utils/registry.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin.cjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
var cac = require('cac');
|
|
5
5
|
var p3 = require('@clack/prompts');
|
|
6
6
|
var pc13 = require('picocolors');
|
|
7
|
-
var
|
|
7
|
+
var path15 = require('path');
|
|
8
8
|
var fs7 = require('fs');
|
|
9
9
|
var url = require('url');
|
|
10
10
|
var Handlebars = require('handlebars');
|
|
@@ -33,13 +33,13 @@ function _interopNamespace(e) {
|
|
|
33
33
|
|
|
34
34
|
var p3__namespace = /*#__PURE__*/_interopNamespace(p3);
|
|
35
35
|
var pc13__default = /*#__PURE__*/_interopDefault(pc13);
|
|
36
|
-
var
|
|
36
|
+
var path15__default = /*#__PURE__*/_interopDefault(path15);
|
|
37
37
|
var fs7__default = /*#__PURE__*/_interopDefault(fs7);
|
|
38
38
|
var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
|
|
39
39
|
|
|
40
40
|
function writeFileSafely(absolutePath, content, options = {}) {
|
|
41
41
|
const projectRoot = options.projectRoot || process.cwd();
|
|
42
|
-
const relPath =
|
|
42
|
+
const relPath = path15__default.default.relative(projectRoot, absolutePath).replace(/\\/g, "/");
|
|
43
43
|
const existedBefore = fs7__default.default.existsSync(absolutePath);
|
|
44
44
|
if (options.dryRun) {
|
|
45
45
|
return {
|
|
@@ -59,7 +59,7 @@ function writeFileSafely(absolutePath, content, options = {}) {
|
|
|
59
59
|
existedBefore: true
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
const dir =
|
|
62
|
+
const dir = path15__default.default.dirname(absolutePath);
|
|
63
63
|
if (!fs7__default.default.existsSync(dir)) {
|
|
64
64
|
fs7__default.default.mkdirSync(dir, { recursive: true });
|
|
65
65
|
}
|
|
@@ -154,20 +154,20 @@ function toStubName(ifaceName) {
|
|
|
154
154
|
return `Stub${base}`;
|
|
155
155
|
}
|
|
156
156
|
function findProjectRoot(startDir = process.cwd()) {
|
|
157
|
-
let current =
|
|
157
|
+
let current = path15__default.default.resolve(startDir);
|
|
158
158
|
while (true) {
|
|
159
|
-
if (fs7__default.default.existsSync(
|
|
159
|
+
if (fs7__default.default.existsSync(path15__default.default.join(current, "package.json"))) {
|
|
160
160
|
return current;
|
|
161
161
|
}
|
|
162
|
-
const parent =
|
|
162
|
+
const parent = path15__default.default.dirname(current);
|
|
163
163
|
if (parent === current) {
|
|
164
|
-
return
|
|
164
|
+
return path15__default.default.resolve(startDir);
|
|
165
165
|
}
|
|
166
166
|
current = parent;
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
function resolveFeaturesDir(projectRoot) {
|
|
170
|
-
return
|
|
170
|
+
return path15__default.default.join(projectRoot, "features");
|
|
171
171
|
}
|
|
172
172
|
function listExistingFeatures(projectRoot) {
|
|
173
173
|
const featuresDir = resolveFeaturesDir(projectRoot);
|
|
@@ -183,14 +183,14 @@ function listDomainInterfaces(projectRoot, featureName) {
|
|
|
183
183
|
const results = [];
|
|
184
184
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
185
185
|
for (const feat of features) {
|
|
186
|
-
const domainDir =
|
|
186
|
+
const domainDir = path15__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
187
187
|
if (!fs7__default.default.existsSync(domainDir)) continue;
|
|
188
188
|
try {
|
|
189
189
|
const files = fs7__default.default.readdirSync(domainDir);
|
|
190
190
|
for (const file of files) {
|
|
191
191
|
if (file.endsWith(".ts") && !file.endsWith(".test.ts") && !file.endsWith(".d.ts")) {
|
|
192
192
|
const name = file.replace(/\.ts$/, "");
|
|
193
|
-
const fullPath =
|
|
193
|
+
const fullPath = path15__default.default.join(domainDir, file);
|
|
194
194
|
if (/^I[A-Z]/.test(name)) {
|
|
195
195
|
results.push({
|
|
196
196
|
name,
|
|
@@ -221,7 +221,7 @@ function listDomainEntities(projectRoot, featureName) {
|
|
|
221
221
|
const results = [];
|
|
222
222
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
223
223
|
for (const feat of features) {
|
|
224
|
-
const domainDir =
|
|
224
|
+
const domainDir = path15__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
225
225
|
if (!fs7__default.default.existsSync(domainDir)) continue;
|
|
226
226
|
try {
|
|
227
227
|
const files = fs7__default.default.readdirSync(domainDir);
|
|
@@ -231,7 +231,7 @@ function listDomainEntities(projectRoot, featureName) {
|
|
|
231
231
|
if (!/^I[A-Z]/.test(name)) {
|
|
232
232
|
results.push({
|
|
233
233
|
name,
|
|
234
|
-
fullPath:
|
|
234
|
+
fullPath: path15__default.default.join(domainDir, file),
|
|
235
235
|
feature: feat
|
|
236
236
|
});
|
|
237
237
|
}
|
|
@@ -246,7 +246,7 @@ function listUseCases(projectRoot, featureName) {
|
|
|
246
246
|
const results = [];
|
|
247
247
|
const features = featureName ? [featureName] : listExistingFeatures(projectRoot);
|
|
248
248
|
for (const feat of features) {
|
|
249
|
-
const useCasesDir =
|
|
249
|
+
const useCasesDir = path15__default.default.join(resolveFeaturesDir(projectRoot), feat, "useCases");
|
|
250
250
|
if (!fs7__default.default.existsSync(useCasesDir)) continue;
|
|
251
251
|
try {
|
|
252
252
|
const files = fs7__default.default.readdirSync(useCasesDir);
|
|
@@ -255,7 +255,7 @@ function listUseCases(projectRoot, featureName) {
|
|
|
255
255
|
const name = file.replace(/\.ts$/, "");
|
|
256
256
|
results.push({
|
|
257
257
|
name,
|
|
258
|
-
fullPath:
|
|
258
|
+
fullPath: path15__default.default.join(useCasesDir, file),
|
|
259
259
|
feature: feat
|
|
260
260
|
});
|
|
261
261
|
}
|
|
@@ -284,30 +284,30 @@ function getTemplatesDir() {
|
|
|
284
284
|
if (cachedTemplatesDir && fs7__default.default.existsSync(cachedTemplatesDir)) {
|
|
285
285
|
return cachedTemplatesDir;
|
|
286
286
|
}
|
|
287
|
-
const currentDir = typeof __dirname !== "undefined" ? __dirname :
|
|
288
|
-
const cand1 =
|
|
287
|
+
const currentDir = typeof __dirname !== "undefined" ? __dirname : path15__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bin.cjs', document.baseURI).href))));
|
|
288
|
+
const cand1 = path15__default.default.resolve(currentDir, "../../templates");
|
|
289
289
|
if (fs7__default.default.existsSync(cand1)) {
|
|
290
290
|
cachedTemplatesDir = cand1;
|
|
291
291
|
return cand1;
|
|
292
292
|
}
|
|
293
|
-
const cand2 =
|
|
293
|
+
const cand2 = path15__default.default.resolve(currentDir, "../templates");
|
|
294
294
|
if (fs7__default.default.existsSync(cand2)) {
|
|
295
295
|
cachedTemplatesDir = cand2;
|
|
296
296
|
return cand2;
|
|
297
297
|
}
|
|
298
|
-
const cand3 =
|
|
298
|
+
const cand3 = path15__default.default.resolve(currentDir, "templates");
|
|
299
299
|
if (fs7__default.default.existsSync(cand3)) {
|
|
300
300
|
cachedTemplatesDir = cand3;
|
|
301
301
|
return cand3;
|
|
302
302
|
}
|
|
303
303
|
let curr = currentDir;
|
|
304
304
|
while (true) {
|
|
305
|
-
const candTemplates =
|
|
305
|
+
const candTemplates = path15__default.default.join(curr, "templates");
|
|
306
306
|
if (fs7__default.default.existsSync(candTemplates)) {
|
|
307
307
|
cachedTemplatesDir = candTemplates;
|
|
308
308
|
return candTemplates;
|
|
309
309
|
}
|
|
310
|
-
const parent =
|
|
310
|
+
const parent = path15__default.default.dirname(curr);
|
|
311
311
|
if (parent === curr) break;
|
|
312
312
|
curr = parent;
|
|
313
313
|
}
|
|
@@ -315,7 +315,7 @@ function getTemplatesDir() {
|
|
|
315
315
|
}
|
|
316
316
|
var templateCache = /* @__PURE__ */ new Map();
|
|
317
317
|
function loadTemplate(relativePath) {
|
|
318
|
-
const fullPath =
|
|
318
|
+
const fullPath = path15__default.default.isAbsolute(relativePath) ? relativePath : path15__default.default.join(getTemplatesDir(), relativePath);
|
|
319
319
|
return fs7__default.default.readFileSync(fullPath, "utf-8");
|
|
320
320
|
}
|
|
321
321
|
function renderTemplateFile(relativePath, context) {
|
|
@@ -403,8 +403,8 @@ function generateDomainEntityCode(name, kind = "interface", properties = []) {
|
|
|
403
403
|
function generateDomain(options) {
|
|
404
404
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
405
405
|
const entityName = toPascalCase(options.name);
|
|
406
|
-
const targetDir = options.targetDir ||
|
|
407
|
-
const filePath =
|
|
406
|
+
const targetDir = options.targetDir || path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
|
|
407
|
+
const filePath = path15__default.default.join(targetDir, `${entityName}.ts`);
|
|
408
408
|
const code = generateDomainEntityCode(
|
|
409
409
|
entityName,
|
|
410
410
|
options.kind || "interface",
|
|
@@ -453,8 +453,8 @@ function generateInterfaceCode(ifaceName, kind = "abstractClass", entityName, me
|
|
|
453
453
|
function generateInterface(options) {
|
|
454
454
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
455
455
|
const ifaceName = ensureInterfacePrefix(options.name);
|
|
456
|
-
const targetDir = options.targetDir ||
|
|
457
|
-
const filePath =
|
|
456
|
+
const targetDir = options.targetDir || path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "domain");
|
|
457
|
+
const filePath = path15__default.default.join(targetDir, `${ifaceName}.ts`);
|
|
458
458
|
const code = generateInterfaceCode(
|
|
459
459
|
ifaceName,
|
|
460
460
|
options.kind || "abstractClass",
|
|
@@ -699,21 +699,21 @@ function findInterfaceFile(projectRoot, ifaceName, featureName, customPath) {
|
|
|
699
699
|
];
|
|
700
700
|
const features = featureName ? [featureName, ...listExistingFeatures(projectRoot).filter((f) => f !== featureName)] : listExistingFeatures(projectRoot);
|
|
701
701
|
for (const feat of features) {
|
|
702
|
-
const domainDir =
|
|
702
|
+
const domainDir = path15__default.default.join(resolveFeaturesDir(projectRoot), feat, "domain");
|
|
703
703
|
if (!fs7__default.default.existsSync(domainDir)) continue;
|
|
704
704
|
for (const cand of candidateNames) {
|
|
705
|
-
const p1 =
|
|
705
|
+
const p1 = path15__default.default.join(domainDir, `${cand}.ts`);
|
|
706
706
|
if (fs7__default.default.existsSync(p1)) {
|
|
707
707
|
return { filePath: p1, ifaceName: cand, feature: feat };
|
|
708
708
|
}
|
|
709
709
|
}
|
|
710
710
|
}
|
|
711
711
|
for (const cand of candidateNames) {
|
|
712
|
-
const p1 =
|
|
712
|
+
const p1 = path15__default.default.join(projectRoot, "domain", `${cand}.ts`);
|
|
713
713
|
if (fs7__default.default.existsSync(p1)) return { filePath: p1, ifaceName: cand };
|
|
714
|
-
const p22 =
|
|
714
|
+
const p22 = path15__default.default.join(projectRoot, "src", "domain", `${cand}.ts`);
|
|
715
715
|
if (fs7__default.default.existsSync(p22)) return { filePath: p22, ifaceName: cand };
|
|
716
|
-
const p32 =
|
|
716
|
+
const p32 = path15__default.default.join(projectRoot, "interfaces", `${cand}.ts`);
|
|
717
717
|
if (fs7__default.default.existsSync(p32)) return { filePath: p32, ifaceName: cand };
|
|
718
718
|
}
|
|
719
719
|
return null;
|
|
@@ -813,7 +813,7 @@ function generateStubCode(stubClassName, ifaceName, entityName, featureName, met
|
|
|
813
813
|
const entitiesVar = `${entityVar}s`;
|
|
814
814
|
const idKey = `${entityVar}Id`;
|
|
815
815
|
const impPath = ifaceImportPath || `../domain/${ifaceName}.js`;
|
|
816
|
-
const entityImportPath = ifaceImportPath ? `${
|
|
816
|
+
const entityImportPath = ifaceImportPath ? `${path15__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
|
|
817
817
|
const importsByFrom = /* @__PURE__ */ new Map();
|
|
818
818
|
for (const imp of domainImports) {
|
|
819
819
|
if (imp.name === ifaceName || imp.name === baseEntity) continue;
|
|
@@ -862,7 +862,7 @@ function generateConcreteInfraCode(className, ifaceName, dependencies = [], meth
|
|
|
862
862
|
if (baseEntity) {
|
|
863
863
|
finalMethods = synthesizeCrudMethods(baseEntity);
|
|
864
864
|
if (!finalDomainImports.some((imp) => imp.name === baseEntity)) {
|
|
865
|
-
const importPath = ifaceImportPath ? `${
|
|
865
|
+
const importPath = ifaceImportPath ? `${path15__default.default.dirname(ifaceImportPath)}/${baseEntity}.js` : `../domain/${baseEntity}.js`;
|
|
866
866
|
finalDomainImports.push({
|
|
867
867
|
name: baseEntity,
|
|
868
868
|
from: importPath,
|
|
@@ -907,8 +907,8 @@ function generateInfrastructure(options) {
|
|
|
907
907
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
908
908
|
const className = toPascalCase(options.name);
|
|
909
909
|
const isFeatureScope = options.scope !== "global" && Boolean(options.feature);
|
|
910
|
-
const targetDir = options.targetDir || (isFeatureScope ?
|
|
911
|
-
const filePath =
|
|
910
|
+
const targetDir = options.targetDir || (isFeatureScope ? path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "infrastructure") : path15__default.default.join(projectRoot, "infrastructure"));
|
|
911
|
+
const filePath = path15__default.default.join(targetDir, `${className}.ts`);
|
|
912
912
|
let code;
|
|
913
913
|
if (options.implementsInterface) {
|
|
914
914
|
const rawIfaceName = options.implementsInterface;
|
|
@@ -922,7 +922,7 @@ function generateInfrastructure(options) {
|
|
|
922
922
|
const ifaceFilePath = hierarchy.ifaceFilePath;
|
|
923
923
|
let ifaceImportPath;
|
|
924
924
|
if (ifaceFilePath) {
|
|
925
|
-
let rel =
|
|
925
|
+
let rel = path15__default.default.relative(targetDir, ifaceFilePath).replace(/\\/g, "/").replace(/\.ts$/, ".js");
|
|
926
926
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
927
927
|
ifaceImportPath = rel;
|
|
928
928
|
} else if (isFeatureScope) {
|
|
@@ -935,8 +935,8 @@ function generateInfrastructure(options) {
|
|
|
935
935
|
if (new RegExp(`\\b${item.name}\\b`).test(allSignatures)) {
|
|
936
936
|
let fromPath;
|
|
937
937
|
if (imp.specifier.startsWith(".") && ifaceFilePath) {
|
|
938
|
-
const absTarget =
|
|
939
|
-
let rel =
|
|
938
|
+
const absTarget = path15__default.default.resolve(path15__default.default.dirname(ifaceFilePath), imp.specifier);
|
|
939
|
+
let rel = path15__default.default.relative(targetDir, absTarget).replace(/\\/g, "/");
|
|
940
940
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
941
941
|
fromPath = rel;
|
|
942
942
|
} else {
|
|
@@ -1123,8 +1123,8 @@ function generateUseCase(options) {
|
|
|
1123
1123
|
const files = [];
|
|
1124
1124
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1125
1125
|
const ucName = toPascalCase(options.name);
|
|
1126
|
-
const targetDir = options.targetDir ||
|
|
1127
|
-
const filePath =
|
|
1126
|
+
const targetDir = options.targetDir || path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "useCases");
|
|
1127
|
+
const filePath = path15__default.default.join(targetDir, `${ucName}.ts`);
|
|
1128
1128
|
const code = generateUseCaseCode(
|
|
1129
1129
|
ucName,
|
|
1130
1130
|
options.dependencies || [],
|
|
@@ -1140,7 +1140,7 @@ function generateUseCase(options) {
|
|
|
1140
1140
|
})
|
|
1141
1141
|
);
|
|
1142
1142
|
if (options.includeTest) {
|
|
1143
|
-
const testPath =
|
|
1143
|
+
const testPath = path15__default.default.join(targetDir, `${ucName}.test.ts`);
|
|
1144
1144
|
const testCode = generateUseCaseTestCode(ucName, options.dependencies || []);
|
|
1145
1145
|
files.push(
|
|
1146
1146
|
writeFileSafely(testPath, testCode, {
|
|
@@ -1208,9 +1208,9 @@ function generateHttpHandler(options) {
|
|
|
1208
1208
|
const files = [];
|
|
1209
1209
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1210
1210
|
const className = toPascalCase(options.name);
|
|
1211
|
-
const pxDir =
|
|
1212
|
-
const handlersDir =
|
|
1213
|
-
const pxIndexPath =
|
|
1211
|
+
const pxDir = path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress");
|
|
1212
|
+
const handlersDir = path15__default.default.join(pxDir, "handlers");
|
|
1213
|
+
const pxIndexPath = path15__default.default.join(pxDir, "index.ts");
|
|
1214
1214
|
if (!fs7__default.default.existsSync(pxIndexPath)) {
|
|
1215
1215
|
const featurePath = options.routePrefix || `/${options.feature.toLowerCase()}`;
|
|
1216
1216
|
const pxIndexContent = renderTemplate(expressIndexTemplate, {
|
|
@@ -1224,7 +1224,7 @@ function generateHttpHandler(options) {
|
|
|
1224
1224
|
})
|
|
1225
1225
|
);
|
|
1226
1226
|
}
|
|
1227
|
-
const handlerFilePath =
|
|
1227
|
+
const handlerFilePath = path15__default.default.join(handlersDir, `${className}.ts`);
|
|
1228
1228
|
const code = generateHttpHandlerCode(
|
|
1229
1229
|
className,
|
|
1230
1230
|
options.method || "get",
|
|
@@ -1245,7 +1245,7 @@ function generateHttpHandler(options) {
|
|
|
1245
1245
|
return files;
|
|
1246
1246
|
}
|
|
1247
1247
|
function updateOrGenerateDiProvider(featureDir, featureName, bindings = [], options = {}) {
|
|
1248
|
-
const providerPath =
|
|
1248
|
+
const providerPath = path15__default.default.join(featureDir, "diProvider.ts");
|
|
1249
1249
|
const pascalFeature = toPascalCase(featureName);
|
|
1250
1250
|
const providerModuleName = `${pascalFeature}Provider`;
|
|
1251
1251
|
if (fs7__default.default.existsSync(providerPath) && !options.overwrite) {
|
|
@@ -1308,7 +1308,7 @@ function generateFeature(options) {
|
|
|
1308
1308
|
const projectRoot = options.projectRoot || findProjectRoot();
|
|
1309
1309
|
const rawName = options.name.trim();
|
|
1310
1310
|
const featureName = toCamelCase(rawName);
|
|
1311
|
-
const targetDir = options.targetDir ||
|
|
1311
|
+
const targetDir = options.targetDir || path15__default.default.join(resolveFeaturesDir(projectRoot), featureName);
|
|
1312
1312
|
const routePath = options.routePath || `/${featureName}`;
|
|
1313
1313
|
const rawEntities = [];
|
|
1314
1314
|
if (options.entityNames && options.entityNames.length > 0) {
|
|
@@ -1329,7 +1329,7 @@ function generateFeature(options) {
|
|
|
1329
1329
|
const domainFile = generateDomain({
|
|
1330
1330
|
name: ent,
|
|
1331
1331
|
feature: featureName,
|
|
1332
|
-
targetDir:
|
|
1332
|
+
targetDir: path15__default.default.join(targetDir, "domain"),
|
|
1333
1333
|
projectRoot,
|
|
1334
1334
|
dryRun: options.dryRun,
|
|
1335
1335
|
overwrite: options.overwrite,
|
|
@@ -1349,7 +1349,7 @@ function generateFeature(options) {
|
|
|
1349
1349
|
const ifaceFile = generateInterface({
|
|
1350
1350
|
name: ifaceName,
|
|
1351
1351
|
feature: featureName,
|
|
1352
|
-
targetDir:
|
|
1352
|
+
targetDir: path15__default.default.join(targetDir, "domain"),
|
|
1353
1353
|
entityName: ent,
|
|
1354
1354
|
projectRoot,
|
|
1355
1355
|
dryRun: options.dryRun,
|
|
@@ -1366,7 +1366,7 @@ function generateFeature(options) {
|
|
|
1366
1366
|
const stubFile = generateInfrastructure({
|
|
1367
1367
|
name: stubName,
|
|
1368
1368
|
feature: featureName,
|
|
1369
|
-
targetDir:
|
|
1369
|
+
targetDir: path15__default.default.join(targetDir, "infrastructure"),
|
|
1370
1370
|
kind: "stub",
|
|
1371
1371
|
implementsInterface: ifaceName,
|
|
1372
1372
|
entityName: ent,
|
|
@@ -1408,7 +1408,7 @@ function generateFeature(options) {
|
|
|
1408
1408
|
const ucFiles = generateUseCase({
|
|
1409
1409
|
name: ucName,
|
|
1410
1410
|
feature: featureName,
|
|
1411
|
-
targetDir:
|
|
1411
|
+
targetDir: path15__default.default.join(targetDir, "useCases"),
|
|
1412
1412
|
dependencies: options.includeInterface !== false ? [ifaceName] : [],
|
|
1413
1413
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1414
1414
|
outputProperties: [{ name: entVar, type: primaryEntity }],
|
|
@@ -1453,7 +1453,7 @@ function generateFeature(options) {
|
|
|
1453
1453
|
const ucFiles = generateUseCase({
|
|
1454
1454
|
name: ucName,
|
|
1455
1455
|
feature: featureName,
|
|
1456
|
-
targetDir:
|
|
1456
|
+
targetDir: path15__default.default.join(targetDir, "useCases"),
|
|
1457
1457
|
dependencies: deps,
|
|
1458
1458
|
inputProperties: [{ name: entVar, type: ent }],
|
|
1459
1459
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1486,7 +1486,7 @@ function generateFeature(options) {
|
|
|
1486
1486
|
const ucFiles = generateUseCase({
|
|
1487
1487
|
name: ucName,
|
|
1488
1488
|
feature: featureName,
|
|
1489
|
-
targetDir:
|
|
1489
|
+
targetDir: path15__default.default.join(targetDir, "useCases"),
|
|
1490
1490
|
dependencies: deps,
|
|
1491
1491
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1492
1492
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1519,7 +1519,7 @@ function generateFeature(options) {
|
|
|
1519
1519
|
const ucFiles = generateUseCase({
|
|
1520
1520
|
name: ucName,
|
|
1521
1521
|
feature: featureName,
|
|
1522
|
-
targetDir:
|
|
1522
|
+
targetDir: path15__default.default.join(targetDir, "useCases"),
|
|
1523
1523
|
dependencies: deps,
|
|
1524
1524
|
inputProperties: [
|
|
1525
1525
|
{ name: "page", type: "number", optional: true },
|
|
@@ -1563,7 +1563,7 @@ function generateFeature(options) {
|
|
|
1563
1563
|
const ucFiles = generateUseCase({
|
|
1564
1564
|
name: ucName,
|
|
1565
1565
|
feature: featureName,
|
|
1566
|
-
targetDir:
|
|
1566
|
+
targetDir: path15__default.default.join(targetDir, "useCases"),
|
|
1567
1567
|
dependencies: deps,
|
|
1568
1568
|
inputProperties: [{ name: entVar, type: ent }],
|
|
1569
1569
|
outputProperties: [{ name: entVar, type: ent }],
|
|
@@ -1596,7 +1596,7 @@ function generateFeature(options) {
|
|
|
1596
1596
|
const ucFiles = generateUseCase({
|
|
1597
1597
|
name: ucName,
|
|
1598
1598
|
feature: featureName,
|
|
1599
|
-
targetDir:
|
|
1599
|
+
targetDir: path15__default.default.join(targetDir, "useCases"),
|
|
1600
1600
|
dependencies: deps,
|
|
1601
1601
|
inputProperties: [{ name: idParam, type: "string" }],
|
|
1602
1602
|
outputProperties: [{ name: "success", type: "boolean" }],
|
|
@@ -1633,7 +1633,7 @@ function generateFeature(options) {
|
|
|
1633
1633
|
const ucFiles = generateUseCase({
|
|
1634
1634
|
name: ucName,
|
|
1635
1635
|
feature: featureName,
|
|
1636
|
-
targetDir:
|
|
1636
|
+
targetDir: path15__default.default.join(targetDir, "useCases"),
|
|
1637
1637
|
dependencies: customUc.dependencies || [],
|
|
1638
1638
|
inputProperties: customUc.inputProperties || [],
|
|
1639
1639
|
outputProperties: customUc.outputProperties || [],
|
|
@@ -1665,8 +1665,8 @@ function generateFeature(options) {
|
|
|
1665
1665
|
}
|
|
1666
1666
|
}
|
|
1667
1667
|
if (options.includeExpress !== false) {
|
|
1668
|
-
const pxDir =
|
|
1669
|
-
const pxIndexPath =
|
|
1668
|
+
const pxDir = path15__default.default.join(targetDir, "pxExpress");
|
|
1669
|
+
const pxIndexPath = path15__default.default.join(pxDir, "index.ts");
|
|
1670
1670
|
if (!files.some((f) => f.absolutePath === pxIndexPath)) {
|
|
1671
1671
|
const pxIndexContent = renderTemplate(expressIndexTemplate, { routePath });
|
|
1672
1672
|
files.push(
|
|
@@ -1794,7 +1794,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
1794
1794
|
).trim();
|
|
1795
1795
|
}
|
|
1796
1796
|
const normalizedName = toCamelCase(name);
|
|
1797
|
-
const defaultDir =
|
|
1797
|
+
const defaultDir = path15__default.default.relative(projectRoot, path15__default.default.join(resolveFeaturesDir(projectRoot), normalizedName));
|
|
1798
1798
|
let targetDirRel = defaultDir;
|
|
1799
1799
|
if (!flags.yes && !flags.target) {
|
|
1800
1800
|
targetDirRel = handleCancel(
|
|
@@ -1805,7 +1805,7 @@ async function runFeatureCommand(featureNameArg, flags = {}) {
|
|
|
1805
1805
|
})
|
|
1806
1806
|
).trim();
|
|
1807
1807
|
}
|
|
1808
|
-
const targetDir = flags.target ?
|
|
1808
|
+
const targetDir = flags.target ? path15__default.default.resolve(projectRoot, flags.target) : path15__default.default.resolve(projectRoot, targetDirRel);
|
|
1809
1809
|
let includeExpress = flags.express !== void 0 ? Boolean(flags.express) : true;
|
|
1810
1810
|
let routePath = `/${normalizedName}`;
|
|
1811
1811
|
let includeDomain = true;
|
|
@@ -2473,7 +2473,7 @@ async function runInfrastructureCommand(classNameArg, flags = {}) {
|
|
|
2473
2473
|
const infraFile = generateInfrastructure(options);
|
|
2474
2474
|
files.push(infraFile);
|
|
2475
2475
|
if (registerInProvider && scope === "feature" && feature && implementsInterface) {
|
|
2476
|
-
const featureDir =
|
|
2476
|
+
const featureDir = path15__default.default.join(resolveFeaturesDir(projectRoot), feature);
|
|
2477
2477
|
const providerFile = updateOrGenerateDiProvider(
|
|
2478
2478
|
featureDir,
|
|
2479
2479
|
feature,
|
|
@@ -2635,7 +2635,7 @@ async function runInterfaceCommand(interfaceNameArg, flags = {}) {
|
|
|
2635
2635
|
files.push(stubFile);
|
|
2636
2636
|
}
|
|
2637
2637
|
if (registerInProvider && generateStub) {
|
|
2638
|
-
const featureDir =
|
|
2638
|
+
const featureDir = path15__default.default.join(resolveFeaturesDir(projectRoot), feature);
|
|
2639
2639
|
const providerFile = updateOrGenerateDiProvider(
|
|
2640
2640
|
featureDir,
|
|
2641
2641
|
feature,
|
|
@@ -2823,21 +2823,21 @@ function generateInjectable(options) {
|
|
|
2823
2823
|
const className = toPascalCase(options.name);
|
|
2824
2824
|
let targetDir = "";
|
|
2825
2825
|
if (options.customPath) {
|
|
2826
|
-
targetDir =
|
|
2826
|
+
targetDir = path15__default.default.isAbsolute(options.customPath) ? options.customPath : path15__default.default.join(projectRoot, options.customPath);
|
|
2827
2827
|
} else if (options.location === "feature-service" && options.feature) {
|
|
2828
|
-
targetDir =
|
|
2828
|
+
targetDir = path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services");
|
|
2829
2829
|
} else if (options.location === "feature-transformer" && options.feature) {
|
|
2830
|
-
targetDir =
|
|
2830
|
+
targetDir = path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "pxExpress", "transformers");
|
|
2831
2831
|
} else if (options.location === "module") {
|
|
2832
|
-
targetDir =
|
|
2832
|
+
targetDir = path15__default.default.join(projectRoot, "modules", className);
|
|
2833
2833
|
} else {
|
|
2834
|
-
targetDir = options.feature ?
|
|
2834
|
+
targetDir = options.feature ? path15__default.default.join(resolveFeaturesDir(projectRoot), options.feature, "services") : path15__default.default.join(projectRoot, "shared", className.toLowerCase());
|
|
2835
2835
|
}
|
|
2836
|
-
const filePath =
|
|
2836
|
+
const filePath = path15__default.default.join(targetDir, `${className}.ts`);
|
|
2837
2837
|
let ifaceName;
|
|
2838
2838
|
if (options.generateInterface) {
|
|
2839
2839
|
ifaceName = `I${className}`;
|
|
2840
|
-
const ifacePath =
|
|
2840
|
+
const ifacePath = path15__default.default.join(targetDir, `${ifaceName}.ts`);
|
|
2841
2841
|
const ifaceContent = renderTemplate(injectableInterfaceTemplate, { ifaceName });
|
|
2842
2842
|
files.push(
|
|
2843
2843
|
writeFileSafely(ifacePath, ifaceContent, {
|
|
@@ -3071,40 +3071,105 @@ async function handleCreate(type, name, flags = {}) {
|
|
|
3071
3071
|
}
|
|
3072
3072
|
}
|
|
3073
3073
|
var DEFAULT_REGISTRY_BASE = "https://raw.githubusercontent.com/solid-stack-digital/mason-registry/main";
|
|
3074
|
+
function normalizeRegistryUrl(urlOrPath, baseDir) {
|
|
3075
|
+
let trimmed = urlOrPath.trim();
|
|
3076
|
+
const gitSshRegex = /^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
3077
|
+
const sshMatch = trimmed.match(gitSshRegex);
|
|
3078
|
+
if (sshMatch && sshMatch[1] && sshMatch[2]) {
|
|
3079
|
+
return `https://raw.githubusercontent.com/${sshMatch[1]}/${sshMatch[2]}/main`;
|
|
3080
|
+
}
|
|
3081
|
+
const githubWebRegex = /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^/]+))?\/?$/;
|
|
3082
|
+
const webMatch = trimmed.match(githubWebRegex);
|
|
3083
|
+
if (webMatch && webMatch[1] && webMatch[2]) {
|
|
3084
|
+
const owner = webMatch[1];
|
|
3085
|
+
const repo = webMatch[2];
|
|
3086
|
+
const branch = webMatch[3] || "main";
|
|
3087
|
+
return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
|
|
3088
|
+
}
|
|
3089
|
+
if (baseDir && (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed === "." || trimmed === "..")) {
|
|
3090
|
+
return path15__default.default.resolve(baseDir, trimmed);
|
|
3091
|
+
}
|
|
3092
|
+
return trimmed;
|
|
3093
|
+
}
|
|
3094
|
+
function findLocalRegistry(startDir = process.cwd()) {
|
|
3095
|
+
let current = path15__default.default.resolve(startDir);
|
|
3096
|
+
while (true) {
|
|
3097
|
+
const candidate = path15__default.default.join(current, "mason-registry");
|
|
3098
|
+
if (fs7__default.default.existsSync(candidate) && fs7__default.default.existsSync(path15__default.default.join(candidate, "index.json"))) {
|
|
3099
|
+
return candidate;
|
|
3100
|
+
}
|
|
3101
|
+
const parent = path15__default.default.dirname(current);
|
|
3102
|
+
if (parent === current) break;
|
|
3103
|
+
current = parent;
|
|
3104
|
+
}
|
|
3105
|
+
return null;
|
|
3106
|
+
}
|
|
3074
3107
|
function getRegistryBase(projectRoot, override) {
|
|
3108
|
+
const rootDir = projectRoot ? path15__default.default.resolve(projectRoot) : process.cwd();
|
|
3075
3109
|
if (override && override.trim()) {
|
|
3076
|
-
return override.trim();
|
|
3110
|
+
return normalizeRegistryUrl(override.trim(), rootDir);
|
|
3077
3111
|
}
|
|
3078
3112
|
if (process.env.MASON_REGISTRY_URL && process.env.MASON_REGISTRY_URL.trim()) {
|
|
3079
|
-
return process.env.MASON_REGISTRY_URL.trim();
|
|
3113
|
+
return normalizeRegistryUrl(process.env.MASON_REGISTRY_URL.trim(), rootDir);
|
|
3080
3114
|
}
|
|
3081
|
-
|
|
3082
|
-
|
|
3115
|
+
const configLocations = [
|
|
3116
|
+
path15__default.default.join(rootDir, "mason.config.json"),
|
|
3117
|
+
path15__default.default.join(process.cwd(), "mason.config.json")
|
|
3118
|
+
];
|
|
3119
|
+
for (const configPath of configLocations) {
|
|
3083
3120
|
if (fs7__default.default.existsSync(configPath)) {
|
|
3084
3121
|
try {
|
|
3085
3122
|
const config = JSON.parse(fs7__default.default.readFileSync(configPath, "utf-8"));
|
|
3086
3123
|
if (config.registry && typeof config.registry === "string") {
|
|
3087
|
-
return config.registry.trim();
|
|
3124
|
+
return normalizeRegistryUrl(config.registry.trim(), path15__default.default.dirname(configPath));
|
|
3088
3125
|
}
|
|
3089
3126
|
} catch {
|
|
3090
3127
|
}
|
|
3091
3128
|
}
|
|
3092
3129
|
}
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3130
|
+
const pkgLocations = [
|
|
3131
|
+
path15__default.default.join(rootDir, "package.json"),
|
|
3132
|
+
path15__default.default.join(process.cwd(), "package.json")
|
|
3133
|
+
];
|
|
3134
|
+
for (const pkgPath of pkgLocations) {
|
|
3135
|
+
if (fs7__default.default.existsSync(pkgPath)) {
|
|
3136
|
+
try {
|
|
3137
|
+
const pkg = JSON.parse(fs7__default.default.readFileSync(pkgPath, "utf-8"));
|
|
3138
|
+
if (pkg.mason?.registry && typeof pkg.mason.registry === "string") {
|
|
3139
|
+
return normalizeRegistryUrl(pkg.mason.registry.trim(), path15__default.default.dirname(pkgPath));
|
|
3140
|
+
}
|
|
3141
|
+
} catch {
|
|
3142
|
+
}
|
|
3097
3143
|
}
|
|
3098
3144
|
}
|
|
3145
|
+
const localRegistry = findLocalRegistry(rootDir);
|
|
3146
|
+
if (localRegistry) {
|
|
3147
|
+
return localRegistry;
|
|
3148
|
+
}
|
|
3099
3149
|
return DEFAULT_REGISTRY_BASE;
|
|
3100
3150
|
}
|
|
3101
3151
|
async function fetchRegistryFile(registryBase, relPath) {
|
|
3102
3152
|
const cleanRelPath = relPath.replace(/^\/+/, "");
|
|
3103
3153
|
if (registryBase.startsWith("http://") || registryBase.startsWith("https://")) {
|
|
3104
3154
|
const url = `${registryBase.replace(/\/+$/, "")}/${cleanRelPath}`;
|
|
3105
|
-
const
|
|
3155
|
+
const headers = {};
|
|
3156
|
+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
3157
|
+
if (token) {
|
|
3158
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
3159
|
+
}
|
|
3160
|
+
const res = await fetch(url, { headers });
|
|
3106
3161
|
if (!res.ok) {
|
|
3107
|
-
|
|
3162
|
+
let extraHint = "";
|
|
3163
|
+
if (res.status === 404) {
|
|
3164
|
+
extraHint = `
|
|
3165
|
+
Possible reasons:
|
|
3166
|
+
\u2022 If using a private GitHub repository, ensure GITHUB_TOKEN is set in your environment.
|
|
3167
|
+
\u2022 If your registry has not yet been pushed to GitHub, point to your local directory:
|
|
3168
|
+
- CLI flag: mason import ... --registry /path/to/mason-registry
|
|
3169
|
+
- Environment: export MASON_REGISTRY_URL=/path/to/mason-registry
|
|
3170
|
+
- Config file: Create mason.config.json with { "registry": "/path/to/mason-registry" }`;
|
|
3171
|
+
}
|
|
3172
|
+
throw new Error(`Failed to fetch ${cleanRelPath} from ${url} (HTTP ${res.status}: ${res.statusText})${extraHint}`);
|
|
3108
3173
|
}
|
|
3109
3174
|
return await res.text();
|
|
3110
3175
|
}
|
|
@@ -3112,7 +3177,7 @@ async function fetchRegistryFile(registryBase, relPath) {
|
|
|
3112
3177
|
if (baseDir.startsWith("file://")) {
|
|
3113
3178
|
baseDir = url.fileURLToPath(baseDir);
|
|
3114
3179
|
}
|
|
3115
|
-
const filePath =
|
|
3180
|
+
const filePath = path15__default.default.resolve(baseDir, cleanRelPath);
|
|
3116
3181
|
if (!fs7__default.default.existsSync(filePath)) {
|
|
3117
3182
|
throw new Error(`Registry file not found at ${filePath}`);
|
|
3118
3183
|
}
|
|
@@ -3178,14 +3243,14 @@ function findClosestMatch(target, candidates) {
|
|
|
3178
3243
|
return null;
|
|
3179
3244
|
}
|
|
3180
3245
|
function detectPackageManager(projectRoot) {
|
|
3181
|
-
if (fs7__default.default.existsSync(
|
|
3182
|
-
if (fs7__default.default.existsSync(
|
|
3183
|
-
if (fs7__default.default.existsSync(
|
|
3246
|
+
if (fs7__default.default.existsSync(path15__default.default.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
3247
|
+
if (fs7__default.default.existsSync(path15__default.default.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
3248
|
+
if (fs7__default.default.existsSync(path15__default.default.join(projectRoot, "bun.lockb")) || fs7__default.default.existsSync(path15__default.default.join(projectRoot, "bun.lock"))) return "bun";
|
|
3184
3249
|
return "npm";
|
|
3185
3250
|
}
|
|
3186
3251
|
function getMissingNpmPackages(projectRoot, requiredPackages) {
|
|
3187
3252
|
if (!requiredPackages || requiredPackages.length === 0) return [];
|
|
3188
|
-
const pkgJsonPath =
|
|
3253
|
+
const pkgJsonPath = path15__default.default.join(projectRoot, "package.json");
|
|
3189
3254
|
if (!fs7__default.default.existsSync(pkgJsonPath)) {
|
|
3190
3255
|
return requiredPackages;
|
|
3191
3256
|
}
|
|
@@ -3312,7 +3377,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3312
3377
|
}
|
|
3313
3378
|
const sharedDeps = manifest.dependencies?.shared || [];
|
|
3314
3379
|
for (const dep of sharedDeps) {
|
|
3315
|
-
const depPath =
|
|
3380
|
+
const depPath = path15__default.default.join(projectRoot, "src", "shared", dep);
|
|
3316
3381
|
if (!fs7__default.default.existsSync(depPath) && !importedModules.has(`shared:${dep}`)) {
|
|
3317
3382
|
p3__namespace.log.info(` \u21B3 Resolving required shared dependency: ${pc13__default.default.cyan(dep)}`);
|
|
3318
3383
|
await importModuleRecursive("shared", dep);
|
|
@@ -3320,7 +3385,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3320
3385
|
}
|
|
3321
3386
|
const featureDeps = manifest.dependencies?.features || [];
|
|
3322
3387
|
for (const dep of featureDeps) {
|
|
3323
|
-
const depPath =
|
|
3388
|
+
const depPath = path15__default.default.join(projectRoot, "src", "features", dep);
|
|
3324
3389
|
if (!fs7__default.default.existsSync(depPath) && !importedModules.has(`feature:${dep}`)) {
|
|
3325
3390
|
p3__namespace.log.info(` \u21B3 Resolving required feature dependency: ${pc13__default.default.cyan(dep)}`);
|
|
3326
3391
|
await importModuleRecursive("feature", dep);
|
|
@@ -3330,21 +3395,21 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3330
3395
|
requiredNpmPackages.add(pkg);
|
|
3331
3396
|
}
|
|
3332
3397
|
const folder = modType === "shared" ? "shared" : "features";
|
|
3333
|
-
const targetDir =
|
|
3398
|
+
const targetDir = path15__default.default.join(projectRoot, "src", folder, modName);
|
|
3334
3399
|
for (const file of manifest.files || []) {
|
|
3335
3400
|
if (file === "registry.json") continue;
|
|
3336
3401
|
const remoteFilePath = `${folder}/${modName}/${file}`;
|
|
3337
|
-
const localFilePath =
|
|
3402
|
+
const localFilePath = path15__default.default.join(targetDir, file);
|
|
3338
3403
|
if (fs7__default.default.existsSync(localFilePath) && !flags.overwrite) {
|
|
3339
|
-
p3__namespace.log.warn(` \u21B3 Skipping existing file: ${pc13__default.default.dim(
|
|
3404
|
+
p3__namespace.log.warn(` \u21B3 Skipping existing file: ${pc13__default.default.dim(path15__default.default.relative(projectRoot, localFilePath))} (use --overwrite to replace)`);
|
|
3340
3405
|
continue;
|
|
3341
3406
|
}
|
|
3342
3407
|
const content = await fetchRegistryFile(registryBase, remoteFilePath);
|
|
3343
3408
|
if (!flags.dryRun) {
|
|
3344
|
-
fs7__default.default.mkdirSync(
|
|
3409
|
+
fs7__default.default.mkdirSync(path15__default.default.dirname(localFilePath), { recursive: true });
|
|
3345
3410
|
fs7__default.default.writeFileSync(localFilePath, content, "utf-8");
|
|
3346
3411
|
}
|
|
3347
|
-
const displayPath =
|
|
3412
|
+
const displayPath = path15__default.default.relative(projectRoot, localFilePath);
|
|
3348
3413
|
totalWrittenFiles.push(displayPath);
|
|
3349
3414
|
p3__namespace.log.message(` ${pc13__default.default.green("+")} ${displayPath}`);
|
|
3350
3415
|
}
|