lakutata 3.1.4 → 3.1.6
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 +11 -11
- package/README.zh-CN.md +5 -5
- package/dist/cjs/exports/NwjsAdapter.d.ts +1 -0
- package/dist/cjs/exports/NwjsAdapter.js +20 -0
- package/dist/cjs/exports/ReactNativeAdapter.d.ts +1 -0
- package/dist/cjs/exports/ReactNativeAdapter.js +20 -0
- package/dist/esm/exports/NwjsAdapter.js +1 -0
- package/dist/esm/exports/ReactNativeAdapter.js +1 -0
- package/dist/types/exports/NwjsAdapter.d.ts +1 -0
- package/dist/types/exports/ReactNativeAdapter.d.ts +1 -0
- package/doc/en/Application.md +6 -1
- package/doc/en/Barcode.md +386 -0
- package/doc/en/Cache.md +2 -1
- package/doc/en/Command.md +20 -4
- package/doc/en/ContainerdIntegration.md +1 -1
- package/doc/en/Database.md +4 -0
- package/doc/en/DatabaseDrivers.md +75 -4
- package/doc/en/Entrypoint.md +4 -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 +16 -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/Migrations.md +2 -2
- package/doc/en/NativeAddons.md +12 -2
- package/doc/en/Overview.md +14 -11
- package/doc/en/Packaging.md +8 -1
- package/doc/en/ProjectStructure.md +18 -3
- package/doc/en/ServiceCalls.md +85 -5
- package/doc/en/UpgradingFrom1.md +2 -2
- package/doc/en/UpgradingFrom2.md +4 -4
- package/doc/en/WebRTC.md +4 -4
- package/doc/en/examples/MobileApp.md +730 -0
- package/doc/en/examples/README.md +2 -0
- package/doc/en/examples/TrayApp.md +1061 -0
- package/doc/zh/Application.md +3 -1
- package/doc/zh/Barcode.md +313 -0
- package/doc/zh/Cache.md +1 -1
- package/doc/zh/Command.md +12 -3
- package/doc/zh/ContainerdIntegration.md +1 -1
- package/doc/zh/Database.md +2 -0
- package/doc/zh/DatabaseDrivers.md +52 -2
- package/doc/zh/Entrypoint.md +3 -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 +12 -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/Migrations.md +1 -1
- package/doc/zh/NativeAddons.md +4 -2
- package/doc/zh/Overview.md +5 -4
- package/doc/zh/Packaging.md +6 -1
- package/doc/zh/ProjectStructure.md +5 -2
- package/doc/zh/ServiceCalls.md +65 -2
- package/doc/zh/UpgradingFrom1.md +2 -2
- package/doc/zh/UpgradingFrom2.md +3 -3
- package/doc/zh/WebRTC.md +1 -1
- package/doc/zh/examples/MobileApp.md +671 -0
- package/doc/zh/examples/README.md +2 -0
- package/doc/zh/examples/TrayApp.md +980 -0
- package/package.json +36 -16
package/doc/en/ServiceCalls.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
[Entrypoint](Entrypoint.md).
|
|
5
|
+
plain HTTP, Socket.IO, JSON-RPC 2.0 (over HTTP, WebSocket or the standard input and output), the IPC of Electron, the
|
|
6
|
+
windows of NW.js and the user interface of a mobile application of React Native, as this guide describes, and gRPC, NATS
|
|
7
|
+
and the data channels of WebRTC, which have their own guides. The controllers and their actions are described in
|
|
8
|
+
[Controllers](Controllers.md), the entrypoint and its adapters in [Entrypoint](Entrypoint.md).
|
|
9
9
|
|
|
10
10
|
## 1. A first service
|
|
11
11
|
|
|
@@ -136,7 +136,8 @@ 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, NW.js and React Native answer with an envelope; JSON-RPC answers with its own
|
|
140
|
+
responses (section 4).
|
|
140
141
|
|
|
141
142
|
```text
|
|
142
143
|
{"success": true, "error": null, "payload": <the result>}
|
|
@@ -179,6 +180,8 @@ export async function call<T>(message: Record<string, unknown>): Promise<T> {
|
|
|
179
180
|
| `socketIOServiceEntrypoint()` | `lakutata/adapter/socket.io` | `socket.io` (`socket.io-client` on the clients) | An emit with an acknowledgement | Socket.IO events |
|
|
180
181
|
| `jsonRPCServiceEntrypoint()` | `lakutata/adapter/jsonrpc` | `ws`, for WebSocket | A JSON-RPC 2.0 request | Notifications (WebSocket, stdio) |
|
|
181
182
|
| `electronIPCServiceEntrypoint()` | `lakutata/adapter/electron` | (Electron) | `ipcRenderer.invoke()` | IPC messages |
|
|
183
|
+
| `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 |
|
|
184
|
+
| `reactNativeServiceEntrypoint()` | `lakutata/adapter/react-native` | | A line of JSON from the host | Lines of JSON |
|
|
182
185
|
| `grpcServiceEntrypoint()` | `@lakutata/grpc/service` | `@lakutata/grpc` | See [GRPC](GRPC.md) | gRPC streams |
|
|
183
186
|
| `natsServiceEntrypoint()` | `@lakutata/nats` | `@lakutata/nats` | See [NATS](NATS.md) | NATS messages |
|
|
184
187
|
| `webrtcServiceEntrypoint()` | `@lakutata/webrtc` | `@lakutata/webrtc` | A JSON-RPC 2.0 request on a data channel, see [WebRTC](WebRTC.md) | Notifications |
|
|
@@ -468,6 +471,79 @@ contextBridge.exposeInMainWorld('service', {
|
|
|
468
471
|
- The Electron templates of `lakutata create` contain a preload script of this shape, and a `window.ipc` for the pages,
|
|
469
472
|
whose `invoke()` returns the payload or throws the error.
|
|
470
473
|
|
|
474
|
+
### NW.js
|
|
475
|
+
|
|
476
|
+
`nwjsServiceEntrypoint()` serves the actions to the windows of an NW.js application, in its background script (its
|
|
477
|
+
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
|
|
478
|
+
from its content (its sandbox is ignored): the user interface runs in a `<webview>`, without Node.js, held by a trusted
|
|
479
|
+
page of the window (its host page). The adapter puts a bridge on the global object that NW.js shares with its windows,
|
|
480
|
+
`global[Symbol.for(key)]`; the host page forwards the requests of the interface to it, and gives it the function that
|
|
481
|
+
pushes the events to the interface.
|
|
482
|
+
|
|
483
|
+
| Option | Default | Meaning |
|
|
484
|
+
|---|---|---|
|
|
485
|
+
| `key` | `'lakutata:service'` (`NWJS_SERVICE_BRIDGE`) | The key of the bridge on the global object |
|
|
486
|
+
| `global` | the global object of NW.js | The object the bridge is put on, or a stand-in in the tests |
|
|
487
|
+
|
|
488
|
+
| Method of the bridge | Meaning |
|
|
489
|
+
|---|---|
|
|
490
|
+
| `invoke(message, clientId)` | Invokes an action: resolves to the envelope, never rejects |
|
|
491
|
+
| `subscribe(clientId, push)` | Makes a page a client: the events pushed to it are given to `push(event, args)` |
|
|
492
|
+
| `unsubscribe(clientId)` | Removes a client, when its page is loaded again or its window closed: its requests in progress are aborted |
|
|
493
|
+
|
|
494
|
+
The host page forwards the messages of the interface, from the page loaded in its `<webview>` only:
|
|
495
|
+
|
|
496
|
+
```javascript
|
|
497
|
+
const view = document.querySelector('webview')
|
|
498
|
+
const origin = new URL(view.src).origin
|
|
499
|
+
const bridge = global[Symbol.for('lakutata:service')]
|
|
500
|
+
const send = (message) => view.contentWindow.postMessage(message, origin)
|
|
501
|
+
window.addEventListener('message', async (event) => {
|
|
502
|
+
if (event.source !== view.contentWindow || event.origin !== origin) return
|
|
503
|
+
const {type, id, message, clientId} = event.data
|
|
504
|
+
if (type === 'invoke') send({type: 'response', id: id, response: await bridge.invoke(message, clientId)})
|
|
505
|
+
if (type === 'subscribe') bridge.subscribe(clientId, (name, args) => send({type: 'event', name: name, args: args}))
|
|
506
|
+
})
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
- The `<webview>` loads the files of the application when its partition is declared in the manifest of NW.js:
|
|
510
|
+
`"webview": {"partitions": [{"name": "trusted", "accessible_resources": ["<all_urls>"]}]}` (the builder writes it).
|
|
511
|
+
- A page loaded again in the `<webview>` is a new client: the host page unsubscribes the previous one.
|
|
512
|
+
- The NW.js templates of `lakutata create` contain such a host page (`packages/app/host`), and a `window.ipc` for the
|
|
513
|
+
interface like the one of the Electron templates.
|
|
514
|
+
|
|
515
|
+
### React Native
|
|
516
|
+
|
|
517
|
+
`reactNativeServiceEntrypoint()` serves the actions to the user interface of a mobile application of React Native
|
|
518
|
+
(Android, iOS, HarmonyOS), in the Node.js that the application embeds. The native module of the application starts
|
|
519
|
+
Node.js and gives it one end of a socket, whose file descriptor is in the environment variable `LAKUTATA_NODE_FD`. The
|
|
520
|
+
adapter reads the messages of the host on that socket and writes its responses and events there, one JSON object per
|
|
521
|
+
line. The values arrive as JSON carries them: a `Date` arrives as its string, a `Buffer` as `{type, data}`, `undefined`
|
|
522
|
+
is left out, and a result that JSON cannot hold (a `bigint`, a cycle) is answered with an error.
|
|
523
|
+
|
|
524
|
+
| Option | Default | Meaning |
|
|
525
|
+
|---|---|---|
|
|
526
|
+
| `socket` | a socket on the file descriptor in `LAKUTATA_NODE_FD` | The connection to the host, or a stand-in in the tests |
|
|
527
|
+
| `pause` | | Called when the application goes to the background, before the host is told that the application is ready for it |
|
|
528
|
+
| `resume` | | Called when the application comes back from the background |
|
|
529
|
+
|
|
530
|
+
| The host writes | The adapter answers |
|
|
531
|
+
|---|---|
|
|
532
|
+
| `{"type":"invoke","id":1,"clientId":"ui","data":{"cmd":"greet","name":"you"}}` | `{"type":"response","id":1,"response":{"success":true,"error":null,"payload":…}}` |
|
|
533
|
+
| `{"type":"subscribe","clientId":"ui"}` | `{"type":"subscribed","clientId":"ui"}`, then the events pushed to the client |
|
|
534
|
+
| `{"type":"unsubscribe","clientId":"ui"}` | Nothing; the requests of the client in progress are aborted |
|
|
535
|
+
| `{"type":"pause"}` | `{"type":"paused"}`, once the `pause` option has run |
|
|
536
|
+
| `{"type":"resume"}` | Nothing; the `resume` option runs |
|
|
537
|
+
|
|
538
|
+
- The lines that the host writes before the application listens wait in the socket: none is lost. The answer to the
|
|
539
|
+
subscription tells the interface that the application is ready.
|
|
540
|
+
- On iOS, the host asks the system for time to finish before the application is suspended, sends `pause`, and lets the
|
|
541
|
+
application be suspended once `paused` comes (or when the time runs out).
|
|
542
|
+
- When Node.js ends (`process.exit()`, an uncaught exception), the mobile application keeps running: the native module
|
|
543
|
+
reports the exit code and can start Node.js again.
|
|
544
|
+
- The `mobile-react` template of `lakutata create` contains such a native module, and an `ipc` for the interface like
|
|
545
|
+
the one of the Electron templates, both in its package `packages/ipc`.
|
|
546
|
+
|
|
471
547
|
## 5. Clients and events
|
|
472
548
|
|
|
473
549
|
The transports that keep their clients connected can push events to them. A client is identified by the id it gives:
|
|
@@ -480,6 +556,8 @@ The transports that keep their clients connected can push events to them. A clie
|
|
|
480
556
|
| JSON-RPC over WebSocket | The `id` header or `id` query parameter of the connection, else a random id |
|
|
481
557
|
| JSON-RPC over stdio | `'stdio'` |
|
|
482
558
|
| Electron | The id the page gives when it subscribes or invokes |
|
|
559
|
+
| NW.js | The id the host page gives to the bridge for its page |
|
|
560
|
+
| React Native | The id the user interface gives when it subscribes or invokes |
|
|
483
561
|
| WebRTC | The member id of the caller in its room |
|
|
484
562
|
|
|
485
563
|
An action reads the id of its client in `this.context.clientId`. The `entrypoint` component pushes the events:
|
|
@@ -515,6 +593,8 @@ A client receives `notify(clientId, 'progress', 50, 'half')` as:
|
|
|
515
593
|
| Socket.IO | `socket.on('progress', (percent, label) => …)` |
|
|
516
594
|
| JSON-RPC (WebSocket, stdio) | `{"jsonrpc": "2.0", "method": "progress", "params": [50, "half"]}` |
|
|
517
595
|
| Electron | `('progress', [50, 'half'])`, through the `subscribe` of the preload script above |
|
|
596
|
+
| NW.js | `('progress', [50, 'half'])`, given to the function of the `subscribe` of the bridge |
|
|
597
|
+
| React Native | The line `{"type":"event","clientId":…,"event":"progress","args":[50,"half"]}`, which the host passes to the interface |
|
|
518
598
|
| WebRTC | `proxy.on('progress', (percent, label) => …)` of a `PeerServiceProxy` |
|
|
519
599
|
|
|
520
600
|
## 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
|
|