@svton/cli 1.2.0 → 1.2.2

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.
Files changed (103) hide show
  1. package/dist/index.js +20 -7
  2. package/dist/index.mjs +20 -7
  3. package/features.json +339 -0
  4. package/package.json +4 -1
  5. package/templates/apps/admin/next-env.d.ts +2 -0
  6. package/templates/apps/admin/next.config.js +15 -0
  7. package/templates/apps/admin/package.json.tpl +54 -0
  8. package/templates/apps/admin/postcss.config.js +6 -0
  9. package/templates/apps/admin/src/app/globals.css +37 -0
  10. package/templates/apps/admin/src/app/layout.tsx +19 -0
  11. package/templates/apps/admin/src/app/login/page.tsx +96 -0
  12. package/templates/apps/admin/src/app/page.tsx +8 -0
  13. package/templates/apps/admin/src/app/users/page.tsx +165 -0
  14. package/templates/apps/admin/src/components/ui/switch.tsx +29 -0
  15. package/templates/apps/admin/src/hooks/useAPI.ts +130 -0
  16. package/templates/apps/admin/src/lib/api-client.ts +112 -0
  17. package/templates/apps/admin/src/lib/api-server.ts +95 -0
  18. package/templates/apps/admin/tailwind.config.js +54 -0
  19. package/templates/apps/admin/tsconfig.json +22 -0
  20. package/templates/apps/backend/.env.example +29 -0
  21. package/templates/apps/backend/nest-cli.json +8 -0
  22. package/templates/apps/backend/package.json.tpl +57 -0
  23. package/templates/apps/backend/prisma/schema.prisma +72 -0
  24. package/templates/apps/backend/prisma/seed.ts +32 -0
  25. package/templates/apps/backend/src/app.controller.ts +15 -0
  26. package/templates/apps/backend/src/app.module.ts +85 -0
  27. package/templates/apps/backend/src/app.service.ts +12 -0
  28. package/templates/apps/backend/src/auth/auth.controller.ts +31 -0
  29. package/templates/apps/backend/src/auth/auth.module.ts +27 -0
  30. package/templates/apps/backend/src/auth/auth.service.ts +89 -0
  31. package/templates/apps/backend/src/auth/jwt-auth.guard.ts +5 -0
  32. package/templates/apps/backend/src/auth/jwt.strategy.ts +27 -0
  33. package/templates/apps/backend/src/config/env.schema.ts +35 -0
  34. package/templates/apps/backend/src/main.ts +51 -0
  35. package/templates/apps/backend/src/object-storage/object-storage.controller.ts +114 -0
  36. package/templates/apps/backend/src/object-storage/object-storage.module.ts +7 -0
  37. package/templates/apps/backend/src/prisma/prisma.module.ts +9 -0
  38. package/templates/apps/backend/src/prisma/prisma.service.ts +13 -0
  39. package/templates/apps/backend/src/user/user.controller.ts +50 -0
  40. package/templates/apps/backend/src/user/user.module.ts +12 -0
  41. package/templates/apps/backend/src/user/user.service.ts +117 -0
  42. package/templates/apps/backend/tsconfig.json +23 -0
  43. package/templates/apps/mobile/babel.config.js +8 -0
  44. package/templates/apps/mobile/config/index.ts +65 -0
  45. package/templates/apps/mobile/package.json.tpl +48 -0
  46. package/templates/apps/mobile/project.config.json.tpl +17 -0
  47. package/templates/apps/mobile/src/app.config.ts +9 -0
  48. package/templates/apps/mobile/src/app.scss +4 -0
  49. package/templates/apps/mobile/src/app.ts +8 -0
  50. package/templates/apps/mobile/src/hooks/useAPI.ts +285 -0
  51. package/templates/apps/mobile/src/pages/index/index.scss +7 -0
  52. package/templates/apps/mobile/src/pages/index/index.tsx +49 -0
  53. package/templates/apps/mobile/src/services/api.ts +155 -0
  54. package/templates/apps/mobile/src/services/upload.service.ts +41 -0
  55. package/templates/apps/mobile/tsconfig.json +21 -0
  56. package/templates/configs/authz.config.ts +10 -0
  57. package/templates/configs/cache.config.ts +14 -0
  58. package/templates/configs/oauth.config.ts +20 -0
  59. package/templates/configs/payment.config.ts +44 -0
  60. package/templates/configs/queue.config.ts +21 -0
  61. package/templates/configs/rate-limit.config.ts +16 -0
  62. package/templates/configs/sms.config.ts +11 -0
  63. package/templates/configs/storage.config.ts +14 -0
  64. package/templates/examples/README.md +258 -0
  65. package/templates/examples/authz/README.md +273 -0
  66. package/templates/examples/authz/roles.guard.ts +37 -0
  67. package/templates/examples/authz/user.controller.ts +116 -0
  68. package/templates/examples/cache/README.md +82 -0
  69. package/templates/examples/cache/user.controller.ts +42 -0
  70. package/templates/examples/cache/user.service.ts +78 -0
  71. package/templates/examples/oauth/README.md +192 -0
  72. package/templates/examples/oauth/auth.controller.ts +99 -0
  73. package/templates/examples/oauth/auth.service.ts +97 -0
  74. package/templates/examples/payment/README.md +151 -0
  75. package/templates/examples/payment/order.controller.ts +56 -0
  76. package/templates/examples/payment/order.service.ts +132 -0
  77. package/templates/examples/payment/webhook.controller.ts +73 -0
  78. package/templates/examples/queue/README.md +134 -0
  79. package/templates/examples/queue/email.controller.ts +34 -0
  80. package/templates/examples/queue/email.processor.ts +68 -0
  81. package/templates/examples/queue/email.service.ts +64 -0
  82. package/templates/examples/rate-limit/README.md +249 -0
  83. package/templates/examples/rate-limit/api.controller.ts +113 -0
  84. package/templates/examples/sms/README.md +121 -0
  85. package/templates/examples/sms/sms.service.ts +69 -0
  86. package/templates/examples/sms/verification.controller.ts +100 -0
  87. package/templates/examples/storage/README.md +224 -0
  88. package/templates/examples/storage/upload.controller.ts +117 -0
  89. package/templates/examples/storage/upload.service.ts +123 -0
  90. package/templates/packages/types/package.json.tpl +16 -0
  91. package/templates/packages/types/src/api.ts +88 -0
  92. package/templates/packages/types/src/common.ts +89 -0
  93. package/templates/packages/types/src/index.ts +3 -0
  94. package/templates/packages/types/tsconfig.json +16 -0
  95. package/templates/skills/authz.skill.md +42 -0
  96. package/templates/skills/base.skill.md +57 -0
  97. package/templates/skills/cache.skill.md +88 -0
  98. package/templates/skills/oauth.skill.md +41 -0
  99. package/templates/skills/payment.skill.md +129 -0
  100. package/templates/skills/queue.skill.md +140 -0
  101. package/templates/skills/rate-limit.skill.md +38 -0
  102. package/templates/skills/sms.skill.md +39 -0
  103. package/templates/skills/storage.skill.md +42 -0
package/dist/index.js CHANGED
@@ -132,11 +132,18 @@ async function copyTemplateFiles(config) {
132
132
  let templateDir = null;
133
133
  let needCleanup = false;
134
134
  const cliPackageRoot = import_path2.default.dirname(__dirname);
135
- const frameworkRoot = import_path2.default.dirname(import_path2.default.dirname(cliPackageRoot));
136
- const localTemplateDir = import_path2.default.join(frameworkRoot, "templates");
137
- if (await import_fs_extra2.default.pathExists(localTemplateDir)) {
138
- templateDir = localTemplateDir;
139
- logger.debug(`Using local template directory: ${templateDir}`);
135
+ const packagedTemplateDir = import_path2.default.join(cliPackageRoot, "../templates");
136
+ if (await import_fs_extra2.default.pathExists(packagedTemplateDir)) {
137
+ templateDir = packagedTemplateDir;
138
+ logger.debug(`Using packaged template directory: ${templateDir}`);
139
+ }
140
+ if (!templateDir) {
141
+ const frameworkRoot = import_path2.default.dirname(import_path2.default.dirname(cliPackageRoot));
142
+ const localTemplateDir = import_path2.default.join(frameworkRoot, "templates");
143
+ if (await import_fs_extra2.default.pathExists(localTemplateDir)) {
144
+ templateDir = localTemplateDir;
145
+ logger.debug(`Using local template directory: ${templateDir}`);
146
+ }
140
147
  }
141
148
  if (!templateDir) {
142
149
  logger.info("Downloading templates from GitHub...");
@@ -685,7 +692,13 @@ async function initGit(projectName) {
685
692
  var import_fs_extra4 = __toESM(require("fs-extra"));
686
693
  var import_path3 = __toESM(require("path"));
687
694
  async function loadFeaturesConfig() {
688
- const configPath = import_path3.default.join(__dirname, "../../features.json");
695
+ const configPath = import_path3.default.join(__dirname, "../features.json");
696
+ if (!import_fs_extra4.default.existsSync(configPath)) {
697
+ const devPath = import_path3.default.join(__dirname, "../../features.json");
698
+ if (import_fs_extra4.default.existsSync(devPath)) {
699
+ return await import_fs_extra4.default.readJSON(devPath);
700
+ }
701
+ }
689
702
  return await import_fs_extra4.default.readJSON(configPath);
690
703
  }
691
704
  function getFeatureChoices(config) {
@@ -1071,7 +1084,7 @@ async function createProjectFromTemplate(config) {
1071
1084
  }
1072
1085
 
1073
1086
  // package.json
1074
- var version = "1.2.0";
1087
+ var version = "1.2.2";
1075
1088
 
1076
1089
  // src/index.ts
1077
1090
  async function cli() {
package/dist/index.mjs CHANGED
@@ -105,11 +105,18 @@ async function copyTemplateFiles(config) {
105
105
  let templateDir = null;
106
106
  let needCleanup = false;
107
107
  const cliPackageRoot = path2.dirname(__dirname);
108
- const frameworkRoot = path2.dirname(path2.dirname(cliPackageRoot));
109
- const localTemplateDir = path2.join(frameworkRoot, "templates");
110
- if (await fs2.pathExists(localTemplateDir)) {
111
- templateDir = localTemplateDir;
112
- logger.debug(`Using local template directory: ${templateDir}`);
108
+ const packagedTemplateDir = path2.join(cliPackageRoot, "../templates");
109
+ if (await fs2.pathExists(packagedTemplateDir)) {
110
+ templateDir = packagedTemplateDir;
111
+ logger.debug(`Using packaged template directory: ${templateDir}`);
112
+ }
113
+ if (!templateDir) {
114
+ const frameworkRoot = path2.dirname(path2.dirname(cliPackageRoot));
115
+ const localTemplateDir = path2.join(frameworkRoot, "templates");
116
+ if (await fs2.pathExists(localTemplateDir)) {
117
+ templateDir = localTemplateDir;
118
+ logger.debug(`Using local template directory: ${templateDir}`);
119
+ }
113
120
  }
114
121
  if (!templateDir) {
115
122
  logger.info("Downloading templates from GitHub...");
@@ -658,7 +665,13 @@ async function initGit(projectName) {
658
665
  import fs4 from "fs-extra";
659
666
  import path3 from "path";
660
667
  async function loadFeaturesConfig() {
661
- const configPath = path3.join(__dirname, "../../features.json");
668
+ const configPath = path3.join(__dirname, "../features.json");
669
+ if (!fs4.existsSync(configPath)) {
670
+ const devPath = path3.join(__dirname, "../../features.json");
671
+ if (fs4.existsSync(devPath)) {
672
+ return await fs4.readJSON(devPath);
673
+ }
674
+ }
662
675
  return await fs4.readJSON(configPath);
663
676
  }
664
677
  function getFeatureChoices(config) {
@@ -1044,7 +1057,7 @@ async function createProjectFromTemplate(config) {
1044
1057
  }
1045
1058
 
1046
1059
  // package.json
1047
- var version = "1.2.0";
1060
+ var version = "1.2.2";
1048
1061
 
1049
1062
  // src/index.ts
1050
1063
  async function cli() {
package/features.json ADDED
@@ -0,0 +1,339 @@
1
+ {
2
+ "features": {
3
+ "cache": {
4
+ "name": "缓存",
5
+ "description": "基于 Redis 的声明式缓存",
6
+ "category": "backend",
7
+ "packages": {
8
+ "dependencies": {
9
+ "@svton/nestjs-cache": "latest",
10
+ "@svton/nestjs-redis": "latest"
11
+ }
12
+ },
13
+ "envVars": [
14
+ { "key": "REDIS_HOST", "default": "localhost", "description": "Redis 主机地址" },
15
+ { "key": "REDIS_PORT", "default": "6379", "description": "Redis 端口" },
16
+ { "key": "REDIS_PASSWORD", "default": "", "description": "Redis 密码(可选)" }
17
+ ],
18
+ "configFiles": [
19
+ {
20
+ "path": "src/config/cache.config.ts",
21
+ "template": "configs/cache.config.ts"
22
+ }
23
+ ],
24
+ "moduleImports": [
25
+ {
26
+ "from": "@svton/nestjs-cache",
27
+ "import": "CacheModule"
28
+ }
29
+ ],
30
+ "moduleRegistration": {
31
+ "type": "forRootAsync",
32
+ "module": "CacheModule",
33
+ "config": "useCacheConfig(configService)"
34
+ },
35
+ "exampleFiles": {
36
+ "source": "examples/cache",
37
+ "target": "src/examples/cache",
38
+ "description": "缓存装饰器使用示例"
39
+ },
40
+ "skillFile": {
41
+ "template": "skills/cache.skill.md",
42
+ "target": ".kiro/skills/cache.md"
43
+ }
44
+ },
45
+ "queue": {
46
+ "name": "消息队列",
47
+ "description": "基于 BullMQ 的异步任务处理",
48
+ "category": "backend",
49
+ "packages": {
50
+ "dependencies": {
51
+ "@svton/nestjs-queue": "latest",
52
+ "@svton/nestjs-redis": "latest"
53
+ }
54
+ },
55
+ "envVars": [
56
+ { "key": "REDIS_HOST", "default": "localhost", "description": "Redis 主机地址" },
57
+ { "key": "REDIS_PORT", "default": "6379", "description": "Redis 端口" }
58
+ ],
59
+ "configFiles": [
60
+ {
61
+ "path": "src/config/queue.config.ts",
62
+ "template": "configs/queue.config.ts"
63
+ }
64
+ ],
65
+ "moduleImports": [
66
+ {
67
+ "from": "@svton/nestjs-queue",
68
+ "import": "QueueModule"
69
+ }
70
+ ],
71
+ "moduleRegistration": {
72
+ "type": "forRootAsync",
73
+ "module": "QueueModule",
74
+ "config": "useQueueConfig(configService)"
75
+ },
76
+ "exampleFiles": {
77
+ "source": "examples/queue",
78
+ "target": "src/examples/queue",
79
+ "description": "队列任务处理示例"
80
+ },
81
+ "skillFile": {
82
+ "template": "skills/queue.skill.md",
83
+ "target": ".kiro/skills/queue.md"
84
+ }
85
+ },
86
+ "payment": {
87
+ "name": "支付",
88
+ "description": "微信支付 + 支付宝",
89
+ "category": "backend",
90
+ "packages": {
91
+ "dependencies": {
92
+ "@svton/nestjs-payment": "latest"
93
+ }
94
+ },
95
+ "envVars": [
96
+ { "key": "WECHAT_MCH_ID", "default": "", "description": "微信商户号" },
97
+ { "key": "WECHAT_PRIVATE_KEY", "default": "", "description": "微信商户 API 私钥路径" },
98
+ { "key": "WECHAT_SERIAL_NO", "default": "", "description": "微信商户 API 证书序列号" },
99
+ { "key": "WECHAT_API_V3_KEY", "default": "", "description": "微信 APIv3 密钥" },
100
+ { "key": "WECHAT_APP_ID", "default": "", "description": "微信关联的 AppID" },
101
+ { "key": "ALIPAY_APP_ID", "default": "", "description": "支付宝应用 ID" },
102
+ { "key": "ALIPAY_PRIVATE_KEY", "default": "", "description": "支付宝应用私钥路径" },
103
+ { "key": "ALIPAY_PUBLIC_KEY", "default": "", "description": "支付宝公钥路径" }
104
+ ],
105
+ "configFiles": [
106
+ {
107
+ "path": "src/config/payment.config.ts",
108
+ "template": "configs/payment.config.ts"
109
+ }
110
+ ],
111
+ "moduleImports": [
112
+ {
113
+ "from": "@svton/nestjs-payment",
114
+ "import": "PaymentModule"
115
+ }
116
+ ],
117
+ "moduleRegistration": {
118
+ "type": "forRootAsync",
119
+ "module": "PaymentModule",
120
+ "config": "usePaymentConfig(configService)"
121
+ },
122
+ "exampleFiles": {
123
+ "source": "examples/payment",
124
+ "target": "src/examples/payment",
125
+ "description": "支付功能示例(微信/支付宝)"
126
+ },
127
+ "skillFile": {
128
+ "template": "skills/payment.skill.md",
129
+ "target": ".kiro/skills/payment.md"
130
+ }
131
+ },
132
+ "oauth": {
133
+ "name": "OAuth 登录",
134
+ "description": "微信登录(开放平台/公众号/小程序)",
135
+ "category": "backend",
136
+ "packages": {
137
+ "dependencies": {
138
+ "@svton/nestjs-oauth": "latest"
139
+ }
140
+ },
141
+ "envVars": [
142
+ { "key": "WECHAT_OPEN_APP_ID", "default": "", "description": "微信开放平台 AppID" },
143
+ { "key": "WECHAT_OPEN_APP_SECRET", "default": "", "description": "微信开放平台 AppSecret" },
144
+ { "key": "WECHAT_MINI_APP_ID", "default": "", "description": "微信小程序 AppID" },
145
+ { "key": "WECHAT_MINI_APP_SECRET", "default": "", "description": "微信小程序 AppSecret" }
146
+ ],
147
+ "configFiles": [
148
+ {
149
+ "path": "src/config/oauth.config.ts",
150
+ "template": "configs/oauth.config.ts"
151
+ }
152
+ ],
153
+ "moduleImports": [
154
+ {
155
+ "from": "@svton/nestjs-oauth",
156
+ "import": "OAuthModule"
157
+ }
158
+ ],
159
+ "moduleRegistration": {
160
+ "type": "forRootAsync",
161
+ "module": "OAuthModule",
162
+ "config": "useOAuthConfig(configService)"
163
+ },
164
+ "exampleFiles": {
165
+ "source": "examples/oauth",
166
+ "target": "src/examples/oauth",
167
+ "description": "OAuth 登录示例"
168
+ },
169
+ "skillFile": {
170
+ "template": "skills/oauth.skill.md",
171
+ "target": ".kiro/skills/oauth.md"
172
+ }
173
+ },
174
+ "sms": {
175
+ "name": "短信",
176
+ "description": "阿里云/腾讯云短信发送",
177
+ "category": "backend",
178
+ "packages": {
179
+ "dependencies": {
180
+ "@svton/nestjs-sms": "latest"
181
+ }
182
+ },
183
+ "envVars": [
184
+ { "key": "SMS_PROVIDER", "default": "aliyun", "description": "短信服务商 (aliyun/tencent)" },
185
+ { "key": "SMS_ACCESS_KEY_ID", "default": "", "description": "AccessKey ID" },
186
+ { "key": "SMS_ACCESS_KEY_SECRET", "default": "", "description": "AccessKey Secret" },
187
+ { "key": "SMS_SIGN_NAME", "default": "", "description": "短信签名" }
188
+ ],
189
+ "configFiles": [
190
+ {
191
+ "path": "src/config/sms.config.ts",
192
+ "template": "configs/sms.config.ts"
193
+ }
194
+ ],
195
+ "moduleImports": [
196
+ {
197
+ "from": "@svton/nestjs-sms",
198
+ "import": "SmsModule"
199
+ }
200
+ ],
201
+ "moduleRegistration": {
202
+ "type": "forRootAsync",
203
+ "module": "SmsModule",
204
+ "config": "useSmsConfig(configService)"
205
+ },
206
+ "exampleFiles": {
207
+ "source": "examples/sms",
208
+ "target": "src/examples/sms",
209
+ "description": "短信发送示例"
210
+ },
211
+ "skillFile": {
212
+ "template": "skills/sms.skill.md",
213
+ "target": ".kiro/skills/sms.md"
214
+ }
215
+ },
216
+ "storage": {
217
+ "name": "对象存储",
218
+ "description": "七牛云/阿里云 OSS",
219
+ "category": "backend",
220
+ "packages": {
221
+ "dependencies": {
222
+ "@svton/nestjs-object-storage": "latest",
223
+ "@svton/nestjs-object-storage-qiniu-kodo": "latest"
224
+ }
225
+ },
226
+ "envVars": [
227
+ { "key": "STORAGE_PROVIDER", "default": "qiniu", "description": "存储服务商 (qiniu/aliyun)" },
228
+ { "key": "QINIU_ACCESS_KEY", "default": "", "description": "七牛云 AccessKey" },
229
+ { "key": "QINIU_SECRET_KEY", "default": "", "description": "七牛云 SecretKey" },
230
+ { "key": "QINIU_BUCKET", "default": "", "description": "七牛云存储空间名称" },
231
+ { "key": "QINIU_DOMAIN", "default": "", "description": "七牛云 CDN 域名" }
232
+ ],
233
+ "configFiles": [
234
+ {
235
+ "path": "src/config/storage.config.ts",
236
+ "template": "configs/storage.config.ts"
237
+ }
238
+ ],
239
+ "moduleImports": [
240
+ {
241
+ "from": "@svton/nestjs-object-storage",
242
+ "import": "ObjectStorageModule"
243
+ }
244
+ ],
245
+ "moduleRegistration": {
246
+ "type": "forRootAsync",
247
+ "module": "ObjectStorageModule",
248
+ "config": "useStorageConfig(configService)"
249
+ },
250
+ "exampleFiles": {
251
+ "source": "examples/storage",
252
+ "target": "src/examples/storage",
253
+ "description": "文件上传示例"
254
+ },
255
+ "skillFile": {
256
+ "template": "skills/storage.skill.md",
257
+ "target": ".kiro/skills/storage.md"
258
+ }
259
+ },
260
+ "rateLimit": {
261
+ "name": "限流",
262
+ "description": "接口访问频率限制",
263
+ "category": "backend",
264
+ "packages": {
265
+ "dependencies": {
266
+ "@svton/nestjs-rate-limit": "latest",
267
+ "@svton/nestjs-redis": "latest"
268
+ }
269
+ },
270
+ "envVars": [
271
+ { "key": "REDIS_HOST", "default": "localhost", "description": "Redis 主机地址" },
272
+ { "key": "REDIS_PORT", "default": "6379", "description": "Redis 端口" }
273
+ ],
274
+ "configFiles": [
275
+ {
276
+ "path": "src/config/rate-limit.config.ts",
277
+ "template": "configs/rate-limit.config.ts"
278
+ }
279
+ ],
280
+ "moduleImports": [
281
+ {
282
+ "from": "@svton/nestjs-rate-limit",
283
+ "import": "RateLimitModule"
284
+ }
285
+ ],
286
+ "moduleRegistration": {
287
+ "type": "forRootAsync",
288
+ "module": "RateLimitModule",
289
+ "config": "useRateLimitConfig(configService)"
290
+ },
291
+ "exampleFiles": {
292
+ "source": "examples/rate-limit",
293
+ "target": "src/examples/rate-limit",
294
+ "description": "限流使用示例"
295
+ },
296
+ "skillFile": {
297
+ "template": "skills/rate-limit.skill.md",
298
+ "target": ".kiro/skills/rate-limit.md"
299
+ }
300
+ },
301
+ "authz": {
302
+ "name": "权限控制",
303
+ "description": "RBAC 权限管理",
304
+ "category": "backend",
305
+ "packages": {
306
+ "dependencies": {
307
+ "@svton/nestjs-authz": "latest"
308
+ }
309
+ },
310
+ "envVars": [],
311
+ "configFiles": [
312
+ {
313
+ "path": "src/config/authz.config.ts",
314
+ "template": "configs/authz.config.ts"
315
+ }
316
+ ],
317
+ "moduleImports": [
318
+ {
319
+ "from": "@svton/nestjs-authz",
320
+ "import": "AuthzModule"
321
+ }
322
+ ],
323
+ "moduleRegistration": {
324
+ "type": "forRootAsync",
325
+ "module": "AuthzModule",
326
+ "config": "useAuthzConfig(configService)"
327
+ },
328
+ "exampleFiles": {
329
+ "source": "examples/authz",
330
+ "target": "src/examples/authz",
331
+ "description": "权限控制示例"
332
+ },
333
+ "skillFile": {
334
+ "template": "skills/authz.skill.md",
335
+ "target": ".kiro/skills/authz.md"
336
+ }
337
+ }
338
+ }
339
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svton/cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Svton CLI - Create full-stack applications with NestJS, Next.js, and Taro",
5
5
  "keywords": [
6
6
  "cli",
@@ -30,10 +30,13 @@
30
30
  "files": [
31
31
  "dist",
32
32
  "bin",
33
+ "features.json",
34
+ "templates",
33
35
  "README.md",
34
36
  "LICENSE"
35
37
  ],
36
38
  "scripts": {
39
+ "prebuild": "node scripts/copy-templates.js",
37
40
  "build": "tsup src/index.ts --format cjs,esm --dts",
38
41
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
39
42
  "type-check": "tsc --noEmit",
@@ -0,0 +1,2 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
@@ -0,0 +1,15 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true,
4
+ transpilePackages: ['@svton/hooks'],
5
+ images: {
6
+ remotePatterns: [
7
+ {
8
+ protocol: 'https',
9
+ hostname: '**',
10
+ },
11
+ ],
12
+ },
13
+ };
14
+
15
+ module.exports = nextConfig;
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "{{ORG_NAME}}/admin",
3
+ "version": "1.0.0",
4
+ "description": "{{PROJECT_NAME}} 管理后台",
5
+ "scripts": {
6
+ "dev": "next dev -p 3001",
7
+ "build": "next build",
8
+ "start": "next start -p 3001",
9
+ "lint": "next lint",
10
+ "type-check": "tsc --noEmit",
11
+ "clean": "rm -rf .next"
12
+ },
13
+ "dependencies": {
14
+ "@hookform/resolvers": "^3.3.3",
15
+ "@radix-ui/react-avatar": "^1.0.4",
16
+ "@radix-ui/react-dialog": "^1.0.5",
17
+ "@radix-ui/react-dropdown-menu": "^2.0.6",
18
+ "@radix-ui/react-label": "^2.0.2",
19
+ "@radix-ui/react-select": "^2.0.0",
20
+ "@radix-ui/react-separator": "^1.0.3",
21
+ "@radix-ui/react-slot": "^1.0.2",
22
+ "@radix-ui/react-switch": "^1.2.6",
23
+ "@radix-ui/react-tabs": "^1.0.4",
24
+ "@radix-ui/react-toast": "^1.1.5",
25
+ "@svton/api-client": "^1.0.0",
26
+ "@svton/hooks": "^1.0.0",
27
+ "{{ORG_NAME}}/types": "workspace:*",
28
+ "axios": "^1.7.9",
29
+ "class-variance-authority": "^0.7.1",
30
+ "clsx": "^2.1.1",
31
+ "dayjs": "^1.11.13",
32
+ "lucide-react": "^0.462.0",
33
+ "next": "^15.0.0",
34
+ "react": "^19.0.0",
35
+ "react-dom": "^19.0.0",
36
+ "react-hook-form": "^7.49.0",
37
+ "swr": "^2.2.5",
38
+ "tailwind-merge": "^3.0.0",
39
+ "zod": "^3.22.4",
40
+ "zustand": "^5.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^22.0.0",
44
+ "@types/react": "^19.0.0",
45
+ "@types/react-dom": "^19.0.0",
46
+ "autoprefixer": "^10.4.22",
47
+ "eslint": "^9.0.0",
48
+ "eslint-config-next": "^15.0.0",
49
+ "postcss": "^8.5.0",
50
+ "tailwindcss": "^3.4.0",
51
+ "tailwindcss-animate": "^1.0.7",
52
+ "typescript": "^5.7.0"
53
+ }
54
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -0,0 +1,37 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 100%;
8
+ --foreground: 222.2 84% 4.9%;
9
+ --card: 0 0% 100%;
10
+ --card-foreground: 222.2 84% 4.9%;
11
+ --popover: 0 0% 100%;
12
+ --popover-foreground: 222.2 84% 4.9%;
13
+ --primary: 222.2 47.4% 11.2%;
14
+ --primary-foreground: 210 40% 98%;
15
+ --secondary: 210 40% 96.1%;
16
+ --secondary-foreground: 222.2 47.4% 11.2%;
17
+ --muted: 210 40% 96.1%;
18
+ --muted-foreground: 215.4 16.3% 46.9%;
19
+ --accent: 210 40% 96.1%;
20
+ --accent-foreground: 222.2 47.4% 11.2%;
21
+ --destructive: 0 84.2% 60.2%;
22
+ --destructive-foreground: 210 40% 98%;
23
+ --border: 214.3 31.8% 91.4%;
24
+ --input: 214.3 31.8% 91.4%;
25
+ --ring: 222.2 84% 4.9%;
26
+ --radius: 0.5rem;
27
+ }
28
+ }
29
+
30
+ @layer base {
31
+ * {
32
+ @apply border-border;
33
+ }
34
+ body {
35
+ @apply bg-background text-foreground;
36
+ }
37
+ }
@@ -0,0 +1,19 @@
1
+ import type { Metadata } from 'next';
2
+ import './globals.css';
3
+
4
+ export const metadata: Metadata = {
5
+ title: '管理后台',
6
+ description: '项目管理后台',
7
+ };
8
+
9
+ export default function RootLayout({
10
+ children,
11
+ }: {
12
+ children: React.ReactNode;
13
+ }) {
14
+ return (
15
+ <html lang="zh-CN">
16
+ <body>{children}</body>
17
+ </html>
18
+ );
19
+ }