@webqit/webflo 0.20.25 → 0.20.27
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/package.json +8 -5
- package/src/build-pi/index.js +7 -5
- package/src/init-pi/index.js +0 -1
- package/src/runtime-pi/{WebfloRuntime.js → AppRuntime.js} +57 -113
- package/src/runtime-pi/webflo-client/DeviceCapabilities.js +1 -1
- package/src/runtime-pi/webflo-client/WebfloClient.js +163 -95
- package/src/runtime-pi/webflo-client/{WebfloRootClient1.js → WebfloRootClientA.js} +39 -56
- package/src/runtime-pi/webflo-client/{WebfloRootClient2.js → WebfloRootClientB.js} +3 -3
- package/src/runtime-pi/webflo-client/WebfloSubClient.js +28 -15
- package/src/runtime-pi/webflo-client/index.js +3 -3
- package/src/runtime-pi/webflo-messaging/ClientPortMixin.js +13 -0
- package/src/runtime-pi/{webflo-server/messaging/ClientRequestRealtime.js → webflo-messaging/ClientRequestPort001.js} +13 -9
- package/src/runtime-pi/webflo-messaging/ClientRequestPort010.js +4 -0
- package/src/runtime-pi/webflo-messaging/ClientRequestPort100.js +17 -0
- package/src/runtime-pi/webflo-messaging/WebfloTenancy001.js +27 -0
- package/src/runtime-pi/webflo-messaging/WebfloTenant001.js +27 -0
- package/src/runtime-pi/webflo-routing/HttpCookies101.js +53 -0
- package/src/runtime-pi/webflo-routing/HttpCookies110.js +3 -0
- package/src/runtime-pi/webflo-routing/{HttpEvent.js → HttpEvent111.js} +95 -73
- package/src/runtime-pi/webflo-routing/HttpKeyvalInterface.js +120 -0
- package/src/runtime-pi/webflo-routing/HttpSession001.js +24 -0
- package/src/runtime-pi/webflo-routing/HttpSession110.js +3 -0
- package/src/runtime-pi/webflo-routing/{HttpThread.js → HttpThread111.js} +54 -13
- package/src/runtime-pi/webflo-routing/{HttpUser.js → HttpUser111.js} +10 -23
- package/src/runtime-pi/webflo-routing/KeyvalsFactory001.js +53 -0
- package/src/runtime-pi/webflo-routing/KeyvalsFactory110.js +48 -0
- package/src/runtime-pi/webflo-routing/KeyvalsFactoryInterface.js +56 -0
- package/src/runtime-pi/webflo-routing/{WebfloRouter.js → WebfloRouter111.js} +5 -6
- package/src/runtime-pi/webflo-server/WebfloServer.js +262 -266
- package/src/runtime-pi/webflo-worker/WebfloWorker.js +97 -44
- package/src/util.js +3 -2
- package/src/runtime-pi/apis.js +0 -9
- package/src/runtime-pi/webflo-client/ClientSideCookies.js +0 -18
- package/src/runtime-pi/webflo-fetch/LiveResponse.js +0 -476
- package/src/runtime-pi/webflo-fetch/index.js +0 -419
- package/src/runtime-pi/webflo-fetch/util.js +0 -28
- package/src/runtime-pi/webflo-messaging/WQBroadcastChannel.js +0 -10
- package/src/runtime-pi/webflo-messaging/WQMessageChannel.js +0 -26
- package/src/runtime-pi/webflo-messaging/WQMessageEvent.js +0 -87
- package/src/runtime-pi/webflo-messaging/WQMessagePort.js +0 -38
- package/src/runtime-pi/webflo-messaging/WQRelayPort.js +0 -47
- package/src/runtime-pi/webflo-messaging/WQSockPort.js +0 -111
- package/src/runtime-pi/webflo-messaging/WQStarPort.js +0 -112
- package/src/runtime-pi/webflo-messaging/wq-message-port.js +0 -413
- package/src/runtime-pi/webflo-routing/HttpCookies.js +0 -43
- package/src/runtime-pi/webflo-routing/HttpSession.js +0 -11
- package/src/runtime-pi/webflo-routing/HttpState.js +0 -182
- package/src/runtime-pi/webflo-server/ServerSideCookies.js +0 -22
- package/src/runtime-pi/webflo-server/ServerSideSession.js +0 -40
- package/src/runtime-pi/webflo-server/messaging/Client.js +0 -27
- package/src/runtime-pi/webflo-server/messaging/Clients.js +0 -25
- package/src/runtime-pi/webflo-url/Url.js +0 -156
- package/src/runtime-pi/webflo-url/index.js +0 -1
- package/src/runtime-pi/webflo-url/urlpattern.js +0 -38
- package/src/runtime-pi/webflo-url/util.js +0 -109
- package/src/runtime-pi/webflo-url/xURL.js +0 -94
- package/src/runtime-pi/webflo-worker/WorkerSideCookies.js +0 -21
|
@@ -1,476 +0,0 @@
|
|
|
1
|
-
import { Observer, LiveProgramHandle } from '@webqit/use-live';
|
|
2
|
-
import { _isObject, _isTypeObject } from '@webqit/util/js/index.js';
|
|
3
|
-
import { publishMutations, applyMutations } from '../webflo-messaging/wq-message-port.js';
|
|
4
|
-
import { WQBroadcastChannel } from '../webflo-messaging/WQBroadcastChannel.js';
|
|
5
|
-
import { WQSockPort } from '../webflo-messaging/WQSockPort.js';
|
|
6
|
-
import { response as responseShim } from './index.js';
|
|
7
|
-
import { _wq, _await } from '../../util.js';
|
|
8
|
-
import { isTypeStream } from './util.js';
|
|
9
|
-
|
|
10
|
-
export class LiveResponse extends EventTarget {
|
|
11
|
-
|
|
12
|
-
[Symbol.toStringTag] = 'LiveResponse';
|
|
13
|
-
|
|
14
|
-
static test(data) {
|
|
15
|
-
if (data instanceof LiveResponse
|
|
16
|
-
|| data?.[Symbol.toStringTag] === 'LiveResponse') {
|
|
17
|
-
return 'LiveResponse';
|
|
18
|
-
}
|
|
19
|
-
if (data instanceof Response) {
|
|
20
|
-
return 'Response';
|
|
21
|
-
}
|
|
22
|
-
if (isGenerator(data)) {
|
|
23
|
-
return 'Generator';
|
|
24
|
-
}
|
|
25
|
-
if (data instanceof LiveProgramHandle
|
|
26
|
-
|| data?.[Symbol.toStringTag] === 'LiveProgramHandle') {
|
|
27
|
-
return 'LiveProgramHandle';
|
|
28
|
-
}
|
|
29
|
-
return 'Default';
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static async from(data, ...args) {
|
|
33
|
-
if (this.test(data) === 'LiveResponse') {
|
|
34
|
-
return data.clone(...args);
|
|
35
|
-
}
|
|
36
|
-
if (this.test(data) === 'Response') {
|
|
37
|
-
return await this.fromResponse(data, ...args);
|
|
38
|
-
}
|
|
39
|
-
if (this.test(data) === 'Generator') {
|
|
40
|
-
return await this.fromGenerator(data, ...args);
|
|
41
|
-
}
|
|
42
|
-
if (this.test(data) === 'LiveProgramHandle') {
|
|
43
|
-
return this.fromLiveProgramHandle(data, ...args);
|
|
44
|
-
}
|
|
45
|
-
return new this(data, ...args);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
static async fromResponse(response, options = {}) {
|
|
49
|
-
if (!(response instanceof Response)) {
|
|
50
|
-
throw new Error('Argument must be a Response instance.');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let body = null;
|
|
54
|
-
try { body = await responseShim.prototype.parse.value.call(response); } catch(e) {}
|
|
55
|
-
|
|
56
|
-
// Instance
|
|
57
|
-
const instance = new this(body, {
|
|
58
|
-
status: responseShim.prototype.status.get.call(response),
|
|
59
|
-
statusText: response.statusText,
|
|
60
|
-
headers: response.headers,
|
|
61
|
-
done: false,
|
|
62
|
-
...options,
|
|
63
|
-
});
|
|
64
|
-
const responseMeta = _wq(response, 'meta');
|
|
65
|
-
_wq(instance).set('meta', responseMeta);
|
|
66
|
-
|
|
67
|
-
// Generator binding
|
|
68
|
-
if (this.hasBackground(response) === 2) {
|
|
69
|
-
const backgroundPort = this.getBackground(response);
|
|
70
|
-
if (_isTypeObject(body) && !isTypeStream(body)) {
|
|
71
|
-
applyMutations.call(backgroundPort,
|
|
72
|
-
body,
|
|
73
|
-
response.headers.get('X-Live-Response-Message-ID').trim(),
|
|
74
|
-
{ signal: instance.#abortController.signal }
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
// Capture subsequent frames?
|
|
78
|
-
backgroundPort.addEventListener('response.replace', (e) => {
|
|
79
|
-
const { body, ...options } = e.data;
|
|
80
|
-
instance.#replaceWith(body, options);
|
|
81
|
-
}, { signal: instance.#abortController.signal });
|
|
82
|
-
backgroundPort.addEventListener('close', () => {
|
|
83
|
-
instance.#extendLifecycle(Promise.resolve());
|
|
84
|
-
}, { once: true, signal: instance.#abortController.signal });
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Data props
|
|
88
|
-
instance.#type = response.type;
|
|
89
|
-
instance.#redirected = response.redirected;
|
|
90
|
-
instance.#url = response.url;
|
|
91
|
-
// Lifecycle props
|
|
92
|
-
instance.#generator = response;
|
|
93
|
-
instance.#generatorType = 'Response';
|
|
94
|
-
|
|
95
|
-
return instance;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
static async fromGenerator(gen, options = {}) {
|
|
99
|
-
if (!isGenerator(gen)) {
|
|
100
|
-
throw new Error('Argument must be a generator or async generator.');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const firstFrame = await gen.next();
|
|
104
|
-
const firstValue = await firstFrame.value;
|
|
105
|
-
|
|
106
|
-
if (firstValue instanceof Response && firstFrame.done && options.done !== false/* && value.responsesOK*/) {
|
|
107
|
-
return firstValue;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
let instance;
|
|
111
|
-
let frame = firstFrame;
|
|
112
|
-
let value = firstValue;
|
|
113
|
-
let $$await;
|
|
114
|
-
|
|
115
|
-
const $options = { done: firstFrame.done, ...options };
|
|
116
|
-
if (this.test(value) === 'LiveResponse') {
|
|
117
|
-
instance = new this;
|
|
118
|
-
const responseMeta = _wq(value, 'meta');
|
|
119
|
-
_wq(instance).set('meta', responseMeta);
|
|
120
|
-
$$await = instance.#replaceWith(value, $options);
|
|
121
|
-
} else {
|
|
122
|
-
instance = await this.from/*important*/(value, $options);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
(async function () {
|
|
126
|
-
await $$await;
|
|
127
|
-
instance.#generator = gen;
|
|
128
|
-
instance.#generatorType = 'Generator';
|
|
129
|
-
while (!frame.done && !options.done && !instance.#abortController.signal.aborted) {
|
|
130
|
-
frame = await gen.next();
|
|
131
|
-
value = await frame.value;
|
|
132
|
-
if (!instance.#abortController.signal.aborted) {
|
|
133
|
-
await instance.#replaceWith(value, { done: frame.done });
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
})();
|
|
137
|
-
|
|
138
|
-
return instance;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
static async fromLiveProgramHandle(liveProgramHandle, options = {}) {
|
|
142
|
-
if (!this.test(liveProgramHandle) === 'LiveProgramHandle') {
|
|
143
|
-
throw new Error('Argument must be a UseLive LiveProgramHandle instance.');
|
|
144
|
-
}
|
|
145
|
-
const instance = new this;
|
|
146
|
-
await instance.replaceWith(liveProgramHandle.value, { done: false, ...options });
|
|
147
|
-
if (instance.#generatorType === 'Default') {
|
|
148
|
-
instance.#generator = liveProgramHandle;
|
|
149
|
-
instance.#generatorType = 'LiveProgramHandle';
|
|
150
|
-
}
|
|
151
|
-
Observer.observe(
|
|
152
|
-
liveProgramHandle,
|
|
153
|
-
'value',
|
|
154
|
-
(e) => instance.#replaceWith(e.value),
|
|
155
|
-
{ signal: instance.#abortController.signal }
|
|
156
|
-
);
|
|
157
|
-
return instance;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
static hasBackground(respone) {
|
|
161
|
-
let liveLevel = (respone.headers?.get?.('X-Background-Messaging-Port')?.trim() || _wq(respone, 'meta').has('background_port')) && 1 || 0;
|
|
162
|
-
liveLevel += respone.headers?.get?.('X-Live-Response-Message-ID')?.trim() && 1 || 0;
|
|
163
|
-
return liveLevel;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
static getBackground(respone) {
|
|
167
|
-
if (!/Response/.test(this.test(respone) )) return;
|
|
168
|
-
const responseMeta = _wq(respone, 'meta');
|
|
169
|
-
if (!responseMeta.has('background_port')) {
|
|
170
|
-
const value = respone.headers.get('X-Background-Messaging-Port')?.trim();
|
|
171
|
-
if (value) {
|
|
172
|
-
const [proto, portID] = value.split(':');
|
|
173
|
-
let backgroundPort;
|
|
174
|
-
if (proto === 'br') {
|
|
175
|
-
backgroundPort = new WQBroadcastChannel(portID);
|
|
176
|
-
} else if (proto === 'ws') {
|
|
177
|
-
backgroundPort = new WQSockPort(portID);
|
|
178
|
-
} else {
|
|
179
|
-
throw new Error(`Unknown background messaging protocol: ${proto}`);
|
|
180
|
-
}
|
|
181
|
-
responseMeta.set('background_port', backgroundPort);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return responseMeta.get('background_port');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
#generator = null;
|
|
188
|
-
#generatorType = 'Default';
|
|
189
|
-
get generatorType() { return this.#generatorType; }
|
|
190
|
-
|
|
191
|
-
#abortController = new AbortController;
|
|
192
|
-
|
|
193
|
-
disconnect() {
|
|
194
|
-
// Disconnection from existing generator
|
|
195
|
-
this.#abortController.abort();
|
|
196
|
-
this.#generator = null;
|
|
197
|
-
this.#generatorType = 'Default';
|
|
198
|
-
// and a new signal system
|
|
199
|
-
this.#abortController = new AbortController;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/* INSTANCE */
|
|
203
|
-
|
|
204
|
-
constructor(body, ...args) {
|
|
205
|
-
super();
|
|
206
|
-
this.#replaceWith(body, ...args);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/* Level 1 props */
|
|
210
|
-
|
|
211
|
-
body = null; // Managed at #replaceWith()
|
|
212
|
-
|
|
213
|
-
#headers = new Headers;
|
|
214
|
-
get headers() { return this.#headers; }
|
|
215
|
-
|
|
216
|
-
#status = 200;
|
|
217
|
-
get status() { return this.#status; }
|
|
218
|
-
|
|
219
|
-
#statusText = '';
|
|
220
|
-
get statusText() { return this.#statusText; }
|
|
221
|
-
|
|
222
|
-
get ok() { return this.#status >= 200 && this.#status < 299; }
|
|
223
|
-
|
|
224
|
-
get bodyUsed() { return false; }
|
|
225
|
-
|
|
226
|
-
/* Level 2 props */
|
|
227
|
-
|
|
228
|
-
#type = 'basic';
|
|
229
|
-
get type() { return this.#type; }
|
|
230
|
-
|
|
231
|
-
#redirected = false;
|
|
232
|
-
get redirected() { return this.#redirected; }
|
|
233
|
-
|
|
234
|
-
#url = null;
|
|
235
|
-
get url() { return this.#url; }
|
|
236
|
-
|
|
237
|
-
/* Level 3 props */
|
|
238
|
-
|
|
239
|
-
get background() { return this.constructor.getBackground(this); }
|
|
240
|
-
|
|
241
|
-
/* Lifecycle methods */
|
|
242
|
-
|
|
243
|
-
whileLive(returningThePromise = false) {
|
|
244
|
-
if (returningThePromise) {
|
|
245
|
-
return this.#lifeCycleResolutionPromise;
|
|
246
|
-
}
|
|
247
|
-
return this.#currentFramePromise !== null;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
#currentFramePromise;
|
|
251
|
-
#lifeCycleResolve;
|
|
252
|
-
#lifeCycleReject;
|
|
253
|
-
#lifeCycleResolutionPromise = new Promise((resolve, reject) => {
|
|
254
|
-
this.#lifeCycleResolve = resolve;
|
|
255
|
-
this.#lifeCycleReject = reject;
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
#extendLifecycle(promise) {
|
|
259
|
-
if (this.#currentFramePromise === null) {
|
|
260
|
-
throw new Error('Event lifecycle already complete.');
|
|
261
|
-
}
|
|
262
|
-
this.#currentFramePromise = promise;
|
|
263
|
-
promise.then((value) => {
|
|
264
|
-
if (this.#currentFramePromise === promise) {
|
|
265
|
-
this.#currentFramePromise = null;
|
|
266
|
-
this.#lifeCycleResolve(value);
|
|
267
|
-
}
|
|
268
|
-
}).catch((e) => {
|
|
269
|
-
if (this.#currentFramePromise === promise) {
|
|
270
|
-
this.#currentFramePromise = null;
|
|
271
|
-
this.#lifeCycleReject(e);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
async #replaceWith(body, ...args) {
|
|
277
|
-
|
|
278
|
-
if (body instanceof Promise) {
|
|
279
|
-
this.#extendLifecycle(body);
|
|
280
|
-
return await new Promise((resolve, reject) => {
|
|
281
|
-
let aborted = false;
|
|
282
|
-
this.#abortController.signal.addEventListener('abort', () => {
|
|
283
|
-
aborted = true
|
|
284
|
-
resolve();
|
|
285
|
-
});
|
|
286
|
-
body.then(async (resolveData) => {
|
|
287
|
-
resolve();
|
|
288
|
-
if (aborted) return;
|
|
289
|
-
await this.#replaceWith(resolveData, ...args);
|
|
290
|
-
});
|
|
291
|
-
body.catch((e) => reject(e));
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const options = _isObject(args[0]/* !ORDER 1 */) ? { ...args.shift() } : {};
|
|
296
|
-
const frameClosure = typeof args[0]/* !ORDER 2 */ === 'function' ? args.shift() : null;
|
|
297
|
-
|
|
298
|
-
if ('status' in options) {
|
|
299
|
-
options.status = parseInt(options.status);
|
|
300
|
-
if (options.status < 200 || options.status > 599) {
|
|
301
|
-
throw new Error(`The status provided (${options.status}) is outside the range [200, 599].`);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
if ('statusText' in options) {
|
|
305
|
-
options.statusText = String(options.statusText);
|
|
306
|
-
}
|
|
307
|
-
if (options.headers && !(options.headers instanceof Headers)) {
|
|
308
|
-
options.headers = new Headers(options.headers);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const execReplaceWith = (responseLike) => {
|
|
312
|
-
const $body = responseLike.body;
|
|
313
|
-
this.#status = responseLike.status;
|
|
314
|
-
this.#statusText = responseLike.statusText;
|
|
315
|
-
for (const [name] of [/*IMPORTANT*/...this.#headers.entries()]) { // for some reason, some entries not produced when not spread
|
|
316
|
-
this.#headers.delete(name);
|
|
317
|
-
}
|
|
318
|
-
for (const [name, value] of responseLike.headers.entries()) {
|
|
319
|
-
this.#headers.append(name, value);
|
|
320
|
-
}
|
|
321
|
-
this.#type = responseLike.type;
|
|
322
|
-
this.#redirected = responseLike.redirected;
|
|
323
|
-
this.#url = responseLike.url;
|
|
324
|
-
// Must come after all property assignments above because it fires events
|
|
325
|
-
Observer.defineProperty(this, 'body', { get: () => $body, enumerable: true, configurable: true });
|
|
326
|
-
this.dispatchEvent(new Event('replace'));
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
const execReplaceWithResponse = async (response, options) => {
|
|
330
|
-
this.#generator = response;
|
|
331
|
-
this.#generatorType = response instanceof Response ? 'Response' : 'LiveResponse';
|
|
332
|
-
const body = response instanceof Response ? await responseShim.prototype.parse.value.call(response) : response.body;
|
|
333
|
-
execReplaceWith({
|
|
334
|
-
body,
|
|
335
|
-
status: responseShim.prototype.status.get.call(response),
|
|
336
|
-
statusText: response.statusText,
|
|
337
|
-
headers: response.headers,
|
|
338
|
-
...options,
|
|
339
|
-
type: response.type,
|
|
340
|
-
redirected: response.redirected,
|
|
341
|
-
url: response.url,
|
|
342
|
-
});
|
|
343
|
-
if (this.constructor.test(response) === 'LiveResponse') {
|
|
344
|
-
response.addEventListener('replace', () => execReplaceWith(response), { signal: this.#abortController.signal });
|
|
345
|
-
return await response.whileLive(true);
|
|
346
|
-
}
|
|
347
|
-
return Promise.resolve();
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
const execReplaceWithBody = async (body, options) => {
|
|
351
|
-
execReplaceWith({
|
|
352
|
-
body,
|
|
353
|
-
status: 200,
|
|
354
|
-
statusText: '',
|
|
355
|
-
headers: new Headers,
|
|
356
|
-
...options,
|
|
357
|
-
type: 'basic',
|
|
358
|
-
redirected: false,
|
|
359
|
-
url: null
|
|
360
|
-
});
|
|
361
|
-
if (frameClosure) {
|
|
362
|
-
const reactiveProxy = _isTypeObject(body) && !isTypeStream(body)
|
|
363
|
-
? Observer.proxy(body, { chainable: true, membrane: body })
|
|
364
|
-
: body;
|
|
365
|
-
return await frameClosure.call(this, reactiveProxy);
|
|
366
|
-
}
|
|
367
|
-
return Promise.resolve();
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
let donePromise;
|
|
371
|
-
if (/Response/.test(body)) {
|
|
372
|
-
if (frameClosure) {
|
|
373
|
-
throw new Error('frameClosure unsupported for inputs of type response.');
|
|
374
|
-
}
|
|
375
|
-
donePromise = execReplaceWithResponse(body, options);
|
|
376
|
-
} else {
|
|
377
|
-
donePromise = execReplaceWithBody(body, options);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (options.done === false) {
|
|
381
|
-
this.#extendLifecycle(new Promise(() => { }));
|
|
382
|
-
} else {
|
|
383
|
-
this.#extendLifecycle(donePromise);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
return await new Promise((resolve, reject) => {
|
|
387
|
-
this.#abortController.signal.addEventListener('abort', resolve);
|
|
388
|
-
donePromise.then(() => resolve());
|
|
389
|
-
donePromise.catch((e) => reject(e));
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async replaceWith(body, ...args) {
|
|
394
|
-
if (!this.whileLive()) {
|
|
395
|
-
throw new Error(`Instance already "complete".`);
|
|
396
|
-
}
|
|
397
|
-
this.disconnect(); // Disconnect from existing source if any
|
|
398
|
-
await this.#replaceWith(body, ...args);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
toResponse({ client: clientPort, signal: abortSignal } = {}) {
|
|
402
|
-
const response = responseShim.from.value(this.body, {
|
|
403
|
-
status: this.status,
|
|
404
|
-
statusText: this.statusText,
|
|
405
|
-
headers: this.headers,
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
const responseMeta = _wq(this, 'meta');
|
|
409
|
-
_wq(response).set('meta', responseMeta);
|
|
410
|
-
|
|
411
|
-
if (clientPort && this.whileLive()) {
|
|
412
|
-
const liveResponseMessageID = Date.now().toString();
|
|
413
|
-
response.headers.set('X-Live-Response-Message-ID', liveResponseMessageID);
|
|
414
|
-
|
|
415
|
-
// Publish mutations
|
|
416
|
-
if (_isTypeObject(this.body) && !isTypeStream(this.body)) {
|
|
417
|
-
publishMutations.call(clientPort, this.body, liveResponseMessageID, { signal: abortSignal/* stop observing mutations on body when we abort */ });
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// Publish replacements?
|
|
421
|
-
const replaceHandler = () => {
|
|
422
|
-
const headers = Object.fromEntries([...this.headers.entries()]);
|
|
423
|
-
if (headers?.['set-cookie']) {
|
|
424
|
-
delete headers['set-cookie'];
|
|
425
|
-
console.warn('Warning: The "set-cookie" header is not supported for security reasons and has been removed from the response.');
|
|
426
|
-
}
|
|
427
|
-
clientPort.postMessage({
|
|
428
|
-
body: this.body,
|
|
429
|
-
status: this.status,
|
|
430
|
-
statusText: this.statusText,
|
|
431
|
-
headers,
|
|
432
|
-
done: !this.whileLive(),
|
|
433
|
-
}, { wqEventOptions: { type: 'response.replace', live: true/*gracefully ignored if not an object*/ }, observerOptions: { signal: abortSignal/* stop observing mutations on body when we abort */ } });
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
this.addEventListener('replace', replaceHandler, { signal: abortSignal/* stop listening when we abort */ });
|
|
437
|
-
}
|
|
438
|
-
return response;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
async * toGenerator({ signal: abortSignal } = {}) {
|
|
442
|
-
do {
|
|
443
|
-
yield $this.body;
|
|
444
|
-
} while (await new Promise((resolve) => {
|
|
445
|
-
this.addEventListener('replace', () => resolve(true), { once: true, signal: abortSignal });
|
|
446
|
-
this.whileLive(true).then(() => resolve(false));
|
|
447
|
-
}));
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
toLiveProgramHandle({ signal: abortSignal } = {}) {
|
|
451
|
-
const state = new LiveProgramHandleX;
|
|
452
|
-
const replaceHandler = () => Observer.defineProperty(state, 'value', { value: this.body, enumerable: true, configurable: true });
|
|
453
|
-
this.addEventListener('replace', replaceHandler, { signal: abortSignal });
|
|
454
|
-
replaceHandler();
|
|
455
|
-
return state;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
clone(init = {}) {
|
|
459
|
-
const clone = new this.constructor();
|
|
460
|
-
const responseMeta = _wq(this, 'meta');
|
|
461
|
-
_wq(clone).set('meta', responseMeta);
|
|
462
|
-
clone.replaceWith(this, init);
|
|
463
|
-
return clone;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
export const isGenerator = (obj) => {
|
|
468
|
-
return typeof obj?.next === 'function' &&
|
|
469
|
-
typeof obj?.throw === 'function' &&
|
|
470
|
-
typeof obj?.return === 'function';
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
class LiveProgramHandleX extends LiveProgramHandle {
|
|
474
|
-
constructor() { }
|
|
475
|
-
abort() { }
|
|
476
|
-
}
|