@linyjs/plugin-docs 0.1.1 → 0.1.3

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
@@ -33,6 +33,22 @@ cat node_modules/@linyjs/plugin-docs/docs/getting-started/quick-start.md
33
33
  ls node_modules/@linyjs/plugin-docs/docs/api-reference/
34
34
  ```
35
35
 
36
+ ### 快速创建插件项目
37
+
38
+ 使用 CLI 工具创建新的插件项目:
39
+
40
+ ```bash
41
+ # 创建新的插件项目
42
+ npx @linyjs/cli init my-plugin
43
+ cd my-plugin
44
+ npm install
45
+
46
+ # 进入开发模式
47
+ npx @linyjs/cli dev
48
+ ```
49
+
50
+ CLI 工具会自动创建完整的项目结构,包含 package.json、TypeScript 配置和示例代码。
51
+
36
52
  ### 生成示例项目
37
53
 
38
54
  使用 CLI 工具生成示例项目:
@@ -58,7 +74,8 @@ docs/
58
74
  │ ├── client-module.md # 客户端模块
59
75
  │ ├── ui-slots.md # UI扩展插槽
60
76
  │ ├── permissions.md # 权限管理
61
- └── data-persistence.md # 数据持久化
77
+ ├── data-persistence.md # 数据持久化
78
+ │ └── authentication.md # 用户认证
62
79
  ├── api-reference/ # API参考
63
80
  │ ├── server-interface.md
64
81
  │ ├── client-interface.md
@@ -86,12 +103,40 @@ examples/
86
103
  - 详细的 README 说明
87
104
  - 可直接打包为 .mpk 文件
88
105
 
106
+ ## 🔧 核心模块
107
+
108
+ linyjs 提供了以下核心模块,插件可以通过依赖注入方式调用这些基础服务:
109
+
110
+ ### @linyjs/mongodb
111
+ **MongoDB 数据库服务**
112
+ - 提供数据持久化存储
113
+ - 支持 CRUD 操作和复杂查询
114
+ - 详情:[数据持久化指南](./docs/guides/data-persistence.md)
115
+
116
+ ### @linyjs/auth
117
+ **用户认证系统**
118
+ - 支持用户注册、登录、Token 验证
119
+ - 提供 JWT 身份验证
120
+ - 详情:[认证指南](./docs/guides/authentication.md)
121
+
122
+ ### @linyjs/permission
123
+ **权限管理系统**
124
+ - 基于角色的访问控制(RBAC)
125
+ - 细粒度的权限定义
126
+ - 详情:[权限管理指南](./docs/guides/permissions.md)
127
+
89
128
  ## 🔗 相关链接
90
129
 
91
130
  - [linyjs 框架](https://github.com/linyjs/linyjs)
92
131
  - [CLI 工具文档](https://github.com/linyjs/linyjs/tree/main/packages/cli)
93
132
  - [报告文档问题](https://github.com/linyjs/linyjs/issues)
94
133
 
134
+ ## 📖 核心模块指南
135
+
136
+ - 💾 [数据持久化](./docs/guides/data-persistence.md) - 使用 @linyjs/mongodb
137
+ - 🔐 [用户认证](./docs/guides/authentication.md) - 使用 @linyjs/auth
138
+ - 🛡️ [权限管理](./docs/guides/permissions.md) - 使用 @linyjs/permission
139
+
95
140
  ## 📄 许可证
96
141
 
97
142
  MIT License
@@ -330,11 +330,31 @@ registry.register({
330
330
 
331
331
  ---
332
332
 
333
+ ## 基础模块
334
+
335
+ linyjs 框架提供了以下基础模块,插件开发者可以通过依赖注入方式使用:
336
+
337
+ ### 数据库模块
338
+ - **@linyjs/mongodb** - 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
 
@@ -24,6 +24,25 @@
24
24
 
25
25
  ### 步骤 1: 初始化项目
26
26
 
27
+ **推荐方式:使用 CLI 工具自动创建项目**
28
+
29
+ ```bash
30
+ # 使用 @linyjs/cli 创建项目目录和基本文件
31
+ npx @linyjs/cli init hello-plugin
32
+ cd hello-plugin
33
+
34
+ # 安装依赖
35
+ npm install
36
+ ```
37
+
38
+ CLI 工具会自动创建:
39
+ - package.json (已配置依赖和脚本)
40
+ - tsconfig.json (TypeScript 配置)
41
+ - src/server/index.ts (服务端代码模板)
42
+ - src/client/index.tsx (客户端代码模板)
43
+
44
+ **传统方式:手动创建项目**
45
+
27
46
  ```bash
28
47
  # 创建项目目录
29
48
  mkdir hello-plugin && cd hello-plugin
@@ -36,20 +55,24 @@ npm install @linyjs/server-module-interface @linyjs/client-module-interface reac
36
55
  npm install -D typescript @types/react
37
56
  ```
38
57
 
39
- ### 步骤 2: 创建项目结构
58
+ ### 步骤 2: 项目结构
59
+
60
+ 使用 CLI 工具创建的项目已经包含了完整的文件结构:
40
61
 
41
62
  ```
42
63
  hello-plugin/
43
- ├── package.json
44
- ├── tsconfig.json
64
+ ├── package.json # 已预配置的依赖和脚本
65
+ ├── tsconfig.json # 已配置 TypeScript
45
66
  └── src/
46
67
  ├── server/
47
- │ └── index.ts # 服务端入口
68
+ │ └── index.ts # 服务端入口 (已包含示例代码)
48
69
  └── client/
49
- └── index.tsx # 客户端入口
70
+ └── index.tsx # 客户端入口 (已包含示例代码)
50
71
  ```
51
72
 
52
- **创建 tsconfig.json:**
73
+ **注意**:使用 CLI 创建的项目已经包含了预配置的 package.json 和 tsconfig.json,无需手动创建。
74
+
75
+ 如果你使用了传统方式,需要**手动创建 tsconfig.json:**
53
76
 
54
77
  ```json
55
78
  {
@@ -72,7 +95,9 @@ hello-plugin/
72
95
 
73
96
  ### 步骤 3: 编写服务端代码
74
97
 
75
- 创建 `src/server/index.ts`:
98
+ **使用 CLI 创建的项目已经包含了示例代码**,你已经可以开始开发或修改现有代码。
99
+
100
+ 如果你需要自定义或创建新的服务端代码,编辑 `src/server/index.ts`:
76
101
 
77
102
  ```typescript
78
103
  import type { IModule } from '@linyjs/server-module-interface';
@@ -103,7 +128,9 @@ export const helloServerModule: IModule = {
103
128
 
104
129
  ### 步骤 4: 编写客户端代码
105
130
 
106
- 创建 `src/client/index.tsx`:
131
+ **使用 CLI 创建的项目已经包含了示例代码**,你已经可以开始开发或修改现有代码。
132
+
133
+ 如果你需要自定义或创建新的客户端代码,编辑 `src/client/index.tsx`:
107
134
 
108
135
  ```typescript
109
136
  import type { IModule } from '@linyjs/client-module-interface';
@@ -140,9 +167,25 @@ export const helloClientModule: IModule = {
140
167
 
141
168
  ### 步骤 5: 构建和打包
142
169
 
170
+ **推荐方式:使用开发模式 (dev)**
171
+
172
+ ```bash
173
+ # 一键打包、安装到开发环境
174
+ npx @linyjs/cli dev
175
+ ```
176
+
177
+ 这会:
178
+ 1. 自动编译 TypeScript
179
+ 2. 打包为 .mpk 文件
180
+ 3. 安装到 SSR 的 extensions 目录
181
+ 4. 注册到 packages.json
182
+ 5. 准备就绪后重启 SSR 服务器即可测试
183
+
184
+ **传统方式:手动打包**
185
+
143
186
  ```bash
144
187
  # 编译 TypeScript
145
- npx tsc
188
+ npm run build
146
189
 
147
190
  # 使用 CLI 打包为 .mpk 文件
148
191
  npx @linyjs/cli pack
@@ -152,6 +195,18 @@ npx @linyjs/cli pack
152
195
 
153
196
  ### 步骤 6: 测试插件
154
197
 
198
+ **使用 CLI dev 模式**(已自动完成安装和注册):
199
+
200
+ ```bash
201
+ # 启动 SSR 服务器
202
+ cd /path/to/linyjs/packages/ssr
203
+ npx tsx src/demo/dev-server-with-pkg.tsx
204
+ ```
205
+
206
+ 访问 `http://localhost:3000/hello` 查看你的插件!
207
+
208
+ **手动部署**:
209
+
155
210
  ```bash
156
211
  # 将插件复制到 extensions 目录
157
212
  cp hello-plugin.mpk /path/to/linyjs/packages/ssr/extensions/
@@ -0,0 +1,420 @@
1
+ # 用户认证
2
+
3
+ 本指南介绍如何在 linyjs 插件中使用认证系统实现用户登录、注册和权限验证。
4
+
5
+ ## 概述
6
+
7
+ linyjs 提供完整的用户认证系统,支持:
8
+
9
+ - 🔐 用户注册和登录
10
+ - 🪙 JWT Token 认证
11
+ - 🛡️ 路由级别的认证保护
12
+ - 👤 用户信息管理
13
+
14
+ ## 配置认证服务
15
+
16
+ ### 在服务端模块中注入依赖
17
+
18
+ ```typescript
19
+ import type { IModule } from '@linyjs/server-module-interface';
20
+ import { login, register, verifyToken } from '@linyjs/auth';
21
+
22
+ export const myServerModule: IModule = {
23
+ name: 'myServer',
24
+ moduleDependencies: ['auth'], // 依赖认证模块
25
+ serviceDefs: [
26
+ {
27
+ serviceTag: 'authController',
28
+ serviceImpl: AuthController,
29
+ dependencies: [], // 依赖注入将在类构造函数中使用
30
+ meta: { usageType: 'controller' }
31
+ }
32
+ ]
33
+ };
34
+ ```
35
+
36
+ ## 基本认证操作
37
+
38
+ ### 用户注册
39
+
40
+ ```typescript
41
+ import { register } from '@linyjs/auth';
42
+
43
+ class AuthController {
44
+ getRoutes() {
45
+ return [{
46
+ method: 'POST' as const,
47
+ path: '/api/auth/register',
48
+ middlewares: [],
49
+ responseType: 'json' as const,
50
+ handler: async (req: any) => {
51
+ const { username, email, password } = req.body;
52
+
53
+ try {
54
+ const result = await register(username, email, password);
55
+ return {
56
+ success: true,
57
+ message: 'Registration successful',
58
+ data: result
59
+ };
60
+ } catch (error) {
61
+ return {
62
+ success: false,
63
+ message: error instanceof Error ? error.message : 'Registration failed'
64
+ };
65
+ }
66
+ }
67
+ }];
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### 用户登录
73
+
74
+ ```typescript
75
+ import { login } from '@linyjs/auth';
76
+
77
+ class AuthController {
78
+ getRoutes() {
79
+ return [{
80
+ method: 'POST' as const,
81
+ path: '/api/auth/login',
82
+ middlewares: [],
83
+ responseType: 'json' as const,
84
+ handler: async (req: any) => {
85
+ const { identifier, password } = req.body;
86
+
87
+ try {
88
+ const result = await login(identifier, password);
89
+ return {
90
+ success: true,
91
+ message: 'Login successful',
92
+ data: result
93
+ };
94
+ } catch (error) {
95
+ return {
96
+ success: false,
97
+ message: error instanceof Error ? error.message : 'Login failed'
98
+ };
99
+ }
100
+ }
101
+ }];
102
+ }
103
+ }
104
+ ```
105
+
106
+ ### Token 验证
107
+
108
+ ```typescript
109
+ import { verifyToken, getUserById } from '@linyjs/auth';
110
+
111
+ class AuthController {
112
+ getRoutes() {
113
+ return [{
114
+ method: 'GET' as const,
115
+ path: '/api/auth/me',
116
+ middlewares: [],
117
+ responseType: 'json' as const,
118
+ handler: async (req: any) => {
119
+ const token = req.headers.authorization?.replace('Bearer ', '');
120
+
121
+ if (!token) {
122
+ return {
123
+ success: false,
124
+ message: 'No token provided'
125
+ };
126
+ }
127
+
128
+ try {
129
+ const payload = await verifyToken(token);
130
+ const user = await getUserById(payload.userId);
131
+
132
+ return {
133
+ success: true,
134
+ data: user
135
+ };
136
+ } catch (error) {
137
+ return {
138
+ success: false,
139
+ message: 'Invalid token'
140
+ };
141
+ }
142
+ }
143
+ }];
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## 认证中间件
149
+
150
+ ### 创建认证中间件
151
+
152
+ ```typescript
153
+ import { verifyToken, getUserById } from '@linyjs/auth';
154
+
155
+ async function authMiddleware(req: any, res: any, next: any) {
156
+ const token = req.headers.authorization?.replace('Bearer ', '');
157
+
158
+ if (!token) {
159
+ return res.status(401).json({
160
+ success: false,
161
+ message: 'Authentication token required'
162
+ });
163
+ }
164
+
165
+ try {
166
+ const payload = await verifyToken(token);
167
+ const user = await getUserById(payload.userId);
168
+
169
+ if (!user) {
170
+ return res.status(401).json({
171
+ success: false,
172
+ message: 'User not found'
173
+ });
174
+ }
175
+
176
+ // 将用户信息添加到请求对象
177
+ req.user = user;
178
+ req.userId = user._id;
179
+
180
+ next();
181
+ } catch (error) {
182
+ return res.status(401).json({
183
+ success: false,
184
+ message: 'Invalid authentication token'
185
+ });
186
+ }
187
+ }
188
+ ```
189
+
190
+ ### 使用认证中间件
191
+
192
+ ```typescript
193
+ class ProtectedController {
194
+ getRoutes() {
195
+ return [{
196
+ method: 'GET' as const,
197
+ path: '/api/protected',
198
+ middlewares: [authMiddleware], // 使用认证中间件
199
+ responseType: 'json' as const,
200
+ handler: async (req: any) => {
201
+ return {
202
+ success: true,
203
+ message: `Hello ${req.user.username}! You have access to this protected route.`
204
+ };
205
+ }
206
+ }];
207
+ }
208
+ }
209
+ ```
210
+
211
+ ## 客户端认证
212
+
213
+ ### 登录表单示例
214
+
215
+ ```typescript
216
+ import type { IModule } from '@linyjs/client-module-interface';
217
+ import React, { useState } from 'react';
218
+
219
+ function LoginForm() {
220
+ const [formData, setFormData] = useState({
221
+ identifier: '',
222
+ password: ''
223
+ });
224
+ const [error, setError] = useState('');
225
+
226
+ const handleSubmit = async (e: React.FormEvent) => {
227
+ e.preventDefault();
228
+
229
+ try {
230
+ const response = await fetch('/api/auth/login', {
231
+ method: 'POST',
232
+ headers: {
233
+ 'Content-Type': 'application/json'
234
+ },
235
+ body: JSON.stringify(formData)
236
+ });
237
+
238
+ const result = await response.json();
239
+
240
+ if (result.success) {
241
+ // 保存 token 到 localStorage 或 cookie
242
+ localStorage.setItem('token', result.data.token);
243
+ // 跳转或刷新页面
244
+ window.location.reload();
245
+ } else {
246
+ setError(result.message);
247
+ }
248
+ } catch (err) {
249
+ setError('Network error');
250
+ }
251
+ };
252
+
253
+ return (
254
+ <form onSubmit={handleSubmit}>
255
+ <div>
256
+ <label>用户名或邮箱:</label>
257
+ <input
258
+ type="text"
259
+ value={formData.identifier}
260
+ onChange={(e) => setFormData({ ...formData, identifier: e.target.value })}
261
+ required
262
+ />
263
+ </div>
264
+ <div>
265
+ <label>密码:</label>
266
+ <input
267
+ type="password"
268
+ value={formData.password}
269
+ onChange={(e) => setFormData({ ...formData, password: e.target.value })}
270
+ required
271
+ />
272
+ </div>
273
+ {error && <div className="error">{error}</div>}
274
+ <button type="submit">登录</button>
275
+ </form>
276
+ );
277
+ }
278
+
279
+ export const authClientModule: IModule = {
280
+ name: 'authClient',
281
+ serviceDefs: [{
282
+ serviceTag: 'loginForm',
283
+ serviceImpl: function() {
284
+ getComponents() {
285
+ return {
286
+ LoginForm: {
287
+ component: LoginForm,
288
+ meta: { usageType: 'normal_component' }
289
+ }
290
+ };
291
+ }
292
+ },
293
+ meta: { usageType: 'normal_service' }
294
+ }]
295
+ };
296
+ ```
297
+
298
+ ## 认证状态管理
299
+
300
+ ### 创建认证 Hook
301
+
302
+ ```typescript
303
+ import { useState, useEffect } from 'react';
304
+
305
+ interface User {
306
+ _id: string;
307
+ username: string;
308
+ email: string;
309
+ createdAt: Date;
310
+ roles?: string[];
311
+ }
312
+
313
+ export function useAuth() {
314
+ const [user, setUser] = useState<User | null>(null);
315
+ const [loading, setLoading] = useState(true);
316
+
317
+ useEffect(() => {
318
+ const token = localStorage.getItem('token');
319
+
320
+ if (!token) {
321
+ setLoading(false);
322
+ return;
323
+ }
324
+
325
+ fetch('/api/auth/me', {
326
+ headers: {
327
+ 'Authorization': `Bearer ${token}`
328
+ }
329
+ })
330
+ .then(response => response.json())
331
+ .then(result => {
332
+ if (result.success) {
333
+ setUser(result.data);
334
+ } else {
335
+ localStorage.removeItem('token');
336
+ }
337
+ })
338
+ .finally(() => {
339
+ setLoading(false);
340
+ });
341
+ }, []);
342
+
343
+ const login = async (identifier: string, password: string) => {
344
+ const response = await fetch('/api/auth/login', {
345
+ method: 'POST',
346
+ headers: {
347
+ 'Content-Type': 'application/json'
348
+ },
349
+ body: JSON.stringify({ identifier, password })
350
+ });
351
+
352
+ const result = await response.json();
353
+
354
+ if (result.success) {
355
+ localStorage.setItem('token', result.data.token);
356
+ setUser(result.data.user);
357
+ return true;
358
+ }
359
+
360
+ return false;
361
+ };
362
+
363
+ const logout = () => {
364
+ localStorage.removeItem('token');
365
+ setUser(null);
366
+ };
367
+
368
+ const isAuthenticated = !!user;
369
+
370
+ return {
371
+ user,
372
+ loading,
373
+ isAuthenticated,
374
+ login,
375
+ logout
376
+ };
377
+ }
378
+ ```
379
+
380
+ ## 最佳实践
381
+
382
+ ### 1. Token 存储
383
+ - 使用 `localStorage` 或 `cookie` 存储 token
384
+ - 考虑安全性时优先使用 `httpOnly` cookie
385
+ - 实现 token 自动刷新机制
386
+
387
+ ### 2. 错误处理
388
+ - 捕获并处理认证相关的错误
389
+ - 提供用户友好的错误消息
390
+ - 记录详细的错误日志用于调试
391
+
392
+ ### 3. 安全性
393
+ - 始终在服务端验证 token
394
+ - 不要在客户端存储敏感信息
395
+ - 使用强密码策略
396
+ - 考虑实现两步验证增强安全性
397
+
398
+ ### 4. 用户体验
399
+ - 记住用户的登录状态
400
+ - 自动续期 token 避免频繁登录
401
+ - 在 token 过期时友好提示用户
402
+
403
+ ## 故障排除
404
+
405
+ ### 常见问题
406
+
407
+ 1. **Token 无法验证**
408
+ - 检查 JWT_SECRET 是否正确配置
409
+ - 确认 token 未过期
410
+ - 验证 token 格式是否正确
411
+
412
+ 2. **用户无法登录**
413
+ - 检查用户名/邮箱和密码是否正确
414
+ - 确认用户账户已激活
415
+ - 检查数据库连接是否正常
416
+
417
+ 3. **中间件无法获取用户信息**
418
+ - 确认 token 在请求头中正确传递
419
+ - 检查 verifyToken 函数是否正常工作
420
+ - 验证 getUserById 是否能找到对应用户
@@ -306,6 +306,9 @@ npx @linyjs/cli validate *.mpk
306
306
  - 🔧 [API 参考](../../docs/api-reference/server-interface.md)
307
307
  - 📚 [服务端模块指南](../../docs/guides/server-module.md)
308
308
  - 🎨 [客户端模块指南](../../docs/guides/client-module.md)
309
+ - 💾 [数据持久化](../../docs/guides/data-persistence.md) - 使用 MongoDB 模块
310
+ - 🔐 [用户认证](../../docs/guides/authentication.md) - 使用 Auth 模块
311
+ - 🛡️ [权限管理](../../docs/guides/permissions.md) - 使用 Permission 模块
309
312
 
310
313
  ## 许可证
311
314
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linyjs/plugin-docs",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Plugin development documentation and examples for linyjs framework",
5
5
  "keywords": [
6
6
  "linyjs",