lowlander 0.2.1 → 0.2.2
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 +251 -6
- package/build/client/client.d.ts +153 -0
- package/build/client/client.js +317 -0
- package/build/client/client.js.map +1 -0
- package/build/examples/helloworld/client/js/admin.d.ts +11 -0
- package/build/examples/helloworld/client/js/admin.js +87 -0
- package/build/examples/helloworld/client/js/admin.js.map +1 -0
- package/build/examples/helloworld/client/js/base.d.ts +4 -0
- package/{examples/helloworld/client/js/base.ts → build/examples/helloworld/client/js/base.js} +13 -25
- package/build/examples/helloworld/client/js/base.js.map +1 -0
- package/build/examples/helloworld/server/api.d.ts +40 -0
- package/build/examples/helloworld/server/api.d.ts.map +1 -0
- package/{examples/helloworld/server/api.ts → build/examples/helloworld/server/api.js} +58 -66
- package/build/examples/helloworld/server/api.js.map +1 -0
- package/build/examples/helloworld/server/main.d.ts +2 -0
- package/build/examples/helloworld/server/main.d.ts.map +1 -0
- package/{examples/helloworld/server/main.ts → build/examples/helloworld/server/main.js} +3 -8
- package/build/examples/helloworld/server/main.js.map +1 -0
- package/build/server/protocol.d.ts +12 -0
- package/build/server/protocol.d.ts.map +1 -0
- package/build/server/protocol.js +19 -0
- package/build/server/protocol.js.map +1 -0
- package/build/server/server.d.ts +191 -0
- package/build/server/server.d.ts.map +1 -0
- package/build/server/server.js +379 -0
- package/build/server/server.js.map +1 -0
- package/build/server/wshandler.d.ts +11 -0
- package/build/server/wshandler.d.ts.map +1 -0
- package/build/server/wshandler.js +126 -0
- package/build/server/wshandler.js.map +1 -0
- package/build/tsconfig.client.tsbuildinfo +1 -0
- package/build/tsconfig.server.tsbuildinfo +1 -0
- package/package.json +14 -8
- package/server/server.ts +1 -0
- package/skill/SKILL.md +605 -0
- package/AGENTS.md +0 -2
- package/ROADMAP.md +0 -13
- package/bun.lock +0 -281
- package/examples/helloworld/client/js/admin.ts +0 -94
- package/examples/helloworld/package.json +0 -8
- package/tests/fake-warpsocket.ts +0 -452
- package/tests/helloworld.test.ts +0 -151
- package/tsconfig.client.json +0 -18
- package/tsconfig.json +0 -24
- package/tsconfig.server.json +0 -17
- package/tsconfig.test.json +0 -13
- /package/{examples → build/examples}/helloworld/client/assets/style.css +0 -0
- /package/{examples → build/examples}/helloworld/client/index.html +0 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import * as E from "edinburgh";
|
|
2
|
+
import DataPack from "edinburgh/datapack";
|
|
3
|
+
import * as realWarpsocket from 'warpsocket';
|
|
4
|
+
// Get log level from environment variable
|
|
5
|
+
// 0: no logging (default)
|
|
6
|
+
// 1: connections & lifecycle (connect/disconnect/reconnect, worker startup)
|
|
7
|
+
// 2: RPC calls & responses (method calls, incoming responses, errors)
|
|
8
|
+
// 3: model streaming & internals (onSave, model changes, stream processing)
|
|
9
|
+
export const logLevel = parseInt(process.env.LOWLANDER_LOG_LEVEL || "0") || 0;
|
|
10
|
+
/** @internal Warpsocket implementation; swapped to FakeWarpSocket in test mode. */
|
|
11
|
+
export let warpsocket = realWarpsocket;
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { dirname, resolve } from 'path';
|
|
14
|
+
const WSHANDLER_FILE = resolve(dirname(fileURLToPath(import.meta.url)), 'wshandler.js');
|
|
15
|
+
/** @internal WarpSocket channel id prefix for model streams */
|
|
16
|
+
const CHANNEL_TYPE_MODEL = 1;
|
|
17
|
+
/** @internal Registry mapping model classes to their stream types */
|
|
18
|
+
const streamTypesPerModel = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* Base class for stream types created by {@link createStreamType}.
|
|
21
|
+
* @typeParam T - The projected model type
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export class StreamTypeBase {
|
|
25
|
+
_instance;
|
|
26
|
+
/** @internal */
|
|
27
|
+
static fields;
|
|
28
|
+
/** @internal */
|
|
29
|
+
static id;
|
|
30
|
+
/** @internal */
|
|
31
|
+
constructor(_instance) {
|
|
32
|
+
this._instance = _instance;
|
|
33
|
+
}
|
|
34
|
+
toString() {
|
|
35
|
+
let streamTypes = streamTypesPerModel.get(this._instance.constructor) || [];
|
|
36
|
+
return `{Stream model=${this._instance.toString()} type=${streamTypes.indexOf(this.constructor)}}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Returns a stable numeric ID for a key tuple, allocating a new one if needed.
|
|
41
|
+
* Safe for multiple WarpSocket threads.
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
function getIdForData(namespace, ...data) {
|
|
45
|
+
const dataKeyPack = new DataPack().write(namespace);
|
|
46
|
+
for (const d of data)
|
|
47
|
+
dataKeyPack.write(d);
|
|
48
|
+
const dataKey = dataKeyPack.toUint8Array();
|
|
49
|
+
const idPack = warpsocket.getKey(dataKey);
|
|
50
|
+
if (idPack) {
|
|
51
|
+
return new DataPack(idPack).readNumber();
|
|
52
|
+
}
|
|
53
|
+
const countKey = new DataPack().write(namespace).toUint8Array();
|
|
54
|
+
while (true) {
|
|
55
|
+
// Insert a new stream type
|
|
56
|
+
const countPack = warpsocket.getKey(countKey);
|
|
57
|
+
const newCount = countPack ? new DataPack(countPack).readNumber() + 1 : 1;
|
|
58
|
+
const newCountPack = new DataPack().write(newCount).toUint8Array();
|
|
59
|
+
if (warpsocket.setKeyIf(countKey, newCountPack, countPack)) {
|
|
60
|
+
if (warpsocket.setKeyIf(dataKey, newCountPack, undefined)) {
|
|
61
|
+
return newCount; // Success
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Raced, try again
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Creates a stream type for reactive model streaming to clients with automatic updates.
|
|
69
|
+
*
|
|
70
|
+
* Specify which fields to include; when they change, updates are pushed to subscribed clients.
|
|
71
|
+
* Supports nested linked models and type-safe field selection.
|
|
72
|
+
*
|
|
73
|
+
* @typeParam T - The model type
|
|
74
|
+
* @typeParam S - The field selection
|
|
75
|
+
*
|
|
76
|
+
* @param Model - The Edinburgh model class
|
|
77
|
+
* @param selection - Field selection: `true` for simple fields, nested object for linked models
|
|
78
|
+
* @returns Stream type class to instantiate in API functions
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* @registerModel
|
|
83
|
+
* class Person extends Model {
|
|
84
|
+
* name = field(string);
|
|
85
|
+
* age = field(number);
|
|
86
|
+
* password = field(string);
|
|
87
|
+
* friends = field(array(link(Person)));
|
|
88
|
+
* }
|
|
89
|
+
*
|
|
90
|
+
* // Exclude password, include friends' names
|
|
91
|
+
* const PersonStream = createStreamType(Person, {
|
|
92
|
+
* name: true,
|
|
93
|
+
* age: true,
|
|
94
|
+
* friends: { name: true }
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* export function streamPerson() {
|
|
98
|
+
* const person = Person.byName.get('Alice')!;
|
|
99
|
+
* return new PersonStream(person);
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export function createStreamType(Model, selection) {
|
|
104
|
+
let streamTypes = streamTypesPerModel.get(Model);
|
|
105
|
+
if (!streamTypes)
|
|
106
|
+
streamTypesPerModel.set(Model, streamTypes = []);
|
|
107
|
+
const streamTypeId = getIdForData("streamType", Model.tableName, selection);
|
|
108
|
+
const fields = {};
|
|
109
|
+
for (const prop of Array.from(Object.keys(selection)).sort()) {
|
|
110
|
+
if (!Model.fields.hasOwnProperty(prop)) {
|
|
111
|
+
throw new Error(`Property ${prop} does not exist in model ${Model.name}`);
|
|
112
|
+
}
|
|
113
|
+
const LinkedModel = Model.fields[prop].type.getLinkedModel();
|
|
114
|
+
if (selection[prop] === true) {
|
|
115
|
+
if (LinkedModel)
|
|
116
|
+
throw new Error(`Property ${prop} is a link; must specify sub-selection`);
|
|
117
|
+
fields[prop] = true; // Include field without tracking links
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
if (!LinkedModel)
|
|
121
|
+
throw new Error(`Property ${prop} is not a link; cannot specify sub-selection`);
|
|
122
|
+
const SubStreamType = createStreamType(LinkedModel, selection[prop]);
|
|
123
|
+
fields[prop] = SubStreamType.id;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
class StreamType extends StreamTypeBase {
|
|
127
|
+
static fields = fields;
|
|
128
|
+
static id = streamTypeId;
|
|
129
|
+
}
|
|
130
|
+
streamTypes.push(StreamType);
|
|
131
|
+
return StreamType;
|
|
132
|
+
}
|
|
133
|
+
/** Writes `value` to `pack`, replacing Model instances with XOR'd hash refs. */
|
|
134
|
+
function writeModelField(pack, value, streamTypeId) {
|
|
135
|
+
if (typeof value !== 'object' || value == null) {
|
|
136
|
+
pack.write(value);
|
|
137
|
+
}
|
|
138
|
+
else if (value instanceof E.Model) {
|
|
139
|
+
pack.writeCustom('model', value.getPrimaryKeyHash() + streamTypeId);
|
|
140
|
+
}
|
|
141
|
+
else if (Array.isArray(value)) {
|
|
142
|
+
pack.writeCollection('array', () => {
|
|
143
|
+
for (const item of value)
|
|
144
|
+
writeModelField(pack, item, streamTypeId);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
pack.writeCollection('object', () => {
|
|
149
|
+
for (const key of Object.keys(value)) {
|
|
150
|
+
pack.write(key);
|
|
151
|
+
writeModelField(pack, value[key], streamTypeId);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Tracks link deltas for subscription management. */
|
|
157
|
+
function updateLinkDeltas(value, linkDeltas, streamTypeId, delta) {
|
|
158
|
+
if (typeof value !== 'object' || value == null)
|
|
159
|
+
return;
|
|
160
|
+
if (Array.isArray(value)) {
|
|
161
|
+
for (const item of value)
|
|
162
|
+
updateLinkDeltas(item, linkDeltas, streamTypeId, delta);
|
|
163
|
+
}
|
|
164
|
+
else if (value instanceof E.Model) {
|
|
165
|
+
let map = linkDeltas.get(value);
|
|
166
|
+
if (!map)
|
|
167
|
+
linkDeltas.set(value, map = new Map());
|
|
168
|
+
const v = (map.get(streamTypeId) || 0) + delta;
|
|
169
|
+
if (v)
|
|
170
|
+
map.set(streamTypeId, v);
|
|
171
|
+
else
|
|
172
|
+
map.delete(streamTypeId);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
for (const key of Object.keys(value)) {
|
|
176
|
+
updateLinkDeltas(value[key], linkDeltas, streamTypeId, delta);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
E.setOnSaveCallback((commitId, items) => {
|
|
181
|
+
if (logLevel >= 3)
|
|
182
|
+
console.log('[lowlander] onSave', commitId);
|
|
183
|
+
for (const [model, changed] of items.entries()) {
|
|
184
|
+
const streamTypes = streamTypesPerModel.get(model.constructor);
|
|
185
|
+
if (logLevel >= 3)
|
|
186
|
+
console.log('[lowlander] Model changed:', model, changed, `streams=${streamTypes?.length}`);
|
|
187
|
+
if (!streamTypes)
|
|
188
|
+
continue;
|
|
189
|
+
for (const StreamType of streamTypes) {
|
|
190
|
+
const channelName = DataPack.createUint8Array(CHANNEL_TYPE_MODEL, model.getPrimaryKeyHash() + StreamType.id);
|
|
191
|
+
if (logLevel >= 3)
|
|
192
|
+
console.log('[lowlander] Processing stream type', StreamType.name, 'channel', channelName);
|
|
193
|
+
// Don't bother constructing a change message if nobody is listening
|
|
194
|
+
if (!warpsocket.hasSubscriptions(channelName))
|
|
195
|
+
continue;
|
|
196
|
+
// When an instance is first created, we can't possibly have any references to it yet, so we don't need to emit it.
|
|
197
|
+
if (changed !== 'created') {
|
|
198
|
+
sendModel(channelName, model, commitId, StreamType, changed);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
/**
|
|
204
|
+
* Sends (updated) data for `model` to `target`.
|
|
205
|
+
* `target` is a virtual socket with a requestId+'d' user prefix, or a channel that subscribes such virtual sockets.
|
|
206
|
+
*/
|
|
207
|
+
export function sendModel(target, model, commitId, StreamType, changed) {
|
|
208
|
+
let pack = new DataPack();
|
|
209
|
+
pack.write(model.getPrimaryKeyHash() + StreamType.id);
|
|
210
|
+
pack.write(commitId);
|
|
211
|
+
let mustSend = false;
|
|
212
|
+
if (changed === 'deleted') {
|
|
213
|
+
pack.write(null);
|
|
214
|
+
mustSend = true;
|
|
215
|
+
}
|
|
216
|
+
else { // changed is an object or 'created'
|
|
217
|
+
const linkDeltas = new Map();
|
|
218
|
+
pack.writeCollection('object', (addRecord) => {
|
|
219
|
+
for (const fieldName in StreamType.fields) {
|
|
220
|
+
if (typeof changed === 'object' && !changed.hasOwnProperty(fieldName))
|
|
221
|
+
continue;
|
|
222
|
+
let streamIndex = StreamType.fields[fieldName];
|
|
223
|
+
const fieldValue = model[fieldName];
|
|
224
|
+
mustSend = true;
|
|
225
|
+
if (typeof streamIndex === 'number') {
|
|
226
|
+
pack.write(fieldName);
|
|
227
|
+
writeModelField(pack, fieldValue, streamIndex);
|
|
228
|
+
updateLinkDeltas(fieldValue, linkDeltas, streamIndex, 1);
|
|
229
|
+
if (typeof changed === 'object')
|
|
230
|
+
updateLinkDeltas(changed[fieldName], linkDeltas, streamIndex, -1);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
addRecord(fieldName, fieldValue);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
for (const linkedModel of linkDeltas.keys()) {
|
|
238
|
+
let streamIndexMap = linkDeltas.get(linkedModel);
|
|
239
|
+
const subStreamTypes = streamTypesPerModel.get(linkedModel.constructor);
|
|
240
|
+
for (const subStreamType of subStreamTypes) {
|
|
241
|
+
const delta = streamIndexMap.get(subStreamType.id);
|
|
242
|
+
if (delta) { // Only in case delta is set and non-zero
|
|
243
|
+
pushModel(target, linkedModel, commitId, subStreamType, delta);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// else: Do nothing in case of changed=="created", as there can't be any subscribers yet at this time.
|
|
249
|
+
// If at least one field was updated, send the packet
|
|
250
|
+
if (mustSend) {
|
|
251
|
+
warpsocket.send(target, pack.toUint8Array(false));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Subscribes `target` to this model, and sends initial data.
|
|
256
|
+
* `target` is a virtual socket with a requestId+'d' user prefix, or a channel that subscribes such virtual sockets.
|
|
257
|
+
*/
|
|
258
|
+
export function pushModel(target, model, commitId, SubStreamType, delta) {
|
|
259
|
+
const subChannel = DataPack.createUint8Array(CHANNEL_TYPE_MODEL, model.getPrimaryKeyHash() + SubStreamType.id);
|
|
260
|
+
let changedSocketIds = warpsocket.subscribe(target, subChannel, delta);
|
|
261
|
+
if (changedSocketIds.length > 0) {
|
|
262
|
+
sendModel(changedSocketIds, model, commitId, SubStreamType, delta > 0 ? 'created' : 'deleted');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Wraps a server-side API object to create a stateful, type-safe proxy accessible from clients.
|
|
267
|
+
* Use for authentication, sessions, or any stateful context that persists across RPC calls.
|
|
268
|
+
*
|
|
269
|
+
* @typeParam API - The server-side API object type
|
|
270
|
+
* @typeParam RETURN - The value type returned to the client
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```ts
|
|
274
|
+
* export class UserAPI {
|
|
275
|
+
* constructor(public user: User) {}
|
|
276
|
+
* getSecret() { return this.user.secret; }
|
|
277
|
+
* }
|
|
278
|
+
*
|
|
279
|
+
* export async function authenticate(token: string) {
|
|
280
|
+
* const user = await validateToken(token);
|
|
281
|
+
* return new ServerProxy(new UserAPI(user), user.name);
|
|
282
|
+
* }
|
|
283
|
+
*
|
|
284
|
+
* // Client: auth.value is user name, auth.serverProxy.getSecret() calls UserAPI method
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
export class ServerProxy {
|
|
288
|
+
api;
|
|
289
|
+
value;
|
|
290
|
+
/**
|
|
291
|
+
* @param api - Server-side API object exposed to the client
|
|
292
|
+
* @param value - Value returned immediately to the client
|
|
293
|
+
*/
|
|
294
|
+
constructor(api, value) {
|
|
295
|
+
this.api = api;
|
|
296
|
+
this.value = value;
|
|
297
|
+
}
|
|
298
|
+
toString() {
|
|
299
|
+
return `{ServerProxy proxy=${this.api.constructor?.name} value=${this.value}}`;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Server-side socket for pushing data to a client. Server functions with `Socket<T>` parameters
|
|
304
|
+
* receive client callbacks on the client side.
|
|
305
|
+
*
|
|
306
|
+
* @typeParam T - Data type sent through the socket
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* // Server
|
|
311
|
+
* export function streamNumbers(socket: Socket<number>) {
|
|
312
|
+
* setInterval(() => {
|
|
313
|
+
* if (!socket.send(Math.random())) clearInterval(interval);
|
|
314
|
+
* }, 1000);
|
|
315
|
+
* }
|
|
316
|
+
*
|
|
317
|
+
* // Client
|
|
318
|
+
* api.streamNumbers(num => console.log(num));
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
export class Socket {
|
|
322
|
+
virtualSocketId;
|
|
323
|
+
/** @internal */
|
|
324
|
+
constructor(virtualSocketId) {
|
|
325
|
+
this.virtualSocketId = virtualSocketId;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Sends data to the client.
|
|
329
|
+
* @param data - Data to send (automatically serialized)
|
|
330
|
+
* @returns `true` if sent, `false` if socket is closed
|
|
331
|
+
*/
|
|
332
|
+
send(data) {
|
|
333
|
+
const buffer = data instanceof Uint8Array ? data : new DataPack().write(data).toUint8Array();
|
|
334
|
+
return warpsocket.send(this.virtualSocketId, buffer);
|
|
335
|
+
}
|
|
336
|
+
/** @internal */
|
|
337
|
+
subscribe(channel, delta = 1) {
|
|
338
|
+
if (!(channel instanceof Uint8Array)) {
|
|
339
|
+
channel = new DataPack().write(channel).toUint8Array();
|
|
340
|
+
}
|
|
341
|
+
warpsocket.subscribe(this.virtualSocketId, channel, delta);
|
|
342
|
+
}
|
|
343
|
+
toString() {
|
|
344
|
+
return `{Socket id=${this.virtualSocketId}}`;
|
|
345
|
+
}
|
|
346
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
347
|
+
return this.toString();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Starts the Lowlander WebSocket server.
|
|
352
|
+
*
|
|
353
|
+
* @param mainApiFile - Absolute path to the compiled API file exporting server functions
|
|
354
|
+
* @param opts.bind - Address and port (default: '0.0.0.0:8080')
|
|
355
|
+
* @param opts.threads - Worker thread count (default: auto)
|
|
356
|
+
* @param opts.injectWarpSocket - For testing: inject a custom WarpSocket implementation (e.g. FakeWarpSocket)
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* ```ts
|
|
360
|
+
* import { start } from 'lowlander/server';
|
|
361
|
+
* import { fileURLToPath } from 'url';
|
|
362
|
+
* import { resolve, dirname } from 'path';
|
|
363
|
+
*
|
|
364
|
+
* const API_FILE = resolve(dirname(fileURLToPath(import.meta.url)), 'api.js');
|
|
365
|
+
* start(API_FILE, { bind: '0.0.0.0:8080' });
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
export async function start(mainApiFile, opts = {}) {
|
|
369
|
+
if (opts.injectWarpSocket) {
|
|
370
|
+
warpsocket = opts.injectWarpSocket;
|
|
371
|
+
}
|
|
372
|
+
await warpsocket.start({
|
|
373
|
+
bind: opts.bind || '0.0.0.0:8080',
|
|
374
|
+
threads: opts.threads,
|
|
375
|
+
workerPath: WSHANDLER_FILE,
|
|
376
|
+
workerArg: mainApiFile,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const socketProxies: Map<number, Map<number, any>>;
|
|
2
|
+
export interface Request {
|
|
3
|
+
socketId: number;
|
|
4
|
+
requestId: number;
|
|
5
|
+
token: Uint8Array;
|
|
6
|
+
}
|
|
7
|
+
export declare function handleOpen(socketId: number, ip: string): void;
|
|
8
|
+
export declare function handleStart(apiFile: any): Promise<void>;
|
|
9
|
+
export declare function handleBinaryMessage(message: Uint8Array, socketId: number): Promise<void>;
|
|
10
|
+
export declare function handleClose(socketId: number): void;
|
|
11
|
+
//# sourceMappingURL=wshandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wshandler.d.ts","sourceRoot":"","sources":["../../server/wshandler.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa,+BAAsC,CAAC;AAEjE,MAAM,WAAW,OAAO;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,UAAU,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAEtD;AAWD,wBAAsB,WAAW,CAAC,OAAO,EAAE,GAAG,iBAG7C;AAGD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAkG9E;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,QAG3C"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import DataPack from 'edinburgh/datapack';
|
|
2
|
+
import { warpsocket, Socket, StreamTypeBase, pushModel, ServerProxy, logLevel } from './server.js';
|
|
3
|
+
import { SERVER_MESSAGES, CLIENT_MESSAGES } from './protocol.js';
|
|
4
|
+
import * as E from 'edinburgh';
|
|
5
|
+
let mainApi;
|
|
6
|
+
export const socketProxies = new Map(); // {socketId: {proxyId: proxyObject}}
|
|
7
|
+
export function handleOpen(socketId, ip) {
|
|
8
|
+
if (logLevel >= 1)
|
|
9
|
+
console.log('[lowlander] Client connected', socketId, ip);
|
|
10
|
+
}
|
|
11
|
+
function send(socketIdOrChannel, ...data) {
|
|
12
|
+
warpsocket.send(socketIdOrChannel, DataPack.createUint8Array(...data));
|
|
13
|
+
}
|
|
14
|
+
function sendError(socketId, requestId, message) {
|
|
15
|
+
console.warn('Sending error', message);
|
|
16
|
+
send(socketId, requestId, SERVER_MESSAGES.error, message);
|
|
17
|
+
}
|
|
18
|
+
export async function handleStart(apiFile) {
|
|
19
|
+
if (logLevel >= 1)
|
|
20
|
+
console.log('[lowlander] Worker started, loading', apiFile);
|
|
21
|
+
mainApi = await import(apiFile);
|
|
22
|
+
}
|
|
23
|
+
export async function handleBinaryMessage(message, socketId) {
|
|
24
|
+
const pack = new DataPack(message);
|
|
25
|
+
const requestId = pack.readPositiveInt();
|
|
26
|
+
const type = pack.readNumber();
|
|
27
|
+
if (type === CLIENT_MESSAGES.cancel) {
|
|
28
|
+
// Delete server proxy object, if any
|
|
29
|
+
const cancelRequestId = pack.readPositiveInt();
|
|
30
|
+
const proxies = socketProxies.get(socketId);
|
|
31
|
+
if (proxies)
|
|
32
|
+
proxies.delete(cancelRequestId);
|
|
33
|
+
// Delete any virtual sockets created for this request
|
|
34
|
+
for (const virtualSocketId of pack.read() || []) {
|
|
35
|
+
// The second argument makes sure we're not deleting virtual
|
|
36
|
+
// sockets created by other requests
|
|
37
|
+
warpsocket.deleteVirtualSocket(virtualSocketId, socketId);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (type === CLIENT_MESSAGES.call) {
|
|
41
|
+
const proxyId = pack.read();
|
|
42
|
+
let api;
|
|
43
|
+
if (typeof proxyId === 'number') {
|
|
44
|
+
const proxies = socketProxies.get(socketId);
|
|
45
|
+
api = proxies?.get(proxyId);
|
|
46
|
+
if (!api) {
|
|
47
|
+
return sendError(socketId, requestId, `Proxy ${proxyId} not found`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (proxyId === undefined) {
|
|
51
|
+
if (!mainApi) {
|
|
52
|
+
return sendError(socketId, requestId, 'Server not ready');
|
|
53
|
+
}
|
|
54
|
+
api = mainApi;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return sendError(socketId, requestId, 'Invalid proxyId');
|
|
58
|
+
}
|
|
59
|
+
// Obtain function reference
|
|
60
|
+
const methodName = pack.readString();
|
|
61
|
+
let func = api[methodName];
|
|
62
|
+
if (typeof func !== 'function' || methodName.startsWith('_')) {
|
|
63
|
+
return sendError(socketId, requestId, `Method not found: ${methodName}`);
|
|
64
|
+
}
|
|
65
|
+
// Parse args
|
|
66
|
+
const virtualSocketIds = [];
|
|
67
|
+
const params = pack.read({
|
|
68
|
+
cb: function (callbackIndex) {
|
|
69
|
+
const virtualSocketId = warpsocket.createVirtualSocket(socketId, DataPack.createUint8Array(requestId, callbackIndex));
|
|
70
|
+
virtualSocketIds.push(virtualSocketId);
|
|
71
|
+
return new Socket(virtualSocketId);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
if (!Array.isArray(params)) {
|
|
75
|
+
return sendError(socketId, requestId, `Params must be an array`);
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
let pendingSend;
|
|
79
|
+
await E.transact(async () => {
|
|
80
|
+
let response = await func.apply(api, params);
|
|
81
|
+
if (logLevel >= 2)
|
|
82
|
+
console.log('[lowlander] Called', methodName, 'with', params, '->', typeof response === 'object' && response ? response.toString() : JSON.stringify(response));
|
|
83
|
+
// Result processing/sending should be within the transaction, as it may involve (lazy) loading models
|
|
84
|
+
if (response instanceof ServerProxy) {
|
|
85
|
+
let proxies = socketProxies.get(socketId);
|
|
86
|
+
if (!proxies)
|
|
87
|
+
socketProxies.set(socketId, proxies = new Map());
|
|
88
|
+
if (logLevel >= 3)
|
|
89
|
+
console.log('[lowlander] Setting proxy id', requestId, 'for socket', socketId);
|
|
90
|
+
proxies.set(requestId, response.api);
|
|
91
|
+
pendingSend = () => send(socketId, requestId, SERVER_MESSAGES.response_proxy, response.value, virtualSocketIds);
|
|
92
|
+
}
|
|
93
|
+
else if (response instanceof StreamTypeBase) {
|
|
94
|
+
const StreamType = response.constructor;
|
|
95
|
+
const instance = response._instance;
|
|
96
|
+
// Create a virtual socket for the model updates, prefixed by requestId + 'd'
|
|
97
|
+
const virtualSocketId = warpsocket.createVirtualSocket(socketId, DataPack.createUint8Array(requestId, SERVER_MESSAGES.model_data));
|
|
98
|
+
virtualSocketIds.push(virtualSocketId);
|
|
99
|
+
// Push the model (and any linked models) to the client
|
|
100
|
+
pushModel(virtualSocketId, instance, 0, StreamType, 1);
|
|
101
|
+
// Then respond, indicating which row should be top level
|
|
102
|
+
pendingSend = () => send(socketId, requestId, SERVER_MESSAGES.response_model, virtualSocketIds, instance.getPrimaryKeyHash() + StreamType.id);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// A regular result
|
|
106
|
+
pendingSend = () => send(socketId, requestId, SERVER_MESSAGES.response, response, virtualSocketIds);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
// Send response after transaction has committed
|
|
110
|
+
pendingSend();
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('RPC error', error);
|
|
114
|
+
sendError(socketId, requestId, error.message || 'Internal error');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
sendError(socketId, requestId, `Unknown message type: ${type}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export function handleClose(socketId) {
|
|
122
|
+
if (logLevel >= 1)
|
|
123
|
+
console.log('[lowlander] Client disconnected', socketId);
|
|
124
|
+
socketProxies.delete(socketId);
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=wshandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wshandler.js","sourceRoot":"","sources":["../../server/wshandler.ts"],"names":[],"mappings":"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"}
|