@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.
@@ -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 = importDeclarations.map(({ from, imports }) => {
56
- const specifiers = imports.map(
57
- (imp) => t.importSpecifier(t.identifier(imp), t.identifier(imp))
58
- );
59
- return t.importDeclaration(specifiers, t.stringLiteral(from));
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 = "1.4.1";
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-5I5LPFKU.mjs");
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 = "1.4.1";
1241
+ var version = "2.0.0";
1220
1242
 
1221
1243
  // src/index.ts
1222
1244
  async function cli() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svton/cli",
3
- "version": "1.4.1",
3
+ "version": "2.0.0",
4
4
  "description": "Svton CLI - Create full-stack applications with NestJS, Next.js, and Taro",
5
5
  "keywords": [
6
6
  "cli",