lakutata 3.1.4 → 3.1.5
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 +7 -7
- package/README.zh-CN.md +4 -4
- package/dist/cjs/exports/NwjsAdapter.d.ts +1 -0
- package/dist/cjs/exports/NwjsAdapter.js +20 -0
- package/dist/esm/exports/NwjsAdapter.js +1 -0
- package/dist/types/exports/NwjsAdapter.d.ts +1 -0
- package/doc/en/Application.md +1 -1
- package/doc/en/Cache.md +2 -1
- package/doc/en/Command.md +10 -4
- package/doc/en/ContainerdIntegration.md +1 -1
- package/doc/en/DatabaseDrivers.md +3 -2
- package/doc/en/Entrypoint.md +3 -2
- package/doc/en/Exceptions.md +1 -1
- package/doc/en/FFI.md +1 -1
- package/doc/en/GRPC.md +1 -1
- package/doc/en/GettingStarted.md +15 -2
- package/doc/en/HTTP.md +1 -0
- package/doc/en/I18n.md +1 -1
- package/doc/en/Installers.md +34 -6
- package/doc/en/Math.md +1 -1
- package/doc/en/NativeAddons.md +9 -2
- package/doc/en/Overview.md +6 -6
- package/doc/en/Packaging.md +4 -1
- package/doc/en/ProjectStructure.md +8 -3
- package/doc/en/ServiceCalls.md +47 -3
- package/doc/en/UpgradingFrom1.md +2 -2
- package/doc/en/UpgradingFrom2.md +4 -4
- package/doc/en/WebRTC.md +4 -4
- package/doc/zh/Application.md +1 -1
- package/doc/zh/Cache.md +1 -1
- package/doc/zh/Command.md +7 -3
- package/doc/zh/ContainerdIntegration.md +1 -1
- package/doc/zh/DatabaseDrivers.md +1 -1
- package/doc/zh/Entrypoint.md +2 -1
- package/doc/zh/Exceptions.md +1 -1
- package/doc/zh/FFI.md +1 -1
- package/doc/zh/GRPC.md +1 -1
- package/doc/zh/GettingStarted.md +11 -2
- package/doc/zh/HTTP.md +1 -0
- package/doc/zh/I18n.md +1 -1
- package/doc/zh/Installers.md +16 -5
- package/doc/zh/Math.md +1 -1
- package/doc/zh/NativeAddons.md +3 -2
- package/doc/zh/Overview.md +3 -3
- package/doc/zh/Packaging.md +4 -1
- package/doc/zh/ProjectStructure.md +4 -2
- package/doc/zh/ServiceCalls.md +39 -2
- package/doc/zh/UpgradingFrom1.md +2 -2
- package/doc/zh/UpgradingFrom2.md +3 -3
- package/doc/zh/WebRTC.md +1 -1
- package/package.json +26 -16
package/doc/zh/ServiceCalls.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lakutata 服务调用
|
|
2
2
|
|
|
3
|
-
服务动作(`@ServiceAction`)通过消息而不是 URL 来调用:消息是一个对象,其中一部分键用来选择动作,称为**模式**,其余的键就是输入。同一组动作可以同时通过多种传输方式提供:本指南介绍的普通 HTTP、Socket.IO、JSON-RPC 2.0(基于 HTTP、WebSocket
|
|
3
|
+
服务动作(`@ServiceAction`)通过消息而不是 URL 来调用:消息是一个对象,其中一部分键用来选择动作,称为**模式**,其余的键就是输入。同一组动作可以同时通过多种传输方式提供:本指南介绍的普通 HTTP、Socket.IO、JSON-RPC 2.0(基于 HTTP、WebSocket 或标准输入输出)、Electron 的 IPC 和 NW.js 的窗口,以及在各自指南中介绍的 gRPC、NATS 和 WebRTC 的数据通道。控制器及其动作见 [Controllers](Controllers.md),入口及其适配器见 [Entrypoint](Entrypoint.md)。
|
|
4
4
|
|
|
5
5
|
## 1. 第一个服务
|
|
6
6
|
|
|
@@ -128,7 +128,7 @@ class OrderController extends Controller {
|
|
|
128
128
|
|
|
129
129
|
## 3. 响应
|
|
130
130
|
|
|
131
|
-
HTTP 服务、Socket.IO 和
|
|
131
|
+
HTTP 服务、Socket.IO、Electron 和 NW.js 以封套响应;JSON-RPC 使用它自己的响应格式(第 4 节)。
|
|
132
132
|
|
|
133
133
|
```text
|
|
134
134
|
{"success": true, "error": null, "payload": <结果>}
|
|
@@ -165,6 +165,7 @@ export async function call<T>(message: Record<string, unknown>): Promise<T> {
|
|
|
165
165
|
| `socketIOServiceEntrypoint()` | `lakutata/adapter/socket.io` | `socket.io`(客户端需要 `socket.io-client`) | 带确认回调的 emit | Socket.IO 事件 |
|
|
166
166
|
| `jsonRPCServiceEntrypoint()` | `lakutata/adapter/jsonrpc` | WebSocket 需要 `ws` | JSON-RPC 2.0 请求 | 通知(WebSocket、stdio) |
|
|
167
167
|
| `electronIPCServiceEntrypoint()` | `lakutata/adapter/electron` | (Electron) | `ipcRenderer.invoke()` | IPC 消息 |
|
|
168
|
+
| `nwjsServiceEntrypoint()` | `lakutata/adapter/nwjs` | (NW.js) | 窗口的宿主页面对桥接对象的一次调用 | 调用宿主页面交给它的函数 |
|
|
168
169
|
| `grpcServiceEntrypoint()` | `@lakutata/grpc/service` | `@lakutata/grpc` | 见 [GRPC](GRPC.md) | gRPC 流 |
|
|
169
170
|
| `natsServiceEntrypoint()` | `@lakutata/nats` | `@lakutata/nats` | 见 [NATS](NATS.md) | NATS 消息 |
|
|
170
171
|
| `webrtcServiceEntrypoint()` | `@lakutata/webrtc` | `@lakutata/webrtc` | 数据通道上的 JSON-RPC 2.0 请求,见 [WebRTC](WebRTC.md) | 通知 |
|
|
@@ -420,6 +421,40 @@ contextBridge.exposeInMainWorld('service', {
|
|
|
420
421
|
- `lakutata/adapter/electron` 中的 `ipcEventOfContext(this.context)` 返回请求的 IPC 事件,用来找到发出请求的窗口。
|
|
421
422
|
- `lakutata create` 的 Electron 模板包含同样形式的预加载脚本,并为页面提供了 `window.ipc`,它的 `invoke()` 返回结果,或者抛出错误。
|
|
422
423
|
|
|
424
|
+
### NW.js
|
|
425
|
+
|
|
426
|
+
`nwjsServiceEntrypoint()` 在 NW.js 应用的后台脚本(它的 Node.js 上下文)中,向它的窗口提供动作。NW.js 让窗口里的页面都能使用 Node.js,页面里的 iframe 也挡不住 iframe 中的内容使用它(iframe 的 sandbox 会被忽略):所以用户界面运行在没有 Node.js 的 `<webview>` 中,由窗口里一个受信任的页面(宿主页面)承载。适配器在 NW.js 与窗口共享的全局对象上放一个桥接对象 `global[Symbol.for(key)]`;宿主页面把界面的请求转发给它,并把向界面推送事件的函数交给它。
|
|
427
|
+
|
|
428
|
+
| 选项 | 默认值 | 含义 |
|
|
429
|
+
|---|---|---|
|
|
430
|
+
| `key` | `'lakutata:service'`(`NWJS_SERVICE_BRIDGE`) | 桥接对象在全局对象上的键 |
|
|
431
|
+
| `global` | NW.js 的全局对象 | 放置桥接对象的对象,测试时可以传入替身 |
|
|
432
|
+
|
|
433
|
+
| 桥接对象的方法 | 含义 |
|
|
434
|
+
|---|---|
|
|
435
|
+
| `invoke(message, clientId)` | 调用一个动作:解析为封套,从不拒绝 |
|
|
436
|
+
| `subscribe(clientId, push)` | 把一个页面登记为客户端:推送给它的事件交给 `push(event, args)` |
|
|
437
|
+
| `unsubscribe(clientId)` | 页面重新加载或窗口关闭时移除这个客户端:它进行中的请求会被中止 |
|
|
438
|
+
|
|
439
|
+
宿主页面只转发自己的 `<webview>` 里加载的页面发来的消息:
|
|
440
|
+
|
|
441
|
+
```javascript
|
|
442
|
+
const view = document.querySelector('webview')
|
|
443
|
+
const origin = new URL(view.src).origin
|
|
444
|
+
const bridge = global[Symbol.for('lakutata:service')]
|
|
445
|
+
const send = (message) => view.contentWindow.postMessage(message, origin)
|
|
446
|
+
window.addEventListener('message', async (event) => {
|
|
447
|
+
if (event.source !== view.contentWindow || event.origin !== origin) return
|
|
448
|
+
const {type, id, message, clientId} = event.data
|
|
449
|
+
if (type === 'invoke') send({type: 'response', id: id, response: await bridge.invoke(message, clientId)})
|
|
450
|
+
if (type === 'subscribe') bridge.subscribe(clientId, (name, args) => send({type: 'event', name: name, args: args}))
|
|
451
|
+
})
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
- `<webview>` 的分区在 NW.js 的清单中声明过,它才能加载应用的文件:`"webview": {"partitions": [{"name": "trusted", "accessible_resources": ["<all_urls>"]}]}`(由构建器写入)。
|
|
455
|
+
- `<webview>` 里重新加载的页面是一个新的客户端:宿主页面会取消前一个客户端的订阅。
|
|
456
|
+
- `lakutata create` 的 NW.js 模板包含这样的宿主页面(`packages/app/host`),并为界面提供了和 Electron 模板一样的 `window.ipc`。
|
|
457
|
+
|
|
423
458
|
## 5. 客户端与事件
|
|
424
459
|
|
|
425
460
|
保持连接的传输方式可以向客户端推送事件。客户端通过它给出的 id 来识别:
|
|
@@ -432,6 +467,7 @@ contextBridge.exposeInMainWorld('service', {
|
|
|
432
467
|
| 基于 WebSocket 的 JSON-RPC | 连接的 `id` 请求头或 `id` 查询参数,否则为随机 id |
|
|
433
468
|
| 基于 stdio 的 JSON-RPC | `'stdio'` |
|
|
434
469
|
| Electron | 页面在订阅或调用时给出的 id |
|
|
470
|
+
| NW.js | 宿主页面为它的页面交给桥接对象的 id |
|
|
435
471
|
| WebRTC | 调用方在房间里的成员 id |
|
|
436
472
|
|
|
437
473
|
动作从 `this.context.clientId` 读取它的客户端 id。`entrypoint` 组件负责推送事件:
|
|
@@ -466,6 +502,7 @@ class TaskController extends Controller {
|
|
|
466
502
|
| Socket.IO | `socket.on('progress', (percent, label) => …)` |
|
|
467
503
|
| JSON-RPC(WebSocket、stdio) | `{"jsonrpc": "2.0", "method": "progress", "params": [50, "half"]}` |
|
|
468
504
|
| Electron | 通过上面预加载脚本中的 `subscribe` 收到 `('progress', [50, 'half'])` |
|
|
505
|
+
| NW.js | 交给桥接对象 `subscribe` 的函数收到 `('progress', [50, 'half'])` |
|
|
469
506
|
| WebRTC | `PeerServiceProxy` 的 `proxy.on('progress', (percent, label) => …)` |
|
|
470
507
|
|
|
471
508
|
## 6. 停止与离开
|
package/doc/zh/UpgradingFrom1.md
CHANGED
|
@@ -13,7 +13,7 @@ Lakutata 1.x 是一组包:`@lakutata/core` 1.x、模块 `@lakutata-module/*`
|
|
|
13
13
|
| 模块系统 | CommonJS:导入不带扩展名,使用 `__dirname` | ES 模块:相对导入以 `.js` 结尾 |
|
|
14
14
|
| 服务动作 | `@lakutata-module/service` 的 `@Controller({_ctrl: …})` 和 `@PATTERN({_act: …})` | `lakutata/decorator/ctrl` 的 `@ServiceAction({…})` |
|
|
15
15
|
| 校验 | 交给 `@Accept` 的 `Validator` schema(yup) | 带 `@Expect` 的 DTO 类 |
|
|
16
|
-
| Node.js | `>=14.15.1`(`@lakutata/core` 1.0.60) |
|
|
16
|
+
| Node.js | `>=14.15.1`(`@lakutata/core` 1.0.60) | `>=18.10.0` |
|
|
17
17
|
|
|
18
18
|
**3.x 的 `@lakutata/core` 不是 1.x 那个库的新版本。** 它是 Lakutata 3 的核心,只是用了同一个名字,API 完全不同。在 1.x 项目中执行 `npm install @lakutata/core@latest`,或者使用 `*` 这样的版本范围,都会用它替换 1.x 的核心库,导致构建失败。不要逐个升级 1.x 的包:移植后的应用依赖 `lakutata` 3,它会带来自己的 `@lakutata/core`。
|
|
19
19
|
|
|
@@ -314,7 +314,7 @@ Application.run(() => ({
|
|
|
314
314
|
|
|
315
315
|
- **测试。** 1.x 中连接共享开发服务器、直接启动应用的 `npm test`,改为对编译后的测试运行 `node --test`:每个测试文件用 `Application.run(config(port))` 在自己的端口上启动应用,调用它,最后释放它;组件放在 `Container` 中单独测试;其他服务用替身代替(见[示例](examples/README.md))。
|
|
316
316
|
- **`package.json` 中的 `lakutata` 字段**在 1.x 中告诉命令行工具项目的类型(`type`)、目录和配置文件。在 3.x 中这个字段有别的含义(打包应用的 `resources` 和 `installer`,见 [Packaging](Packaging.md)):请删除 1.x 的这个字段。
|
|
317
|
-
- **Node.js、TypeScript 和模块系统。** Node.js
|
|
317
|
+
- **Node.js、TypeScript 和模块系统。** Node.js `>=18.10.0`,与模板一样使用 TypeScript 6,ES 模块(`"type": "module"`,相对导入以 `.js` 结尾),`tsconfig.json` 继承 `lakutata/tsconfig.json`。
|
|
318
318
|
- **端口。** 1.x 的服务模块监听自己的端口(默认 6912),注册中心监听另一个端口(6911)。3.x 的适配器监听各自选项中的端口,而使用 NATS 的服务只主动连接 NATS 服务器:`Dockerfile` 改为暴露这些端口。
|
|
319
319
|
- **脚本。** 模板的脚本取代了 `shx rm -rf ./build`(改为 `lakutata clean`)、安装时编译的 `prepare`,以及开发入口;`lakutata-deploy` 没有对应项:`service` 模板带有 `Dockerfile` 和 `docker:build` 脚本,镜像由部署环境自己的工具推送。
|
|
320
320
|
|
package/doc/zh/UpgradingFrom2.md
CHANGED
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
| 导出的函数 | 大驼峰:`BuildEntrypoints`、`BuildDatabaseOptions`、`MD5` | 小驼峰:`buildEntrypoints`、`buildDatabaseOptions`、`md5` |
|
|
15
15
|
| 传输方式 | 手写:`BuildHTTPEntrypoint((module, routeMap, handler, registerDestroy) => …)` | 适配器:`lakutata/adapter/express` 中的 `expressHTTPEntrypoint()` 等 |
|
|
16
16
|
| 只有 3.x 才有的子路径 | | `lakutata/utils`、`lakutata/security`、`lakutata/adapter/*`、`lakutata/com/{containerd,mutex,queue,i18n}` |
|
|
17
|
-
| Node.js | `>=20` |
|
|
17
|
+
| Node.js | `>=20` | `>=18.10.0` |
|
|
18
18
|
|
|
19
19
|
`npx @lakutata/cli info` 会显示命令行工具、框架和 Node.js 的版本,以及项目声明的和实际安装的 `lakutata` 版本。没有升级命令:下面的步骤需要手动完成。
|
|
20
20
|
|
|
21
21
|
## 2. 升级步骤
|
|
22
22
|
|
|
23
|
-
- **Node.js** `^22.13.0 || >=24.11.0
|
|
23
|
+
- **Node.js** `>=18.10.0`(3.0 到 3.1 需要 `^22.13.0 || >=24.11.0`)。2.x 需要的版本(`>=20`)都包括在内:`engines`、CI 的版本矩阵和 Dockerfile 都可以不变。
|
|
24
24
|
- **支持 `"module": "Node20"` 的 TypeScript**(模板使用 TypeScript 6):`lakutata/tsconfig.json` 现在设置了这个选项(2.x 中是 `Node16`),更旧的编译器不认识它。
|
|
25
25
|
- **`package.json`**:`"type": "module"`,`lakutata` 为 `^3.0.0`,`@lakutata/*` 包也写 `^3.0.0`,`@lakutata/cli` 放在 `devDependencies` 中。不要把 `lakutata` 的版本号照抄给其他包:补丁版只发布改动过的包,各包的最新版本可能不同(比如 `lakutata` 是 3.1.4,`@lakutata/ffi` 是 3.1.2)。
|
|
26
26
|
- **全新安装**:删除 `node_modules` 和锁文件,再重新安装。原地升级可能留下多份 `@lakutata/core`,它们的类和装饰器元数据互不相通(跨副本的 `instanceof` 和注入都会失败)。`npm ls @lakutata/core` 必须只显示一个版本。
|
|
@@ -204,7 +204,7 @@ Application
|
|
|
204
204
|
## 6. 检查升级结果
|
|
205
205
|
|
|
206
206
|
```bash
|
|
207
|
-
node --version #
|
|
207
|
+
node --version # >=18.10.0
|
|
208
208
|
npm ls lakutata @lakutata/core # 每个包只有一个版本
|
|
209
209
|
npm run build # tsc 没有错误:没有遗留的 2.x 导入
|
|
210
210
|
grep -rnE "process\.on\('SIG|\|\| ''|(startup|launched|beforeDestroy|acceptsOption)\(|AccessDenyException|=== 500" src
|
package/doc/zh/WebRTC.md
CHANGED
|
@@ -163,7 +163,7 @@ export class Telemetry extends Component {
|
|
|
163
163
|
}
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
`http:` 或 `https:` 的 URL 使用 Socket.IO(需要安装 `socket.io-client`),`ws:` 或 `wss:` 的 URL 使用 Node.js 22 和 Bun 自带的 `WebSocket` 走 JSON-RPC
|
|
166
|
+
`http:` 或 `https:` 的 URL 使用 Socket.IO(需要安装 `socket.io-client`),`ws:` 或 `wss:` 的 URL 使用 Node.js 22 和 Bun 自带的 `WebSocket` 走 JSON-RPC,没有时使用 `ws` 包的 `WebSocket`(需要安装 `ws`)。它的选项:`url`、`id`(默认是随机的 UUID)、`path`(Socket.IO 的路径)、`auth`(Socket.IO 握手的更多字段,比如令牌)、`timeout`,以及它的连接的选项(`iceTransportPolicy`、`icePortRange`、`iceAdditionalHostAddresses`、`codecs`、`threads`)。它是 `@Transient` 的:每次 `getObject()` 都得到一个新的客户端,`close()` 会离开它的房间并断开连接。
|
|
167
167
|
|
|
168
168
|
### 调用应用的动作
|
|
169
169
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lakutata",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.5",
|
|
4
4
|
"description": "An IoC application framework for Node.js and TypeScript: one programming model for web services, CLI tools, desktop (Electron) and embedded applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -194,6 +194,16 @@
|
|
|
194
194
|
"default": "./dist/cjs/exports/ElectronAdapter.js"
|
|
195
195
|
}
|
|
196
196
|
},
|
|
197
|
+
"./adapter/nwjs": {
|
|
198
|
+
"import": {
|
|
199
|
+
"types": "./dist/types/exports/NwjsAdapter.d.ts",
|
|
200
|
+
"default": "./dist/esm/exports/NwjsAdapter.js"
|
|
201
|
+
},
|
|
202
|
+
"require": {
|
|
203
|
+
"types": "./dist/cjs/exports/NwjsAdapter.d.ts",
|
|
204
|
+
"default": "./dist/cjs/exports/NwjsAdapter.js"
|
|
205
|
+
}
|
|
206
|
+
},
|
|
197
207
|
"./com/logger": {
|
|
198
208
|
"import": {
|
|
199
209
|
"types": "./dist/types/exports/LoggerComponent.d.ts",
|
|
@@ -314,7 +324,7 @@
|
|
|
314
324
|
}
|
|
315
325
|
},
|
|
316
326
|
"engines": {
|
|
317
|
-
"node": "
|
|
327
|
+
"node": ">=18.10.0"
|
|
318
328
|
},
|
|
319
329
|
"author": "alex.ma",
|
|
320
330
|
"license": "MIT",
|
|
@@ -354,19 +364,19 @@
|
|
|
354
364
|
"mcp"
|
|
355
365
|
],
|
|
356
366
|
"dependencies": {
|
|
357
|
-
"@lakutata/cache": "3.1.
|
|
358
|
-
"@lakutata/containerd": "3.1.
|
|
359
|
-
"@lakutata/core": "3.1.
|
|
360
|
-
"@lakutata/docker": "3.1.
|
|
361
|
-
"@lakutata/entrypoint": "3.1.
|
|
362
|
-
"@lakutata/i18n": "3.1.
|
|
363
|
-
"@lakutata/logger": "3.1.
|
|
364
|
-
"@lakutata/monitor": "3.1.
|
|
365
|
-
"@lakutata/mutex": "3.1.
|
|
366
|
-
"@lakutata/orm": "3.1.
|
|
367
|
-
"@lakutata/queue": "3.1.
|
|
368
|
-
"@lakutata/security": "3.1.
|
|
369
|
-
"@lakutata/utils": "3.1.
|
|
367
|
+
"@lakutata/cache": "3.1.5",
|
|
368
|
+
"@lakutata/containerd": "3.1.5",
|
|
369
|
+
"@lakutata/core": "3.1.5",
|
|
370
|
+
"@lakutata/docker": "3.1.5",
|
|
371
|
+
"@lakutata/entrypoint": "3.1.5",
|
|
372
|
+
"@lakutata/i18n": "3.1.5",
|
|
373
|
+
"@lakutata/logger": "3.1.5",
|
|
374
|
+
"@lakutata/monitor": "3.1.5",
|
|
375
|
+
"@lakutata/mutex": "3.1.5",
|
|
376
|
+
"@lakutata/orm": "3.1.5",
|
|
377
|
+
"@lakutata/queue": "3.1.5",
|
|
378
|
+
"@lakutata/security": "3.1.5",
|
|
379
|
+
"@lakutata/utils": "3.1.5"
|
|
370
380
|
},
|
|
371
381
|
"files": [
|
|
372
382
|
"dist",
|
|
@@ -379,7 +389,7 @@
|
|
|
379
389
|
],
|
|
380
390
|
"peerDependencies": {
|
|
381
391
|
"@inquirer/prompts": "^7.0.0 || ^8.0.0",
|
|
382
|
-
"@lakutata/netif": "~3.1.
|
|
392
|
+
"@lakutata/netif": "~3.1.5",
|
|
383
393
|
"commander": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0",
|
|
384
394
|
"express": "^4.21.0 || ^5.0.0",
|
|
385
395
|
"fastify": "^5.0.0",
|