lowlander 0.2.3 → 0.3.0
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 +102 -48
- package/build/client/client.d.ts +7 -6
- package/build/client/client.js +64 -7
- package/build/client/client.js.map +1 -1
- package/build/examples/helloworld/server/api.d.ts +25 -8
- package/build/examples/helloworld/server/api.d.ts.map +1 -1
- package/build/examples/helloworld/server/api.js +49 -40
- package/build/examples/helloworld/server/api.js.map +1 -1
- package/build/server/protocol.js +1 -1
- package/build/server/protocol.js.map +1 -1
- package/build/server/server.d.ts +26 -18
- package/build/server/server.d.ts.map +1 -1
- package/build/server/server.js +22 -14
- package/build/server/server.js.map +1 -1
- package/build/server/wshandler.d.ts +1 -1
- package/build/server/wshandler.d.ts.map +1 -1
- package/build/server/wshandler.js +41 -8
- package/build/server/wshandler.js.map +1 -1
- package/build/tsconfig.client.tsbuildinfo +1 -1
- package/build/tsconfig.server.tsbuildinfo +1 -1
- package/client/client.ts +77 -15
- package/package.json +3 -3
- package/server/protocol.ts +1 -1
- package/server/server.ts +29 -24
- package/server/wshandler.ts +40 -9
- package/skill/SKILL.md +57 -8
- package/skill/ServerProxy.md +5 -0
- package/skill/createStreamType.md +13 -13
- package/skill/pushModel.md +1 -1
- package/skill/sendModel.md +1 -1
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var Person_1, MyModel_1;
|
|
8
1
|
import * as E from "edinburgh";
|
|
9
2
|
import { ServerProxy, createStreamType } from "lowlander/server";
|
|
10
3
|
import * as warpsocket from "warpsocket";
|
|
@@ -20,7 +13,7 @@ export class UserAPI {
|
|
|
20
13
|
this.userName = userName;
|
|
21
14
|
}
|
|
22
15
|
get user() {
|
|
23
|
-
const result = Person.
|
|
16
|
+
const result = Person.get(this.userName);
|
|
24
17
|
if (!result)
|
|
25
18
|
throw new Error(`User '${this.userName}' not found`);
|
|
26
19
|
return result;
|
|
@@ -35,48 +28,53 @@ export class UserAPI {
|
|
|
35
28
|
return true;
|
|
36
29
|
}
|
|
37
30
|
}
|
|
38
|
-
const friend = Person.
|
|
31
|
+
const friend = Person.get(friendName);
|
|
39
32
|
if (!friend)
|
|
40
33
|
return false;
|
|
41
34
|
this.user.friends.push(friend);
|
|
42
35
|
return true;
|
|
43
36
|
}
|
|
37
|
+
onDrop() {
|
|
38
|
+
this.user.onlineCount--;
|
|
39
|
+
}
|
|
44
40
|
}
|
|
45
41
|
// Authentication example - returns a ServerProxy with both a value and API object
|
|
46
42
|
export async function authenticate(auth) {
|
|
47
|
-
|
|
48
|
-
const user = Person.byName.get(auth);
|
|
43
|
+
const user = Person.get(auth);
|
|
49
44
|
if (!user)
|
|
50
45
|
throw new Error('User not found');
|
|
46
|
+
user.onlineCount++;
|
|
51
47
|
// Client receives 'secret' as .value and UserAPI methods via .serverProxy
|
|
52
48
|
return new ServerProxy(new UserAPI(auth), 'secret');
|
|
53
49
|
}
|
|
50
|
+
export function getOnlineUsers() {
|
|
51
|
+
return [...Person.findBy('online')].map(p => p.name);
|
|
52
|
+
}
|
|
53
|
+
export function greet(name, greeting = 'Hello') {
|
|
54
|
+
return `${greeting}, ${name}!`;
|
|
55
|
+
}
|
|
54
56
|
// Edinburgh model definitions
|
|
55
|
-
|
|
56
|
-
static { Person_1 = this; }
|
|
57
|
-
static byName = E.primary(Person_1, 'name');
|
|
57
|
+
const Person = E.defineModel('Person', class {
|
|
58
58
|
name = E.field(E.string);
|
|
59
59
|
age = E.field(E.number);
|
|
60
|
-
friends = E.field(E.array(E.link(
|
|
60
|
+
friends = E.field(E.array(E.link(() => Person)));
|
|
61
61
|
password = E.field(E.string);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
],
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
onlineCount = E.field(E.number);
|
|
63
|
+
}, {
|
|
64
|
+
pk: 'name',
|
|
65
|
+
index: { online: (p) => p.onlineCount > 0 ? [true] : [] },
|
|
66
|
+
});
|
|
67
|
+
const MyModel = E.defineModel('MyModel', class {
|
|
68
68
|
id = E.field(E.identifier);
|
|
69
69
|
name = E.field(E.string);
|
|
70
|
-
next = E.field(E.opt(E.link(
|
|
70
|
+
next = E.field(E.opt(E.link(() => MyModel)));
|
|
71
71
|
owner = E.field(E.link(Person));
|
|
72
72
|
createdAt = E.field(E.dateTime);
|
|
73
73
|
meta = E.field(E.record(E.number));
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
E.registerModel
|
|
79
|
-
], MyModel);
|
|
74
|
+
}, {
|
|
75
|
+
pk: 'id',
|
|
76
|
+
unique: { name: 'name' },
|
|
77
|
+
});
|
|
80
78
|
let ids;
|
|
81
79
|
export async function resetTestData(deleteEverything) {
|
|
82
80
|
if (deleteEverything) {
|
|
@@ -86,13 +84,16 @@ export async function resetTestData(deleteEverything) {
|
|
|
86
84
|
// in a new (nested) transaction, as deleteEverything will have done *its* work in separate transactions
|
|
87
85
|
// as well, and we need access to its results.
|
|
88
86
|
await E.transact(() => {
|
|
89
|
-
let p1 = Person.
|
|
90
|
-
let p2 = Person.
|
|
91
|
-
let p3 = Person.
|
|
87
|
+
let p1 = Person.get('Frank') || new Person({ name: 'Frank', age: 45, password: 'secret' });
|
|
88
|
+
let p2 = Person.get('Alice') || new Person({ name: 'Alice', age: 25, password: 'hidden', friends: [p1] });
|
|
89
|
+
let p3 = Person.get('Bob') || new Person({ name: 'Bob', age: 65, password: 'himom', friends: [p1, p2] });
|
|
92
90
|
if (p1.getState() === "created")
|
|
93
91
|
p1.friends = [p2, p3];
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
// Reset onlineCount on startup (no clients connected yet)
|
|
93
|
+
for (const p of [p1, p2, p3])
|
|
94
|
+
p.onlineCount = 0;
|
|
95
|
+
let m1 = MyModel.getBy('name', 'Test') || new MyModel({ name: 'Test', owner: p1, meta: { score: 42, level: 7 } });
|
|
96
|
+
let m2 = MyModel.getBy('name', 'Another') || new MyModel({ name: 'Another', owner: p2, next: m1, meta: {} });
|
|
96
97
|
ids = { p1: p1.name, p2: p2.name, m1: m1.id, m2: m2.id };
|
|
97
98
|
});
|
|
98
99
|
}
|
|
@@ -100,7 +101,7 @@ resetTestData(false);
|
|
|
100
101
|
``;
|
|
101
102
|
await E.transact(() => {
|
|
102
103
|
E.dump();
|
|
103
|
-
for (const p of Person.
|
|
104
|
+
for (const p of Person.find()) {
|
|
104
105
|
console.log('Person:', p.name, 'age', p.age, 'friends', p.friends.map(f => f.name).join(','), 'password', p.password);
|
|
105
106
|
}
|
|
106
107
|
});
|
|
@@ -119,31 +120,39 @@ const MyStream = createStreamType(MyModel, {
|
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
});
|
|
123
|
+
const CachedStream = createStreamType(MyModel, {
|
|
124
|
+
name: true,
|
|
125
|
+
owner: { name: true },
|
|
126
|
+
}, { cache: 60 });
|
|
122
127
|
// Example of model streaming - returns a reactive proxy that auto-updates on changes
|
|
123
128
|
export function streamModel() {
|
|
124
|
-
const m1 = MyModel.
|
|
129
|
+
const m1 = MyModel.get(ids.m1);
|
|
125
130
|
return new MyStream(m1);
|
|
126
131
|
}
|
|
132
|
+
export function streamModelCached() {
|
|
133
|
+
const m1 = MyModel.get(ids.m1);
|
|
134
|
+
return new CachedStream(m1);
|
|
135
|
+
}
|
|
127
136
|
export async function incrOwnerAge(delta) {
|
|
128
|
-
const m1 = MyModel.
|
|
137
|
+
const m1 = MyModel.get(ids.m1);
|
|
129
138
|
const current = m1.owner.age;
|
|
130
139
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
131
140
|
m1.owner.age = current + delta;
|
|
132
141
|
}
|
|
133
142
|
export function setOwnerAge(age) {
|
|
134
|
-
const m1 = MyModel.
|
|
143
|
+
const m1 = MyModel.get(ids.m1);
|
|
135
144
|
m1.owner.age = age;
|
|
136
145
|
}
|
|
137
146
|
export function setModelName(name) {
|
|
138
|
-
const m1 = MyModel.
|
|
147
|
+
const m1 = MyModel.get(ids.m1);
|
|
139
148
|
m1.name = name;
|
|
140
149
|
}
|
|
141
150
|
export function setMeta(key, value) {
|
|
142
|
-
const m1 = MyModel.
|
|
151
|
+
const m1 = MyModel.get(ids.m1);
|
|
143
152
|
m1.meta = { ...m1.meta, [key]: value };
|
|
144
153
|
}
|
|
145
154
|
export function deleteMeta(key) {
|
|
146
|
-
const m1 = MyModel.
|
|
155
|
+
const m1 = MyModel.get(ids.m1);
|
|
147
156
|
const copy = { ...m1.meta };
|
|
148
157
|
delete copy[key];
|
|
149
158
|
m1.meta = copy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../examples/helloworld/server/api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../examples/helloworld/server/api.ts"],"names":[],"mappings":"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"}
|
package/build/server/protocol.js
CHANGED
|
@@ -5,7 +5,7 @@ export const SERVER_MESSAGES = {
|
|
|
5
5
|
error: 'e', // followed by errorMessage
|
|
6
6
|
response: 'r', // followed by result + virtualSocketIds
|
|
7
7
|
response_proxy: 'p', // followed by result + virtualSocketIds (like above, but indicate that a ServerProxy has been created for this request)
|
|
8
|
-
response_model: 'm', // followed by virtualSocketIds + dbKey
|
|
8
|
+
response_model: 'm', // followed by virtualSocketIds + dbKey + cacheMs (undefined = no caching/dedup)
|
|
9
9
|
model_data: 'd', // followed by dbKey + commitId + delta
|
|
10
10
|
};
|
|
11
11
|
// The virtualSocketIds in a response or response_model is stored by the client and must
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../server/protocol.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,KAAK;AAEL,kCAAkC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,KAAK,EAAE,GAAG,EAAE,2BAA2B;IACvC,QAAQ,EAAE,GAAG,EAAE,wCAAwC;IACvD,cAAc,EAAE,GAAG,EAAE,wHAAwH;IAC7I,cAAc,EAAE,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../server/protocol.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,KAAK;AAEL,kCAAkC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,KAAK,EAAE,GAAG,EAAE,2BAA2B;IACvC,QAAQ,EAAE,GAAG,EAAE,wCAAwC;IACvD,cAAc,EAAE,GAAG,EAAE,wHAAwH;IAC7I,cAAc,EAAE,GAAG,EAAE,gFAAgF;IACrG,UAAU,EAAE,GAAG,EAAE,uCAAuC;CAC3D,CAAC;AAEF,wFAAwF;AACxF,2BAA2B;AAC3B,yHAAyH;AAEzH,kCAAkC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,IAAI,EAAE,CAAC,EAAE,4DAA4D;IACrE,MAAM,EAAE,CAAC,EAAE,2DAA2D;CACzE,CAAC"}
|
package/build/server/server.d.ts
CHANGED
|
@@ -3,15 +3,13 @@ import * as realWarpsocket from 'warpsocket';
|
|
|
3
3
|
export declare const logLevel: number;
|
|
4
4
|
/** @internal Warpsocket implementation; swapped to FakeWarpSocket in test mode. */
|
|
5
5
|
export declare let warpsocket: typeof realWarpsocket;
|
|
6
|
-
/** @internal Type alias for Edinburgh model classes */
|
|
7
|
-
type ModelClass = typeof E.Model<unknown>;
|
|
8
6
|
/**
|
|
9
7
|
* Base class for stream types created by {@link createStreamType}.
|
|
10
8
|
* @typeParam T - The projected model type
|
|
11
9
|
* @internal
|
|
12
10
|
*/
|
|
13
11
|
export declare abstract class StreamTypeBase<T> {
|
|
14
|
-
_instance: E.Model<
|
|
12
|
+
_instance: E.Model<unknown> & T;
|
|
15
13
|
/** @internal */
|
|
16
14
|
static fields: {
|
|
17
15
|
[key: string]: true | number;
|
|
@@ -19,7 +17,8 @@ export declare abstract class StreamTypeBase<T> {
|
|
|
19
17
|
/** @internal */
|
|
20
18
|
static id: number;
|
|
21
19
|
/** @internal */
|
|
22
|
-
|
|
20
|
+
static cache: number | undefined;
|
|
21
|
+
constructor(_instance: E.Model<unknown> & T);
|
|
23
22
|
toString(): string;
|
|
24
23
|
}
|
|
25
24
|
/**
|
|
@@ -56,38 +55,42 @@ type Project<T, S> = S extends true ? T : T extends ReadonlyArray<infer U> ? Rea
|
|
|
56
55
|
*
|
|
57
56
|
* @param Model - The Edinburgh model class
|
|
58
57
|
* @param selection - Field selection: `true` for simple fields, nested object for linked models
|
|
58
|
+
* @param options - Optional settings
|
|
59
|
+
* @param options.cache - Seconds the client should linger the stream after out-of-scope, enabling instant reuse and dedup on repeat calls
|
|
59
60
|
* @returns Stream type class to instantiate in API functions
|
|
60
61
|
*
|
|
61
62
|
* @example
|
|
62
63
|
* ```ts
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* // Exclude password, include friends' names
|
|
64
|
+
* const Person = E.defineModel('Person', class {
|
|
65
|
+
* name = E.field(E.string);
|
|
66
|
+
* age = E.field(E.number);
|
|
67
|
+
* password = E.field(E.string);
|
|
68
|
+
* friends = E.field(E.array(E.link(() => Person)));
|
|
69
|
+
* }, { pk: 'name' });
|
|
70
|
+
*
|
|
71
|
+
* // Exclude password, include friends' names; cache 30s
|
|
72
72
|
* const PersonStream = createStreamType(Person, {
|
|
73
73
|
* name: true,
|
|
74
74
|
* age: true,
|
|
75
75
|
* friends: { name: true }
|
|
76
|
-
* });
|
|
76
|
+
* }, { cache: 30 });
|
|
77
77
|
*
|
|
78
78
|
* export function streamPerson() {
|
|
79
|
-
* const person = Person.
|
|
79
|
+
* const person = Person.get('Alice')!;
|
|
80
80
|
* return new PersonStream(person);
|
|
81
81
|
* }
|
|
82
82
|
* ```
|
|
83
83
|
*/
|
|
84
|
-
export declare function createStreamType<T, S extends FieldSelection<T>>(Model:
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
export declare function createStreamType<T, S extends FieldSelection<T>>(Model: E.AnyModelClass & (new (...args: any[]) => T), selection: S & ValidateSelection<T, S>, options?: {
|
|
85
|
+
cache?: number;
|
|
86
|
+
}): {
|
|
87
|
+
new (_instance: E.ModelBase & Project<T, S>): {
|
|
88
|
+
_instance: E.ModelBase & Project<T, S>;
|
|
87
89
|
toString(): string;
|
|
88
90
|
};
|
|
89
91
|
fields: Record<string, number | true>;
|
|
90
92
|
id: number;
|
|
93
|
+
cache: number | undefined;
|
|
91
94
|
};
|
|
92
95
|
/**
|
|
93
96
|
* Sends (updated) data for `model` to `target`.
|
|
@@ -103,6 +106,10 @@ export declare function pushModel(target: number | Uint8Array | number[], model:
|
|
|
103
106
|
* Wraps a server-side API object to create a stateful, type-safe proxy accessible from clients.
|
|
104
107
|
* Use for authentication, sessions, or any stateful context that persists across RPC calls.
|
|
105
108
|
*
|
|
109
|
+
* If the API object has an `onDrop()` method, it is called when the proxy is dropped, either
|
|
110
|
+
* because the client cancelled the request (scope cleanup) or the WebSocket disconnected.
|
|
111
|
+
* Use this to clean up server-side state kept on behalf of the client.
|
|
112
|
+
*
|
|
106
113
|
* @typeParam API - The server-side API object type
|
|
107
114
|
* @typeParam RETURN - The value type returned to the client
|
|
108
115
|
*
|
|
@@ -111,6 +118,7 @@ export declare function pushModel(target: number | Uint8Array | number[], model:
|
|
|
111
118
|
* export class UserAPI {
|
|
112
119
|
* constructor(public user: User) {}
|
|
113
120
|
* getSecret() { return this.user.secret; }
|
|
121
|
+
* onDrop() { console.log('client gone'); }
|
|
114
122
|
* }
|
|
115
123
|
*
|
|
116
124
|
* export async function authenticate(token: string) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,WAAW,CAAC;AAE/B,OAAO,KAAK,cAAc,MAAM,YAAY,CAAC;AAO7C,eAAO,MAAM,QAAQ,QAAwD,CAAC;AAE9E,mFAAmF;AACnF,eAAO,IAAI,UAAU,EAAE,OAAO,cAA+B,CAAC;AAa9D
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":"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"}
|
package/build/server/server.js
CHANGED
|
@@ -28,6 +28,7 @@ export class StreamTypeBase {
|
|
|
28
28
|
/** @internal */
|
|
29
29
|
static id;
|
|
30
30
|
/** @internal */
|
|
31
|
+
static cache;
|
|
31
32
|
constructor(_instance) {
|
|
32
33
|
this._instance = _instance;
|
|
33
34
|
}
|
|
@@ -75,32 +76,33 @@ function getIdForData(namespace, ...data) {
|
|
|
75
76
|
*
|
|
76
77
|
* @param Model - The Edinburgh model class
|
|
77
78
|
* @param selection - Field selection: `true` for simple fields, nested object for linked models
|
|
79
|
+
* @param options - Optional settings
|
|
80
|
+
* @param options.cache - Seconds the client should linger the stream after out-of-scope, enabling instant reuse and dedup on repeat calls
|
|
78
81
|
* @returns Stream type class to instantiate in API functions
|
|
79
82
|
*
|
|
80
83
|
* @example
|
|
81
84
|
* ```ts
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* }
|
|
85
|
+
* const Person = E.defineModel('Person', class {
|
|
86
|
+
* name = E.field(E.string);
|
|
87
|
+
* age = E.field(E.number);
|
|
88
|
+
* password = E.field(E.string);
|
|
89
|
+
* friends = E.field(E.array(E.link(() => Person)));
|
|
90
|
+
* }, { pk: 'name' });
|
|
89
91
|
*
|
|
90
|
-
* // Exclude password, include friends' names
|
|
92
|
+
* // Exclude password, include friends' names; cache 30s
|
|
91
93
|
* const PersonStream = createStreamType(Person, {
|
|
92
94
|
* name: true,
|
|
93
95
|
* age: true,
|
|
94
96
|
* friends: { name: true }
|
|
95
|
-
* });
|
|
97
|
+
* }, { cache: 30 });
|
|
96
98
|
*
|
|
97
99
|
* export function streamPerson() {
|
|
98
|
-
* const person = Person.
|
|
100
|
+
* const person = Person.get('Alice')!;
|
|
99
101
|
* return new PersonStream(person);
|
|
100
102
|
* }
|
|
101
103
|
* ```
|
|
102
104
|
*/
|
|
103
|
-
export function createStreamType(Model, selection) {
|
|
105
|
+
export function createStreamType(Model, selection, options) {
|
|
104
106
|
let streamTypes = streamTypesPerModel.get(Model);
|
|
105
107
|
if (!streamTypes)
|
|
106
108
|
streamTypesPerModel.set(Model, streamTypes = []);
|
|
@@ -126,6 +128,7 @@ export function createStreamType(Model, selection) {
|
|
|
126
128
|
class StreamType extends StreamTypeBase {
|
|
127
129
|
static fields = fields;
|
|
128
130
|
static id = streamTypeId;
|
|
131
|
+
static cache = options?.cache;
|
|
129
132
|
}
|
|
130
133
|
streamTypes.push(StreamType);
|
|
131
134
|
return StreamType;
|
|
@@ -138,7 +141,7 @@ function writeModelField(pack, value, streamTypeId) {
|
|
|
138
141
|
else if (value instanceof E.Model) {
|
|
139
142
|
pack.writeCustom('model', value.getPrimaryKeyHash() + streamTypeId);
|
|
140
143
|
}
|
|
141
|
-
else if (Array.isArray(value)) {
|
|
144
|
+
else if (Array.isArray(value) || value instanceof Set) {
|
|
142
145
|
pack.writeCollection('array', () => {
|
|
143
146
|
for (const item of value)
|
|
144
147
|
writeModelField(pack, item, streamTypeId);
|
|
@@ -157,7 +160,7 @@ function writeModelField(pack, value, streamTypeId) {
|
|
|
157
160
|
function updateLinkDeltas(value, linkDeltas, streamTypeId, delta) {
|
|
158
161
|
if (typeof value !== 'object' || value == null)
|
|
159
162
|
return;
|
|
160
|
-
if (Array.isArray(value)) {
|
|
163
|
+
if (Array.isArray(value) || value instanceof Set) {
|
|
161
164
|
for (const item of value)
|
|
162
165
|
updateLinkDeltas(item, linkDeltas, streamTypeId, delta);
|
|
163
166
|
}
|
|
@@ -220,7 +223,7 @@ export function sendModel(target, model, commitId, StreamType, changed) {
|
|
|
220
223
|
if (typeof changed === 'object' && !changed.hasOwnProperty(fieldName))
|
|
221
224
|
continue;
|
|
222
225
|
let streamIndex = StreamType.fields[fieldName];
|
|
223
|
-
|
|
226
|
+
let fieldValue = model[fieldName];
|
|
224
227
|
mustSend = true;
|
|
225
228
|
if (typeof streamIndex === 'number') {
|
|
226
229
|
pack.write(fieldName);
|
|
@@ -266,6 +269,10 @@ export function pushModel(target, model, commitId, SubStreamType, delta) {
|
|
|
266
269
|
* Wraps a server-side API object to create a stateful, type-safe proxy accessible from clients.
|
|
267
270
|
* Use for authentication, sessions, or any stateful context that persists across RPC calls.
|
|
268
271
|
*
|
|
272
|
+
* If the API object has an `onDrop()` method, it is called when the proxy is dropped, either
|
|
273
|
+
* because the client cancelled the request (scope cleanup) or the WebSocket disconnected.
|
|
274
|
+
* Use this to clean up server-side state kept on behalf of the client.
|
|
275
|
+
*
|
|
269
276
|
* @typeParam API - The server-side API object type
|
|
270
277
|
* @typeParam RETURN - The value type returned to the client
|
|
271
278
|
*
|
|
@@ -274,6 +281,7 @@ export function pushModel(target, model, commitId, SubStreamType, delta) {
|
|
|
274
281
|
* export class UserAPI {
|
|
275
282
|
* constructor(public user: User) {}
|
|
276
283
|
* getSecret() { return this.user.secret; }
|
|
284
|
+
* onDrop() { console.log('client gone'); }
|
|
277
285
|
* }
|
|
278
286
|
*
|
|
279
287
|
* export async function authenticate(token: string) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,WAAW,CAAC;AAC/B,OAAO,QAAQ,MAAM,oBAAoB,CAAC;AAC1C,OAAO,KAAK,cAAc,MAAM,YAAY,CAAC;AAE7C,0CAA0C;AAC1C,0BAA0B;AAC1B,4EAA4E;AAC5E,sEAAsE;AACtE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;AAE9E,mFAAmF;AACnF,MAAM,CAAC,IAAI,UAAU,GAA0B,cAAc,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAExC,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;AAExF,+DAA+D;AAC/D,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,qEAAqE;AACrE,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,5 +7,5 @@ export interface Request {
|
|
|
7
7
|
export declare function handleOpen(socketId: number, ip: string): void;
|
|
8
8
|
export declare function handleStart(apiFile: any): Promise<void>;
|
|
9
9
|
export declare function handleBinaryMessage(message: Uint8Array, socketId: number): Promise<void>;
|
|
10
|
-
export declare function handleClose(socketId: number): void
|
|
10
|
+
export declare function handleClose(socketId: number): Promise<void>;
|
|
11
11
|
//# sourceMappingURL=wshandler.d.ts.map
|
|
@@ -1 +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,
|
|
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,iBAkH9E;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,iBAkBjD"}
|
|
@@ -28,8 +28,19 @@ export async function handleBinaryMessage(message, socketId) {
|
|
|
28
28
|
// Delete server proxy object, if any
|
|
29
29
|
const cancelRequestId = pack.readPositiveInt();
|
|
30
30
|
const proxies = socketProxies.get(socketId);
|
|
31
|
-
if (proxies)
|
|
31
|
+
if (proxies) {
|
|
32
|
+
/** Call `onDrop()` on a proxy if it has one. Runs in a transaction; errors are logged. */
|
|
33
|
+
const proxy = proxies.get(cancelRequestId);
|
|
32
34
|
proxies.delete(cancelRequestId);
|
|
35
|
+
if (proxy && typeof proxy.onDrop === 'function') {
|
|
36
|
+
try {
|
|
37
|
+
await E.transact(() => proxy.onDrop());
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.error('cancel request onDrop error', err);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
33
44
|
// Delete any virtual sockets created for this request
|
|
34
45
|
for (const virtualSocketId of pack.read() || []) {
|
|
35
46
|
// The second argument makes sure we're not deleting virtual
|
|
@@ -75,20 +86,24 @@ export async function handleBinaryMessage(message, socketId) {
|
|
|
75
86
|
return sendError(socketId, requestId, `Params must be an array`);
|
|
76
87
|
}
|
|
77
88
|
try {
|
|
78
|
-
let
|
|
89
|
+
let pendingPacket;
|
|
79
90
|
await E.transact(async () => {
|
|
80
91
|
let response = await func.apply(api, params);
|
|
81
92
|
if (logLevel >= 2)
|
|
82
93
|
console.log('[lowlander] Called', methodName, 'with', params, '->', typeof response === 'object' && response ? response.toString() : JSON.stringify(response));
|
|
83
|
-
// Result processing/
|
|
94
|
+
// Result processing/serialization should be within the transaction, as it may involve (lazy) loading models.
|
|
95
|
+
// The actual socket send remains deferred until after commit.
|
|
84
96
|
if (response instanceof ServerProxy) {
|
|
97
|
+
if (response.value instanceof StreamTypeBase) {
|
|
98
|
+
throw new Error('ServerProxy values cannot be streamed models; return the stream directly or from a proxy method instead');
|
|
99
|
+
}
|
|
85
100
|
let proxies = socketProxies.get(socketId);
|
|
86
101
|
if (!proxies)
|
|
87
102
|
socketProxies.set(socketId, proxies = new Map());
|
|
88
103
|
if (logLevel >= 3)
|
|
89
104
|
console.log('[lowlander] Setting proxy id', requestId, 'for socket', socketId);
|
|
90
105
|
proxies.set(requestId, response.api);
|
|
91
|
-
|
|
106
|
+
pendingPacket = DataPack.createUint8Array(requestId, SERVER_MESSAGES.response_proxy, response.value, virtualSocketIds);
|
|
92
107
|
}
|
|
93
108
|
else if (response instanceof StreamTypeBase) {
|
|
94
109
|
const StreamType = response.constructor;
|
|
@@ -99,15 +114,16 @@ export async function handleBinaryMessage(message, socketId) {
|
|
|
99
114
|
// Push the model (and any linked models) to the client
|
|
100
115
|
pushModel(virtualSocketId, instance, 0, StreamType, 1);
|
|
101
116
|
// Then respond, indicating which row should be top level
|
|
102
|
-
|
|
117
|
+
const cacheMs = StreamType.cache !== undefined ? StreamType.cache * 1000 : undefined;
|
|
118
|
+
pendingPacket = DataPack.createUint8Array(requestId, SERVER_MESSAGES.response_model, virtualSocketIds, instance.getPrimaryKeyHash() + StreamType.id, cacheMs);
|
|
103
119
|
}
|
|
104
120
|
else {
|
|
105
121
|
// A regular result
|
|
106
|
-
|
|
122
|
+
pendingPacket = DataPack.createUint8Array(requestId, SERVER_MESSAGES.response, response, virtualSocketIds);
|
|
107
123
|
}
|
|
108
124
|
});
|
|
109
125
|
// Send response after transaction has committed
|
|
110
|
-
|
|
126
|
+
warpsocket.send(socketId, pendingPacket);
|
|
111
127
|
}
|
|
112
128
|
catch (error) {
|
|
113
129
|
console.error('RPC error', error);
|
|
@@ -118,9 +134,26 @@ export async function handleBinaryMessage(message, socketId) {
|
|
|
118
134
|
sendError(socketId, requestId, `Unknown message type: ${type}`);
|
|
119
135
|
}
|
|
120
136
|
}
|
|
121
|
-
export function handleClose(socketId) {
|
|
137
|
+
export async function handleClose(socketId) {
|
|
122
138
|
if (logLevel >= 1)
|
|
123
139
|
console.log('[lowlander] Client disconnected', socketId);
|
|
140
|
+
const proxies = socketProxies.get(socketId);
|
|
141
|
+
if (!proxies)
|
|
142
|
+
return;
|
|
124
143
|
socketProxies.delete(socketId);
|
|
144
|
+
if (!proxies.values().some(p => typeof p.onDrop === 'function'))
|
|
145
|
+
return;
|
|
146
|
+
await E.transact(async () => {
|
|
147
|
+
for (const proxy of proxies.values()) {
|
|
148
|
+
if (typeof proxy?.onDrop === 'function') {
|
|
149
|
+
try {
|
|
150
|
+
await proxy.onDrop();
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
console.error('handleClose onDrop error', err);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
125
158
|
}
|
|
126
159
|
//# sourceMappingURL=wshandler.js.map
|