@fastcar/cli 0.0.7 → 0.1.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/README.md +259 -21
- package/bin/cli.js +202 -32
- package/package.json +3 -3
- package/skills/fastcar-database/SKILL.md +374 -0
- package/skills/fastcar-framework/SKILL.md +661 -0
- package/skills/fastcar-framework/assets/project-template/package.json +24 -0
- package/skills/fastcar-framework/assets/project-template/resource/application.yml +14 -0
- package/skills/fastcar-framework/assets/project-template/src/app.ts +18 -0
- package/skills/fastcar-framework/assets/project-template/src/component/StartupRunner.ts +15 -0
- package/skills/fastcar-framework/assets/project-template/src/controller/HelloController.ts +21 -0
- package/skills/fastcar-framework/assets/project-template/src/service/HelloService.ts +12 -0
- package/skills/fastcar-framework/assets/project-template/tsconfig.json +21 -0
- package/skills/fastcar-framework/references/api-reference.md +353 -0
- package/skills/fastcar-rpc-microservices/SKILL.md +311 -0
- package/skills/fastcar-serverless/SKILL.md +211 -0
- package/skills/fastcar-toolkit/SKILL.md +282 -0
- package/src/init.js +615 -201
- package/src/pack.js +204 -0
- package/src/reverse.js +204 -0
- package/src/skill-targets.js +74 -0
- package/src/skill.js +362 -0
- package/src/templates.json +32 -0
- package/src/utils.js +51 -66
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Component } from "@fastcar/core/annotation";
|
|
2
|
+
import { ApplicationStart, ApplicationStop } from "@fastcar/core/annotation";
|
|
3
|
+
|
|
4
|
+
@Component
|
|
5
|
+
export default class StartupRunner {
|
|
6
|
+
@ApplicationStart(100)
|
|
7
|
+
async onStart() {
|
|
8
|
+
console.log("🚀 应用初始化完成");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@ApplicationStop
|
|
12
|
+
async onStop() {
|
|
13
|
+
console.log("👋 应用正在关闭...");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Controller, Autowired } from "@fastcar/core/annotation";
|
|
2
|
+
import { GET, REQUEST } from "@fastcar/koa/annotation";
|
|
3
|
+
import HelloService from "../service/HelloService";
|
|
4
|
+
|
|
5
|
+
@Controller
|
|
6
|
+
@REQUEST("/hello")
|
|
7
|
+
export default class HelloController {
|
|
8
|
+
@Autowired
|
|
9
|
+
private helloService!: HelloService;
|
|
10
|
+
|
|
11
|
+
@GET
|
|
12
|
+
async index() {
|
|
13
|
+
const message = this.helloService.sayHello("FastCar");
|
|
14
|
+
return { message, timestamp: new Date().toISOString() };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@GET("/health")
|
|
18
|
+
async health() {
|
|
19
|
+
return { status: "ok", uptime: process.uptime() };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Service } from "@fastcar/core/annotation";
|
|
2
|
+
|
|
3
|
+
@Service
|
|
4
|
+
export default class HelloService {
|
|
5
|
+
sayHello(name: string): string {
|
|
6
|
+
return `Hello, ${name}! Welcome to FastCar.`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
getCurrentTime(): string {
|
|
10
|
+
return new Date().toLocaleString("zh-CN");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"experimentalDecorators": true,
|
|
13
|
+
"emitDecoratorMetadata": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"declaration": true,
|
|
16
|
+
"declarationMap": true,
|
|
17
|
+
"sourceMap": true
|
|
18
|
+
},
|
|
19
|
+
"include": ["src/**/*"],
|
|
20
|
+
"exclude": ["node_modules", "dist"]
|
|
21
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# FastCar API 参考
|
|
2
|
+
|
|
3
|
+
## @fastcar/core
|
|
4
|
+
|
|
5
|
+
### 核心装饰器
|
|
6
|
+
|
|
7
|
+
#### @Application
|
|
8
|
+
标记应用入口类。
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
@Application
|
|
12
|
+
class App {
|
|
13
|
+
app!: FastCarApplication;
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
#### @Component / @Service / @Controller / @Repository
|
|
18
|
+
标记可注入组件。
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
@Component // 通用组件
|
|
22
|
+
@Service // 服务层
|
|
23
|
+
@Controller // 控制器
|
|
24
|
+
@Repository // 数据访问层
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
#### @Autowired
|
|
28
|
+
依赖注入。
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
@Autowired
|
|
32
|
+
private service!: MyService;
|
|
33
|
+
|
|
34
|
+
// 指定名称注入
|
|
35
|
+
@Autowired
|
|
36
|
+
@BeanName("UserService")
|
|
37
|
+
private userService!: UserService;
|
|
38
|
+
|
|
39
|
+
// 别名注入
|
|
40
|
+
@AliasInjection("cache")
|
|
41
|
+
private cacheService!: CacheService;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### @Configure
|
|
45
|
+
配置类映射。
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
@Configure("database.yml")
|
|
49
|
+
class DatabaseConfig {
|
|
50
|
+
host!: string;
|
|
51
|
+
port!: number;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### @Value
|
|
56
|
+
获取配置值。
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
@Value("server.port")
|
|
60
|
+
port!: number;
|
|
61
|
+
|
|
62
|
+
@Value("app.name", "default-name") // 带默认值
|
|
63
|
+
appName!: string;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 生命周期装饰器
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
@ApplicationStart(order?) // 启动时执行,order 越小优先级越高
|
|
70
|
+
@ApplicationStop(order?) // 停止前执行
|
|
71
|
+
@ApplicationInit(order?) // 初始化方法
|
|
72
|
+
@ApplicationDestory(order?) // 销毁方法
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 验证装饰器
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
@ValidForm // 开启方法参数校验
|
|
79
|
+
@Rule(rules?) // 校验规则配置
|
|
80
|
+
@NotNull // 参数不能为空
|
|
81
|
+
@Size({minSize?, maxSize?}) // 大小限制
|
|
82
|
+
@Type(type) // 指定参数类型
|
|
83
|
+
@DefaultVal(val) // 设置默认值
|
|
84
|
+
@ValidCustom(fn, msg?) // 自定义校验
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## @fastcar/koa
|
|
90
|
+
|
|
91
|
+
### 路由装饰器
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
@Get(path?) // GET 请求
|
|
95
|
+
@Post(path?) // POST 请求
|
|
96
|
+
@Put(path?) // PUT 请求
|
|
97
|
+
@Delete(path?) // DELETE 请求
|
|
98
|
+
@Patch(path?) // PATCH 请求
|
|
99
|
+
@RequestMapping(path) // 通用路由
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 参数装饰器
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
@Param(name) // URL 参数 /:id
|
|
106
|
+
@Query(name?) // 查询参数 ?key=value
|
|
107
|
+
@Body // 请求体
|
|
108
|
+
@Header(name?) // 请求头
|
|
109
|
+
@Ctx // Koa Context
|
|
110
|
+
@Request // 请求对象
|
|
111
|
+
@Response // 响应对象
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 示例
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
@Controller
|
|
118
|
+
@RequestMapping("/api/users")
|
|
119
|
+
class UserController {
|
|
120
|
+
@Get
|
|
121
|
+
async list(@Query("page") page: number = 1) {
|
|
122
|
+
return { page, data: [] };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@Get("/:id")
|
|
126
|
+
async get(@Param("id") id: string) {
|
|
127
|
+
return { id };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@Post
|
|
131
|
+
async create(@Body user: UserDTO) {
|
|
132
|
+
return { created: user };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## @fastcar/mysql
|
|
140
|
+
|
|
141
|
+
### 实体装饰器
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
@Table(name) // 映射表名
|
|
145
|
+
@Field(name) // 映射字段
|
|
146
|
+
@PrimaryKey // 主键标记
|
|
147
|
+
@IsSerial // 自增字段
|
|
148
|
+
@DBType(type) // 数据库类型
|
|
149
|
+
@DS(name) // 指定数据源
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Repository 装饰器
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
@Repository
|
|
156
|
+
class UserRepository {
|
|
157
|
+
@SqlSession
|
|
158
|
+
private session!: SqlSession;
|
|
159
|
+
|
|
160
|
+
// 基础 CRUD
|
|
161
|
+
async findById(id: number) {
|
|
162
|
+
return this.session.findById(User, id);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async findAll() {
|
|
166
|
+
return this.session.findAll(User);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async save(entity: User) {
|
|
170
|
+
return this.session.save(User, entity);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async update(entity: User) {
|
|
174
|
+
return this.session.update(User, entity);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async deleteById(id: number) {
|
|
178
|
+
return this.session.deleteById(User, id);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 自定义查询
|
|
182
|
+
async findByName(name: string) {
|
|
183
|
+
return this.session.query(`SELECT * FROM users WHERE name = ?`, [name]);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 事务
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
@Transactional
|
|
192
|
+
try {
|
|
193
|
+
await userRepository.save(user);
|
|
194
|
+
await orderRepository.save(order);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
// 自动回滚
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## @fastcar/redis
|
|
203
|
+
|
|
204
|
+
### 装饰器
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
@RedisClient // 注入 Redis 客户端
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 使用示例
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
@Service
|
|
214
|
+
class CacheService {
|
|
215
|
+
@RedisClient
|
|
216
|
+
private redis!: RedisClient;
|
|
217
|
+
|
|
218
|
+
async get(key: string) {
|
|
219
|
+
return this.redis.get(key);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async set(key: string, value: string, ttl?: number) {
|
|
223
|
+
await this.redis.set(key, value, ttl);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async del(key: string) {
|
|
227
|
+
await this.redis.del(key);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async expire(key: string, seconds: number) {
|
|
231
|
+
await this.redis.expire(key, seconds);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## @fastcar/timer
|
|
239
|
+
|
|
240
|
+
### 装饰器
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
@Scheduled(interval) // 间隔执行(毫秒)
|
|
244
|
+
@Cron(expression) // Cron 表达式
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Cron 表达式
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// 格式: 秒 分 时 日 月 周
|
|
251
|
+
@Cron("0 */5 * * * *") // 每 5 分钟
|
|
252
|
+
@Cron("0 0 * * * *") // 每小时
|
|
253
|
+
@Cron("0 0 0 * * *") // 每天 0 点
|
|
254
|
+
@Cron("0 0 9 * * MON") // 每周一 9 点
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## @fastcar/workerpool
|
|
260
|
+
|
|
261
|
+
### 装饰器
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
@WorkerPool(options) // 工作线程池
|
|
265
|
+
@WorkerTask // 标记为 Worker 任务
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 使用示例
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
@Component
|
|
272
|
+
class ComputeService {
|
|
273
|
+
@WorkerPool({ minWorkers: 2, maxWorkers: 4 })
|
|
274
|
+
private pool!: WorkerPool;
|
|
275
|
+
|
|
276
|
+
@WorkerTask
|
|
277
|
+
fibonacci(n: number): number {
|
|
278
|
+
if (n < 2) return n;
|
|
279
|
+
return this.fibonacci(n - 1) + this.fibonacci(n - 2);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async compute(data: number[]) {
|
|
283
|
+
return this.pool.execute(this.fibonacci, data);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## 工具类
|
|
291
|
+
|
|
292
|
+
### DateUtil
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
DateUtil.toDateTime(); // "2024-03-10 15:30:45"
|
|
296
|
+
DateUtil.toDay(); // "2024-03-10"
|
|
297
|
+
DateUtil.toHms(); // "15:30:45"
|
|
298
|
+
DateUtil.toDateTimeMS(); // "2024-03-10 15:30:45.123"
|
|
299
|
+
DateUtil.toCutDown(3665); // "1:1:5" (倒计时)
|
|
300
|
+
DateUtil.getTimeStr(3600000); // "1.00h"
|
|
301
|
+
DateUtil.getDateTime("2024-03-10"); // 时间戳
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### CryptoUtil
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
CryptoUtil.aesEncode(key, iv, data); // AES 加密
|
|
308
|
+
CryptoUtil.aesDecode(key, iv, encrypted); // AES 解密
|
|
309
|
+
CryptoUtil.shaEncode(key, data); // SHA HMAC
|
|
310
|
+
CryptoUtil.gcmEncrypt(password, message); // AES-GCM 加密
|
|
311
|
+
CryptoUtil.gcmDecrypt(password, encrypted); // AES-GCM 解密
|
|
312
|
+
CryptoUtil.sha256Encode(password); // SHA256 + Salt
|
|
313
|
+
CryptoUtil.sha256Very(password, salt, hash); // 验证
|
|
314
|
+
CryptoUtil.getHashStr(16); // 生成随机字符串
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### FileUtil
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
FileUtil.getFilePathList("./src"); // 递归获取文件列表
|
|
321
|
+
FileUtil.getSuffix("/path/file.ts"); // "ts"
|
|
322
|
+
FileUtil.getFileName("/path/file.ts"); // "file"
|
|
323
|
+
FileUtil.getResource("./config.yml"); // 加载配置文件
|
|
324
|
+
FileUtil.formatBytes(1024 * 1024); // "1.00(M)"
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### TypeUtil
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
TypeUtil.isFunction(fn); // 是否为函数
|
|
331
|
+
TypeUtil.isClass(cls); // 是否为类
|
|
332
|
+
TypeUtil.isPromise(p); // 是否为 Promise
|
|
333
|
+
TypeUtil.isArray(arr); // 是否为数组
|
|
334
|
+
TypeUtil.isDate(d); // 是否为日期
|
|
335
|
+
TypeUtil.isTSORJS(path); // 是否为 TS/JS 文件
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### ValidationUtil
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
ValidationUtil.isNotNull(val); // 非空检查
|
|
342
|
+
ValidationUtil.isNumber(val); // 数字检查
|
|
343
|
+
ValidationUtil.isNotMinSize(val, min); // 最小值/长度检查
|
|
344
|
+
ValidationUtil.checkType(val, type); // 类型检查
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### MixTool
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
MixTool.mix(A, B); // 混合多个类
|
|
351
|
+
MixTool.copyProperties(target, src); // 复制属性
|
|
352
|
+
MixTool.assign(target, src); // 对象赋值
|
|
353
|
+
```
|