imean-service-engine 1.5.0 → 1.7.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 CHANGED
@@ -18,6 +18,7 @@
18
18
  - 支持双向通信
19
19
  - 使用 Brotli 压缩,减少数据传输量
20
20
  - 自动重连和心跳检测
21
+ - 🌐 内置 PageRenderPlugin 支持服务端渲染页面,集成 HTMX 和 Hyperscript
21
22
 
22
23
  ## TODOs
23
24
 
@@ -135,6 +136,273 @@ const found = await client.users.getUser(user.id);
135
136
 
136
137
  ## 高级特性
137
138
 
139
+ ### PageRenderPlugin - 服务端渲染页面
140
+
141
+ PageRenderPlugin 为微服务框架提供了服务端渲染页面的能力,集成了 HTMX 和 Hyperscript,让你可以轻松构建现代化的 Web 应用。
142
+
143
+ #### 启用 PageRenderPlugin
144
+
145
+ ```typescript
146
+ import { Microservice, PageRenderPlugin } from "imean-service-engine";
147
+
148
+ const service = new Microservice({
149
+ modules: [UserService],
150
+ plugins: [new PageRenderPlugin()],
151
+ });
152
+ ```
153
+
154
+ #### 使用 @Page 装饰器
155
+
156
+ 使用 `@Page` 装饰器可以将模块方法暴露为 Web 页面:
157
+
158
+ ```typescript
159
+ import { Page, HtmxLayout } from "imean-service-engine";
160
+
161
+ @Module("web")
162
+ class WebService {
163
+ @Page({
164
+ path: "/greeting",
165
+ method: "get",
166
+ description: "问候页面",
167
+ })
168
+ greetingPage(ctx: Context) {
169
+ return (
170
+ <HtmxLayout title="问候页面">
171
+ <div class="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 p-8">
172
+ <div class="max-w-4xl mx-auto">
173
+ <h1 class="text-4xl font-bold text-center text-gray-800 mb-8">
174
+ HTMX 交互示例
175
+ </h1>
176
+ <div class="bg-white rounded-lg shadow-lg p-6">
177
+ <h2 class="text-2xl font-semibold mb-4 text-gray-700">问候语</h2>
178
+ <div id="greeting" class="text-xl p-4 bg-blue-50 rounded-lg">
179
+ 欢迎使用微服务框架!
180
+ </div>
181
+ <button
182
+ class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
183
+ hx-post="/api/greeting"
184
+ hx-target="#greeting"
185
+ hx-swap="innerHTML"
186
+ >
187
+ 更新问候语
188
+ </button>
189
+ </div>
190
+ </div>
191
+ </div>
192
+ </HtmxLayout>
193
+ );
194
+ }
195
+
196
+ @Page({
197
+ path: "/greeting",
198
+ method: "post",
199
+ description: "更新问候语",
200
+ })
201
+ updateGreeting(ctx: Context) {
202
+ return "你好,世界!当前时间:" + new Date().toLocaleString();
203
+ }
204
+ }
205
+ ```
206
+
207
+ #### JSX 配置
208
+
209
+ 要使用 JSX 语法,需要在 `tsconfig.json` 中配置:
210
+
211
+ ```json
212
+ {
213
+ "compilerOptions": {
214
+ "jsx": "react-jsx",
215
+ "jsxImportSource": "hono/jsx"
216
+ }
217
+ }
218
+ ```
219
+
220
+ #### HtmxLayout 组件
221
+
222
+ `HtmxLayout` 提供了预配置的页面布局,包含:
223
+
224
+ - HTMX 库(最新版本)
225
+ - Hyperscript 库(最新版本)
226
+ - Tailwind CSS(CDN 版本)
227
+ - 响应式设计支持
228
+ - 默认图标
229
+
230
+ ```typescript
231
+ import { HtmxLayout } from "imean-service-engine";
232
+
233
+ // 基本用法
234
+ const page = (
235
+ <HtmxLayout title="我的页面">
236
+ <div>页面内容</div>
237
+ </HtmxLayout>
238
+ );
239
+
240
+ // 自定义图标
241
+ const pageWithCustomIcon = (
242
+ <HtmxLayout title="我的页面" favicon={<link rel="icon" href="/custom-icon.ico" />}>
243
+ <div>页面内容</div>
244
+ </HtmxLayout>
245
+ );
246
+ ```
247
+
248
+ #### BaseLayout 组件
249
+
250
+ 如果你不想使用 HTMX 和 Hyperscript,而是想使用其他前端框架(如 React、Vue 等),可以使用 `BaseLayout` 组件:
251
+
252
+ ```typescript
253
+ import { BaseLayout } from "imean-service-engine";
254
+
255
+ // 使用 BaseLayout 自定义页面
256
+ const customPage = (
257
+ <BaseLayout title="自定义页面">
258
+ <div>页面内容</div>
259
+ </BaseLayout>
260
+ );
261
+
262
+ // 自定义头部内容
263
+ const pageWithCustomHead = (
264
+ <BaseLayout
265
+ title="自定义页面"
266
+ heads={
267
+ <>
268
+ <link rel="stylesheet" href="/custom.css" />
269
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
270
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
271
+ </>
272
+ }
273
+ >
274
+ <div id="root">React 应用将在这里渲染</div>
275
+ </BaseLayout>
276
+ );
277
+ ```
278
+
279
+ `BaseLayout` 提供:
280
+ - 基本的 HTML 结构
281
+ - 可自定义的 `<head>` 内容
282
+ - 可自定义的页面标题
283
+ - 可自定义的图标
284
+
285
+ #### HTMX 交互示例
286
+
287
+ 结合 HTMX 可以实现丰富的交互效果:
288
+
289
+ ```typescript
290
+ @Page({
291
+ path: "/users",
292
+ method: "get",
293
+ description: "用户列表页面",
294
+ })
295
+ usersPage(ctx: Context) {
296
+ return (
297
+ <HtmxLayout title="用户管理">
298
+ <div class="container mx-auto p-8">
299
+ <h1 class="text-3xl font-bold mb-6">用户管理</h1>
300
+
301
+ {/* 用户列表 */}
302
+ <div
303
+ id="user-list"
304
+ hx-get="/api/users/list"
305
+ hx-trigger="load"
306
+ >
307
+ 加载中...
308
+ </div>
309
+
310
+ {/* 添加用户表单 */}
311
+ <div class="mt-8 bg-white rounded-lg shadow p-6">
312
+ <h2 class="text-xl font-semibold mb-4">添加新用户</h2>
313
+ <form
314
+ hx-post="/api/users/add"
315
+ hx-target="#user-list"
316
+ hx-swap="outerHTML"
317
+ >
318
+ <div class="grid grid-cols-2 gap-4">
319
+ <input
320
+ type="text"
321
+ name="name"
322
+ placeholder="姓名"
323
+ class="px-3 py-2 border rounded-md"
324
+ required
325
+ />
326
+ <input
327
+ type="number"
328
+ name="age"
329
+ placeholder="年龄"
330
+ class="px-3 py-2 border rounded-md"
331
+ required
332
+ />
333
+ </div>
334
+ <button
335
+ type="submit"
336
+ class="mt-4 px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
337
+ >
338
+ 添加用户
339
+ </button>
340
+ </form>
341
+ </div>
342
+ </div>
343
+ </HtmxLayout>
344
+ );
345
+ }
346
+ ```
347
+
348
+ #### Hyperscript 增强交互
349
+
350
+ 使用 Hyperscript 可以实现更复杂的客户端逻辑:
351
+
352
+ ```typescript
353
+ // 带加载状态的按钮
354
+ <button
355
+ hx-post="/api/users/refresh"
356
+ hx-target="#user-list"
357
+ hx-swap="innerHTML"
358
+ _="on htmx:beforeRequest hide #button-text then show #loading-spinner end
359
+ on htmx:afterRequest hide #loading-spinner then show #button-text end"
360
+ >
361
+ <span id="loading-spinner" class="htmx-indicator">
362
+ <svg class="animate-spin h-4 w-4" viewBox="0 0 24 24">
363
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
364
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
365
+ </svg>
366
+ 加载中...
367
+ </span>
368
+ <span id="button-text">刷新用户列表</span>
369
+ </button>
370
+ ```
371
+
372
+ #### 服务状态页面
373
+
374
+ PageRenderPlugin 自动在服务根路径(`/api`)提供服务的状态页面,显示:
375
+
376
+ - 服务基本信息(名称、版本、环境)
377
+ - 模块列表和 API 端点
378
+ - 服务健康状态
379
+
380
+ 访问 `http://localhost:3000/api` 即可查看服务状态页面。
381
+
382
+ #### 最佳实践
383
+
384
+ 1. **页面组织**:将页面逻辑与 API 逻辑分离
385
+ 2. **组件复用**:使用 HtmxLayout 确保一致的页面结构
386
+ 3. **渐进增强**:优先使用 HTMX 实现交互,必要时使用 Hyperscript
387
+ 4. **响应式设计**:利用 Tailwind CSS 构建响应式界面
388
+ 5. **布局选择**:
389
+ - 使用 `HtmxLayout` 进行快速原型开发和简单交互
390
+ - 使用 `BaseLayout` 集成复杂的前端框架(React、Vue 等)
391
+ - 根据项目需求选择合适的布局组件
392
+
393
+ ```typescript
394
+ // 推荐的目录结构
395
+ src/
396
+ ├── pages/ # 页面组件
397
+ │ ├── users.tsx
398
+ │ └── dashboard.tsx
399
+ ├── services/ # 服务模块
400
+ │ ├── user.ts
401
+ │ └── web.ts
402
+ └── layouts/ # 自定义布局
403
+ └── admin.tsx
404
+ ```
405
+
138
406
  ### 幂等性和重试机制
139
407
 
140
408
  框架提供了智能的重试机制,但仅对标记为幂等的操作生效:
@@ -180,6 +448,35 @@ interface ActionOptions {
180
448
  }
181
449
  ```
182
450
 
451
+ #### @Page(options: PageOptions)
452
+
453
+ 定义一个页面路由(需要启用 PageRenderPlugin)。
454
+
455
+ ```typescript
456
+ interface PageOptions {
457
+ method: "get" | "post" | "put" | "delete" | "patch" | "options";
458
+ path: string;
459
+ description?: string;
460
+ }
461
+ ```
462
+
463
+ 示例:
464
+
465
+ ```typescript
466
+ @Page({
467
+ path: "/dashboard",
468
+ method: "get",
469
+ description: "仪表板页面",
470
+ })
471
+ dashboardPage(ctx: Context) {
472
+ return (
473
+ <HtmxLayout title="仪表板">
474
+ <div>仪表板内容</div>
475
+ </HtmxLayout>
476
+ );
477
+ }
478
+ ```
479
+
183
480
  ### Microservice
184
481
 
185
482
  #### constructor(options: MicroserviceOptions)
@@ -190,6 +487,7 @@ interface ActionOptions {
190
487
  interface MicroserviceOptions {
191
488
  modules: (new () => any)[]; // 模块类数组
192
489
  prefix?: string; // API 前缀,默认为 "/api"
490
+ plugins?: Plugin[]; // 插件数组,如 PageRenderPlugin
193
491
  }
194
492
  ```
195
493