@linyjs/plugin-docs 0.1.2 → 0.1.4

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 CHANGED
@@ -74,13 +74,15 @@ docs/
74
74
  │ ├── client-module.md # 客户端模块
75
75
  │ ├── ui-slots.md # UI扩展插槽
76
76
  │ ├── permissions.md # 权限管理
77
- └── data-persistence.md # 数据持久化
77
+ ├── data-persistence.md # 数据持久化
78
+ │ └── authentication.md # 用户认证
78
79
  ├── api-reference/ # API参考
79
80
  │ ├── server-interface.md
80
81
  │ ├── client-interface.md
81
82
  │ └── ui-slots-interface.md
82
83
  ├── best-practices/ # 最佳实践
83
84
  │ ├── naming-conventions.md
85
+ │ ├── service-definition.md # ServiceDef 代码风格规范
84
86
  │ ├── error-handling.md
85
87
  │ ├── performance.md
86
88
  │ └── security.md
@@ -102,11 +104,33 @@ examples/
102
104
  - 详细的 README 说明
103
105
  - 可直接打包为 .mpk 文件
104
106
 
105
- ## 🔗 相关链接
107
+ ## 🔧 核心模块
106
108
 
107
- - [linyjs 框架](https://github.com/linyjs/linyjs)
108
- - [CLI 工具文档](https://github.com/linyjs/linyjs/tree/main/packages/cli)
109
- - [报告文档问题](https://github.com/linyjs/linyjs/issues)
109
+ linyjs 提供了以下核心模块,插件可以通过依赖注入方式调用这些基础服务:
110
+
111
+ ### @linyjs/mdb
112
+ **MongoDB 数据库服务**
113
+ - 提供数据持久化存储
114
+ - 支持 CRUD 操作和复杂查询
115
+ - 详情:[数据持久化指南](./docs/guides/data-persistence.md)
116
+
117
+ ### @linyjs/auth
118
+ **用户认证系统**
119
+ - 支持用户注册、登录、Token 验证
120
+ - 提供 JWT 身份验证
121
+ - 详情:[认证指南](./docs/guides/authentication.md)
122
+
123
+ ### @linyjs/permission
124
+ **权限管理系统**
125
+ - 基于角色的访问控制(RBAC)
126
+ - 细粒度的权限定义
127
+ - 详情:[权限管理指南](./docs/guides/permissions.md)
128
+
129
+ ## 📖 核心模块指南
130
+
131
+ - 💾 [数据持久化](./docs/guides/data-persistence.md) - 使用 @linyjs/mdb
132
+ - 🔐 [用户认证](./docs/guides/authentication.md) - 使用 @linyjs/auth
133
+ - 🛡️ [权限管理](./docs/guides/permissions.md) - 使用 @linyjs/permission
110
134
 
111
135
  ## 📄 许可证
112
136
 
@@ -330,11 +330,31 @@ registry.register({
330
330
 
331
331
  ---
332
332
 
333
+ ## 基础模块
334
+
335
+ linyjs 框架提供了以下基础模块,插件开发者可以通过依赖注入方式使用:
336
+
337
+ ### 数据库模块
338
+ - **@linyjs/mdb** - MongoDB 数据库服务
339
+ - 提供数据库连接、CRUD 操作、索引管理等功能
340
+ - 详见:[数据持久化指南](../guides/data-persistence.md)
341
+
342
+ ### 认证模块
343
+ - **@linyjs/auth** - 用户认证系统
344
+ - 提供用户注册、登录、Token 验证等功能
345
+ - 详见:[认证指南](../guides/authentication.md)
346
+
347
+ ### 权限模块
348
+ - **@linyjs/permission** - 权限管理系统
349
+ - 提供基于角色的访问控制(RBAC)
350
+ - 详见:[权限管理指南](../guides/permissions.md)
351
+
333
352
  ## 相关文档
334
353
 
335
354
  - 📖 [服务端模块开发](../guides/server-module.md)
336
355
  - 💻 [客户端模块开发](../guides/client-module.md)
337
356
  - 🎨 [UI 扩展插槽](../guides/ui-slots.md)
357
+ - 💾 [基础模块使用指南](../README.md#-核心模块)
338
358
 
339
359
  ---
340
360
 
@@ -459,4 +459,4 @@ function getUserFriendlyError(error: string): string {
459
459
 
460
460
  ---
461
461
 
462
- **上一篇**: [命名规范](./naming-conventions.md) | **下一篇**: [性能优化](./performance.md)
462
+ **上一篇**: [ServiceDef 代码风格规范](./service-definition.md) | **下一篇**: [性能优化](./performance.md)
@@ -487,9 +487,10 @@ git commit -m "Update the documentation for the slot feature" # 太长
487
487
  ## 相关文档
488
488
 
489
489
  - ⚠️ [错误处理](./error-handling.md)
490
+ - 📐 [ServiceDef 代码风格规范](./service-definition.md)
490
491
  - ⚡ [性能优化](./performance.md)
491
492
  - 🔒 [安全性](./security.md)
492
493
 
493
494
  ---
494
495
 
495
- **上一篇**: [数据持久化](../guides/data-persistence.md) | **下一篇**: [错误处理](./error-handling.md)
496
+ **上一篇**: [数据持久化](../guides/data-persistence.md) | **下一篇**: [ServiceDef 代码风格规范](./service-definition.md)
@@ -150,10 +150,10 @@ function ResponsiveImage() {
150
150
  ```typescript
151
151
  // ✅ 推荐:使用索引和投影
152
152
  class OptimizedArticleService {
153
- constructor(private mongodb: IMongoDBService) {}
153
+ constructor(private mongodbService: IMongoDBService) {}
154
154
 
155
155
  async getArticles() {
156
- const db = this.mongodb.getDb();
156
+ const db = this.mongodbService.getDb();
157
157
  const collection = db.collection('articles');
158
158
 
159
159
  // 使用索引字段查询
@@ -175,7 +175,7 @@ class OptimizedArticleService {
175
175
 
176
176
  // 添加索引
177
177
  async createIndexes() {
178
- const db = this.mongodb.getDb();
178
+ const db = this.mongodbService.getDb();
179
179
  const collection = db.collection('articles');
180
180
 
181
181
  await collection.createIndex({ status: 1, createdAt: -1 });
@@ -259,7 +259,7 @@ class AsyncProcessingService {
259
259
 
260
260
  private async getBatchData(offset: number, limit: number) {
261
261
  // 获取数据批次
262
- const db = this.mongodb.getDb();
262
+ const db = this.mongodbService.getDb();
263
263
  return db.collection('items')
264
264
  .find()
265
265
  .skip(offset)
@@ -0,0 +1,332 @@
1
+ # ServiceDef 代码风格规范
2
+
3
+ 本指南介绍 linyjs 插件开发中 `ServiceDef` 的两条核心代码风格规范,确保代码组织一致、可读、易维护。
4
+
5
+ ## 为什么需要规范?
6
+
7
+ - 📖 **提高可读性** — 服务定义与实现放在一起,一目了然
8
+ - 🔍 **便于查找** — 看到类就能找到它的 ServiceDef,反之亦然
9
+ - 🛠️ **减少错误** — 独立声明减少缩进层级,避免括号匹配错误
10
+ - 🤝 **团队协作** — 统一风格,降低 review 沟通成本
11
+
12
+ ---
13
+
14
+ ## 规则一:ServiceDef 必须声明为独立变量
15
+
16
+ ### 规则说明
17
+
18
+ `ServiceDef` 必须先声明为独立变量,然后在 `serviceDefs` 数组中通过变量名引用。**禁止**将 `ServiceDef` 对象字面量直接内联在 `serviceDefs` 数组中。
19
+
20
+ ### ✅ 正确写法
21
+
22
+ ```typescript
23
+ import type { IModule, IServiceDef } from '@linyjs/server-module-interface';
24
+
25
+ class HelloController {
26
+ getRoutes() {
27
+ return [/* ... */];
28
+ }
29
+ }
30
+
31
+ const helloControllerDef: IServiceDef = {
32
+ serviceTag: 'helloController',
33
+ serviceImpl: HelloController,
34
+ meta: { usageType: 'controller' }
35
+ };
36
+
37
+ export const helloServerModule: IModule = {
38
+ name: 'helloServer',
39
+ serviceDefs: [helloControllerDef]
40
+ };
41
+ ```
42
+
43
+ ### ❌ 错误写法
44
+
45
+ ```typescript
46
+ import type { IModule } from '@linyjs/server-module-interface';
47
+
48
+ class HelloController {
49
+ getRoutes() {
50
+ return [/* ... */];
51
+ }
52
+ }
53
+
54
+ export const helloServerModule: IModule = {
55
+ name: 'helloServer',
56
+ serviceDefs: [
57
+ {
58
+ serviceTag: 'helloController',
59
+ serviceImpl: HelloController,
60
+ meta: { usageType: 'controller' }
61
+ }
62
+ ]
63
+ };
64
+ ```
65
+
66
+ ### 原因
67
+
68
+ | 对比项 | 独立变量声明 | 内联在数组中 |
69
+ |--------|------------|------------|
70
+ | 缩进层级 | 浅(2层) | 深(4层+) |
71
+ | 可读性 | 高,变量名即语义 | 低,大段对象字面量淹没模块声明 |
72
+ | 复用性 | 可被多个模块引用 | 无法复用 |
73
+ | 维护性 | 修改时不影响模块声明 | 修改时需在数组中定位 |
74
+
75
+ ---
76
+
77
+ ## 规则二:ServiceDef 声明必须与实现类放在同一个文件中
78
+
79
+ ### 规则说明
80
+
81
+ `ServiceDef` 声明必须紧挨着它的 `serviceImpl` 实现类,放在同一个文件中。**禁止**将 `ServiceDef` 和实现类分离到不同文件,然后在模块入口文件中重新声明。
82
+
83
+ ### ✅ 正确写法
84
+
85
+ **`src/server/services/article-controller.ts`**
86
+
87
+ ```typescript
88
+ import type { IControllerService, IControllerServiceDef } from '@linyjs/server-module-interface';
89
+
90
+ export class ArticleController implements IControllerService {
91
+ getRoutes() {
92
+ return [/* ... */];
93
+ }
94
+ }
95
+
96
+ export const articleControllerDef: IControllerServiceDef = {
97
+ serviceTag: 'articleController',
98
+ serviceImpl: ArticleController,
99
+ dependencies: ['mdb.mongoDBService'],
100
+ meta: { usageType: 'controller' }
101
+ };
102
+ ```
103
+
104
+ **`src/server/server-module.ts`**
105
+
106
+ ```typescript
107
+ import type { IModule } from '@linyjs/server-module-interface';
108
+ import { articleControllerDef } from './services/article-controller.js';
109
+
110
+ export const articleServerModule: IModule = {
111
+ name: 'articleServer',
112
+ moduleDependencies: ['mdb'],
113
+ serviceDefs: [articleControllerDef]
114
+ };
115
+ ```
116
+
117
+ ### ❌ 错误写法
118
+
119
+ **`src/server/services/article-controller.ts`** — 只有类,没有 ServiceDef
120
+
121
+ ```typescript
122
+ export class ArticleController implements IControllerService {
123
+ getRoutes() {
124
+ return [/* ... */];
125
+ }
126
+ }
127
+ ```
128
+
129
+ **`src/server/server-module.ts`** — ServiceDef 与类分离
130
+
131
+ ```typescript
132
+ import { ArticleController } from './services/article-controller.js';
133
+
134
+ const articleControllerDef: IControllerServiceDef = {
135
+ serviceTag: 'articleController',
136
+ serviceImpl: ArticleController,
137
+ dependencies: ['mdb.mongoDBService'],
138
+ meta: { usageType: 'controller' }
139
+ };
140
+
141
+ export const articleServerModule: IModule = {
142
+ name: 'articleServer',
143
+ moduleDependencies: ['mdb'],
144
+ serviceDefs: [articleControllerDef]
145
+ };
146
+ ```
147
+
148
+ ### 原因
149
+
150
+ | 对比项 | 同文件放置 | 分离到不同文件 |
151
+ |--------|----------|-------------|
152
+ | 内聚性 | 高,定义与实现在一起 | 低,需跨文件查找 |
153
+ | 修改成本 | 低,改一处即可 | 高,可能漏改 |
154
+ | 文件职责 | 清晰,每个文件自包含 | 模糊,入口文件混杂声明 |
155
+
156
+ ---
157
+
158
+ ## 完整示例
159
+
160
+ 以下是一个完整的服务端模块示例,遵循两条规范:
161
+
162
+ ### 项目结构
163
+
164
+ ```
165
+ src/server/
166
+ ├── controllers/
167
+ │ └── article-controller.ts # ArticleController 类 + articleControllerDef
168
+ ├── middleware/
169
+ │ └── auth-middleware.ts # AuthMiddleware 类 + authMiddlewareDef
170
+ ├── services/
171
+ │ └── article-service.ts # ArticleService 类 + articleServiceDef
172
+ └── server-module.ts # 模块入口,只做导入和组装
173
+ ```
174
+
175
+ ### 控制器文件
176
+
177
+ **`src/server/controllers/article-controller.ts`**
178
+
179
+ ```typescript
180
+ import type { IControllerService, IControllerServiceDef } from '@linyjs/server-module-interface';
181
+
182
+ export class ArticleController implements IControllerService {
183
+ getRoutes() {
184
+ return [
185
+ {
186
+ method: 'GET' as const,
187
+ path: '/api/articles',
188
+ middlewares: [],
189
+ responseType: 'json' as const,
190
+ handler: async () => {
191
+ return { articles: [] };
192
+ }
193
+ }
194
+ ];
195
+ }
196
+ }
197
+
198
+ export const articleControllerDef: IControllerServiceDef = {
199
+ serviceTag: 'articleController',
200
+ serviceImpl: ArticleController,
201
+ dependencies: ['articleService'],
202
+ meta: { usageType: 'controller' }
203
+ };
204
+ ```
205
+
206
+ ### 中间件文件
207
+
208
+ **`src/server/middleware/auth-middleware.ts`**
209
+
210
+ ```typescript
211
+ import type { IMiddlewareService, IMiddlewareServiceDef } from '@linyjs/server-module-interface';
212
+
213
+ export class AuthMiddleware implements IMiddlewareService {
214
+ getMiddlewares() {
215
+ return [{
216
+ middlewareId: 'auth',
217
+ handler: async (params, ctx, next) => {
218
+ // 认证逻辑...
219
+ await next();
220
+ }
221
+ }];
222
+ }
223
+ }
224
+
225
+ export const authMiddlewareDef: IMiddlewareServiceDef = {
226
+ serviceTag: 'authMiddleware',
227
+ serviceImpl: AuthMiddleware,
228
+ meta: { usageType: 'middleware' }
229
+ };
230
+ ```
231
+
232
+ ### 模块入口文件
233
+
234
+ **`src/server/server-module.ts`**
235
+
236
+ ```typescript
237
+ import type { IModule } from '@linyjs/server-module-interface';
238
+ import { articleControllerDef } from './controllers/article-controller.js';
239
+ import { authMiddlewareDef } from './middleware/auth-middleware.js';
240
+
241
+ export const myServerModule: IModule = {
242
+ name: 'myServer',
243
+ serviceDefs: [articleControllerDef, authMiddlewareDef]
244
+ };
245
+ ```
246
+
247
+ > 模块入口文件只负责**导入和组装**,不包含任何 ServiceDef 声明或服务实现类。
248
+
249
+ ---
250
+
251
+ ## 客户端模块同样适用
252
+
253
+ 以上两条规范同样适用于客户端模块:
254
+
255
+ ### ✅ 正确写法
256
+
257
+ **`src/client/index.tsx`**
258
+
259
+ ```typescript
260
+ import type { IModule, IRouteDef } from '@linyjs/client-module-interface';
261
+ import React from 'react';
262
+
263
+ function HelloPage() {
264
+ return <div>Hello!</div>;
265
+ }
266
+
267
+ class HelloRouteService implements IRouteService {
268
+ basePath = '/hello';
269
+
270
+ getRoutes() {
271
+ return [{
272
+ path: '/',
273
+ component: HelloPage,
274
+ key: 'hello-page',
275
+ meta: { title: 'Hello' }
276
+ }];
277
+ }
278
+ }
279
+
280
+ const helloRouteDef: IRouteDef = {
281
+ serviceTag: 'helloRoute',
282
+ serviceImpl: HelloRouteService,
283
+ meta: { usageType: 'route' }
284
+ };
285
+
286
+ export const helloClientModule: IModule = {
287
+ name: 'helloClient',
288
+ serviceDefs: [helloRouteDef]
289
+ };
290
+ ```
291
+
292
+ ### ❌ 错误写法
293
+
294
+ ```typescript
295
+ // ServiceDef 内联在数组中,且使用了匿名类
296
+ export const helloClientModule: IModule = {
297
+ name: 'helloClient',
298
+ serviceDefs: [{
299
+ serviceTag: 'helloRoute',
300
+ serviceImpl: class {
301
+ basePath = '/hello';
302
+ getRoutes() { /* ... */ }
303
+ },
304
+ meta: { usageType: 'route' }
305
+ }]
306
+ };
307
+ ```
308
+
309
+ > 客户端模块中如果文件较小(如 Hello World 级别),可以将类、ServiceDef 和模块声明放在同一个文件中。但仍然禁止内联在 `serviceDefs` 数组中,也禁止使用匿名类作为 `serviceImpl`。
310
+
311
+ ---
312
+
313
+ ## 检查清单
314
+
315
+ 在提交代码前,请检查以下几点:
316
+
317
+ - [ ] 所有 `ServiceDef` 都声明为独立变量,未内联在 `serviceDefs` 数组中
318
+ - [ ] 每个 `ServiceDef` 声明都紧挨着对应的实现类,在同一个文件中
319
+ - [ ] `serviceImpl` 使用具名类,不使用匿名类或内联箭头函数
320
+ - [ ] 模块入口文件(`server-module.ts` / `client-module.ts`)只做导入和组装,不包含 ServiceDef 声明
321
+ - [ ] 导入类型时包含 `IServiceDef`(或其子类型如 `IControllerServiceDef`),为声明提供类型标注
322
+
323
+ ## 相关文档
324
+
325
+ - 📖 [服务端模块开发](../guides/server-module.md)
326
+ - 📖 [客户端模块开发](../guides/client-module.md)
327
+ - 📖 [命名规范](./naming-conventions.md)
328
+ - ⚠️ [错误处理](./error-handling.md)
329
+
330
+ ---
331
+
332
+ **上一篇**: [命名规范](./naming-conventions.md) | **下一篇**: [错误处理](./error-handling.md)
package/docs/faq.md CHANGED
@@ -110,7 +110,6 @@ export const serviceB = {
110
110
  **A:** 可以通过以下方式:
111
111
  1. **覆盖路由**: 注册相同路径的路由(后加载的优先)
112
112
  2. **扩展 Slot**: 向现有 Slot 添加新组件
113
- 3. **装饰器模式**: 包装其他插件的服务
114
113
 
115
114
  ---
116
115
 
@@ -188,18 +188,18 @@ export class ArticleController implements IControllerService {
188
188
  创建 `src/server/index.ts`:
189
189
 
190
190
  ```typescript
191
- import type { IModule } from '@linyjs/server-module-interface';
191
+ import type { IModule, IServiceDef } from '@linyjs/server-module-interface';
192
192
  import { ArticleController } from './controllers/ArticleController';
193
193
 
194
+ const articleControllerDef: IServiceDef = {
195
+ serviceTag: 'articleController',
196
+ serviceImpl: ArticleController,
197
+ meta: { usageType: 'controller' }
198
+ };
199
+
194
200
  export const blogServerModule: IModule = {
195
201
  name: 'blogServer',
196
- serviceDefs: [
197
- {
198
- serviceTag: 'articleController',
199
- serviceImpl: ArticleController,
200
- meta: { usageType: 'controller' }
201
- }
202
- ]
202
+ serviceDefs: [articleControllerDef]
203
203
  };
204
204
  ```
205
205
 
@@ -308,15 +308,15 @@ class BlogRouteService {
308
308
  }
309
309
  }
310
310
 
311
+ const blogRouteDef: IServiceDef = {
312
+ serviceTag: 'blogRoute',
313
+ serviceImpl: BlogRouteService,
314
+ meta: { usageType: 'route' }
315
+ };
316
+
311
317
  export const blogClientModule: IModule = {
312
318
  name: 'blogClient',
313
- serviceDefs: [
314
- {
315
- serviceTag: 'blogRoute',
316
- serviceImpl: BlogRouteService,
317
- meta: { usageType: 'route' }
318
- }
319
- ]
319
+ serviceDefs: [blogRouteDef]
320
320
  };
321
321
  ```
322
322
 
@@ -65,7 +65,7 @@ npm install @linyjs/plugin-docs
65
65
 
66
66
  ```bash
67
67
  # MongoDB 服务(数据持久化)
68
- npm install @linyjs/mongodb
68
+ npm install @linyjs/mdb
69
69
 
70
70
  # 权限管理
71
71
  npm install @linyjs/permission
@@ -100,7 +100,7 @@ hello-plugin/
100
100
  如果你需要自定义或创建新的服务端代码,编辑 `src/server/index.ts`:
101
101
 
102
102
  ```typescript
103
- import type { IModule } from '@linyjs/server-module-interface';
103
+ import type { IModule, IServiceDef } from '@linyjs/server-module-interface';
104
104
 
105
105
  class HelloController {
106
106
  getRoutes() {
@@ -116,13 +116,15 @@ class HelloController {
116
116
  }
117
117
  }
118
118
 
119
+ const helloControllerDef: IServiceDef = {
120
+ serviceTag: 'helloController',
121
+ serviceImpl: HelloController,
122
+ meta: { usageType: 'controller' }
123
+ };
124
+
119
125
  export const helloServerModule: IModule = {
120
126
  name: 'helloServer',
121
- serviceDefs: [{
122
- serviceTag: 'helloController',
123
- serviceImpl: HelloController,
124
- meta: { usageType: 'controller' }
125
- }]
127
+ serviceDefs: [helloControllerDef]
126
128
  };
127
129
  ```
128
130
 
@@ -133,7 +135,7 @@ export const helloServerModule: IModule = {
133
135
  如果你需要自定义或创建新的客户端代码,编辑 `src/client/index.tsx`:
134
136
 
135
137
  ```typescript
136
- import type { IModule } from '@linyjs/client-module-interface';
138
+ import type { IModule, IServiceDef } from '@linyjs/client-module-interface';
137
139
  import React from 'react';
138
140
 
139
141
  function HelloPage() {
@@ -145,23 +147,27 @@ function HelloPage() {
145
147
  );
146
148
  }
147
149
 
150
+ class HelloRouteService {
151
+ basePath = '/hello';
152
+ getRoutes() {
153
+ return [{
154
+ path: '/',
155
+ component: HelloPage,
156
+ key: 'hello-page',
157
+ meta: { title: 'Hello' }
158
+ }];
159
+ }
160
+ }
161
+
162
+ const helloRouteDef: IServiceDef = {
163
+ serviceTag: 'helloRoute',
164
+ serviceImpl: HelloRouteService,
165
+ meta: { usageType: 'route' }
166
+ };
167
+
148
168
  export const helloClientModule: IModule = {
149
169
  name: 'helloClient',
150
- serviceDefs: [{
151
- serviceTag: 'helloRoute',
152
- serviceImpl: class {
153
- basePath = '/hello';
154
- getRoutes() {
155
- return [{
156
- path: '/',
157
- component: HelloPage,
158
- key: 'hello-page',
159
- meta: { title: 'Hello' }
160
- }];
161
- }
162
- },
163
- meta: { usageType: 'route' }
164
- }]
170
+ serviceDefs: [helloRouteDef]
165
171
  };
166
172
  ```
167
173