remult 3.3.18 → 3.4.0-next.1
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/SseSubscriptionServer.d.ts +2 -0
- package/SseSubscriptionServer.js +4 -2
- package/esm/SseSubscriptionServer.js +3 -1
- package/esm/live-query/data-provider-live-query-storage.js +3 -1
- package/esm/server/remult-api-server.js +6 -1
- package/esm/src/data-api.js +1 -0
- package/esm/src/live-query/LiveQueryClient.js +163 -52
- package/esm/src/live-query/SseSubscriptionClient.js +101 -43
- package/esm/src/live-query/SubscriptionChannel.js +37 -3
- package/esm/src/live-query/SubscriptionServer.js +11 -3
- package/esm/src/remult3/remult3.js +6 -0
- package/live-query/data-provider-live-query-storage.d.ts +4 -1
- package/live-query/data-provider-live-query-storage.js +18 -15
- package/package.json +1 -1
- package/remult-knex/index.d.ts +2 -2
- package/server/remult-api-server.js +13 -9
- package/src/column-interfaces.d.ts +4 -0
- package/src/data-api.js +1 -0
- package/src/live-query/LiveQueryClient.js +215 -97
- package/src/live-query/SseSubscriptionClient.js +143 -83
- package/src/live-query/SubscriptionChannel.d.ts +8 -0
- package/src/live-query/SubscriptionChannel.js +47 -9
- package/src/live-query/SubscriptionServer.d.ts +7 -2
- package/src/live-query/SubscriptionServer.js +20 -10
- package/src/remult3/remult3.d.ts +6 -0
- package/src/remult3/remult3.js +6 -0
|
@@ -5,7 +5,6 @@ var tslib_1 = require("tslib");
|
|
|
5
5
|
var buildRestDataProvider_js_1 = require("../buildRestDataProvider.js");
|
|
6
6
|
var remult_proxy_js_1 = require("../remult-proxy.js");
|
|
7
7
|
var remult_static_js_1 = require("../remult-static.js");
|
|
8
|
-
var remult3_js_1 = require("../remult3/remult3.js");
|
|
9
8
|
var SubscriptionChannel_js_1 = require("./SubscriptionChannel.js");
|
|
10
9
|
var SseSubscriptionClient = /** @class */ (function () {
|
|
11
10
|
function SseSubscriptionClient() {
|
|
@@ -14,11 +13,54 @@ var SseSubscriptionClient = /** @class */ (function () {
|
|
|
14
13
|
var connectionId;
|
|
15
14
|
var channels = new Map();
|
|
16
15
|
var provider = (0, buildRestDataProvider_js_1.buildRestDataProvider)(remult_proxy_js_1.remult.apiClient.httpClient);
|
|
17
|
-
var connected = false;
|
|
18
16
|
var source;
|
|
17
|
+
var retryCount = 0;
|
|
18
|
+
var closed = false;
|
|
19
|
+
var connected = false;
|
|
20
|
+
var reconnectTimer;
|
|
21
|
+
var connectionReady;
|
|
22
|
+
var connectionPromise = new Promise(function (res) {
|
|
23
|
+
connectionReady = res;
|
|
24
|
+
});
|
|
25
|
+
function clearReconnectTimer() {
|
|
26
|
+
if (reconnectTimer !== undefined) {
|
|
27
|
+
clearTimeout(reconnectTimer);
|
|
28
|
+
reconnectTimer = undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function scheduleReconnect() {
|
|
32
|
+
if (closed)
|
|
33
|
+
return;
|
|
34
|
+
clearReconnectTimer();
|
|
35
|
+
var delay = Math.min(500 * Math.pow(2, Math.min(retryCount, 5)), 8000);
|
|
36
|
+
retryCount++;
|
|
37
|
+
reconnectTimer = setTimeout(function () {
|
|
38
|
+
reconnectTimer = undefined;
|
|
39
|
+
createConnection();
|
|
40
|
+
}, delay);
|
|
41
|
+
}
|
|
42
|
+
function resume(force) {
|
|
43
|
+
if (closed)
|
|
44
|
+
return;
|
|
45
|
+
retryCount = 0;
|
|
46
|
+
clearReconnectTimer();
|
|
47
|
+
if (force) {
|
|
48
|
+
createConnection();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
var open = source &&
|
|
52
|
+
typeof EventSource !== 'undefined' &&
|
|
53
|
+
source.readyState !== EventSource.CLOSED;
|
|
54
|
+
if (!open)
|
|
55
|
+
createConnection();
|
|
56
|
+
}
|
|
19
57
|
var client = {
|
|
58
|
+
lastServerEvent: Date.now(),
|
|
59
|
+
resume: resume,
|
|
20
60
|
close: function () {
|
|
21
|
-
|
|
61
|
+
closed = true;
|
|
62
|
+
clearReconnectTimer();
|
|
63
|
+
source === null || source === void 0 ? void 0 : source.close();
|
|
22
64
|
},
|
|
23
65
|
subscribe: function (channel, handler) {
|
|
24
66
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
@@ -27,13 +69,17 @@ var SseSubscriptionClient = /** @class */ (function () {
|
|
|
27
69
|
switch (_a.label) {
|
|
28
70
|
case 0:
|
|
29
71
|
listeners = channels.get(channel);
|
|
30
|
-
if (!!listeners) return [3 /*break*/,
|
|
72
|
+
if (!!listeners) return [3 /*break*/, 3];
|
|
31
73
|
channels.set(channel, (listeners = []));
|
|
32
|
-
return [4 /*yield*/,
|
|
74
|
+
return [4 /*yield*/, connectionPromise];
|
|
33
75
|
case 1:
|
|
34
76
|
_a.sent();
|
|
35
|
-
|
|
77
|
+
if (!!closed) return [3 /*break*/, 3];
|
|
78
|
+
return [4 /*yield*/, subscribeToChannel(channel)];
|
|
36
79
|
case 2:
|
|
80
|
+
_a.sent();
|
|
81
|
+
_a.label = 3;
|
|
82
|
+
case 3:
|
|
37
83
|
listeners.push(handler);
|
|
38
84
|
return [2 /*return*/, function () {
|
|
39
85
|
listeners.splice(listeners.indexOf(handler, 1));
|
|
@@ -52,80 +98,85 @@ var SseSubscriptionClient = /** @class */ (function () {
|
|
|
52
98
|
});
|
|
53
99
|
},
|
|
54
100
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
createConnection();
|
|
76
|
-
}, 500);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
source.addEventListener('connectionId', function (e) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
80
|
-
var _a, _b, channel, e_1_1;
|
|
81
|
-
var e_1, _c;
|
|
82
|
-
return tslib_1.__generator(this, function (_d) {
|
|
83
|
-
switch (_d.label) {
|
|
84
|
-
case 0:
|
|
85
|
-
//@ts-ignore
|
|
86
|
-
connectionId = e.data;
|
|
87
|
-
if (!connected) return [3 /*break*/, 9];
|
|
88
|
-
_d.label = 1;
|
|
89
|
-
case 1:
|
|
90
|
-
_d.trys.push([1, 6, 7, 8]);
|
|
91
|
-
_a = tslib_1.__values(channels.keys()), _b = _a.next();
|
|
92
|
-
_d.label = 2;
|
|
93
|
-
case 2:
|
|
94
|
-
if (!!_b.done) return [3 /*break*/, 5];
|
|
95
|
-
channel = _b.value;
|
|
96
|
-
return [4 /*yield*/, subscribeToChannel(channel)];
|
|
97
|
-
case 3:
|
|
98
|
-
_d.sent();
|
|
99
|
-
_d.label = 4;
|
|
100
|
-
case 4:
|
|
101
|
-
_b = _a.next();
|
|
102
|
-
return [3 /*break*/, 2];
|
|
103
|
-
case 5: return [3 /*break*/, 8];
|
|
104
|
-
case 6:
|
|
105
|
-
e_1_1 = _d.sent();
|
|
106
|
-
e_1 = { error: e_1_1 };
|
|
107
|
-
return [3 /*break*/, 8];
|
|
108
|
-
case 7:
|
|
109
|
-
try {
|
|
110
|
-
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
111
|
-
}
|
|
112
|
-
finally { if (e_1) throw e_1.error; }
|
|
113
|
-
return [7 /*endfinally*/];
|
|
114
|
-
case 8:
|
|
115
|
-
onReconnect();
|
|
116
|
-
return [3 /*break*/, 10];
|
|
117
|
-
case 9:
|
|
118
|
-
connected = true;
|
|
119
|
-
res(client);
|
|
120
|
-
_d.label = 10;
|
|
121
|
-
case 10: return [2 /*return*/];
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}); });
|
|
125
|
-
}
|
|
101
|
+
function noteServerEvent() {
|
|
102
|
+
client.lastServerEvent = Date.now();
|
|
103
|
+
}
|
|
104
|
+
function createConnection() {
|
|
105
|
+
var _this = this;
|
|
106
|
+
if (closed)
|
|
107
|
+
return;
|
|
108
|
+
clearReconnectTimer();
|
|
109
|
+
if (source)
|
|
110
|
+
source.close();
|
|
111
|
+
source = SseSubscriptionClient.createEventSource(remult_proxy_js_1.remult.apiClient.url + '/' + SubscriptionChannel_js_1.streamUrl);
|
|
112
|
+
source.onmessage = function (e) {
|
|
113
|
+
noteServerEvent();
|
|
114
|
+
var message = JSON.parse(e.data);
|
|
115
|
+
var listeners = channels.get(message.channel);
|
|
116
|
+
if (listeners)
|
|
117
|
+
listeners.forEach(function (x) { return x(message.data); });
|
|
118
|
+
};
|
|
119
|
+
source.addEventListener('keep-alive', function () {
|
|
120
|
+
noteServerEvent();
|
|
126
121
|
});
|
|
127
|
-
|
|
128
|
-
|
|
122
|
+
source.onerror = function (e) {
|
|
123
|
+
console.error('Live Query Event Source Error', e);
|
|
124
|
+
source.close();
|
|
125
|
+
if (closed)
|
|
126
|
+
return;
|
|
127
|
+
scheduleReconnect();
|
|
128
|
+
};
|
|
129
|
+
source.addEventListener('connectionId', function (e) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
130
|
+
var _a, _b, channel, e_1_1;
|
|
131
|
+
var e_1, _c;
|
|
132
|
+
return tslib_1.__generator(this, function (_d) {
|
|
133
|
+
switch (_d.label) {
|
|
134
|
+
case 0:
|
|
135
|
+
//@ts-ignore
|
|
136
|
+
connectionId = e.data;
|
|
137
|
+
retryCount = 0;
|
|
138
|
+
noteServerEvent();
|
|
139
|
+
if (!connected) return [3 /*break*/, 9];
|
|
140
|
+
_d.label = 1;
|
|
141
|
+
case 1:
|
|
142
|
+
_d.trys.push([1, 6, 7, 8]);
|
|
143
|
+
_a = tslib_1.__values(channels.keys()), _b = _a.next();
|
|
144
|
+
_d.label = 2;
|
|
145
|
+
case 2:
|
|
146
|
+
if (!!_b.done) return [3 /*break*/, 5];
|
|
147
|
+
channel = _b.value;
|
|
148
|
+
return [4 /*yield*/, subscribeToChannel(channel)];
|
|
149
|
+
case 3:
|
|
150
|
+
_d.sent();
|
|
151
|
+
_d.label = 4;
|
|
152
|
+
case 4:
|
|
153
|
+
_b = _a.next();
|
|
154
|
+
return [3 /*break*/, 2];
|
|
155
|
+
case 5: return [3 /*break*/, 8];
|
|
156
|
+
case 6:
|
|
157
|
+
e_1_1 = _d.sent();
|
|
158
|
+
e_1 = { error: e_1_1 };
|
|
159
|
+
return [3 /*break*/, 8];
|
|
160
|
+
case 7:
|
|
161
|
+
try {
|
|
162
|
+
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
163
|
+
}
|
|
164
|
+
finally { if (e_1) throw e_1.error; }
|
|
165
|
+
return [7 /*endfinally*/];
|
|
166
|
+
case 8:
|
|
167
|
+
onReconnect();
|
|
168
|
+
return [3 /*break*/, 10];
|
|
169
|
+
case 9:
|
|
170
|
+
connected = true;
|
|
171
|
+
connectionReady();
|
|
172
|
+
_d.label = 10;
|
|
173
|
+
case 10: return [2 /*return*/];
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}); });
|
|
177
|
+
}
|
|
178
|
+
createConnection();
|
|
179
|
+
return Promise.resolve(client);
|
|
129
180
|
function subscribeToChannel(channel) {
|
|
130
181
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
131
182
|
var result;
|
|
@@ -139,12 +190,21 @@ var SseSubscriptionClient = /** @class */ (function () {
|
|
|
139
190
|
})];
|
|
140
191
|
case 1:
|
|
141
192
|
result = _a.sent();
|
|
142
|
-
if (!(result === exports.ConnectionNotFoundError)) return [3 /*break*/,
|
|
143
|
-
|
|
193
|
+
if (!(result === exports.ConnectionNotFoundError)) return [3 /*break*/, 4];
|
|
194
|
+
connected = false;
|
|
195
|
+
connectionPromise = new Promise(function (res) {
|
|
196
|
+
connectionReady = res;
|
|
197
|
+
});
|
|
198
|
+
createConnection();
|
|
199
|
+
return [4 /*yield*/, connectionPromise];
|
|
144
200
|
case 2:
|
|
145
201
|
_a.sent();
|
|
146
|
-
|
|
147
|
-
|
|
202
|
+
if (!!closed) return [3 /*break*/, 4];
|
|
203
|
+
return [4 /*yield*/, subscribeToChannel(channel)];
|
|
204
|
+
case 3:
|
|
205
|
+
_a.sent();
|
|
206
|
+
_a.label = 4;
|
|
207
|
+
case 4: return [2 /*return*/];
|
|
148
208
|
}
|
|
149
209
|
});
|
|
150
210
|
});
|
|
@@ -9,6 +9,10 @@ export type Unsubscribe = VoidFunction;
|
|
|
9
9
|
export interface SubscriptionClientConnection {
|
|
10
10
|
subscribe(channel: string, onMessage: (message: any) => void, onError: (err: any) => void): Promise<Unsubscribe>;
|
|
11
11
|
close(): void;
|
|
12
|
+
/** SSE clients set this; missing means no heartbeat tracking (Ably, tests). */
|
|
13
|
+
lastServerEvent?: number;
|
|
14
|
+
/** Foreground / online: reconnect now, skip backoff. `force` kills an OPEN zombie. */
|
|
15
|
+
resume?: (force?: boolean) => void;
|
|
12
16
|
}
|
|
13
17
|
export interface SubscriptionClient {
|
|
14
18
|
openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
|
|
@@ -31,6 +35,10 @@ export declare type LiveQueryChange = {
|
|
|
31
35
|
data: {
|
|
32
36
|
id: any;
|
|
33
37
|
};
|
|
38
|
+
} | {
|
|
39
|
+
type: 'version';
|
|
40
|
+
from: number;
|
|
41
|
+
to: number;
|
|
34
42
|
};
|
|
35
43
|
/**
|
|
36
44
|
* The `SubscriptionChannel` class is used to send messages from the backend to the frontend,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SubscriptionChannel = exports.liveQueryKeepAliveRoute = exports.LiveQuerySubscriber = exports.streamUrl = void 0;
|
|
4
|
+
exports.onBrowserForeground = onBrowserForeground;
|
|
4
5
|
var tslib_1 = require("tslib");
|
|
5
6
|
var sort_js_1 = require("../sort.js");
|
|
6
7
|
var remult_proxy_js_1 = require("../remult-proxy.js");
|
|
@@ -12,9 +13,12 @@ var LiveQuerySubscriber = /** @class */ (function () {
|
|
|
12
13
|
this.repo = repo;
|
|
13
14
|
this.query = query;
|
|
14
15
|
this.unsubscribe = function () { };
|
|
16
|
+
this.unsubscribeChannel = function () { };
|
|
17
|
+
this.unsubscribeQuery = function () { };
|
|
15
18
|
this.defaultQueryState = [];
|
|
16
19
|
this.listeners = [];
|
|
17
20
|
this.id = String(crypto.randomUUID());
|
|
21
|
+
this.version = 0;
|
|
18
22
|
this.queryChannel = "users:".concat(userId, ":queries:").concat(this.id);
|
|
19
23
|
this.id = this.queryChannel;
|
|
20
24
|
}
|
|
@@ -35,6 +39,7 @@ var LiveQuerySubscriber = /** @class */ (function () {
|
|
|
35
39
|
return items;
|
|
36
40
|
});
|
|
37
41
|
}, this.allItemsMessage(items));
|
|
42
|
+
this.version = 0;
|
|
38
43
|
return [2 /*return*/];
|
|
39
44
|
}
|
|
40
45
|
});
|
|
@@ -88,18 +93,32 @@ var LiveQuerySubscriber = /** @class */ (function () {
|
|
|
88
93
|
};
|
|
89
94
|
LiveQuerySubscriber.prototype.handle = function (messages) {
|
|
90
95
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
91
|
-
var x, loadedItems, index, element;
|
|
96
|
+
var ver, data, x, loadedItems, index, element;
|
|
92
97
|
var _this = this;
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
var _a;
|
|
99
|
+
return tslib_1.__generator(this, function (_b) {
|
|
100
|
+
switch (_b.label) {
|
|
95
101
|
case 0:
|
|
96
|
-
|
|
102
|
+
ver = messages.find(function (m) {
|
|
103
|
+
return m.type === 'version';
|
|
104
|
+
});
|
|
105
|
+
if (ver) {
|
|
106
|
+
if (ver.from < this.version)
|
|
107
|
+
return [2 /*return*/];
|
|
108
|
+
if (ver.from > this.version) {
|
|
109
|
+
this.version = ver.to;
|
|
110
|
+
(_a = this.subscribeCode) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
111
|
+
return [2 /*return*/];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
data = messages.filter(function (m) { return m.type !== 'version'; });
|
|
115
|
+
x = data.filter(function (_a) {
|
|
97
116
|
var type = _a.type;
|
|
98
117
|
return type == 'add' || type == 'replace';
|
|
99
118
|
});
|
|
100
119
|
return [4 /*yield*/, (0, repository_internals_js_1.getRepositoryInternals)(this.repo)._fromJsonArray(x.map(function (m) { return m.data.item; }), this.query.options)];
|
|
101
120
|
case 1:
|
|
102
|
-
loadedItems =
|
|
121
|
+
loadedItems = _b.sent();
|
|
103
122
|
for (index = 0; index < x.length; index++) {
|
|
104
123
|
element = x[index];
|
|
105
124
|
element.data.item = loadedItems[index];
|
|
@@ -137,21 +156,22 @@ var LiveQuerySubscriber = /** @class */ (function () {
|
|
|
137
156
|
}
|
|
138
157
|
};
|
|
139
158
|
try {
|
|
140
|
-
for (var
|
|
141
|
-
var message =
|
|
159
|
+
for (var data_1 = tslib_1.__values(data), data_1_1 = data_1.next(); !data_1_1.done; data_1_1 = data_1.next()) {
|
|
160
|
+
var message = data_1_1.value;
|
|
142
161
|
_loop_2(message);
|
|
143
162
|
}
|
|
144
163
|
}
|
|
145
164
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
146
165
|
finally {
|
|
147
166
|
try {
|
|
148
|
-
if (
|
|
167
|
+
if (data_1_1 && !data_1_1.done && (_a = data_1.return)) _a.call(data_1);
|
|
149
168
|
}
|
|
150
169
|
finally { if (e_2) throw e_2.error; }
|
|
151
170
|
}
|
|
152
171
|
return items;
|
|
153
172
|
});
|
|
154
|
-
},
|
|
173
|
+
}, data);
|
|
174
|
+
this.version = ver ? ver.to : this.version + (data.length > 0 ? 1 : 0);
|
|
155
175
|
return [2 /*return*/];
|
|
156
176
|
}
|
|
157
177
|
});
|
|
@@ -160,6 +180,24 @@ var LiveQuerySubscriber = /** @class */ (function () {
|
|
|
160
180
|
return LiveQuerySubscriber;
|
|
161
181
|
}());
|
|
162
182
|
exports.LiveQuerySubscriber = LiveQuerySubscriber;
|
|
183
|
+
//@internal
|
|
184
|
+
function onBrowserForeground(handler) {
|
|
185
|
+
if (typeof document === 'undefined')
|
|
186
|
+
return function () { };
|
|
187
|
+
function onForeground() {
|
|
188
|
+
if (document.visibilityState === 'hidden')
|
|
189
|
+
return;
|
|
190
|
+
handler();
|
|
191
|
+
}
|
|
192
|
+
document.addEventListener('visibilitychange', onForeground);
|
|
193
|
+
window.addEventListener('online', onForeground);
|
|
194
|
+
window.addEventListener('pageshow', onForeground);
|
|
195
|
+
return function () {
|
|
196
|
+
document.removeEventListener('visibilitychange', onForeground);
|
|
197
|
+
window.removeEventListener('online', onForeground);
|
|
198
|
+
window.removeEventListener('pageshow', onForeground);
|
|
199
|
+
};
|
|
200
|
+
}
|
|
163
201
|
exports.liveQueryKeepAliveRoute = '_liveQueryKeepAlive';
|
|
164
202
|
/**
|
|
165
203
|
* The `SubscriptionChannel` class is used to send messages from the backend to the frontend,
|
|
@@ -8,12 +8,16 @@ export interface LiveQueryStorage {
|
|
|
8
8
|
query: StoredQuery;
|
|
9
9
|
setData(data: any): Promise<void>;
|
|
10
10
|
}) => Promise<void>): Promise<void>;
|
|
11
|
-
keepAliveAndReturnUnknownQueryIds(queryIds: string[]): Promise<
|
|
11
|
+
keepAliveAndReturnUnknownQueryIds(queryIds: string[]): Promise<LiveQueryKeepAliveResult>;
|
|
12
12
|
}
|
|
13
|
+
export type LiveQueryKeepAliveResult = {
|
|
14
|
+
unknownQueryIds: string[];
|
|
15
|
+
versions: Record<string, number>;
|
|
16
|
+
};
|
|
13
17
|
export declare class InMemoryLiveQueryStorage implements LiveQueryStorage {
|
|
14
18
|
debugFileSaver: (x: any) => void;
|
|
15
19
|
debug(): void;
|
|
16
|
-
keepAliveAndReturnUnknownQueryIds(ids: string[]): Promise<
|
|
20
|
+
keepAliveAndReturnUnknownQueryIds(ids: string[]): Promise<LiveQueryKeepAliveResult>;
|
|
17
21
|
queries: (StoredQuery & {
|
|
18
22
|
lastUsed: string;
|
|
19
23
|
})[];
|
|
@@ -35,4 +39,5 @@ export interface QueryData {
|
|
|
35
39
|
findOptionsJson: any;
|
|
36
40
|
requestJson: any;
|
|
37
41
|
lastIds: any[];
|
|
42
|
+
version?: number;
|
|
38
43
|
}
|
|
@@ -26,15 +26,16 @@ var LiveQueryPublisher = /** @class */ (function () {
|
|
|
26
26
|
case 0:
|
|
27
27
|
query = tslib_1.__assign({}, q.data);
|
|
28
28
|
return [4 /*yield*/, this.performWithContext(query.requestJson, entityKey, function (repo) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
29
|
-
var messages, currentItems, currentIds, _loop_1, _a, _b, id, _loop_2, currentItems_1, currentItems_1_1, item;
|
|
29
|
+
var messages, currentItems, currentIds, _loop_1, _a, _b, id, _loop_2, currentItems_1, currentItems_1_1, item, from;
|
|
30
30
|
var e_1, _c, e_2, _d;
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
var _e;
|
|
32
|
+
return tslib_1.__generator(this, function (_f) {
|
|
33
|
+
switch (_f.label) {
|
|
33
34
|
case 0:
|
|
34
35
|
messages = [];
|
|
35
36
|
return [4 /*yield*/, repo.find((0, rest_data_provider_js_1.findOptionsFromJson)(query.findOptionsJson, repo.metadata))];
|
|
36
37
|
case 1:
|
|
37
|
-
currentItems =
|
|
38
|
+
currentItems = _f.sent();
|
|
38
39
|
currentIds = currentItems.map(function (x) {
|
|
39
40
|
return repo.getEntityRef(x).getId();
|
|
40
41
|
});
|
|
@@ -103,9 +104,14 @@ var LiveQueryPublisher = /** @class */ (function () {
|
|
|
103
104
|
messages: messages,
|
|
104
105
|
});
|
|
105
106
|
query.lastIds = currentIds;
|
|
107
|
+
if (messages.length > 0) {
|
|
108
|
+
from = (_e = query.version) !== null && _e !== void 0 ? _e : 0;
|
|
109
|
+
query.version = from + 1;
|
|
110
|
+
messages.push({ type: 'version', from: from, to: query.version });
|
|
111
|
+
}
|
|
106
112
|
return [4 /*yield*/, setData(query)];
|
|
107
113
|
case 2:
|
|
108
|
-
|
|
114
|
+
_f.sent();
|
|
109
115
|
if (messages.length > 0)
|
|
110
116
|
this.subscriptionServer().publishMessage(q.id, messages);
|
|
111
117
|
return [2 /*return*/];
|
|
@@ -139,17 +145,20 @@ var InMemoryLiveQueryStorage = /** @class */ (function () {
|
|
|
139
145
|
};
|
|
140
146
|
InMemoryLiveQueryStorage.prototype.keepAliveAndReturnUnknownQueryIds = function (ids) {
|
|
141
147
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
142
|
-
var
|
|
148
|
+
var unknownQueryIds, versions, _loop_3, this_1, ids_1, ids_1_1, id;
|
|
143
149
|
var e_3, _a;
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
var _b, _c;
|
|
151
|
+
return tslib_1.__generator(this, function (_d) {
|
|
152
|
+
unknownQueryIds = [];
|
|
153
|
+
versions = {};
|
|
146
154
|
_loop_3 = function (id) {
|
|
147
155
|
var q = this_1.queries.find(function (q) { return q.id === id; });
|
|
148
156
|
if (q) {
|
|
149
157
|
q.lastUsed = new Date().toISOString();
|
|
158
|
+
versions[id] = (_c = (_b = q.data) === null || _b === void 0 ? void 0 : _b.version) !== null && _c !== void 0 ? _c : 0;
|
|
150
159
|
}
|
|
151
160
|
else
|
|
152
|
-
|
|
161
|
+
unknownQueryIds.push(id);
|
|
153
162
|
};
|
|
154
163
|
this_1 = this;
|
|
155
164
|
try {
|
|
@@ -166,13 +175,14 @@ var InMemoryLiveQueryStorage = /** @class */ (function () {
|
|
|
166
175
|
finally { if (e_3) throw e_3.error; }
|
|
167
176
|
}
|
|
168
177
|
this.debug();
|
|
169
|
-
return [2 /*return*/,
|
|
178
|
+
return [2 /*return*/, { unknownQueryIds: unknownQueryIds, versions: versions }];
|
|
170
179
|
});
|
|
171
180
|
});
|
|
172
181
|
};
|
|
173
182
|
InMemoryLiveQueryStorage.prototype.add = function (query) {
|
|
174
183
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
175
184
|
return tslib_1.__generator(this, function (_a) {
|
|
185
|
+
this.queries = this.queries.filter(function (q) { return q.id !== query.id; });
|
|
176
186
|
this.queries.push(tslib_1.__assign(tslib_1.__assign({}, query), { lastUsed: new Date().toISOString() }));
|
|
177
187
|
this.debug();
|
|
178
188
|
return [2 /*return*/];
|
package/src/remult3/remult3.d.ts
CHANGED
|
@@ -1220,4 +1220,10 @@ export type ClassFieldDecorator<entityType, valueType> = ((target: any, context:
|
|
|
1220
1220
|
};
|
|
1221
1221
|
export declare const flags: {
|
|
1222
1222
|
error500RetryCount: number;
|
|
1223
|
+
/** Client treats SSE as dead if no event for this long */
|
|
1224
|
+
sseStaleMs: number;
|
|
1225
|
+
/** HTTP keep-alive while SSE is healthy (touches lastUsed) */
|
|
1226
|
+
liveQueryKeepAliveMs: number;
|
|
1227
|
+
/** Version poll while SSE is stale */
|
|
1228
|
+
liveQueryPollWhenStaleMs: number;
|
|
1223
1229
|
};
|
package/src/remult3/remult3.js
CHANGED
|
@@ -19,6 +19,12 @@ var wnn = [
|
|
|
19
19
|
];
|
|
20
20
|
exports.flags = {
|
|
21
21
|
error500RetryCount: 4,
|
|
22
|
+
/** Client treats SSE as dead if no event for this long */
|
|
23
|
+
sseStaleMs: 20000,
|
|
24
|
+
/** HTTP keep-alive while SSE is healthy (touches lastUsed) */
|
|
25
|
+
liveQueryKeepAliveMs: 30000,
|
|
26
|
+
/** Version poll while SSE is stale */
|
|
27
|
+
liveQueryPollWhenStaleMs: 1000,
|
|
22
28
|
};
|
|
23
29
|
/*p1 - issues in https://stackblitz.com/edit/demo-allow-delete-based-on-other-entity:
|
|
24
30
|
- don't like the ensure schema
|