@svton/cli 1.4.1 → 2.0.0
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/ast-helper-AGPOPMTY.mjs +124 -0
- package/dist/index.js +48 -7
- package/dist/index.mjs +24 -2
- package/package.json +1 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import "./chunk-Y6FXYEAI.mjs";
|
|
2
|
+
|
|
3
|
+
// src/utils/ast-helper.ts
|
|
4
|
+
import * as parser from "@babel/parser";
|
|
5
|
+
import traverse from "@babel/traverse";
|
|
6
|
+
import generate from "@babel/generator";
|
|
7
|
+
import * as t from "@babel/types";
|
|
8
|
+
import fs from "fs-extra";
|
|
9
|
+
function addImportToFile(code, importDeclarations) {
|
|
10
|
+
const ast = parser.parse(code, {
|
|
11
|
+
sourceType: "module",
|
|
12
|
+
plugins: ["typescript", "decorators-legacy"]
|
|
13
|
+
});
|
|
14
|
+
const existingImports = /* @__PURE__ */ new Map();
|
|
15
|
+
let lastImportIndex = -1;
|
|
16
|
+
traverse(ast, {
|
|
17
|
+
ImportDeclaration(path) {
|
|
18
|
+
const source = path.node.source.value;
|
|
19
|
+
const start = path.node.start;
|
|
20
|
+
if (start !== null && start !== void 0 && start > lastImportIndex) {
|
|
21
|
+
lastImportIndex = start;
|
|
22
|
+
}
|
|
23
|
+
if (!existingImports.has(source)) {
|
|
24
|
+
existingImports.set(source, /* @__PURE__ */ new Set());
|
|
25
|
+
}
|
|
26
|
+
const importSet = existingImports.get(source);
|
|
27
|
+
path.node.specifiers.forEach((spec) => {
|
|
28
|
+
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
|
|
29
|
+
importSet.add(spec.imported.name);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const newImports = [];
|
|
35
|
+
for (const { from, imports } of importDeclarations) {
|
|
36
|
+
const existingSet = existingImports.get(from);
|
|
37
|
+
const newImportNames = existingSet ? imports.filter((imp) => !existingSet.has(imp)) : imports;
|
|
38
|
+
if (newImportNames.length > 0) {
|
|
39
|
+
const specifiers = newImportNames.map(
|
|
40
|
+
(imp) => t.importSpecifier(t.identifier(imp), t.identifier(imp))
|
|
41
|
+
);
|
|
42
|
+
newImports.push(t.importDeclaration(specifiers, t.stringLiteral(from)));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (newImports.length === 0) {
|
|
46
|
+
return code;
|
|
47
|
+
}
|
|
48
|
+
if (lastImportIndex >= 0) {
|
|
49
|
+
const program = ast.program;
|
|
50
|
+
const lastImportNode = program.body.find(
|
|
51
|
+
(node) => node.type === "ImportDeclaration" && node.start !== null && node.start === lastImportIndex
|
|
52
|
+
);
|
|
53
|
+
if (lastImportNode) {
|
|
54
|
+
const index = program.body.indexOf(lastImportNode);
|
|
55
|
+
program.body.splice(index + 1, 0, ...newImports);
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
ast.program.body.unshift(...newImports);
|
|
59
|
+
}
|
|
60
|
+
const output = generate(ast, {
|
|
61
|
+
retainLines: false,
|
|
62
|
+
compact: false
|
|
63
|
+
});
|
|
64
|
+
return output.code;
|
|
65
|
+
}
|
|
66
|
+
function addModuleImports(code, moduleExpressions) {
|
|
67
|
+
const ast = parser.parse(code, {
|
|
68
|
+
sourceType: "module",
|
|
69
|
+
plugins: ["typescript", "decorators-legacy"]
|
|
70
|
+
});
|
|
71
|
+
let modified = false;
|
|
72
|
+
traverse(ast, {
|
|
73
|
+
Decorator(path) {
|
|
74
|
+
if (t.isCallExpression(path.node.expression) && t.isIdentifier(path.node.expression.callee) && path.node.expression.callee.name === "Module") {
|
|
75
|
+
const args = path.node.expression.arguments;
|
|
76
|
+
if (args.length > 0 && t.isObjectExpression(args[0])) {
|
|
77
|
+
const moduleConfig = args[0];
|
|
78
|
+
const importsProperty = moduleConfig.properties.find(
|
|
79
|
+
(prop) => t.isObjectProperty(prop) && t.isIdentifier(prop.key) && prop.key.name === "imports"
|
|
80
|
+
);
|
|
81
|
+
if (importsProperty && t.isObjectProperty(importsProperty)) {
|
|
82
|
+
if (t.isArrayExpression(importsProperty.value)) {
|
|
83
|
+
for (const expr of moduleExpressions) {
|
|
84
|
+
try {
|
|
85
|
+
const exprAst = parser.parseExpression(expr, {
|
|
86
|
+
plugins: ["typescript"]
|
|
87
|
+
});
|
|
88
|
+
importsProperty.value.elements.push(exprAst);
|
|
89
|
+
modified = true;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error(`Failed to parse expression: ${expr}`, error);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
if (!modified) {
|
|
101
|
+
console.warn("Could not find @Module decorator or imports array");
|
|
102
|
+
return code;
|
|
103
|
+
}
|
|
104
|
+
const output = generate(ast, {
|
|
105
|
+
retainLines: false,
|
|
106
|
+
compact: false
|
|
107
|
+
});
|
|
108
|
+
return output.code;
|
|
109
|
+
}
|
|
110
|
+
async function updateAppModuleFile(filePath, imports, moduleExpressions) {
|
|
111
|
+
let code = await fs.readFile(filePath, "utf-8");
|
|
112
|
+
if (imports.length > 0) {
|
|
113
|
+
code = addImportToFile(code, imports);
|
|
114
|
+
}
|
|
115
|
+
if (moduleExpressions.length > 0) {
|
|
116
|
+
code = addModuleImports(code, moduleExpressions);
|
|
117
|
+
}
|
|
118
|
+
await fs.writeFile(filePath, code, "utf-8");
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
addImportToFile,
|
|
122
|
+
addModuleImports,
|
|
123
|
+
updateAppModuleFile
|
|
124
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -43,21 +43,40 @@ function addImportToFile(code, importDeclarations) {
|
|
|
43
43
|
sourceType: "module",
|
|
44
44
|
plugins: ["typescript", "decorators-legacy"]
|
|
45
45
|
});
|
|
46
|
+
const existingImports = /* @__PURE__ */ new Map();
|
|
46
47
|
let lastImportIndex = -1;
|
|
47
48
|
(0, import_traverse.default)(ast, {
|
|
48
49
|
ImportDeclaration(path5) {
|
|
50
|
+
const source = path5.node.source.value;
|
|
49
51
|
const start = path5.node.start;
|
|
50
52
|
if (start !== null && start !== void 0 && start > lastImportIndex) {
|
|
51
53
|
lastImportIndex = start;
|
|
52
54
|
}
|
|
55
|
+
if (!existingImports.has(source)) {
|
|
56
|
+
existingImports.set(source, /* @__PURE__ */ new Set());
|
|
57
|
+
}
|
|
58
|
+
const importSet = existingImports.get(source);
|
|
59
|
+
path5.node.specifiers.forEach((spec) => {
|
|
60
|
+
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
|
|
61
|
+
importSet.add(spec.imported.name);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
53
64
|
}
|
|
54
65
|
});
|
|
55
|
-
const newImports =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
const newImports = [];
|
|
67
|
+
for (const { from, imports } of importDeclarations) {
|
|
68
|
+
const existingSet = existingImports.get(from);
|
|
69
|
+
const newImportNames = existingSet ? imports.filter((imp) => !existingSet.has(imp)) : imports;
|
|
70
|
+
if (newImportNames.length > 0) {
|
|
71
|
+
const specifiers = newImportNames.map(
|
|
72
|
+
(imp) => t.importSpecifier(t.identifier(imp), t.identifier(imp))
|
|
73
|
+
);
|
|
74
|
+
newImports.push(t.importDeclaration(specifiers, t.stringLiteral(from)));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (newImports.length === 0) {
|
|
78
|
+
return code;
|
|
79
|
+
}
|
|
61
80
|
if (lastImportIndex >= 0) {
|
|
62
81
|
const program = ast.program;
|
|
63
82
|
const lastImportNode = program.body.find(
|
|
@@ -992,6 +1011,25 @@ ${featuresList}
|
|
|
992
1011
|
await import_fs_extra5.default.writeFile(indexPath, content);
|
|
993
1012
|
logger.info("Generated capabilities index");
|
|
994
1013
|
}
|
|
1014
|
+
async function copyPrismaTemplates(templateDir, targetPath) {
|
|
1015
|
+
const prismaTemplatesDir = import_path3.default.join(templateDir, "apps/backend/prisma");
|
|
1016
|
+
const prismaDestDir = import_path3.default.join(targetPath, "apps/backend/prisma");
|
|
1017
|
+
if (await import_fs_extra5.default.pathExists(prismaTemplatesDir)) {
|
|
1018
|
+
await import_fs_extra5.default.ensureDir(prismaDestDir);
|
|
1019
|
+
await import_fs_extra5.default.copy(prismaTemplatesDir, prismaDestDir);
|
|
1020
|
+
const files = await import_fs_extra5.default.readdir(prismaDestDir);
|
|
1021
|
+
for (const file of files) {
|
|
1022
|
+
if (file.endsWith(".tpl")) {
|
|
1023
|
+
const filePath = import_path3.default.join(prismaDestDir, file);
|
|
1024
|
+
const newPath = filePath.replace(/\.tpl$/, "");
|
|
1025
|
+
await import_fs_extra5.default.rename(filePath, newPath);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
logger.info("Copied Prisma templates");
|
|
1029
|
+
} else {
|
|
1030
|
+
logger.warn(`Prisma templates not found: ${prismaTemplatesDir}`);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
995
1033
|
async function updatePackageJson(features, config, targetPath) {
|
|
996
1034
|
const packageJsonPath = import_path3.default.join(targetPath, "apps/backend/package.json");
|
|
997
1035
|
const packageJson = await import_fs_extra5.default.readJSON(packageJsonPath);
|
|
@@ -1335,6 +1373,9 @@ async function createProjectFromTemplate(config) {
|
|
|
1335
1373
|
await copyConfigFiles(config.features, featuresConfig, templateDir, config.projectPath);
|
|
1336
1374
|
await copyExampleFiles(config.features, featuresConfig, templateDir, config.projectPath);
|
|
1337
1375
|
await copySkillFiles(config.features, featuresConfig, templateDir, config.projectPath);
|
|
1376
|
+
if (config.template === "backend-only" || config.template === "full-stack") {
|
|
1377
|
+
await copyPrismaTemplates(templateDir, config.projectPath);
|
|
1378
|
+
}
|
|
1338
1379
|
await generateEnvExample(config.features, featuresConfig, config.projectPath);
|
|
1339
1380
|
if (config.template === "backend-only" || config.template === "full-stack") {
|
|
1340
1381
|
await updateAppModule(config.features, featuresConfig, config.projectPath);
|
|
@@ -1360,7 +1401,7 @@ async function createProjectFromTemplate(config) {
|
|
|
1360
1401
|
}
|
|
1361
1402
|
|
|
1362
1403
|
// package.json
|
|
1363
|
-
var version = "
|
|
1404
|
+
var version = "2.0.0";
|
|
1364
1405
|
|
|
1365
1406
|
// src/index.ts
|
|
1366
1407
|
async function cli() {
|
package/dist/index.mjs
CHANGED
|
@@ -848,6 +848,25 @@ ${featuresList}
|
|
|
848
848
|
await fs4.writeFile(indexPath, content);
|
|
849
849
|
logger.info("Generated capabilities index");
|
|
850
850
|
}
|
|
851
|
+
async function copyPrismaTemplates(templateDir, targetPath) {
|
|
852
|
+
const prismaTemplatesDir = path3.join(templateDir, "apps/backend/prisma");
|
|
853
|
+
const prismaDestDir = path3.join(targetPath, "apps/backend/prisma");
|
|
854
|
+
if (await fs4.pathExists(prismaTemplatesDir)) {
|
|
855
|
+
await fs4.ensureDir(prismaDestDir);
|
|
856
|
+
await fs4.copy(prismaTemplatesDir, prismaDestDir);
|
|
857
|
+
const files = await fs4.readdir(prismaDestDir);
|
|
858
|
+
for (const file of files) {
|
|
859
|
+
if (file.endsWith(".tpl")) {
|
|
860
|
+
const filePath = path3.join(prismaDestDir, file);
|
|
861
|
+
const newPath = filePath.replace(/\.tpl$/, "");
|
|
862
|
+
await fs4.rename(filePath, newPath);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
logger.info("Copied Prisma templates");
|
|
866
|
+
} else {
|
|
867
|
+
logger.warn(`Prisma templates not found: ${prismaTemplatesDir}`);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
851
870
|
async function updatePackageJson(features, config, targetPath) {
|
|
852
871
|
const packageJsonPath = path3.join(targetPath, "apps/backend/package.json");
|
|
853
872
|
const packageJson = await fs4.readJSON(packageJsonPath);
|
|
@@ -960,7 +979,7 @@ async function updateAppModule(features, config, targetPath) {
|
|
|
960
979
|
moduleExpressions.push(moduleExpression);
|
|
961
980
|
}
|
|
962
981
|
}
|
|
963
|
-
const { updateAppModuleFile } = await import("./ast-helper-
|
|
982
|
+
const { updateAppModuleFile } = await import("./ast-helper-AGPOPMTY.mjs");
|
|
964
983
|
await updateAppModuleFile(appModulePath, imports, moduleExpressions);
|
|
965
984
|
logger.info("Successfully updated app.module.ts with feature modules");
|
|
966
985
|
} catch (error) {
|
|
@@ -1191,6 +1210,9 @@ async function createProjectFromTemplate(config) {
|
|
|
1191
1210
|
await copyConfigFiles(config.features, featuresConfig, templateDir, config.projectPath);
|
|
1192
1211
|
await copyExampleFiles(config.features, featuresConfig, templateDir, config.projectPath);
|
|
1193
1212
|
await copySkillFiles(config.features, featuresConfig, templateDir, config.projectPath);
|
|
1213
|
+
if (config.template === "backend-only" || config.template === "full-stack") {
|
|
1214
|
+
await copyPrismaTemplates(templateDir, config.projectPath);
|
|
1215
|
+
}
|
|
1194
1216
|
await generateEnvExample(config.features, featuresConfig, config.projectPath);
|
|
1195
1217
|
if (config.template === "backend-only" || config.template === "full-stack") {
|
|
1196
1218
|
await updateAppModule(config.features, featuresConfig, config.projectPath);
|
|
@@ -1216,7 +1238,7 @@ async function createProjectFromTemplate(config) {
|
|
|
1216
1238
|
}
|
|
1217
1239
|
|
|
1218
1240
|
// package.json
|
|
1219
|
-
var version = "
|
|
1241
|
+
var version = "2.0.0";
|
|
1220
1242
|
|
|
1221
1243
|
// src/index.ts
|
|
1222
1244
|
async function cli() {
|