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/en/ServiceCalls.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A service action (`@ServiceAction`) is called with a message rather than a URL: an object whose keys select the action,
|
|
4
4
|
its **pattern**, and whose other keys are the input. The same actions can be served over several transports at once:
|
|
5
|
-
plain HTTP, Socket.IO, JSON-RPC 2.0 (over HTTP, WebSocket or the standard input and output)
|
|
6
|
-
this guide describes, and gRPC, NATS and the data channels of WebRTC, which have their own guides. The controllers and
|
|
5
|
+
plain HTTP, Socket.IO, JSON-RPC 2.0 (over HTTP, WebSocket or the standard input and output), the IPC of Electron and the
|
|
6
|
+
windows of NW.js, as this guide describes, and gRPC, NATS and the data channels of WebRTC, which have their own guides. The controllers and
|
|
7
7
|
their actions are described in [Controllers](Controllers.md), the entrypoint and its adapters in
|
|
8
8
|
[Entrypoint](Entrypoint.md).
|
|
9
9
|
|
|
@@ -136,7 +136,7 @@ class OrderController extends Controller {
|
|
|
136
136
|
|
|
137
137
|
## 3. The response
|
|
138
138
|
|
|
139
|
-
The HTTP service, Socket.IO and
|
|
139
|
+
The HTTP service, Socket.IO, Electron and NW.js answer with an envelope; JSON-RPC answers with its own responses (section 4).
|
|
140
140
|
|
|
141
141
|
```text
|
|
142
142
|
{"success": true, "error": null, "payload": <the result>}
|
|
@@ -179,6 +179,7 @@ export async function call<T>(message: Record<string, unknown>): Promise<T> {
|
|
|
179
179
|
| `socketIOServiceEntrypoint()` | `lakutata/adapter/socket.io` | `socket.io` (`socket.io-client` on the clients) | An emit with an acknowledgement | Socket.IO events |
|
|
180
180
|
| `jsonRPCServiceEntrypoint()` | `lakutata/adapter/jsonrpc` | `ws`, for WebSocket | A JSON-RPC 2.0 request | Notifications (WebSocket, stdio) |
|
|
181
181
|
| `electronIPCServiceEntrypoint()` | `lakutata/adapter/electron` | (Electron) | `ipcRenderer.invoke()` | IPC messages |
|
|
182
|
+
| `nwjsServiceEntrypoint()` | `lakutata/adapter/nwjs` | (NW.js) | A call of its bridge, by the host page of a window | Calls of the function the host page gives |
|
|
182
183
|
| `grpcServiceEntrypoint()` | `@lakutata/grpc/service` | `@lakutata/grpc` | See [GRPC](GRPC.md) | gRPC streams |
|
|
183
184
|
| `natsServiceEntrypoint()` | `@lakutata/nats` | `@lakutata/nats` | See [NATS](NATS.md) | NATS messages |
|
|
184
185
|
| `webrtcServiceEntrypoint()` | `@lakutata/webrtc` | `@lakutata/webrtc` | A JSON-RPC 2.0 request on a data channel, see [WebRTC](WebRTC.md) | Notifications |
|
|
@@ -468,6 +469,47 @@ contextBridge.exposeInMainWorld('service', {
|
|
|
468
469
|
- The Electron templates of `lakutata create` contain a preload script of this shape, and a `window.ipc` for the pages,
|
|
469
470
|
whose `invoke()` returns the payload or throws the error.
|
|
470
471
|
|
|
472
|
+
### NW.js
|
|
473
|
+
|
|
474
|
+
`nwjsServiceEntrypoint()` serves the actions to the windows of an NW.js application, in its background script (its
|
|
475
|
+
Node.js context). NW.js gives Node.js to the pages of its windows, and an iframe of such a page does not keep Node.js
|
|
476
|
+
from its content (its sandbox is ignored): the user interface runs in a `<webview>`, without Node.js, held by a trusted
|
|
477
|
+
page of the window (its host page). The adapter puts a bridge on the global object that NW.js shares with its windows,
|
|
478
|
+
`global[Symbol.for(key)]`; the host page forwards the requests of the interface to it, and gives it the function that
|
|
479
|
+
pushes the events to the interface.
|
|
480
|
+
|
|
481
|
+
| Option | Default | Meaning |
|
|
482
|
+
|---|---|---|
|
|
483
|
+
| `key` | `'lakutata:service'` (`NWJS_SERVICE_BRIDGE`) | The key of the bridge on the global object |
|
|
484
|
+
| `global` | the global object of NW.js | The object the bridge is put on, or a stand-in in the tests |
|
|
485
|
+
|
|
486
|
+
| Method of the bridge | Meaning |
|
|
487
|
+
|---|---|
|
|
488
|
+
| `invoke(message, clientId)` | Invokes an action: resolves to the envelope, never rejects |
|
|
489
|
+
| `subscribe(clientId, push)` | Makes a page a client: the events pushed to it are given to `push(event, args)` |
|
|
490
|
+
| `unsubscribe(clientId)` | Removes a client, when its page is loaded again or its window closed: its requests in progress are aborted |
|
|
491
|
+
|
|
492
|
+
The host page forwards the messages of the interface, from the page loaded in its `<webview>` only:
|
|
493
|
+
|
|
494
|
+
```javascript
|
|
495
|
+
const view = document.querySelector('webview')
|
|
496
|
+
const origin = new URL(view.src).origin
|
|
497
|
+
const bridge = global[Symbol.for('lakutata:service')]
|
|
498
|
+
const send = (message) => view.contentWindow.postMessage(message, origin)
|
|
499
|
+
window.addEventListener('message', async (event) => {
|
|
500
|
+
if (event.source !== view.contentWindow || event.origin !== origin) return
|
|
501
|
+
const {type, id, message, clientId} = event.data
|
|
502
|
+
if (type === 'invoke') send({type: 'response', id: id, response: await bridge.invoke(message, clientId)})
|
|
503
|
+
if (type === 'subscribe') bridge.subscribe(clientId, (name, args) => send({type: 'event', name: name, args: args}))
|
|
504
|
+
})
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
- The `<webview>` loads the files of the application when its partition is declared in the manifest of NW.js:
|
|
508
|
+
`"webview": {"partitions": [{"name": "trusted", "accessible_resources": ["<all_urls>"]}]}` (the builder writes it).
|
|
509
|
+
- A page loaded again in the `<webview>` is a new client: the host page unsubscribes the previous one.
|
|
510
|
+
- The NW.js templates of `lakutata create` contain such a host page (`packages/app/host`), and a `window.ipc` for the
|
|
511
|
+
interface like the one of the Electron templates.
|
|
512
|
+
|
|
471
513
|
## 5. Clients and events
|
|
472
514
|
|
|
473
515
|
The transports that keep their clients connected can push events to them. A client is identified by the id it gives:
|
|
@@ -480,6 +522,7 @@ The transports that keep their clients connected can push events to them. A clie
|
|
|
480
522
|
| JSON-RPC over WebSocket | The `id` header or `id` query parameter of the connection, else a random id |
|
|
481
523
|
| JSON-RPC over stdio | `'stdio'` |
|
|
482
524
|
| Electron | The id the page gives when it subscribes or invokes |
|
|
525
|
+
| NW.js | The id the host page gives to the bridge for its page |
|
|
483
526
|
| WebRTC | The member id of the caller in its room |
|
|
484
527
|
|
|
485
528
|
An action reads the id of its client in `this.context.clientId`. The `entrypoint` component pushes the events:
|
|
@@ -515,6 +558,7 @@ A client receives `notify(clientId, 'progress', 50, 'half')` as:
|
|
|
515
558
|
| Socket.IO | `socket.on('progress', (percent, label) => …)` |
|
|
516
559
|
| JSON-RPC (WebSocket, stdio) | `{"jsonrpc": "2.0", "method": "progress", "params": [50, "half"]}` |
|
|
517
560
|
| Electron | `('progress', [50, 'half'])`, through the `subscribe` of the preload script above |
|
|
561
|
+
| NW.js | `('progress', [50, 'half'])`, given to the function of the `subscribe` of the bridge |
|
|
518
562
|
| WebRTC | `proxy.on('progress', (percent, label) => …)` of a `PeerServiceProxy` |
|
|
519
563
|
|
|
520
564
|
## 6. Stopping and leaving
|
package/doc/en/UpgradingFrom1.md
CHANGED
|
@@ -20,7 +20,7 @@ packages obtained elsewhere may have APIs that this page does not cover.
|
|
|
20
20
|
| Modules | CommonJS: imports without extensions, `__dirname` | ES modules: relative imports ending in `.js` |
|
|
21
21
|
| Service actions | `@Controller({_ctrl: …})` and `@PATTERN({_act: …})` from `@lakutata-module/service` | `@ServiceAction({…})` from `lakutata/decorator/ctrl` |
|
|
22
22
|
| Validation | `Validator` schemas (yup) given to `@Accept` | DTO classes with `@Expect` |
|
|
23
|
-
| Node.js | `>=14.15.1` (`@lakutata/core` 1.0.60) |
|
|
23
|
+
| Node.js | `>=14.15.1` (`@lakutata/core` 1.0.60) | `>=18.10.0` |
|
|
24
24
|
|
|
25
25
|
**`@lakutata/core` 3 is not a new version of the 1.x library.** It is the core of Lakutata 3, a different API under the
|
|
26
26
|
same name. `npm install @lakutata/core@latest`, or a range such as `*`, in a 1.x project puts it in place of the 1.x
|
|
@@ -392,7 +392,7 @@ are built differently, so the entries that 1.x wrote are not found: start with a
|
|
|
392
392
|
- **The `lakutata` field of `package.json`** told the 1.x tool the kind of the project (`type`), its directories and
|
|
393
393
|
its configuration file. In 3.x the field has another meaning (the `resources` and the `installer` of a packed
|
|
394
394
|
application, [Packaging](Packaging.md)): remove the 1.x one.
|
|
395
|
-
- **Node.js, TypeScript and modules.** Node.js
|
|
395
|
+
- **Node.js, TypeScript and modules.** Node.js `>=18.10.0`, TypeScript 6 as in the templates, ES modules
|
|
396
396
|
(`"type": "module"`, relative imports ending in `.js`), `tsconfig.json` extending `lakutata/tsconfig.json`.
|
|
397
397
|
- **Ports.** The service module listened on a port of its own (6912 by default) and the registry on another (6911).
|
|
398
398
|
The 3.x adapters listen on the ports of their options, and a service on NATS only connects out to the NATS server:
|
package/doc/en/UpgradingFrom2.md
CHANGED
|
@@ -17,15 +17,15 @@ It is for the projects that depend on the package `lakutata` at version 2. A pro
|
|
|
17
17
|
| Exported functions | PascalCase: `BuildEntrypoints`, `BuildDatabaseOptions`, `MD5` | camelCase: `buildEntrypoints`, `buildDatabaseOptions`, `md5` |
|
|
18
18
|
| Transports | Written by hand: `BuildHTTPEntrypoint((module, routeMap, handler, registerDestroy) => …)` | Adapters: `expressHTTPEntrypoint()` from `lakutata/adapter/express`… |
|
|
19
19
|
| Subpaths of 3.x only | | `lakutata/utils`, `lakutata/security`, `lakutata/adapter/*`, `lakutata/com/{containerd,mutex,queue,i18n}` |
|
|
20
|
-
| Node.js | `>=20` |
|
|
20
|
+
| Node.js | `>=20` | `>=18.10.0` |
|
|
21
21
|
|
|
22
22
|
`npx @lakutata/cli info` prints the versions of the tool, of the framework and of Node.js, and the `lakutata` version
|
|
23
23
|
that the project declares and the one installed. There is no upgrade command: the steps below are done by hand.
|
|
24
24
|
|
|
25
25
|
## 2. The steps
|
|
26
26
|
|
|
27
|
-
- **Node.js** `^22.13.0 || >=24.11.0`
|
|
28
|
-
|
|
27
|
+
- **Node.js** `>=18.10.0` (3.0 to 3.1 needed `^22.13.0 || >=24.11.0`). The versions 2.x needs (`>=20`) are among them:
|
|
28
|
+
`engines`, the CI matrix and the Dockerfiles can stay.
|
|
29
29
|
- **A TypeScript that knows `"module": "Node20"`** (the templates use TypeScript 6): `lakutata/tsconfig.json` now sets
|
|
30
30
|
it (2.x: `Node16`), and older compilers reject it.
|
|
31
31
|
- **`package.json`**: `"type": "module"`, `lakutata` `^3.0.0`, the `@lakutata/*` packages at `^3.0.0` too, and
|
|
@@ -281,7 +281,7 @@ Application
|
|
|
281
281
|
## 6. Checking the upgrade
|
|
282
282
|
|
|
283
283
|
```bash
|
|
284
|
-
node --version #
|
|
284
|
+
node --version # >=18.10.0
|
|
285
285
|
npm ls lakutata @lakutata/core # one version of each
|
|
286
286
|
npm run build # tsc without errors: no 2.x import left
|
|
287
287
|
grep -rnE "process\.on\('SIG|\|\| ''|(startup|launched|beforeDestroy|acceptsOption)\(|AccessDenyException|=== 500" src
|
package/doc/en/WebRTC.md
CHANGED
|
@@ -224,10 +224,10 @@ export class Telemetry extends Component {
|
|
|
224
224
|
```
|
|
225
225
|
|
|
226
226
|
An `http:` or `https:` URL uses Socket.IO (install `socket.io-client`), a `ws:` or `wss:` URL uses JSON-RPC over the
|
|
227
|
-
`WebSocket` of Node.js 22 and Bun
|
|
228
|
-
(more fields of the Socket.IO handshake, a token), `timeout`,
|
|
229
|
-
`icePortRange`, `iceAdditionalHostAddresses`, `codecs`,
|
|
230
|
-
client, and `close()` leaves its rooms and disconnects.
|
|
227
|
+
global `WebSocket` of Node.js 22 and Bun, else over the `WebSocket` of the package `ws` (install `ws`). Its options: `url`, `id`
|
|
228
|
+
(a random UUID by default), `path` (of Socket.IO), `auth` (more fields of the Socket.IO handshake, a token), `timeout`,
|
|
229
|
+
and the options of its connections (`iceTransportPolicy`, `icePortRange`, `iceAdditionalHostAddresses`, `codecs`,
|
|
230
|
+
`threads`). It is `@Transient`: each `getObject()` gives a new client, and `close()` leaves its rooms and disconnects.
|
|
231
231
|
|
|
232
232
|
### Calling the actions of an application
|
|
233
233
|
|
package/doc/zh/Application.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| 选项 | 含义 |
|
|
10
10
|
|---|---|
|
|
11
|
-
| `id`、`name` | 必填。应用的 ID(同时作为 `process.title
|
|
11
|
+
| `id`、`name` | 必填。应用的 ID(同时作为 `process.title`,NW.js 中除外)和名称(`app.appId`、`app.appName`) |
|
|
12
12
|
| `timezone` | IANA 时区名,或 `'auto'`(默认)表示使用系统时区;写入 `TZ` |
|
|
13
13
|
| `mode` | `'development'` 或 `'production'`,在环境变量未指定时生效(见第 4 节) |
|
|
14
14
|
| `shutdownSignals` | 使应用优雅退出的信号(默认 `['SIGTERM', 'SIGINT']`),或 `false` |
|
package/doc/zh/Cache.md
CHANGED
|
@@ -250,7 +250,7 @@ Application.run(() => ({
|
|
|
250
250
|
|
|
251
251
|
- `table` 中字母、数字和 `_` 以外的字符会被去掉。
|
|
252
252
|
- 语句同步执行:等待被锁住的数据库时,语句会阻塞事件循环,最长 `busyTimeout`。
|
|
253
|
-
- `better-sqlite3` 是原生插件,针对一种运行时构建:Electron 应用需要使用针对其 Electron 版本构建的 `better-sqlite3
|
|
253
|
+
- `better-sqlite3` 是原生插件,针对一种运行时构建:Electron 应用需要使用针对其 Electron 版本构建的 `better-sqlite3`;NW.js 应用会用 NW.js 的头文件重新构建它(需要 0.111.3 及以后的版本:更早的版本无法加载它)。在 Bun 上,存储改用 `bun:sqlite`。
|
|
254
254
|
|
|
255
255
|
### PostgreSQL
|
|
256
256
|
|
package/doc/zh/Command.md
CHANGED
|
@@ -9,7 +9,7 @@ npx @lakutata/cli create --name my-app # 不安装,直接运行
|
|
|
9
9
|
npm install --global @lakutata/cli # 或者在本机安装一次,之后:lakutata create --name my-app
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
模板会把 `@lakutata/cli` 加入项目的 `devDependencies`,所以项目的脚本可以直接调用 `lakutata`,在项目里也可以用 `npx lakutata`。工具需要 Node.js
|
|
12
|
+
模板会把 `@lakutata/cli` 加入项目的 `devDependencies`,所以项目的脚本可以直接调用 `lakutata`,在项目里也可以用 `npx lakutata`。工具需要 Node.js 18.10 或更高版本(`>=18.10.0`)。
|
|
13
13
|
|
|
14
14
|
- `lakutata --help` 列出所有命令,`lakutata help <command>`(或 `lakutata <command> --help`)说明某个命令,`lakutata --version` 输出工具的版本。不带命令运行时,工具输出帮助,并以退出码 1 退出。
|
|
15
15
|
- 选项名用短横线连接(`--package-manager`)。默认开启的布尔选项用 `--no-` 关闭(`--no-git`、`--no-bail`)。
|
|
@@ -34,7 +34,7 @@ lakutata create --name tool --template cli --package-manager none --no-git
|
|
|
34
34
|
| `--path` | `.` | 在哪里创建项目目录(`<path>/<name>`) |
|
|
35
35
|
| `--init` | | 直接在 `--path` 这个已有目录中创建项目 |
|
|
36
36
|
| `--description`、`--author`、`--license` | 许可证为 `UNLICENSED` | 包的信息 |
|
|
37
|
-
| `--with` | | 模板的可选功能,用逗号分隔(`i18n`、`installer`) |
|
|
37
|
+
| `--with` | | 模板的可选功能,用逗号分隔(`i18n`、`installer`、`win7`) |
|
|
38
38
|
| `--package-manager` | `npm`;由 pnpm 或 yarn 启动工具时为对应的包管理器 | `npm`、`pnpm`、`yarn`,或 `none` 表示不安装依赖 |
|
|
39
39
|
| `--no-git` | | 不创建 git 仓库 |
|
|
40
40
|
| `--yes` | | 不询问可选功能,也不要求确认 |
|
|
@@ -67,6 +67,8 @@ lakutata create --name tool --template cli --package-manager none --no-git
|
|
|
67
67
|
|
|
68
68
|
`lakutata package bundle` 和 `package exe` 把编译好的应用打包成单个 JavaScript 文件,或者不需要安装 Node.js 就能运行的可执行文件,见 [Packaging](Packaging.md)。`lakutata package installer` 制作应用的安装包,安装包还可以把应用注册为服务,见 [Installers](Installers.md)。
|
|
69
69
|
|
|
70
|
+
NW.js 应用所用的 NW.js 版本由 `lakutata nwjs use <版本>` 设置(`latest`、`win7` 或某个版本,`lakutata nwjs versions` 会列出这些版本),版本会写进应用的 `package.json`。`lakutata nwjs run [args...]` 在这个 NW.js 的 sdk 版本(带 DevTools)中运行编译好的应用,原生插件会被处理成能在其中加载,并把参数传给应用。应用的安装包里是 normal 版本(见 [Installers](Installers.md) 第 9 节)。
|
|
71
|
+
|
|
70
72
|
## 6. 环境变量
|
|
71
73
|
|
|
72
74
|
| 变量 | 含义 |
|
|
@@ -74,7 +76,9 @@ lakutata create --name tool --template cli --package-manager none --no-git
|
|
|
74
76
|
| `LAKUTATA_LANG` | 工具的语言(`en`、`zh-CN`、`zh-TW`) |
|
|
75
77
|
| `LAKUTATA_NPM_REGISTRY` | 下载模板的仓库(否则取 `npm_config_registry`,再否则为 `https://registry.npmjs.org`) |
|
|
76
78
|
| `LAKUTATA_GITHUB_DOWNLOAD` | 下载 `github:` 模板的地址(默认 `https://github.com`) |
|
|
77
|
-
| `LAKUTATA_CACHE_DIR` |
|
|
79
|
+
| `LAKUTATA_CACHE_DIR` | 工具的缓存目录:模板、制作安装包所用的工具,以及 NW.js 的运行时(默认 `$XDG_CACHE_HOME/lakutata`,否则 `~/.cache/lakutata`) |
|
|
80
|
+
| `LAKUTATA_NWJS_MIRROR` | NW.js 运行时的下载地址(默认 `https://dl.nwjs.io`) |
|
|
81
|
+
| `LAKUTATA_NWJS_VERSIONS` | NW.js 的发布版本列表(默认 `https://nwjs.io/versions.json`) |
|
|
78
82
|
| `NO_COLOR` | 关闭颜色 |
|
|
79
83
|
|
|
80
84
|
工具运行的脚本和应用,拿到的是工具启动时的环境变量。打包后的应用所用的环境变量见 [Packaging](Packaging.md) 第 6 节。
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| 功能 | 需要 |
|
|
10
10
|
|---|---|
|
|
11
|
-
| 全部功能 | Linux,带 runc 的 containerd 1.6 或更高版本,Node.js
|
|
11
|
+
| 全部功能 | Linux,带 runc 的 containerd 1.6 或更高版本,Node.js `>=18.10.0`;应用以 root 运行,或属于拥有 containerd 套接字的用户组 |
|
|
12
12
|
| CNI 网络(包括默认的 `bridge`)、端口发布 | CNI 插件(`bridge`、`portmap`、`host-local` 等,位于 `/opt/cni/bin`、`/usr/lib/cni` 或 `/usr/libexec/cni`,即 `cniPath` 选项)以及 iptables |
|
|
13
13
|
| 带 `stdin` 的 `exec()`、分开的 `stdout`/`stderr`、终端 | 主机上的 `mkfifo`(没有时,`exec()` 把两种输出都放在 `stdout` 中) |
|
|
14
14
|
| 构建 | BuildKit 守护进程(`buildkitd`),本地或远程 |
|
|
@@ -124,7 +124,7 @@ export const db = buildDatabaseOptions({
|
|
|
124
124
|
|
|
125
125
|
- 外键约束是生效的(`PRAGMA foreign_keys = ON`)。只有一个连接:不支持 `poolSize`。
|
|
126
126
|
- **`bigint` 列以数字返回**:超过 2^53 的值会丢失精度。这类值请存在文本列中。
|
|
127
|
-
- `better-sqlite3` 是原生模块,针对某个 Node.js 版本编译。Electron 应用需要针对它的 Electron 版本的构建(`electron-rebuild`,或 better-sqlite3 为 Electron 提供的预编译文件);Bun 无法加载它(在 Bun 上使用 `sqljs`)。
|
|
127
|
+
- `better-sqlite3` 是原生模块,针对某个 Node.js 版本编译。Electron 应用需要针对它的 Electron 版本的构建(`electron-rebuild`,或 better-sqlite3 为 Electron 提供的预编译文件);NW.js 应用会用 NW.js 的头文件重新构建它(需要 0.111.3 及以后的版本:更早的版本请使用 `sqljs`);Bun 无法加载它(在 Bun 上使用 `sqljs`)。
|
|
128
128
|
|
|
129
129
|
## SQLite:sql.js
|
|
130
130
|
|
package/doc/zh/Entrypoint.md
CHANGED
|
@@ -56,6 +56,7 @@ Application.run(() => ({
|
|
|
56
56
|
| `service` | `socketIOServiceEntrypoint()` | `lakutata/adapter/socket.io` | `socket.io` | [ServiceCalls](ServiceCalls.md) |
|
|
57
57
|
| `service` | `jsonRPCServiceEntrypoint()` | `lakutata/adapter/jsonrpc` | `ws`(WebSocket 时) | [ServiceCalls](ServiceCalls.md) |
|
|
58
58
|
| `service` | `electronIPCServiceEntrypoint()` | `lakutata/adapter/electron` | (Electron) | [ServiceCalls](ServiceCalls.md) |
|
|
59
|
+
| `service` | `nwjsServiceEntrypoint()` | `lakutata/adapter/nwjs` | (NW.js) | [ServiceCalls](ServiceCalls.md) |
|
|
59
60
|
| `service` | `grpcServiceEntrypoint()` | `@lakutata/grpc/service` | `@lakutata/grpc` | [GRPC](GRPC.md) |
|
|
60
61
|
| `service` | `natsServiceEntrypoint()` | `@lakutata/nats` | `@lakutata/nats` | [NATS](NATS.md) |
|
|
61
62
|
| `schedule` | `scheduleEntrypoint()` | `lakutata/com/entrypoint` | | [Schedules](Schedules.md) |
|
|
@@ -165,7 +166,7 @@ Application.run(() => ({
|
|
|
165
166
|
|
|
166
167
|
## 6. 向客户端推送事件
|
|
167
168
|
|
|
168
|
-
保持客户端连接的服务传输方式(Socket.IO、Electron、HTTP 服务的事件流、WebSocket 或 stdio 上的 JSON-RPC、gRPC)可以接收应用推送的事件。`entrypoint.notify(clientId, event, ...args)` 把事件发给一个客户端,即某个动作从 `this.context.clientId` 读到的那个客户端,返回客户端是否收到;`entrypoint.broadcast(event, ...args)` 发给所有已连接的客户端,返回客户端的数量。见 [GRPC](GRPC.md) 和 [ServiceCalls](ServiceCalls.md)。
|
|
169
|
+
保持客户端连接的服务传输方式(Socket.IO、Electron、NW.js、HTTP 服务的事件流、WebSocket 或 stdio 上的 JSON-RPC、gRPC)可以接收应用推送的事件。`entrypoint.notify(clientId, event, ...args)` 把事件发给一个客户端,即某个动作从 `this.context.clientId` 读到的那个客户端,返回客户端是否收到;`entrypoint.broadcast(event, ...args)` 发给所有已连接的客户端,返回客户端的数量。见 [GRPC](GRPC.md) 和 [ServiceCalls](ServiceCalls.md)。
|
|
169
170
|
|
|
170
171
|
## 7. 定制入口
|
|
171
172
|
|
package/doc/zh/Exceptions.md
CHANGED
|
@@ -113,7 +113,7 @@ export async function pay(orderId: number, charge: () => Promise<void>): Promise
|
|
|
113
113
|
| 传输方式 | 客户端收到 |
|
|
114
114
|
|---|---|
|
|
115
115
|
| HTTP | 状态码 `statusCode` 和 `{errno, errMsg}`(见 [HTTP](HTTP.md) 第 6 节) |
|
|
116
|
-
| Socket.IO、Electron、HTTP 服务、NATS、gRPC | 完整的错误:它所有的自身属性(见 [ServiceCalls](ServiceCalls.md) 第 3 节) |
|
|
116
|
+
| Socket.IO、Electron、NW.js、HTTP 服务、NATS、gRPC | 完整的错误:它所有的自身属性(见 [ServiceCalls](ServiceCalls.md) 第 3 节) |
|
|
117
117
|
| JSON-RPC | 一个错误:输入不合法时错误码为 `-32602`,没有匹配的动作时为 `-32601`,应用正在停止时为 `-32001`,其他情况为 `-32000`;完整的错误放在 `data` 中 |
|
|
118
118
|
| 命令行 | 标准错误中的 `error: <消息>`,退出码为 1(见 [CLI](CLI.md)) |
|
|
119
119
|
| 定时任务 | 没有客户端:异常交给 `onError`,或者写入日志(见 [Schedules](Schedules.md)) |
|
package/doc/zh/FFI.md
CHANGED
|
@@ -319,7 +319,7 @@ export class Vendor extends NativeLibrary {
|
|
|
319
319
|
|
|
320
320
|
## 12. 运行环境
|
|
321
321
|
|
|
322
|
-
Node.js
|
|
322
|
+
Node.js `>=18.10.0`、Electron 的主进程和 Bun;不支持 Electron 的渲染进程和浏览器。
|
|
323
323
|
|
|
324
324
|
这个包的测试(包括库的线程)在 macOS(arm64:Node.js 24、Bun 1.4、Electron 44)、Linux(arm64,glibc 和 musl:Node.js 24、Bun 1.4)和 Windows 11(arm64,以及模拟运行的 x64:Node.js 24、Bun 1.4)上都能通过。在 macOS 上,还用 `lakutata package` 把一个使用它的应用(它的库在自己的线程里执行)分别打成了 bundle、Node.js 和 Bun 的可执行文件以及 Electron 应用:每一个都能运行,库的线程也都从应用自己的资源目录里加载了自带的库。
|
|
325
325
|
|
package/doc/zh/GRPC.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lakutata gRPC
|
|
2
2
|
|
|
3
|
-
`@lakutata/grpc` 包让应用通过 gRPC 提供服务动作,也能从另一个应用调用这些动作;任何有 gRPC 库的语言都可以调用它们。它用 TypeScript 基于 Node.js
|
|
3
|
+
`@lakutata/grpc` 包让应用通过 gRPC 提供服务动作,也能从另一个应用调用这些动作;任何有 gRPC 库的语言都可以调用它们。它用 TypeScript 基于 Node.js(`>=18.10.0`)的 HTTP/2 模块实现,不需要原生插件,也不需要生成代码。`lakutata` 不包含这个包,需要另外安装:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install lakutata @lakutata/grpc
|
package/doc/zh/GettingStarted.md
CHANGED
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
## 1. 环境要求
|
|
6
6
|
|
|
7
|
-
- Node.js
|
|
7
|
+
- Node.js 18.10 或更高版本(`>=18.10.0`)。少数功能需要较新的 Node.js:
|
|
8
|
+
- Fastify 适配器:Fastify 5 需要 Node.js 18.19、19.9、20 或更高版本(Express 适配器没有这个要求);
|
|
9
|
+
- `@lakutata/queue` 的 Kafka 传输:需要 Node.js 22.22、24.6 或更高版本,这是 `@platformatic/kafka` 的要求;
|
|
10
|
+
- Node.js 的可执行文件(`lakutata package exe` 和安装包):要用 Node.js 20.12、21.7 或更高版本来生成,或者用 `--node-program` 指定这样一个 Node.js;
|
|
11
|
+
- 对框架的对象使用 `await using`:需要 Node.js 18.18、20.4 或更高版本。
|
|
12
|
+
|
|
13
|
+
在 Node.js 18 和 19 上,应用要用 commander 13、@inquirer/prompts 7 和 better-sqlite3 11:它们再往后的大版本需要 Node.js 20 或更高版本。
|
|
14
|
+
|
|
15
|
+
`lakutata create` 生成的项目声明的是 Node.js `>=22.13.0`,Web 模板和桌面应用模板用到的工具需要它。
|
|
8
16
|
- TypeScript,开启它的装饰器(`experimentalDecorators`)及其元数据(`emitDecoratorMetadata`)。框架所需的编译选项以 `lakutata/tsconfig.json` 发布;模板使用 TypeScript 6。
|
|
9
17
|
- ES 模块(`"type": "module"`),和模板一样;包里同时也提供了 CommonJS 构建。
|
|
10
18
|
|
|
@@ -33,12 +41,13 @@ curl 'http://localhost:8080/example?name=you'
|
|
|
33
41
|
| `web-react`、`web-vue` | 提供 React 或 Vue 单页应用(Vite)的 HTTP API |
|
|
34
42
|
| `web-next`、`web-nuxt` | 在同一个进程中提供 Next.js 或 Nuxt 应用的 HTTP API |
|
|
35
43
|
| `electron-react`、`electron-vue` | 桌面应用:Electron,主进程通过 IPC 为 React 或 Vue 渲染进程提供服务 |
|
|
44
|
+
| `nwjs-react`、`nwjs-vue` | 桌面应用:NW.js,后台脚本为隔离在 webview 中的 React 或 Vue 用户界面提供服务 |
|
|
36
45
|
|
|
37
46
|
```bash
|
|
38
47
|
npx @lakutata/cli create --name shop --template service --with i18n,installer
|
|
39
48
|
```
|
|
40
49
|
|
|
41
|
-
`--with` 加入可选功能:所有模板都有 `i18n`(多语言消息),`cli`、`service` 和 `web-*` 模板还有 `installer
|
|
50
|
+
`--with` 加入可选功能:所有模板都有 `i18n`(多语言消息),`cli`、`service` 和 `web-*` 模板还有 `installer`(安装包和系统服务),`nwjs-*` 模板还有 `win7`(能在 Windows 7 上运行的 NW.js 0.72)。在终端里没有给出 `--with` 时,工具会列出这些功能供选择。模板中的文件见 [ProjectStructure](ProjectStructure.md),`lakutata create` 的选项见 [Command](Command.md)。
|
|
42
51
|
|
|
43
52
|
`default` 模板的脚本:
|
|
44
53
|
|
package/doc/zh/HTTP.md
CHANGED
|
@@ -101,6 +101,7 @@ HTTP/1.1 400 Bad Request
|
|
|
101
101
|
|---|---|---|
|
|
102
102
|
| 适配器 | `lakutata/adapter/express` 中的 `expressHTTPEntrypoint()` | `lakutata/adapter/fastify` 中的 `fastifyHTTPEntrypoint()` |
|
|
103
103
|
| 需要安装 | `express`(4 或 5) | `fastify`(5) |
|
|
104
|
+
| Node.js | 18.10 起 | 18.19、19.9、20 起(Fastify 5 需要 `diagnostics_channel.tracingChannel`) |
|
|
104
105
|
|
|
105
106
|
`expressHTTPEntrypoint()` 的选项:
|
|
106
107
|
|
package/doc/zh/I18n.md
CHANGED
|
@@ -164,7 +164,7 @@ Application.run(() => ({
|
|
|
164
164
|
| HTTP(Express、Fastify) | Query 参数 `?lang=`、Cookie `lang`,然后是请求头 `Accept-Language`(按权重) |
|
|
165
165
|
| Socket.IO | 连接握手时的 Query 参数 `lang`、Cookie `lang`、`Accept-Language` |
|
|
166
166
|
| HTTP 服务适配器、JSON-RPC(HTTP、WebSocket) | HTTP 请求(WebSocket 为建立连接的请求)的 Query 参数 `lang`、Cookie `lang`、`Accept-Language` |
|
|
167
|
-
| 命令行、Electron IPC、stdio 上的 JSON-RPC | `environmentVariable` 指定的环境变量(默认没有)、`LANGUAGE`、`LC_ALL`、`LC_MESSAGES`、`LANG`,最后是进程的语言 |
|
|
167
|
+
| 命令行、Electron IPC、NW.js、stdio 上的 JSON-RPC | `environmentVariable` 指定的环境变量(默认没有)、`LANGUAGE`、`LC_ALL`、`LC_MESSAGES`、`LANG`,最后是进程的语言 |
|
|
168
168
|
| 定时任务 | 无(默认语言) |
|
|
169
169
|
|
|
170
170
|
不是语言标签的 Query 参数或 Cookie 值会被跳过。
|
package/doc/zh/Installers.md
CHANGED
|
@@ -16,7 +16,7 @@ npx lakutata package installer --target pkg # 只制作其中几种
|
|
|
16
16
|
✔ dist/installer/greet-1.0.0-arm64.pkg (pkg, 36.0 MB)
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
安装包里是目录布局的可执行文件(`lakutata package exe --layout directory`):程序本身、它的原生插件(`native/`)和资源(`resources/`)。程序用 Node.js 制作;`lakutata.installer.runtime` 为 `"bun"` 时用 Bun
|
|
19
|
+
安装包里是目录布局的可执行文件(`lakutata package exe --layout directory`):程序本身、它的原生插件(`native/`)和资源(`resources/`)。程序用 Node.js 制作;`lakutata.installer.runtime` 为 `"bun"` 时用 Bun 制作。在低于 20.12 的 Node.js 上,和可执行文件一样,用 `--node-program` 指定一个更新的 Node.js。
|
|
20
20
|
|
|
21
21
|
| 平台 | 安装包(默认) | 文件名 | 制作工具 |
|
|
22
22
|
|---|---|---|---|
|
|
@@ -56,18 +56,18 @@ npx lakutata package installer --target pkg # 只制作其中几种
|
|
|
56
56
|
| `description`、`homepage`、`license` | 取自 `package.json` | 软件包的信息 |
|
|
57
57
|
| `maintainer` | `package.json` 的 `author` | 维护者(`Name <email>`);没有时工具会发出警告 |
|
|
58
58
|
| `vendor` | 无 | 供应商;在 Windows 上,发布者是供应商,没有时是维护者 |
|
|
59
|
-
| `runtime` | `node` | 可执行文件用 `node` 或 `bun`;Electron 应用用 `electron`(第 8 节) |
|
|
59
|
+
| `runtime` | `node` | 可执行文件用 `node` 或 `bun`;Electron 应用用 `electron`(第 8 节),NW.js 应用用 `nwjs`(第 9 节) |
|
|
60
60
|
| `addToPath` | `true` | 把程序加入 PATH:Linux 上是 `/usr/bin/<program>`,macOS 上是 `/usr/local/bin/<program>`,Windows 上是机器的 PATH |
|
|
61
61
|
| `service` | 无 | `true`,或服务的选项(第 4 节) |
|
|
62
62
|
| `linux.targets` | `deb`、`rpm`、`tar.gz`;Alpine 上是 `apk`、`tar.gz` | Linux 的安装包(`deb`、`rpm`、`archlinux`、`tar.gz`;Alpine 上是 `apk`、`tar.gz`) |
|
|
63
63
|
| `linux.depends`、`linux.recommends` | 无 | 依赖和推荐的系统软件包(总会加上 C++ 运行库) |
|
|
64
64
|
| `linux.section`、`linux.priority` | 无 | 分类和优先级(deb) |
|
|
65
|
-
| `mac.targets` | `pkg`、`tar.gz` | macOS
|
|
65
|
+
| `mac.targets` | `pkg`、`tar.gz` | macOS 的安装包(NW.js 应用还可以用 `dmg`) |
|
|
66
66
|
| `win.targets` | `nsis`、`msi`、`zip` | Windows 的安装包 |
|
|
67
67
|
| `linux.scripts`、`mac.scripts`、`win.scripts` 等 | 无 | 安装包执行的脚本(第 5 节) |
|
|
68
68
|
| `electron` | 无 | electron-builder 的配置(第 8 节) |
|
|
69
69
|
|
|
70
|
-
`lakutata.icon`(与 `lakutata.installer` 并列)是一张 256 像素或更大的正方形 PNG 图片:它是 Windows 可执行文件和安装程序的图标,也是 Electron 应用的图标。
|
|
70
|
+
`lakutata.icon`(与 `lakutata.installer` 并列)是一张 256 像素或更大的正方形 PNG 图片:它是 Windows 可执行文件和安装程序的图标,也是 Electron 和 NW.js 应用的图标。
|
|
71
71
|
|
|
72
72
|
配置在构建任何东西之前就会检查,不制作的那些安装包的选项也会检查,出错时会指出是哪个字段:
|
|
73
73
|
|
|
@@ -169,7 +169,7 @@ fi
|
|
|
169
169
|
|
|
170
170
|
## 6. 签名
|
|
171
171
|
|
|
172
|
-
- **macOS**:`pkg`
|
|
172
|
+
- **macOS**:`pkg` 安装包和 `dmg` 磁盘映像没有签名,它们安装的程序或应用也只有临时签名(ad hoc)。在组织以外的机器上分发所需要的 Developer ID 签名和公证,目前还不会制作。
|
|
173
173
|
- **Windows**:NSIS 和 MSI 安装包没有签名,分发前请用 signtool 签名。用 Node.js 制作的程序保留着 `node.exe` 的签名,而这个签名已经不再匹配,工具会对此发出警告。
|
|
174
174
|
- **Linux**:软件包没有签名。
|
|
175
175
|
|
|
@@ -230,3 +230,14 @@ jobs:
|
|
|
230
230
|
- **脚本**在 `deb` 和 `rpm` 软件包(全部四种)、`pkg`(`preinstall`、`postinstall`)和 `nsis` 安装程序(`preinstall`、`postinstall`、`preremove`)中执行;其他目标都不执行。
|
|
231
231
|
- **原生插件**按安装时的样子复制:electron-builder 不会重新构建它们。基于 Node-API 的插件可以直接运行;其他插件请在打包前安装它们为 Electron 构建的版本(`electron-rebuild`)(见 [NativeAddons](NativeAddons.md) 第 4 节)。
|
|
232
232
|
- 在 Linux arm64 上,deb 和 rpm 软件包需要系统中的 fpm(`gem install fpm`、`USE_SYSTEM_FPM=true`),Electron 模板的 `Dockerfile.installer` 就是这样安装它的。
|
|
233
|
+
|
|
234
|
+
## 9. NW.js 应用
|
|
235
|
+
|
|
236
|
+
使用 `"runtime": "nwjs"` 时,安装包里是由构建器制作的 NW.js 应用:应用所用 NW.js 版本(它的 `lakutata.nwjs`,由 `lakutata nwjs use` 设置)的 normal 版本,只下载一次到 lakutata 的缓存目录,并按其发布版本的校验和核对;应用放在其中,包括为这个 NW.js 的 Node.js 打包的代码、原生插件、资源(`lakutata.resources`,通过 `resourcesPath()` 读取)和 NW.js 的清单。`nwjs-react` 和 `nwjs-vue` 模板就是这样配置的。
|
|
237
|
+
|
|
238
|
+
- **运行时**以应用的名字命名:Windows 上是 `<name>.exe`,图标和版本信息都是应用的;Linux 上是 `<name>`;macOS 上是 `<productName>.app`,它的 `Info.plist` 给出应用的名称、标识(`appId`)、版本和图标,并重新做临时签名。
|
|
239
|
+
- **安装包**是桌面应用的安装包:默认 macOS 上是 `dmg`,Windows 上是 `nsis`,Linux 上是 `deb`(macOS 上还可以用 `pkg` 和 `tar.gz`,Windows 上可以用 `msi` 和 `zip`,Linux 上可以用 `rpm` 和 `tar.gz`)。Windows 的安装程序把应用加到开始菜单和桌面;`dmg` 磁盘映像里是应用和一个指向 /Applications 的链接,用户把应用拖过去即可,`pkg` 安装包则直接把它装到那里(Intel 版的应用也可以装到 Apple 芯片的 Mac 上);Linux 的软件包会添加应用的桌面入口和图标,并依赖 Chromium 所需的库。
|
|
240
|
+
- **架构**默认是本机的架构,也可以用 `--arch` 指定(`x64`、`ia32`、`arm64`):`ia32` 制作 32 位 Windows 的安装包,应用安装在 32 位程序的目录中。没有 Apple 芯片 Mac 构建的 NW.js 版本(如 0.72),会打包成 Intel 版。
|
|
241
|
+
- **NW.js 应用不是服务**,也不会加入 PATH(`addToPath` 默认为 `false`)。
|
|
242
|
+
- **脚本**和其他应用一样执行,只是 macOS 上的应用是直接删除的:那里不会执行卸载脚本。
|
|
243
|
+
- **原生插件**会被处理成能在 NW.js 中加载:为它的架构重新构建,使用 V8 API 的插件用它的头文件重新构建;在 Windows 上,插件加载的是 NW.js 的 Node.js(见 [NativeAddons](NativeAddons.md) 第 4 节)。
|
package/doc/zh/Math.md
CHANGED
|
@@ -279,7 +279,7 @@ $ curl -X POST localhost:8080/solve -H 'Content-Type: application/json' -d '{"eq
|
|
|
279
279
|
- 公式的长度限制不了它的计算量:`(x + 1)^100000` 很短。能限制计算量的是时限。
|
|
280
280
|
- 这个包的值通过 `toJSON()` 转成 JSON:表达式、方程、十进制数和带单位的值转成它们的文本,解转成文本数组,矩阵转成它的各行。向量是 `Float64Array`,`JSON.stringify()` 会把它写成对象(`{"0": 1, "1": 1}`):请发送 `Array.from(vector)`。
|
|
281
281
|
- `lakutata package` 打出的单文件包、可执行文件和安装包都带着编译好的原生插件(`build/Release/math.node`)。请在每个目标平台上安装这个包之后再打包;原生插件的规则同样适用(见 [Packaging](Packaging.md) 和 [NativeAddons](NativeAddons.md))。
|
|
282
|
-
- 这个包可以在 Node.js
|
|
282
|
+
- 这个包可以在 Node.js `>=18.10.0`、Bun 和 Electron 的主进程中运行,后两者直接加载为 Node.js 编译的插件;不能在 Electron 的渲染进程和浏览器中运行。在 Bun 里,worker 线程里的插件运算还没结束就终止这个线程的话,整个进程会因为 Node-API 的致命错误退出(这是 Bun 1.4 的问题)。
|
|
283
283
|
|
|
284
284
|
## 13. 验证方式,以及不支持的情况
|
|
285
285
|
|
package/doc/zh/NativeAddons.md
CHANGED
|
@@ -61,14 +61,13 @@ pub fn greet(name: String) -> String {
|
|
|
61
61
|
```typescript
|
|
62
62
|
import {createRequire} from 'node:module'
|
|
63
63
|
import path from 'node:path'
|
|
64
|
-
import {fileURLToPath} from 'node:url'
|
|
65
64
|
|
|
66
65
|
type Binding = {
|
|
67
66
|
greet(name: string): string
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
/** The addon built into build/Release, loaded from the directory of the package */
|
|
71
|
-
const binding: Binding = createRequire(
|
|
70
|
+
const binding: Binding = createRequire(__filename)('node-gyp-build')(path.resolve(__dirname, '..'))
|
|
72
71
|
|
|
73
72
|
export function greet(name: string): string {
|
|
74
73
|
return binding.greet(name)
|
|
@@ -87,6 +86,7 @@ export function greet(name: string): string {
|
|
|
87
86
|
- **错误**:node-addon-api 的 C++ 异常会以同类错误抛到 JavaScript 中(`Napi::TypeError` 变成 `TypeError`)。在 Rust 中,类型不对的参数由 napi-rs 拒绝,抛出一个 `Error`,它的 `code` 说明原因(`StringExpected`)。
|
|
88
87
|
- **macOS**:C++ 插件在一个文件中同时为 Intel 和 Apple 芯片的 Mac 构建;Rust 插件只为本机的架构构建(用 `rustup target add` 添加其他架构)。
|
|
89
88
|
- **Node-API**:插件针对 Node-API 第 8 版构建,所有受支持的 Node.js 和 Electron 版本都提供这一版,所以不需要为它们分别重新构建。
|
|
89
|
+
- **CommonJS**:这个包是 CommonJS 包(`"type": "commonjs"`)。`lakutata package` 生成的文件是 CommonJS 格式,用 `require` 加载它,而 `require` 要到 Node.js 20.19、22.12 或更高版本才能加载 ES 模块。
|
|
90
90
|
- 和 `lakutata add` 创建的所有包一样,这个包是 `"private": true`:原生插件通常随应用一起发布,而不单独发布。
|
|
91
91
|
|
|
92
92
|
## 2. 链接库
|
|
@@ -177,5 +177,6 @@ lakutata native link libc --crate # 一个 crate(Rust:carg
|
|
|
177
177
|
- **单文件包和可执行文件**:`lakutata package bundle` 把插件包排除在单文件包之外,连同它们的文件(JavaScript、插件本身、它的动态库,但不包括源码和构建时产生的文件)写入 `dist/<name>.native/`,这个目录随单文件包一起发布;可执行文件则把它们嵌入其中,或者在目录布局中放在自己旁边(见 [Packaging](Packaging.md))。插件是为打包所在机器的平台构建的,所以每个平台的应用要在那个平台上打包(用 CI 的矩阵,Linux 也可以用对应架构的容器)。
|
|
178
178
|
- **基于框架的插件包**(它依赖 `lakutata` 或 `@lakutata/core`,比如为了提供一个组件)则和应用一起打进单文件包,这样框架只有一份,只有插件和它旁边的文件放进这个目录。插件要用下面几种方式之一加载,才会被放进去:像 `lakutata add` 生成的插件包那样,把包的目录交给 `node-gyp-build`;直接 `require` 插件文件;或者用从模块位置构造的路径(`path.join(__dirname, 'prebuilds', ...)`)。用其他方式加载的插件,`lakutata package` 会发出警告。
|
|
179
179
|
- **Electron**:插件按安装时的样子复制。`lakutata add` 创建的插件不需要重新构建就能在 Electron 中运行,所有基于 Node-API 的插件都是如此;基于 Node.js V8 API 的插件,打包前要安装它为 Electron 构建的版本(`electron-rebuild`)。
|
|
180
|
+
- **NW.js**:应用在 NW.js 中运行时(`lakutata nwjs run`,以及打包之后),插件会被处理成能在 NW.js 中加载。为运行时以外的架构构建的插件会从源码重新构建,使用 NW.js 内置 Node.js 的头文件;基于 Node.js V8 API 的插件也会重新构建,使用 NW.js 的头文件(需要 NW.js 0.111.3 及以后的版本:更早的版本,例如用于 Windows 7 的 0.72,只能运行基于 Node-API 的插件)。在 Windows 上,插件加载的是 NW.js 的 Node.js(`node.dll`)。项目里的插件保持原样,项目的测试仍然用 Node.js 运行。
|
|
180
181
|
- **Bun**:Bun 能加载 Node-API 的插件;Bun 可执行文件会对基于 Node.js V8 API 的插件发出警告。
|
|
181
182
|
- **Alpine(musl)**:Node.js 的可执行文件在那里不能加载原生插件,请用 Bun 制作。
|
package/doc/zh/Overview.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lakutata 概述
|
|
2
2
|
|
|
3
|
-
**Lakutata** 是一个基于 IoC 的 Node.js / TypeScript 应用框架,让 Web 服务、命令行工具、桌面(Electron)应用和嵌入式设备共用同一套编程模型。应用是一棵由容器创建的对象树(组件、提供者、控制器):DTO 校验对象的选项和输入,各种传输方式把控制器暴露出去——HTTP(Express、Fastify)、CLI(Commander)、服务调用(HTTP、Socket.IO、JSON-RPC 2.0、gRPC、NATS、Electron IPC)、定时任务和消息队列。同一个控制器方法可以同时通过所有这些方式调用。
|
|
3
|
+
**Lakutata** 是一个基于 IoC 的 Node.js / TypeScript 应用框架,让 Web 服务、命令行工具、桌面(Electron、NW.js)应用和嵌入式设备共用同一套编程模型。应用是一棵由容器创建的对象树(组件、提供者、控制器):DTO 校验对象的选项和输入,各种传输方式把控制器暴露出去——HTTP(Express、Fastify)、CLI(Commander)、服务调用(HTTP、Socket.IO、JSON-RPC 2.0、gRPC、NATS、Electron IPC、NW.js)、定时任务和消息队列。同一个控制器方法可以同时通过所有这些方式调用。
|
|
4
4
|
|
|
5
5
|
`lakutata` 包通过各个子路径重新导出 `@lakutata/*` 系列包(见下表),并为每个应用预置两个组件:`log`(`Logger`,输出与 pino 兼容的 JSON 日志行)和 `entrypoint`(对外提供控制器的 `Entrypoint`)。
|
|
6
6
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
| `lakutata/decorator/ctrl` | `@HTTPAction`、`@GET`…`@OPTIONS`、`@CLIAction`、`@ServiceAction`、`@Schedule`、`@Prefix`、`@UseMiddlewares` |
|
|
22
22
|
| `lakutata/adapter/express`、`lakutata/adapter/fastify` | HTTP 传输 |
|
|
23
23
|
| `lakutata/adapter/commander` | CLI 传输 |
|
|
24
|
-
| `lakutata/adapter/socket.io`、`lakutata/adapter/jsonrpc`、`lakutata/adapter/electron` | 服务传输 |
|
|
24
|
+
| `lakutata/adapter/socket.io`、`lakutata/adapter/jsonrpc`、`lakutata/adapter/electron`、`lakutata/adapter/nwjs` | 服务传输 |
|
|
25
25
|
| `lakutata/com/logger` | `Logger` 组件,预置为 `log`(输出与 pino 兼容的 JSON 行) |
|
|
26
26
|
| `lakutata/orm`、`lakutata/decorator/orm` | TypeORM 及其装饰器 |
|
|
27
27
|
| `lakutata/com/database`、`lakutata/provider/database` | `Database` 组件和提供者 |
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
| [Middlewares](Middlewares.md) | 动作的中间件与访问控制 |
|
|
60
60
|
| [HTTP](HTTP.md) | HTTP 适配器:路由、输入、响应、错误,以及 Express 和 Fastify 的功能 |
|
|
61
61
|
| [CLI](CLI.md) | 命令行工具:命令、选项、提示输入、输出与退出码 |
|
|
62
|
-
| [ServiceCalls](ServiceCalls.md) | 通过 HTTP、Socket.IO、JSON-RPC 2.0 和
|
|
62
|
+
| [ServiceCalls](ServiceCalls.md) | 通过 HTTP、Socket.IO、JSON-RPC 2.0、Electron 和 NW.js 调用服务动作:模式、响应、客户端及其事件 |
|
|
63
63
|
| [GRPC](GRPC.md) | 通过 gRPC 提供服务动作(`@lakutata/grpc`),以及从其他应用和其他语言调用它们 |
|
|
64
64
|
| [NATS](NATS.md) | NATS 组件、通过 NATS 提供服务动作(`@lakutata/nats`)、服务代理及其事件 |
|
|
65
65
|
| [Schedules](Schedules.md) | 定时任务:间隔、cron 表达式、只在一个实例中执行的任务 |
|
package/doc/zh/Packaging.md
CHANGED
|
@@ -38,6 +38,7 @@ node dist/greet.cjs
|
|
|
38
38
|
| `--outfile <file>` | 单文件包的路径,默认 `dist/<name>.cjs` |
|
|
39
39
|
| `--no-minify` | 不压缩(无论是否压缩,类名都会保留) |
|
|
40
40
|
| `--external <modules...>` | 不打进包里的模块,运行时从单文件包旁边的 `node_modules` 加载 |
|
|
41
|
+
| `--node <version>` | 运行单文件包的 Node.js 版本(NW.js 0.70 是 `18.10`):单文件包用这个版本支持的语法生成;默认是运行工具的那个版本 |
|
|
41
42
|
|
|
42
43
|
## 3. 原生插件
|
|
43
44
|
|
|
@@ -99,11 +100,12 @@ npx lakutata package exe --runtime bun # 使用 Bun
|
|
|
99
100
|
|
|
100
101
|
| 选项 | 含义 |
|
|
101
102
|
|---|---|
|
|
102
|
-
| `--runtime node`(默认) |
|
|
103
|
+
| `--runtime node`(默认) | 把单文件包嵌入运行工具的 Node.js(或 `--node-program` 指定的 Node.js)的副本中(Node.js 的单可执行文件应用):在 macOS arm64 上约 110 MB |
|
|
103
104
|
| `--runtime bun` | 由 Bun 编译单文件包(优先用项目中的 `bun` 包,否则用系统的 `bun`):在 macOS arm64 上约 70 MB,启动更快;运行时也就是 Bun |
|
|
104
105
|
| `--layout file`(默认) | 单个文件:原生插件、按路径读取的文件和资源都嵌入其中,启动时解压 |
|
|
105
106
|
| `--layout directory` | `dist/<name>/` 中包含可执行文件、`native/` 和 `resources/`,直接从那里加载,不解压(安装包用的就是这种布局) |
|
|
106
107
|
| `--outdir <directory>` | 可执行文件的输出目录,默认 `dist` |
|
|
108
|
+
| `--node-program <path>` | 嵌入另一个 Node.js,而不是运行工具的那个:需要 Node.js 20.12、21.7 或更高版本(比如 `$(nvm which 22)`),这样较旧的 Node.js 也能运行这个命令;单文件包用它支持的语法生成 |
|
|
107
109
|
| `--entry`、`--no-minify`、`--external` | 与单文件包相同 |
|
|
108
110
|
|
|
109
111
|
- **解压**:单文件布局的可执行文件在第一次运行时,把嵌入的内容解压到缓存目录中一个以内容命名的子目录,所以每个版本只解压一次:macOS 上是 `~/Library/Caches/<name>`,Windows 上是 `%LOCALAPPDATA%\<name>\Cache`,Linux 上是 `$XDG_CACHE_HOME/<name>` 或 `~/.cache/<name>`,也可以用 `LAKUTATA_NATIVE_DIR` 指定目录。缓存目录不可写时,改用临时目录中的 `<name>`(指定了 `LAKUTATA_NATIVE_DIR` 时不会这样)。
|
|
@@ -134,6 +136,7 @@ npx lakutata package exe --runtime bun # 使用 Bun
|
|
|
134
136
|
| 可执行文件,单文件布局 | `true` | 资源解压到的目录 |
|
|
135
137
|
| 可执行文件,目录布局,或已安装的应用 | `true` | 可执行文件旁边的 `resources` |
|
|
136
138
|
| 打包后的 Electron 应用 | `true` | Electron 资源目录中的 `main.resources` |
|
|
139
|
+
| NW.js 应用(由 `lakutata nwjs run` 运行,或已打包) | `true` | 应用目录中的 `resources` |
|
|
137
140
|
|
|
138
141
|
即使应用没有声明资源,`resourcesPath()` 也会返回路径,所以这个目录可能不存在。应用自己决定从哪里读取文件:
|
|
139
142
|
|
|
@@ -45,7 +45,7 @@ Application
|
|
|
45
45
|
|
|
46
46
|
## 2. 工作区模板
|
|
47
47
|
|
|
48
|
-
其他模板都是 npm 工作区:应用是 `packages/app` 这个包,带界面或安装包的模板还会加上 `packages/ui
|
|
48
|
+
其他模板都是 npm 工作区:应用是 `packages/app` 这个包,带界面或安装包的模板还会加上 `packages/ui`(网页、Electron 的渲染进程,或 NW.js 的用户界面)和 `packages/resources`(图标)。`service` 模板:
|
|
49
49
|
|
|
50
50
|
```
|
|
51
51
|
shop/
|
|
@@ -79,6 +79,7 @@ shop/
|
|
|
79
79
|
- `web-next` 和 `web-nuxt`:`packages/ui`,一个 Next.js 或 Nuxt 应用,由应用在同一个进程中渲染。
|
|
80
80
|
- `cli`:一个命令行工具(`commanderCLIEntrypoint`),带有 `package:bundle` 和 `package:exe` 脚本,把它打包到 `dist/`([Packaging](Packaging.md))。
|
|
81
81
|
- `electron-react` 和 `electron-vue`:`packages/app` 中是 Electron 的主进程(它的窗口,以及通过 IPC 提供的服务动作),`packages/ui` 中是渲染进程,还有制作安装包的脚本。
|
|
82
|
+
- `nwjs-react` 和 `nwjs-vue`:`packages/app` 中是 NW.js 的后台脚本(它的窗口:窗口的宿主页面在 `packages/app/host`,用 webview 承载用户界面;以及它的服务动作),`packages/ui` 中是用户界面,NW.js 的版本在 `packages/app/nwjs.json`(由 `npm run nwjs:use -- <版本>` 写入),还有制作安装包的脚本。
|
|
82
83
|
|
|
83
84
|
打包产物写到工作区根目录的 `dist/` 中;`.gitignore` 忽略 `build`、`dist` 以及界面的构建输出。
|
|
84
85
|
|
|
@@ -90,8 +91,9 @@ shop/
|
|
|
90
91
|
|---|---|---|
|
|
91
92
|
| `i18n` | 全部 | `src/locales` 中各语言的消息(`en`、`zh-CN`)、`i18n` 组件、语言中间件,以及 `i18n:check` 和 `i18n:types` 脚本([I18n](I18n.md)) |
|
|
92
93
|
| `installer` | `cli`、`service`、`web-*` | 应用的 `lakutata.installer`、制作安装包的脚本(在本机制作,以及在 Docker 中制作 Linux 的安装包),服务类模板还会注册系统服务([Installers](Installers.md)) |
|
|
94
|
+
| `win7` | `nwjs-*` | 用 NW.js 0.72.0 代替模板发布时的版本:它是最后一个能在 Windows 7、8 和 8.1 上运行的版本;还有制作 32 位 Windows 安装包的 `package:ia32` 脚本 |
|
|
93
95
|
|
|
94
|
-
Electron
|
|
96
|
+
Electron 和 NW.js 模板不需要 `installer` 功能也能制作安装包。
|
|
95
97
|
|
|
96
98
|
## 4. 自己的模板
|
|
97
99
|
|