@svton/cli 2.0.1 → 2.2.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/index.js CHANGED
@@ -860,11 +860,16 @@ function collectEnvVars(features, config) {
860
860
  }
861
861
  return envVars;
862
862
  }
863
- async function generateEnvExample(features, config, targetPath) {
863
+ async function generateEnvExample(features, config, targetPath, database = "mysql") {
864
864
  const envVars = collectEnvVars(features, config);
865
865
  if (envVars.length === 0) {
866
866
  return;
867
867
  }
868
+ const databaseUrls = {
869
+ mysql: "mysql://root:root123456@localhost:3306/{{PROJECT_NAME}}",
870
+ postgresql: "postgresql://postgres:postgres@localhost:5432/{{PROJECT_NAME}}",
871
+ sqlite: "file:./dev.db"
872
+ };
868
873
  const content = [
869
874
  "# ========================================",
870
875
  "# Environment Variables",
@@ -884,7 +889,7 @@ async function generateEnvExample(features, config, targetPath) {
884
889
  "# ========================================",
885
890
  "# Database Configuration",
886
891
  "# ========================================",
887
- "DATABASE_URL=mysql://root:root123456@localhost:3306/{{PROJECT_NAME}}",
892
+ `DATABASE_URL=${databaseUrls[database] || databaseUrls.mysql}`,
888
893
  ""
889
894
  ];
890
895
  const featureGroups = {};
@@ -1011,7 +1016,7 @@ ${featuresList}
1011
1016
  await import_fs_extra5.default.writeFile(indexPath, content);
1012
1017
  logger.info("Generated capabilities index");
1013
1018
  }
1014
- async function copyPrismaTemplates(templateDir, targetPath) {
1019
+ async function copyPrismaTemplates(templateDir, targetPath, database = "mysql") {
1015
1020
  const prismaTemplatesDir = import_path3.default.join(templateDir, "apps/backend/prisma");
1016
1021
  const prismaDestDir = import_path3.default.join(targetPath, "apps/backend/prisma");
1017
1022
  if (await import_fs_extra5.default.pathExists(prismaTemplatesDir)) {
@@ -1022,10 +1027,13 @@ async function copyPrismaTemplates(templateDir, targetPath) {
1022
1027
  if (file.endsWith(".tpl")) {
1023
1028
  const filePath = import_path3.default.join(prismaDestDir, file);
1024
1029
  const newPath = filePath.replace(/\.tpl$/, "");
1025
- await import_fs_extra5.default.rename(filePath, newPath);
1030
+ let content = await import_fs_extra5.default.readFile(filePath, "utf-8");
1031
+ content = content.replace(/provider\s*=\s*"postgresql"/, `provider = "${database}"`);
1032
+ await import_fs_extra5.default.writeFile(newPath, content);
1033
+ await import_fs_extra5.default.remove(filePath);
1026
1034
  }
1027
1035
  }
1028
- logger.info("Copied Prisma templates");
1036
+ logger.info(`Copied Prisma templates with ${database} database`);
1029
1037
  } else {
1030
1038
  logger.warn(`Prisma templates not found: ${prismaTemplatesDir}`);
1031
1039
  }
@@ -1217,6 +1225,8 @@ async function createProject(projectName, options = {}) {
1217
1225
  answers = {
1218
1226
  org: options.org || projectName,
1219
1227
  template: options.template || "full-stack",
1228
+ database: "mysql",
1229
+ // 默认使用 MySQL
1220
1230
  features: [],
1221
1231
  // 默认不选择额外功能
1222
1232
  packageManager: options.packageManager || "pnpm",
@@ -1247,6 +1257,18 @@ async function createProject(projectName, options = {}) {
1247
1257
  ],
1248
1258
  default: options.template || "full-stack"
1249
1259
  },
1260
+ {
1261
+ type: "list",
1262
+ name: "database",
1263
+ message: "Choose a database:",
1264
+ choices: [
1265
+ { name: "MySQL", value: "mysql" },
1266
+ { name: "PostgreSQL", value: "postgresql" },
1267
+ { name: "SQLite", value: "sqlite" }
1268
+ ],
1269
+ default: "mysql",
1270
+ when: (answers2) => answers2.template === "backend-only" || answers2.template === "full-stack"
1271
+ },
1250
1272
  {
1251
1273
  type: "checkbox",
1252
1274
  name: "features",
@@ -1279,6 +1301,7 @@ async function createProject(projectName, options = {}) {
1279
1301
  projectName,
1280
1302
  orgName: answers.org.startsWith("@") ? answers.org : `@${answers.org}`,
1281
1303
  template: answers.template,
1304
+ database: answers.database || "mysql",
1282
1305
  features: answers.features || [],
1283
1306
  packageManager: answers.packageManager,
1284
1307
  installDeps: answers.installDeps,
@@ -1290,6 +1313,9 @@ async function createProject(projectName, options = {}) {
1290
1313
  logger.info(` Project Name: ${import_chalk2.default.white(config.projectName)}`);
1291
1314
  logger.info(` Organization: ${import_chalk2.default.white(config.orgName)}`);
1292
1315
  logger.info(` Template: ${import_chalk2.default.white(config.template)}`);
1316
+ if (config.template === "backend-only" || config.template === "full-stack") {
1317
+ logger.info(` Database: ${import_chalk2.default.white(config.database)}`);
1318
+ }
1293
1319
  if (config.features.length > 0) {
1294
1320
  logger.info(` Features: ${import_chalk2.default.white(config.features.join(", "))}`);
1295
1321
  }
@@ -1374,9 +1400,9 @@ async function createProjectFromTemplate(config) {
1374
1400
  await copyExampleFiles(config.features, featuresConfig, templateDir, config.projectPath);
1375
1401
  await copySkillFiles(config.features, featuresConfig, templateDir, config.projectPath);
1376
1402
  if (config.template === "backend-only" || config.template === "full-stack") {
1377
- await copyPrismaTemplates(templateDir, config.projectPath);
1403
+ await copyPrismaTemplates(templateDir, config.projectPath, config.database);
1378
1404
  }
1379
- await generateEnvExample(config.features, featuresConfig, config.projectPath);
1405
+ await generateEnvExample(config.features, featuresConfig, config.projectPath, config.database);
1380
1406
  if (config.template === "backend-only" || config.template === "full-stack") {
1381
1407
  await updateAppModule(config.features, featuresConfig, config.projectPath);
1382
1408
  }
@@ -1414,7 +1440,7 @@ async function createProjectFromTemplate(config) {
1414
1440
  }
1415
1441
 
1416
1442
  // package.json
1417
- var version = "2.0.1";
1443
+ var version = "2.2.0";
1418
1444
 
1419
1445
  // src/index.ts
1420
1446
  async function cli() {
package/dist/index.mjs CHANGED
@@ -697,11 +697,16 @@ function collectEnvVars(features, config) {
697
697
  }
698
698
  return envVars;
699
699
  }
700
- async function generateEnvExample(features, config, targetPath) {
700
+ async function generateEnvExample(features, config, targetPath, database = "mysql") {
701
701
  const envVars = collectEnvVars(features, config);
702
702
  if (envVars.length === 0) {
703
703
  return;
704
704
  }
705
+ const databaseUrls = {
706
+ mysql: "mysql://root:root123456@localhost:3306/{{PROJECT_NAME}}",
707
+ postgresql: "postgresql://postgres:postgres@localhost:5432/{{PROJECT_NAME}}",
708
+ sqlite: "file:./dev.db"
709
+ };
705
710
  const content = [
706
711
  "# ========================================",
707
712
  "# Environment Variables",
@@ -721,7 +726,7 @@ async function generateEnvExample(features, config, targetPath) {
721
726
  "# ========================================",
722
727
  "# Database Configuration",
723
728
  "# ========================================",
724
- "DATABASE_URL=mysql://root:root123456@localhost:3306/{{PROJECT_NAME}}",
729
+ `DATABASE_URL=${databaseUrls[database] || databaseUrls.mysql}`,
725
730
  ""
726
731
  ];
727
732
  const featureGroups = {};
@@ -848,7 +853,7 @@ ${featuresList}
848
853
  await fs4.writeFile(indexPath, content);
849
854
  logger.info("Generated capabilities index");
850
855
  }
851
- async function copyPrismaTemplates(templateDir, targetPath) {
856
+ async function copyPrismaTemplates(templateDir, targetPath, database = "mysql") {
852
857
  const prismaTemplatesDir = path3.join(templateDir, "apps/backend/prisma");
853
858
  const prismaDestDir = path3.join(targetPath, "apps/backend/prisma");
854
859
  if (await fs4.pathExists(prismaTemplatesDir)) {
@@ -859,10 +864,13 @@ async function copyPrismaTemplates(templateDir, targetPath) {
859
864
  if (file.endsWith(".tpl")) {
860
865
  const filePath = path3.join(prismaDestDir, file);
861
866
  const newPath = filePath.replace(/\.tpl$/, "");
862
- await fs4.rename(filePath, newPath);
867
+ let content = await fs4.readFile(filePath, "utf-8");
868
+ content = content.replace(/provider\s*=\s*"postgresql"/, `provider = "${database}"`);
869
+ await fs4.writeFile(newPath, content);
870
+ await fs4.remove(filePath);
863
871
  }
864
872
  }
865
- logger.info("Copied Prisma templates");
873
+ logger.info(`Copied Prisma templates with ${database} database`);
866
874
  } else {
867
875
  logger.warn(`Prisma templates not found: ${prismaTemplatesDir}`);
868
876
  }
@@ -1054,6 +1062,8 @@ async function createProject(projectName, options = {}) {
1054
1062
  answers = {
1055
1063
  org: options.org || projectName,
1056
1064
  template: options.template || "full-stack",
1065
+ database: "mysql",
1066
+ // 默认使用 MySQL
1057
1067
  features: [],
1058
1068
  // 默认不选择额外功能
1059
1069
  packageManager: options.packageManager || "pnpm",
@@ -1084,6 +1094,18 @@ async function createProject(projectName, options = {}) {
1084
1094
  ],
1085
1095
  default: options.template || "full-stack"
1086
1096
  },
1097
+ {
1098
+ type: "list",
1099
+ name: "database",
1100
+ message: "Choose a database:",
1101
+ choices: [
1102
+ { name: "MySQL", value: "mysql" },
1103
+ { name: "PostgreSQL", value: "postgresql" },
1104
+ { name: "SQLite", value: "sqlite" }
1105
+ ],
1106
+ default: "mysql",
1107
+ when: (answers2) => answers2.template === "backend-only" || answers2.template === "full-stack"
1108
+ },
1087
1109
  {
1088
1110
  type: "checkbox",
1089
1111
  name: "features",
@@ -1116,6 +1138,7 @@ async function createProject(projectName, options = {}) {
1116
1138
  projectName,
1117
1139
  orgName: answers.org.startsWith("@") ? answers.org : `@${answers.org}`,
1118
1140
  template: answers.template,
1141
+ database: answers.database || "mysql",
1119
1142
  features: answers.features || [],
1120
1143
  packageManager: answers.packageManager,
1121
1144
  installDeps: answers.installDeps,
@@ -1127,6 +1150,9 @@ async function createProject(projectName, options = {}) {
1127
1150
  logger.info(` Project Name: ${chalk2.white(config.projectName)}`);
1128
1151
  logger.info(` Organization: ${chalk2.white(config.orgName)}`);
1129
1152
  logger.info(` Template: ${chalk2.white(config.template)}`);
1153
+ if (config.template === "backend-only" || config.template === "full-stack") {
1154
+ logger.info(` Database: ${chalk2.white(config.database)}`);
1155
+ }
1130
1156
  if (config.features.length > 0) {
1131
1157
  logger.info(` Features: ${chalk2.white(config.features.join(", "))}`);
1132
1158
  }
@@ -1211,9 +1237,9 @@ async function createProjectFromTemplate(config) {
1211
1237
  await copyExampleFiles(config.features, featuresConfig, templateDir, config.projectPath);
1212
1238
  await copySkillFiles(config.features, featuresConfig, templateDir, config.projectPath);
1213
1239
  if (config.template === "backend-only" || config.template === "full-stack") {
1214
- await copyPrismaTemplates(templateDir, config.projectPath);
1240
+ await copyPrismaTemplates(templateDir, config.projectPath, config.database);
1215
1241
  }
1216
- await generateEnvExample(config.features, featuresConfig, config.projectPath);
1242
+ await generateEnvExample(config.features, featuresConfig, config.projectPath, config.database);
1217
1243
  if (config.template === "backend-only" || config.template === "full-stack") {
1218
1244
  await updateAppModule(config.features, featuresConfig, config.projectPath);
1219
1245
  }
@@ -1251,7 +1277,7 @@ async function createProjectFromTemplate(config) {
1251
1277
  }
1252
1278
 
1253
1279
  // package.json
1254
- var version = "2.0.1";
1280
+ var version = "2.2.0";
1255
1281
 
1256
1282
  // src/index.ts
1257
1283
  async function cli() {
package/features.json CHANGED
@@ -215,20 +215,26 @@
215
215
  },
216
216
  "storage": {
217
217
  "name": "对象存储",
218
- "description": "七牛云/阿里云 OSS",
218
+ "description": "七牛云/腾讯云 COS",
219
219
  "category": "backend",
220
220
  "packages": {
221
221
  "dependencies": {
222
222
  "@svton/nestjs-object-storage": "latest",
223
- "@svton/nestjs-object-storage-qiniu-kodo": "latest"
223
+ "@svton/nestjs-object-storage-qiniu-kodo": "latest",
224
+ "@svton/nestjs-object-storage-tencent-cos": "latest"
224
225
  }
225
226
  },
226
227
  "envVars": [
227
- { "key": "STORAGE_PROVIDER", "default": "qiniu", "description": "存储服务商 (qiniu/aliyun)" },
228
+ { "key": "STORAGE_PROVIDER", "default": "qiniu", "description": "存储服务商 (qiniu/tencent-cos)" },
228
229
  { "key": "QINIU_ACCESS_KEY", "default": "", "description": "七牛云 AccessKey" },
229
230
  { "key": "QINIU_SECRET_KEY", "default": "", "description": "七牛云 SecretKey" },
230
231
  { "key": "QINIU_BUCKET", "default": "", "description": "七牛云存储空间名称" },
231
- { "key": "QINIU_DOMAIN", "default": "", "description": "七牛云 CDN 域名" }
232
+ { "key": "QINIU_DOMAIN", "default": "", "description": "七牛云 CDN 域名" },
233
+ { "key": "COS_SECRET_ID", "default": "", "description": "腾讯云 COS SecretId" },
234
+ { "key": "COS_SECRET_KEY", "default": "", "description": "腾讯云 COS SecretKey" },
235
+ { "key": "COS_BUCKET", "default": "", "description": "腾讯云 COS 存储桶名称" },
236
+ { "key": "COS_REGION", "default": "ap-guangzhou", "description": "腾讯云 COS 地域" },
237
+ { "key": "COS_DOMAIN", "default": "", "description": "腾讯云 COS 自定义域名(可选)" }
232
238
  ],
233
239
  "configFiles": [
234
240
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svton/cli",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "description": "Svton CLI - Create full-stack applications with NestJS, Next.js, and Taro",
5
5
  "keywords": [
6
6
  "cli",