@livon/client 0.27.0-rc.2 → 0.27.0-rc.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/LICENCE.md +21 -0
- package/README.md +109 -0
- package/dist/client.cjs +455 -1
- package/dist/client.js +407 -1
- package/dist/generate.cjs +983 -5
- package/dist/generate.js +923 -5
- package/dist/index.cjs +64 -1
- package/dist/index.js +12 -1
- package/dist/mini/client.cjs +1 -0
- package/dist/mini/client.d.ts +100 -0
- package/dist/mini/client.js +1 -0
- package/dist/mini/generate.cjs +6 -0
- package/dist/mini/generate.d.ts +37 -0
- package/dist/mini/generate.js +6 -0
- package/dist/mini/index.cjs +1 -0
- package/dist/mini/index.d.ts +7 -0
- package/dist/mini/index.js +1 -0
- package/dist/mini/typeScriptSurfaceTemplate.cjs +1 -0
- package/dist/mini/typeScriptSurfaceTemplate.d.ts +35 -0
- package/dist/mini/typeScriptSurfaceTemplate.js +1 -0
- package/dist/typeScriptSurfaceTemplate.cjs +78 -0
- package/dist/typeScriptSurfaceTemplate.d.ts +35 -0
- package/dist/typeScriptSurfaceTemplate.js +28 -0
- package/package.json +17 -5
package/LICENCE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LIVON contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# @livon/client
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
[@livon/client](https://live-input-vector-output-node.github.io/livon-ts/docs/packages/client) provides deterministic client interface execution and generated-client foundations.
|
|
6
|
+
|
|
7
|
+
Exports include:
|
|
8
|
+
|
|
9
|
+
- `createClient`
|
|
10
|
+
- `createClientModule`
|
|
11
|
+
- `clientModule`
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
pnpm add @livon/client
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Runtime wiring (generated API path)
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import {runtime} from '@livon/runtime';
|
|
23
|
+
import {clientWsTransport} from '@livon/client-ws-transport';
|
|
24
|
+
import {api} from './generated/api';
|
|
25
|
+
|
|
26
|
+
runtime(
|
|
27
|
+
clientWsTransport({url: 'ws://127.0.0.1:3002/ws'}),
|
|
28
|
+
api,
|
|
29
|
+
);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Parameters in this example
|
|
33
|
+
|
|
34
|
+
`clientWsTransport({...})`:
|
|
35
|
+
|
|
36
|
+
- `url` (`string`): websocket endpoint used by client transport.
|
|
37
|
+
|
|
38
|
+
`runtime(transport, api)`:
|
|
39
|
+
|
|
40
|
+
- `transport` (`RuntimeModule`): client transport module.
|
|
41
|
+
- `api` (`RuntimeModule`): generated client module built from server schema.
|
|
42
|
+
|
|
43
|
+
## Subscription handling pattern
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
api({
|
|
47
|
+
onMessage: (payload, ctx) => {
|
|
48
|
+
payload.text;
|
|
49
|
+
ctx.state.get('lastMessage');
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
api.onMessage.off();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Parameters in this example
|
|
57
|
+
|
|
58
|
+
`api({...})`:
|
|
59
|
+
|
|
60
|
+
- `onMessage` (`(payload, ctx) => void`): typed subscription callback.
|
|
61
|
+
- `payload` (in callback): generated payload type from server schema.
|
|
62
|
+
- `ctx` (in callback): runtime context for state/emit/room access.
|
|
63
|
+
|
|
64
|
+
`api.onMessage.off()`:
|
|
65
|
+
|
|
66
|
+
- no parameters; disables one subscription callback stream.
|
|
67
|
+
|
|
68
|
+
## Room-scoped handlers
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
api.room('global')({
|
|
72
|
+
onMessage: (payload) => {
|
|
73
|
+
payload.text;
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Parameters in this example
|
|
79
|
+
|
|
80
|
+
`api.room(roomId)`:
|
|
81
|
+
|
|
82
|
+
- `roomId` (`string`): room selector for scoped schema handling.
|
|
83
|
+
|
|
84
|
+
`api.room(... )({...})`:
|
|
85
|
+
|
|
86
|
+
- `onMessage` (`(payload) => void`): room-scoped subscription callback.
|
|
87
|
+
|
|
88
|
+
## Low-level client module
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import {createClientModule} from '@livon/client';
|
|
92
|
+
import {runtime} from '@livon/runtime';
|
|
93
|
+
|
|
94
|
+
const module = createClientModule({ast});
|
|
95
|
+
runtime(transport, module);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Parameters in this example
|
|
99
|
+
|
|
100
|
+
`createClientModule({...})`:
|
|
101
|
+
|
|
102
|
+
- `ast` (`AstNode`): schema AST used to build executable client interface module.
|
|
103
|
+
|
|
104
|
+
## Related pages
|
|
105
|
+
|
|
106
|
+
- [@livon/runtime](https://live-input-vector-output-node.github.io/livon-ts/docs/packages/runtime)
|
|
107
|
+
- [@livon/client-ws-transport](https://live-input-vector-output-node.github.io/livon-ts/docs/packages/client-ws-transport)
|
|
108
|
+
- [@livon/schema](https://live-input-vector-output-node.github.io/livon-ts/docs/packages/schema)
|
|
109
|
+
- [Schema APIs](https://live-input-vector-output-node.github.io/livon-ts/docs/schema)
|
package/dist/client.cjs
CHANGED
|
@@ -1 +1,455 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
const __rslib_import_meta_url__ = /*#__PURE__*/ (function () {
|
|
3
|
+
return typeof document === 'undefined'
|
|
4
|
+
? new (require('url'.replace('', '')).URL)('file:' + __filename).href
|
|
5
|
+
: (document.currentScript && document.currentScript.src) ||
|
|
6
|
+
new URL('main.js', document.baseURI).href;
|
|
7
|
+
})();
|
|
8
|
+
;
|
|
9
|
+
// The require scope
|
|
10
|
+
var __webpack_require__ = {};
|
|
11
|
+
|
|
12
|
+
// webpack/runtime/define_property_getters
|
|
13
|
+
(() => {
|
|
14
|
+
__webpack_require__.d = (exports, definition) => {
|
|
15
|
+
for(var key in definition) {
|
|
16
|
+
if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
17
|
+
Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
})();
|
|
22
|
+
// webpack/runtime/has_own_property
|
|
23
|
+
(() => {
|
|
24
|
+
__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
25
|
+
})();
|
|
26
|
+
// webpack/runtime/make_namespace_object
|
|
27
|
+
(() => {
|
|
28
|
+
// define __esModule on exports
|
|
29
|
+
__webpack_require__.r = (exports) => {
|
|
30
|
+
if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
31
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
32
|
+
}
|
|
33
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __webpack_exports__ = {};
|
|
37
|
+
__webpack_require__.r(__webpack_exports__);
|
|
38
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
39
|
+
clientModule: () => (clientModule),
|
|
40
|
+
createClient: () => (createClient),
|
|
41
|
+
createClientModule: () => (createClientModule)
|
|
42
|
+
});
|
|
43
|
+
const DEFAULT_REQUEST_KEY = 'livon.client.request';
|
|
44
|
+
const setClientRequest = ({ client, registry, requestKey })=>{
|
|
45
|
+
if (typeof client !== 'object' || client === null || !('setRequest' in client)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const candidate = client;
|
|
49
|
+
if (typeof candidate.setRequest !== 'function') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
candidate.setRequest((event, payload)=>{
|
|
53
|
+
const request = registry.state.get(requestKey);
|
|
54
|
+
if (!request) {
|
|
55
|
+
throw new Error('Client request handler is not available.');
|
|
56
|
+
}
|
|
57
|
+
return request(event, payload);
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const buildClientEventEnvelope = (envelope)=>{
|
|
61
|
+
if ('payload' in envelope) {
|
|
62
|
+
return {
|
|
63
|
+
...envelope,
|
|
64
|
+
payload: envelope.payload
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
...envelope,
|
|
69
|
+
error: envelope.error
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* clientModule is part of the public LIVON API.
|
|
74
|
+
*
|
|
75
|
+
* @remarks
|
|
76
|
+
* Parameter and return types are defined in the TypeScript signature.
|
|
77
|
+
*
|
|
78
|
+
* @see https://live-input-vector-output-node.github.io/livon-ts/docs/packages/client
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* const result = clientModule(undefined as never);
|
|
82
|
+
*/ const clientModule = (client, options = {})=>{
|
|
83
|
+
const register = (registry)=>{
|
|
84
|
+
const requestKey = options.requestKey ?? DEFAULT_REQUEST_KEY;
|
|
85
|
+
setClientRequest({
|
|
86
|
+
client,
|
|
87
|
+
registry,
|
|
88
|
+
requestKey
|
|
89
|
+
});
|
|
90
|
+
registry.onReceive((envelope, _ctx, next)=>{
|
|
91
|
+
client.emitEvent(buildClientEventEnvelope(envelope));
|
|
92
|
+
return next();
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
name: options.name ?? 'client-module',
|
|
97
|
+
register
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
101
|
+
const isArray = (value)=>Array.isArray(value);
|
|
102
|
+
const capitalize = (value)=>value.length === 0 ? value : value.slice(0, 1).toUpperCase() + value.slice(1);
|
|
103
|
+
const camelCaseName = (value)=>{
|
|
104
|
+
if (!value) return value;
|
|
105
|
+
return value.replace(/[^a-zA-Z0-9]+(.)/g, (_, group)=>String(group).toUpperCase()).replace(/^./, (char)=>char.toLowerCase());
|
|
106
|
+
};
|
|
107
|
+
const fieldMethodName = (owner, field)=>`$${camelCaseName(owner)}${capitalize(field)}`;
|
|
108
|
+
const fieldEventName = (owner, field)=>`$${owner}.${field}`;
|
|
109
|
+
const walkAst = (node, visit)=>{
|
|
110
|
+
visit(node);
|
|
111
|
+
node.children?.forEach((child)=>walkAst(child, visit));
|
|
112
|
+
};
|
|
113
|
+
const collectOperations = (root)=>{
|
|
114
|
+
const operations = [];
|
|
115
|
+
walkAst(root, (node)=>{
|
|
116
|
+
if (node.type !== 'operation' || !node.name) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const input = node.children?.[0];
|
|
120
|
+
const output = node.children?.[1];
|
|
121
|
+
operations.push({
|
|
122
|
+
name: node.name,
|
|
123
|
+
input,
|
|
124
|
+
output,
|
|
125
|
+
event: node.name
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
return operations;
|
|
129
|
+
};
|
|
130
|
+
const collectFieldOperations = (root)=>{
|
|
131
|
+
const registry = new Map();
|
|
132
|
+
walkAst(root, (node)=>{
|
|
133
|
+
if (node.type !== 'field') {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const constraints = node.constraints;
|
|
137
|
+
const owner = typeof constraints?.owner === 'string' ? constraints.owner : undefined;
|
|
138
|
+
const field = typeof constraints?.field === 'string' ? constraints.field : undefined;
|
|
139
|
+
if (!owner || !field) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const children = node.children ?? [];
|
|
143
|
+
const dependsOn = children[0];
|
|
144
|
+
const input = children.length === 3 ? children[1] : undefined;
|
|
145
|
+
const output = children.length === 3 ? children[2] : children[1];
|
|
146
|
+
if (!dependsOn) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const spec = {
|
|
150
|
+
owner,
|
|
151
|
+
field,
|
|
152
|
+
input,
|
|
153
|
+
output,
|
|
154
|
+
event: fieldEventName(owner, field)
|
|
155
|
+
};
|
|
156
|
+
if (!registry.has(owner)) {
|
|
157
|
+
registry.set(owner, new Map());
|
|
158
|
+
}
|
|
159
|
+
registry.get(owner).set(field, spec);
|
|
160
|
+
});
|
|
161
|
+
return registry;
|
|
162
|
+
};
|
|
163
|
+
const hydrateByNode = ({ value, node, registry, request })=>{
|
|
164
|
+
if (!node) {
|
|
165
|
+
return value;
|
|
166
|
+
}
|
|
167
|
+
if (node.type === 'array' && isArray(value)) {
|
|
168
|
+
const child = node.children?.[0];
|
|
169
|
+
value.forEach((item, index)=>{
|
|
170
|
+
value[index] = hydrateByNode({
|
|
171
|
+
value: item,
|
|
172
|
+
node: child,
|
|
173
|
+
registry,
|
|
174
|
+
request
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
return value;
|
|
178
|
+
}
|
|
179
|
+
if (node.type === 'tuple' && isArray(value)) {
|
|
180
|
+
const children = node.children ?? [];
|
|
181
|
+
value.forEach((item, index)=>{
|
|
182
|
+
value[index] = hydrateByNode({
|
|
183
|
+
value: item,
|
|
184
|
+
node: children[index],
|
|
185
|
+
registry,
|
|
186
|
+
request
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
if (node.type === 'and') {
|
|
192
|
+
return (node.children ?? []).reduce((current, child)=>hydrateByNode({
|
|
193
|
+
value: current,
|
|
194
|
+
node: child,
|
|
195
|
+
registry,
|
|
196
|
+
request
|
|
197
|
+
}), value);
|
|
198
|
+
}
|
|
199
|
+
if (node.type === 'object' && isRecord(value)) {
|
|
200
|
+
const typeName = node.name;
|
|
201
|
+
if (typeName && registry.has(typeName)) {
|
|
202
|
+
attachFieldOperations({
|
|
203
|
+
target: value,
|
|
204
|
+
typeName,
|
|
205
|
+
registry,
|
|
206
|
+
request
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
const fields = node.children ?? [];
|
|
210
|
+
fields.forEach((fieldNode)=>{
|
|
211
|
+
if (fieldNode.type !== 'field' || !fieldNode.name) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const child = fieldNode.children?.[0];
|
|
215
|
+
if (!child) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
value[fieldNode.name] = hydrateByNode({
|
|
219
|
+
value: value[fieldNode.name],
|
|
220
|
+
node: child,
|
|
221
|
+
registry,
|
|
222
|
+
request
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
if (node.type === 'field') {
|
|
228
|
+
const child = node.children?.[0];
|
|
229
|
+
return hydrateByNode({
|
|
230
|
+
value,
|
|
231
|
+
node: child,
|
|
232
|
+
registry,
|
|
233
|
+
request
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return value;
|
|
237
|
+
};
|
|
238
|
+
const attachFieldOperations = ({ target, typeName, registry, request })=>{
|
|
239
|
+
const operations = registry.get(typeName);
|
|
240
|
+
if (!operations) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!Object.isExtensible(target)) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
operations.forEach((spec, fieldName)=>{
|
|
247
|
+
if (fieldName in target) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
Object.defineProperty(target, fieldName, {
|
|
251
|
+
enumerable: false,
|
|
252
|
+
configurable: true,
|
|
253
|
+
value: async (input)=>{
|
|
254
|
+
const payload = {
|
|
255
|
+
dependsOn: target,
|
|
256
|
+
input
|
|
257
|
+
};
|
|
258
|
+
const result = await request(spec.event, payload);
|
|
259
|
+
return hydrateByNode({
|
|
260
|
+
value: result,
|
|
261
|
+
node: spec.output,
|
|
262
|
+
registry,
|
|
263
|
+
request
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
const normalizeFieldPayload = (payload)=>{
|
|
270
|
+
if (isRecord(payload) && 'dependsOn' in payload) {
|
|
271
|
+
const dependsOn = payload.dependsOn;
|
|
272
|
+
const input = 'input' in payload ? payload.input : undefined;
|
|
273
|
+
if (input === undefined) {
|
|
274
|
+
return {
|
|
275
|
+
dependsOn
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
dependsOn,
|
|
280
|
+
input
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
dependsOn: payload
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
const createClientCore = ({ ast })=>{
|
|
288
|
+
const operations = collectOperations(ast);
|
|
289
|
+
const fieldRegistry = collectFieldOperations(ast);
|
|
290
|
+
let request;
|
|
291
|
+
const client = {};
|
|
292
|
+
client.setRequest = (next)=>{
|
|
293
|
+
request = next;
|
|
294
|
+
};
|
|
295
|
+
const globalHandlers = new Map();
|
|
296
|
+
const globalEnabled = new Map();
|
|
297
|
+
const roomHandlers = new Map();
|
|
298
|
+
const roomEnabled = new Map();
|
|
299
|
+
const registerHandlers = (handlers, roomId)=>{
|
|
300
|
+
const entries = Object.entries(handlers).filter(([, handler])=>typeof handler === 'function');
|
|
301
|
+
if (entries.length === 0) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (!roomId) {
|
|
305
|
+
entries.forEach(([event, handler])=>{
|
|
306
|
+
globalHandlers.set(event, handler);
|
|
307
|
+
globalEnabled.set(event, true);
|
|
308
|
+
});
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const roomMap = roomHandlers.get(roomId) ?? new Map();
|
|
312
|
+
const enabledMap = roomEnabled.get(roomId) ?? new Map();
|
|
313
|
+
entries.forEach(([event, handler])=>{
|
|
314
|
+
roomMap.set(event, handler);
|
|
315
|
+
enabledMap.set(event, true);
|
|
316
|
+
});
|
|
317
|
+
roomHandlers.set(roomId, roomMap);
|
|
318
|
+
roomEnabled.set(roomId, enabledMap);
|
|
319
|
+
};
|
|
320
|
+
const toggleHandler = ({ enabled, event, roomId })=>{
|
|
321
|
+
if (!roomId) {
|
|
322
|
+
globalEnabled.set(event, enabled);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const enabledMap = roomEnabled.get(roomId) ?? new Map();
|
|
326
|
+
enabledMap.set(event, enabled);
|
|
327
|
+
roomEnabled.set(roomId, enabledMap);
|
|
328
|
+
};
|
|
329
|
+
const dispatch = (envelope)=>{
|
|
330
|
+
const ctx = {
|
|
331
|
+
eventId: envelope.id,
|
|
332
|
+
event: envelope.event,
|
|
333
|
+
status: envelope.status,
|
|
334
|
+
metadata: envelope.metadata,
|
|
335
|
+
context: envelope.context,
|
|
336
|
+
room: typeof envelope.metadata?.room === 'string' ? String(envelope.metadata.room) : undefined
|
|
337
|
+
};
|
|
338
|
+
const roomId = ctx.room;
|
|
339
|
+
if (roomId) {
|
|
340
|
+
const enabledMap = roomEnabled.get(roomId);
|
|
341
|
+
const roomMap = roomHandlers.get(roomId);
|
|
342
|
+
const handler = roomMap?.get(envelope.event);
|
|
343
|
+
const isEnabled = enabledMap?.get(envelope.event) ?? true;
|
|
344
|
+
if (handler && isEnabled) {
|
|
345
|
+
handler(envelope.payload, ctx);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const handler = globalHandlers.get(envelope.event);
|
|
349
|
+
const isEnabled = globalEnabled.get(envelope.event) ?? true;
|
|
350
|
+
if (handler && isEnabled) {
|
|
351
|
+
handler(envelope.payload, ctx);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
operations.forEach((op)=>{
|
|
355
|
+
client[op.name] = async (input)=>{
|
|
356
|
+
if (!request) {
|
|
357
|
+
throw new Error('Client request handler is not available.');
|
|
358
|
+
}
|
|
359
|
+
const result = await request(op.event, input);
|
|
360
|
+
return hydrateByNode({
|
|
361
|
+
value: result,
|
|
362
|
+
node: op.output,
|
|
363
|
+
registry: fieldRegistry,
|
|
364
|
+
request
|
|
365
|
+
});
|
|
366
|
+
};
|
|
367
|
+
});
|
|
368
|
+
fieldRegistry.forEach((fields, owner)=>{
|
|
369
|
+
fields.forEach((spec, field)=>{
|
|
370
|
+
const method = fieldMethodName(owner, field);
|
|
371
|
+
if (method in client) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
client[method] = async (payload, input)=>{
|
|
375
|
+
const normalized = normalizeFieldPayload(payload);
|
|
376
|
+
if (!request) {
|
|
377
|
+
throw new Error('Client request handler is not available.');
|
|
378
|
+
}
|
|
379
|
+
const result = await request(spec.event, {
|
|
380
|
+
dependsOn: normalized.dependsOn,
|
|
381
|
+
input: input ?? normalized.input
|
|
382
|
+
});
|
|
383
|
+
return hydrateByNode({
|
|
384
|
+
value: result,
|
|
385
|
+
node: spec.output,
|
|
386
|
+
registry: fieldRegistry,
|
|
387
|
+
request
|
|
388
|
+
});
|
|
389
|
+
};
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
return Object.assign(client, {
|
|
393
|
+
__register: registerHandlers,
|
|
394
|
+
__toggle: (event, enabled, roomId)=>toggleHandler({
|
|
395
|
+
event,
|
|
396
|
+
enabled,
|
|
397
|
+
roomId
|
|
398
|
+
}),
|
|
399
|
+
emitEvent: dispatch
|
|
400
|
+
});
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* createClient is part of the public LIVON API.
|
|
404
|
+
*
|
|
405
|
+
* @remarks
|
|
406
|
+
* Parameter and return types are defined in the TypeScript signature.
|
|
407
|
+
*
|
|
408
|
+
* @see https://live-input-vector-output-node.github.io/livon-ts/docs/packages/client
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* const result = createClient(undefined as never);
|
|
412
|
+
*/ const createClient = (input)=>{
|
|
413
|
+
const client = createClientCore({
|
|
414
|
+
ast: input.ast
|
|
415
|
+
});
|
|
416
|
+
const register = (registry)=>{
|
|
417
|
+
const requestKey = input.requestKey ?? DEFAULT_REQUEST_KEY;
|
|
418
|
+
setClientRequest({
|
|
419
|
+
client,
|
|
420
|
+
registry,
|
|
421
|
+
requestKey
|
|
422
|
+
});
|
|
423
|
+
registry.onReceive((envelope, _ctx, next)=>{
|
|
424
|
+
client.emitEvent(buildClientEventEnvelope(envelope));
|
|
425
|
+
return next();
|
|
426
|
+
});
|
|
427
|
+
};
|
|
428
|
+
const moduleBase = {
|
|
429
|
+
name: input.name ?? 'client',
|
|
430
|
+
register
|
|
431
|
+
};
|
|
432
|
+
const moduleWithClient = Object.assign(moduleBase, client);
|
|
433
|
+
return moduleWithClient;
|
|
434
|
+
};
|
|
435
|
+
/**
|
|
436
|
+
* createClientModule is part of the public LIVON API.
|
|
437
|
+
*
|
|
438
|
+
* @remarks
|
|
439
|
+
* Parameter and return types are defined in the TypeScript signature.
|
|
440
|
+
*
|
|
441
|
+
* @see https://live-input-vector-output-node.github.io/livon-ts/docs/packages/client
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* const result = createClientModule(undefined as never);
|
|
445
|
+
*/ const createClientModule = (input)=>createClient(input);
|
|
446
|
+
|
|
447
|
+
exports.clientModule = __webpack_exports__.clientModule;
|
|
448
|
+
exports.createClient = __webpack_exports__.createClient;
|
|
449
|
+
exports.createClientModule = __webpack_exports__.createClientModule;
|
|
450
|
+
for(var __rspack_i in __webpack_exports__) {
|
|
451
|
+
if(["clientModule","createClient","createClientModule"].indexOf(__rspack_i) === -1) {
|
|
452
|
+
exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|