@linyjs/plugin-docs 0.0.13 → 0.0.15
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 +19 -17
- package/docs/api-reference/index.md +91 -8
- package/docs/best-practices/error-handling.md +3 -3
- package/docs/best-practices/security.md +2 -2
- package/docs/faq.md +1 -1
- package/docs/getting-started/first-plugin.md +3 -3
- package/docs/guides/dependency-injection.md +574 -0
- package/docs/guides/permissions.md +1 -1
- package/docs/guides/server-module.md +92 -18
- package/docs/guides/shared-module-interface.md +349 -0
- package/examples/analytics-plugin/package.json +5 -5
- package/examples/analytics-plugin/src/server/index.ts +4 -4
- package/examples/blog-plugin/package.json +3 -3
- package/examples/blog-plugin/src/server/index.ts +4 -4
- package/examples/hello-world/package.json +2 -2
- package/examples/hello-world/src/server/index.ts +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -65,28 +65,28 @@ npx @linyjs/cli example blog-plugin -o ./my-blog
|
|
|
65
65
|
|
|
66
66
|
```
|
|
67
67
|
docs/
|
|
68
|
-
├── getting-started/
|
|
69
|
-
│ ├── quick-start.md
|
|
70
|
-
│ ├── installation.md
|
|
71
|
-
│ └── first-plugin.md
|
|
72
|
-
├── guides/
|
|
73
|
-
│ ├── server-module.md
|
|
74
|
-
│ ├──
|
|
75
|
-
│ ├──
|
|
76
|
-
│ ├──
|
|
77
|
-
│ ├──
|
|
78
|
-
│
|
|
79
|
-
├──
|
|
80
|
-
│
|
|
81
|
-
|
|
82
|
-
│ └──
|
|
83
|
-
├── best-practices/
|
|
68
|
+
├── getting-started/ # 入门教程
|
|
69
|
+
│ ├── quick-start.md # 快速开始
|
|
70
|
+
│ ├── installation.md # 安装指南
|
|
71
|
+
│ └── first-plugin.md # 第一个插件
|
|
72
|
+
├── guides/ # 进阶指南
|
|
73
|
+
│ ├── server-module.md # 服务端模块
|
|
74
|
+
│ ├── dependency-injection.md # 依赖注入机制
|
|
75
|
+
│ ├── shared-module-interface.md # shared-module-interface 类型包
|
|
76
|
+
│ ├── client-module.md # 客户端模块
|
|
77
|
+
│ ├── ui-slots.md # UI扩展插槽
|
|
78
|
+
│ ├── permissions.md # 权限管理
|
|
79
|
+
│ ├── data-persistence.md # 数据持久化
|
|
80
|
+
│ └── authentication.md # 用户认证
|
|
81
|
+
├── api-reference/ # API参考
|
|
82
|
+
│ └── index.md # 接口定义(含依赖注入接口)
|
|
83
|
+
├── best-practices/ # 最佳实践
|
|
84
84
|
│ ├── naming-conventions.md
|
|
85
85
|
│ ├── service-definition.md # ServiceDef 代码风格规范
|
|
86
86
|
│ ├── error-handling.md
|
|
87
87
|
│ ├── performance.md
|
|
88
88
|
│ └── security.md
|
|
89
|
-
└── faq.md
|
|
89
|
+
└── faq.md # 常见问题
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
## 💡 示例项目
|
|
@@ -128,6 +128,8 @@ linyjs 提供了以下核心模块,插件可以通过依赖注入方式调用
|
|
|
128
128
|
|
|
129
129
|
## 📖 核心模块指南
|
|
130
130
|
|
|
131
|
+
- 📖 [依赖注入机制](./docs/guides/dependency-injection.md) — linyjs DI 机制完整说明
|
|
132
|
+
- 📦 [shared-module-interface](./docs/guides/shared-module-interface.md) — 类型定义包使用说明
|
|
131
133
|
- 💾 [数据持久化](./docs/guides/data-persistence.md) - 使用 @linyjs/mdb
|
|
132
134
|
- 🔐 [用户认证](./docs/guides/authentication.md) - 使用 @linyjs/auth
|
|
133
135
|
- 🛡️ [权限管理](./docs/guides/permissions.md) - 使用 @linyjs/permission
|
|
@@ -41,11 +41,11 @@ export const myModule: IModule = {
|
|
|
41
41
|
服务定义的通用接口。
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
|
-
interface IServiceDef {
|
|
44
|
+
interface IServiceDef<S extends IService = IService, M extends IServiceMetadata = IServiceMetadata> {
|
|
45
45
|
serviceTag: string;
|
|
46
|
-
serviceImpl:
|
|
47
|
-
dependencies?: string[];
|
|
48
|
-
meta
|
|
46
|
+
serviceImpl: IServiceMaker<S>; // class 或工厂函数
|
|
47
|
+
dependencies?: string[]; // 支持 'serviceTag' 或 'moduleName.serviceTag'
|
|
48
|
+
meta?: M;
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
@@ -53,10 +53,12 @@ interface IServiceDef {
|
|
|
53
53
|
|
|
54
54
|
| 字段 | 类型 | 必填 | 说明 |
|
|
55
55
|
|------|------|------|------|
|
|
56
|
-
| `serviceTag` | string | ✅ |
|
|
57
|
-
| `serviceImpl` | class | ✅ |
|
|
58
|
-
| `dependencies` | string[] | ❌ |
|
|
59
|
-
| `meta` | ServiceMetadata | ✅ |
|
|
56
|
+
| `serviceTag` | string | ✅ | 服务的唯一标签(模块内唯一) |
|
|
57
|
+
| `serviceImpl` | class \| function | ✅ | 服务实现,可以是类或工厂函数 |
|
|
58
|
+
| `dependencies` | string[] | ❌ | 依赖的其他服务,支持模块内和跨模块引用 |
|
|
59
|
+
| `meta` | ServiceMetadata | ✅ | 元数据(包含 usageType) |
|
|
60
|
+
|
|
61
|
+
> ⚠️ **构造函数约定**:框架将依赖组装为 `{ serviceTag: instance }` 对象传入构造函数,构造函数**必须使用解构赋值**。详见 [依赖注入机制](../guides/dependency-injection.md#构造函数约定)。
|
|
60
62
|
|
|
61
63
|
---
|
|
62
64
|
|
|
@@ -334,6 +336,17 @@ registry.register({
|
|
|
334
336
|
|
|
335
337
|
linyjs 框架提供了以下基础模块,插件开发者可以通过依赖注入方式使用:
|
|
336
338
|
|
|
339
|
+
### 可注入服务汇总
|
|
340
|
+
|
|
341
|
+
| 依赖引用 | 接口类型 | 来源模块 | 说明 |
|
|
342
|
+
|----------|----------|----------|------|
|
|
343
|
+
| `'mdb.mongoDBService'` | `IMongoDBService` | @linyjs/mdb | MongoDB 数据库服务 |
|
|
344
|
+
| `'authServer.userService'` | `IUserService` | @linyjs/auth | 用户管理服务 |
|
|
345
|
+
| `'authServer.initService'` | - | @linyjs/auth | 系统初始化服务 |
|
|
346
|
+
| `'permissionServer.permissionService'` | `IPermissionService` | @linyjs/permission | 权限检查服务 |
|
|
347
|
+
|
|
348
|
+
> 💡 使用 `@linyjs/shared-module-interface` 包获取这些接口的 TypeScript 类型定义,详见 [shared-module-interface 指南](../guides/shared-module-interface.md)。
|
|
349
|
+
|
|
337
350
|
### 数据库模块
|
|
338
351
|
- **@linyjs/mdb** - MongoDB 数据库服务
|
|
339
352
|
- 提供数据库连接、CRUD 操作、索引管理等功能
|
|
@@ -349,8 +362,78 @@ linyjs 框架提供了以下基础模块,插件开发者可以通过依赖注
|
|
|
349
362
|
- 提供基于角色的访问控制(RBAC)
|
|
350
363
|
- 详见:[权限管理指南](../guides/permissions.md)
|
|
351
364
|
|
|
365
|
+
## 依赖注入接口
|
|
366
|
+
|
|
367
|
+
### IService / IServiceMaker
|
|
368
|
+
|
|
369
|
+
服务基础类型和实现类型定义:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
// 所有服务的基础类型
|
|
373
|
+
type IService = object
|
|
374
|
+
|
|
375
|
+
// 服务类构造器
|
|
376
|
+
type IServiceConstructor<S> = new (...args: any[]) => S
|
|
377
|
+
|
|
378
|
+
// 服务工厂函数
|
|
379
|
+
type IServiceFactory<S> = (...args: any[]) => S
|
|
380
|
+
|
|
381
|
+
// 服务实现(类或工厂函数)
|
|
382
|
+
type IServiceMaker<S> = IServiceConstructor<S> | IServiceFactory<S>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### 依赖引用格式
|
|
386
|
+
|
|
387
|
+
`IServiceDef.dependencies` 中的字符串支持两种格式:
|
|
388
|
+
|
|
389
|
+
| 格式 | 示例 | 说明 |
|
|
390
|
+
|------|------|------|
|
|
391
|
+
| 模块内引用 | `'myService'` | 从当前模块已实例化的服务中查找 |
|
|
392
|
+
| 跨模块引用 | `'mdb.mongoDBService'` | 格式为 `moduleName.serviceTag`,从指定模块查找 |
|
|
393
|
+
|
|
394
|
+
> 📖 完整的依赖注入机制说明,请阅读 [依赖注入机制指南](../guides/dependency-injection.md)。
|
|
395
|
+
|
|
396
|
+
### IMongoDBService
|
|
397
|
+
|
|
398
|
+
由 @linyjs/mdb 模块实现,通过 `'mdb.mongoDBService'` 注入:
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
interface IMongoDBService {
|
|
402
|
+
readonly ObjectId: typeof ObjectId;
|
|
403
|
+
getDb(): Db;
|
|
404
|
+
getCollection<T>(name: string): Collection<T>;
|
|
405
|
+
isConnected(): boolean;
|
|
406
|
+
close(): Promise<void>;
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### IUserService
|
|
411
|
+
|
|
412
|
+
由 @linyjs/auth 模块实现,通过 `'authServer.userService'` 注入:
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
interface IUserService {
|
|
416
|
+
getAllUsers(): Promise<ISafeUser[]>;
|
|
417
|
+
updateUserRoles(userId: string, roles: string[]): Promise<ISafeUser | null>;
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### IPermissionService
|
|
422
|
+
|
|
423
|
+
由 @linyjs/permission 模块实现,通过 `'permissionServer.permissionService'` 注入:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
interface IPermissionService {
|
|
427
|
+
check(user: IPermissionUser | null, permission: PermissionString, context?: Record<string, any>): Promise<IPermissionCheckResult>;
|
|
428
|
+
registerPolicy(policy: IPermissionPolicy): void;
|
|
429
|
+
checkMany(user: IPermissionUser | null, permissions: PermissionString[], context?: Record<string, any>): Promise<Record<PermissionString, IPermissionCheckResult>>;
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
352
433
|
## 相关文档
|
|
353
434
|
|
|
435
|
+
- 📖 [依赖注入机制](../guides/dependency-injection.md) — DI 完整说明
|
|
436
|
+
- 📦 [shared-module-interface 指南](../guides/shared-module-interface.md) — 类型定义包
|
|
354
437
|
- 📖 [服务端模块开发](../guides/server-module.md)
|
|
355
438
|
- 💻 [客户端模块开发](../guides/client-module.md)
|
|
356
439
|
- 🎨 [UI 扩展插槽](../guides/ui-slots.md)
|
|
@@ -35,7 +35,7 @@ handler: async (params, ctx) => {
|
|
|
35
35
|
handler: async (params, ctx) => {
|
|
36
36
|
try {
|
|
37
37
|
// 输入验证错误
|
|
38
|
-
if (!params.
|
|
38
|
+
if (!params.email) {
|
|
39
39
|
return {
|
|
40
40
|
status: 400,
|
|
41
41
|
data: { error: 'Email is required' }
|
|
@@ -43,7 +43,7 @@ handler: async (params, ctx) => {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// 业务逻辑错误
|
|
46
|
-
const user = await findUser(params.
|
|
46
|
+
const user = await findUser(params.email);
|
|
47
47
|
if (!user) {
|
|
48
48
|
return {
|
|
49
49
|
status: 404,
|
|
@@ -92,7 +92,7 @@ class AuthorizationError extends Error {
|
|
|
92
92
|
// 在处理器中使用
|
|
93
93
|
handler: async (params, ctx) => {
|
|
94
94
|
try {
|
|
95
|
-
if (!isValidEmail(params.
|
|
95
|
+
if (!isValidEmail(params.email)) {
|
|
96
96
|
throw new ValidationError('Invalid email format', 'email');
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
```typescript
|
|
17
17
|
// 严格的输入验证
|
|
18
18
|
handler: async (params, ctx) => {
|
|
19
|
-
const { email, password, age } = params
|
|
19
|
+
const { email, password, age } = params;
|
|
20
20
|
|
|
21
21
|
// 邮箱格式验证
|
|
22
22
|
if (!isValidEmail(email)) {
|
|
@@ -73,7 +73,7 @@ const userSchema = Joi.object({
|
|
|
73
73
|
|
|
74
74
|
// 在处理器中使用验证
|
|
75
75
|
handler: async (params, ctx) => {
|
|
76
|
-
const { error, value } = userSchema.validate(params
|
|
76
|
+
const { error, value } = userSchema.validate(params);
|
|
77
77
|
|
|
78
78
|
if (error) {
|
|
79
79
|
return {
|
package/docs/faq.md
CHANGED
|
@@ -162,8 +162,8 @@ export class ArticleController implements IControllerService {
|
|
|
162
162
|
middlewares: [],
|
|
163
163
|
responseType: 'json' as const,
|
|
164
164
|
handler: async (params: any) => {
|
|
165
|
-
const page = parseInt(params.
|
|
166
|
-
const limit = parseInt(params.
|
|
165
|
+
const page = parseInt(params.page || '1');
|
|
166
|
+
const limit = parseInt(params.limit || '10');
|
|
167
167
|
return await this.articleService.getArticles(page, limit);
|
|
168
168
|
}
|
|
169
169
|
},
|
|
@@ -173,7 +173,7 @@ export class ArticleController implements IControllerService {
|
|
|
173
173
|
middlewares: [],
|
|
174
174
|
responseType: 'json' as const,
|
|
175
175
|
handler: async (params: any) => {
|
|
176
|
-
const article = await this.articleService.createArticle(params
|
|
176
|
+
const article = await this.articleService.createArticle(params);
|
|
177
177
|
return { success: true, data: article };
|
|
178
178
|
}
|
|
179
179
|
}
|