@vertexvis/stream-api 0.24.6-canary.0 → 1.0.0-canary.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/dist/bundle.cjs +1095 -0
- package/dist/bundle.cjs.map +1 -0
- package/dist/bundle.js +1080 -0
- package/dist/bundle.js.map +1 -0
- package/dist/connection.d.ts +4 -4
- package/dist/encoder.d.ts +3 -3
- package/dist/errors.d.ts +8 -8
- package/dist/index.d.ts +13 -12
- package/dist/paramsBuilder.d.ts +5 -5
- package/dist/settings.d.ts +106 -106
- package/dist/streamApi.d.ts +327 -327
- package/dist/testing/__tests__/webSocketClientMock.spec.d.ts +1 -1
- package/dist/testing/fixtures/events.d.ts +2 -2
- package/dist/testing/fixtures/index.d.ts +4 -4
- package/dist/testing/fixtures/requests.d.ts +14 -14
- package/dist/testing/fixtures/responses.d.ts +20 -20
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/webSocketClientMock.d.ts +77 -77
- package/dist/time.d.ts +37 -37
- package/dist/types.d.ts +63 -63
- package/dist/validators.d.ts +9 -9
- package/dist/webSocketClient.d.ts +28 -28
- package/package.json +25 -15
- package/dist/bundle.cjs.js +0 -50061
- package/dist/bundle.cjs.js.map +0 -1
- package/dist/bundle.esm.js +0 -50047
- package/dist/bundle.esm.js.map +0 -1
package/dist/bundle.cjs
ADDED
|
@@ -0,0 +1,1095 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var frameStreamingProtos = require('@vertexvis/frame-streaming-protos');
|
|
6
|
+
var utils = require('@vertexvis/utils');
|
|
7
|
+
|
|
8
|
+
function encode(message) {
|
|
9
|
+
return frameStreamingProtos.vertexvis.protobuf.stream.StreamMessage.encode(message).finish();
|
|
10
|
+
}
|
|
11
|
+
function decode(bufferOrBytes) {
|
|
12
|
+
const bytes = bufferOrBytes instanceof ArrayBuffer
|
|
13
|
+
? new Uint8Array(bufferOrBytes)
|
|
14
|
+
: bufferOrBytes;
|
|
15
|
+
const message = frameStreamingProtos.vertexvis.protobuf.stream.StreamMessage.decode(bytes);
|
|
16
|
+
return frameStreamingProtos.vertexvis.protobuf.stream.StreamMessage.toObject(message, {
|
|
17
|
+
defaults: true,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class StreamRequestError extends Error {
|
|
22
|
+
constructor(requestId, requestPayload, summary, details) {
|
|
23
|
+
super(summary != null && summary.length > 0
|
|
24
|
+
? `Stream request failed (${summary})`
|
|
25
|
+
: 'Stream request failed');
|
|
26
|
+
this.requestId = requestId;
|
|
27
|
+
this.requestPayload = requestPayload;
|
|
28
|
+
this.summary = summary;
|
|
29
|
+
this.details = details;
|
|
30
|
+
// Allows for `instanceof` checks. See https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
31
|
+
Object.setPrototypeOf(this, StreamRequestError.prototype);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function defineParams(...definitions) {
|
|
36
|
+
return (settings) => {
|
|
37
|
+
return definitions.reduce((result, def) => ({ ...result, ...def(settings) }), {});
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function defineBoolean(param, prop) {
|
|
41
|
+
return defineValue(param, prop, (v) => {
|
|
42
|
+
if (typeof v === 'boolean') {
|
|
43
|
+
return v ? 'on' : 'off';
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function defineNumber(param, prop) {
|
|
51
|
+
return defineValue(param, prop, (v) => typeof v === 'number' ? v.toString() : undefined);
|
|
52
|
+
}
|
|
53
|
+
function defineString(param, prop) {
|
|
54
|
+
return defineValue(param, prop, (v) => typeof v === 'string' ? v : undefined);
|
|
55
|
+
}
|
|
56
|
+
function defineValue(param, prop, f) {
|
|
57
|
+
return (settings) => {
|
|
58
|
+
const value = f(settings[prop]);
|
|
59
|
+
if (value != null) {
|
|
60
|
+
return { [param]: value };
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function appendSettingsToUrl(url, settings) {
|
|
69
|
+
const defaults = {
|
|
70
|
+
// Settings that you want to set on each WS connection should go here.
|
|
71
|
+
};
|
|
72
|
+
const uri = utils.Uri.parse(url);
|
|
73
|
+
const builder = defineParams(toFrameDeliverySettingsParams(defaults.EXPERIMENTAL_frameDelivery), toAdaptiveRenderingSettingsParams(defaults.EXPERIMENTAL_adaptiveRendering), toQualityOfServiceSettingsParams(defaults.EXPERIMENTAL_qualityOfService));
|
|
74
|
+
const params = builder(settings);
|
|
75
|
+
return utils.Uri.toString(utils.Uri.addQueryParams(params, uri));
|
|
76
|
+
}
|
|
77
|
+
function toFrameDeliverySettingsParams(defaults) {
|
|
78
|
+
return defineSettings((s) => s.EXPERIMENTAL_frameDelivery, defaults, defineParams(defineBoolean('frame-delivery.rate-limit-enabled', 'rateLimitingEnabled'), defineNumber('frame-delivery.packet-loss-threshold', 'packetLossThreshold'), defineNumber('frame-delivery.history-max-size', 'historyMaxSize'), defineString('frame-delivery.timeout', 'timeout'), defineNumber('frame-delivery.timeout-ratio-threshold', 'timeoutRatioThreshold')));
|
|
79
|
+
}
|
|
80
|
+
function toAdaptiveRenderingSettingsParams(defaults) {
|
|
81
|
+
return defineSettings((s) => s.EXPERIMENTAL_adaptiveRendering, defaults, defineParams(defineBoolean('adaptive-rendering.enabled', 'enabled'), defineString('adaptive-rendering.method', 'method'), defineNumber('adaptive-rendering.jpeg-quality-min', 'jpegMinQuality'), defineNumber('adaptive-rendering.jpeg-quality-max', 'jpegMaxQuality'), defineNumber('adaptive-rendering.image-scale-min', 'imageMinScale'), defineNumber('adaptive-rendering.image-scale-max', 'imageMaxScale'), defineNumber('adaptive-rendering.window-size', 'windowSize')));
|
|
82
|
+
}
|
|
83
|
+
function toQualityOfServiceSettingsParams(defaults) {
|
|
84
|
+
return defineSettings((s) => s.EXPERIMENTAL_qualityOfService, defaults, defineParams(defineNumber('qos.history-max-size', 'historyMaxSize')));
|
|
85
|
+
}
|
|
86
|
+
function defineSettings(getter, defaults, builder) {
|
|
87
|
+
return (settings) => {
|
|
88
|
+
const merged = utils.Objects.defaults(getter(settings) || {}, defaults);
|
|
89
|
+
return builder(merged);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Converts a JS date type to a `google.protobuf.Timestamp`. The returned time
|
|
95
|
+
* will be represented as UTC.
|
|
96
|
+
*
|
|
97
|
+
* @param date The date to convert.
|
|
98
|
+
*/
|
|
99
|
+
function toProtoTimestamp(date) {
|
|
100
|
+
const millis = date.getTime();
|
|
101
|
+
return frameStreamingProtos.google.protobuf.Timestamp.create(parseEpochMillis(millis));
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Returns the current date and time as a `google.protobuf.Timestamp`.
|
|
105
|
+
*/
|
|
106
|
+
function currentDateAsProtoTimestamp() {
|
|
107
|
+
return toProtoTimestamp(new Date());
|
|
108
|
+
}
|
|
109
|
+
function toProtoDuration(...args) {
|
|
110
|
+
if (args.length === 2) {
|
|
111
|
+
const start = args[0];
|
|
112
|
+
const end = args[1];
|
|
113
|
+
const millis = end.getTime() - start.getTime();
|
|
114
|
+
return frameStreamingProtos.google.protobuf.Duration.create(parseEpochMillis(millis));
|
|
115
|
+
}
|
|
116
|
+
else if (args.length === 1) {
|
|
117
|
+
const millis = args[0];
|
|
118
|
+
return frameStreamingProtos.google.protobuf.Duration.create(parseEpochMillis(millis));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
throw new Error('Expected input to be a number or start and end date.');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function protoToDate(time) {
|
|
125
|
+
if (time.seconds != null && time.nanos != null) {
|
|
126
|
+
const seconds = typeof time.seconds === 'number' ? time.seconds : time.seconds.toNumber();
|
|
127
|
+
return new Date(seconds * 1000 + time.nanos / 1000000);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/* eslint-enable padding-line-between-statements */
|
|
131
|
+
function parseEpochMillis(millis) {
|
|
132
|
+
const seconds = Math.floor(Math.abs(millis) / 1000);
|
|
133
|
+
const nanos = (millis % 1000) * 1000000;
|
|
134
|
+
return { seconds: seconds * (millis < 0 ? -1 : 1), nanos };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function validateBoundingBox(boundingBox) {
|
|
138
|
+
const boundingBoxXMaxValid = (boundingBox === null || boundingBox === void 0 ? void 0 : boundingBox.xmax) != null && Number.isFinite(boundingBox.xmax);
|
|
139
|
+
const boundingBoxXMinValid = (boundingBox === null || boundingBox === void 0 ? void 0 : boundingBox.xmin) != null && Number.isFinite(boundingBox.xmin);
|
|
140
|
+
const boundingBoxYMaxValid = (boundingBox === null || boundingBox === void 0 ? void 0 : boundingBox.ymax) != null && Number.isFinite(boundingBox.ymax);
|
|
141
|
+
const boundingBoxYMinValid = (boundingBox === null || boundingBox === void 0 ? void 0 : boundingBox.ymin) != null && Number.isFinite(boundingBox.ymin);
|
|
142
|
+
const boundingBoxZMaxValid = (boundingBox === null || boundingBox === void 0 ? void 0 : boundingBox.zmax) != null && Number.isFinite(boundingBox.zmax);
|
|
143
|
+
const boundingBoxZMinValid = (boundingBox === null || boundingBox === void 0 ? void 0 : boundingBox.zmin) != null && Number.isFinite(boundingBox.zmin);
|
|
144
|
+
return (boundingBoxXMaxValid &&
|
|
145
|
+
boundingBoxXMinValid &&
|
|
146
|
+
boundingBoxYMaxValid &&
|
|
147
|
+
boundingBoxYMinValid &&
|
|
148
|
+
boundingBoxZMaxValid &&
|
|
149
|
+
boundingBoxZMinValid);
|
|
150
|
+
}
|
|
151
|
+
function validateCamera(camera) {
|
|
152
|
+
// If a perspective camera is provided, verify it is valid
|
|
153
|
+
if (camera.perspective != null) {
|
|
154
|
+
const perspectiveCameraIsValid = validatePerspectiveCamera(camera.perspective);
|
|
155
|
+
return perspectiveCameraIsValid;
|
|
156
|
+
}
|
|
157
|
+
// If an orthographic camera is provided, verify it is valid
|
|
158
|
+
if (camera.orthographic != null) {
|
|
159
|
+
const orthographicCameraIsValid = validateOrthographicCamera(camera.orthographic);
|
|
160
|
+
return orthographicCameraIsValid;
|
|
161
|
+
}
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
function validatePerspectiveCamera(camera) {
|
|
165
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
166
|
+
const lookAtXValid = ((_a = camera.lookAt) === null || _a === void 0 ? void 0 : _a.x) != null && Number.isFinite(camera.lookAt.x);
|
|
167
|
+
const lookAtYValid = ((_b = camera.lookAt) === null || _b === void 0 ? void 0 : _b.y) != null && Number.isFinite(camera.lookAt.y);
|
|
168
|
+
const lookAtZValid = ((_c = camera.lookAt) === null || _c === void 0 ? void 0 : _c.z) != null && Number.isFinite(camera.lookAt.z);
|
|
169
|
+
const positionXValid = ((_d = camera.position) === null || _d === void 0 ? void 0 : _d.x) != null && Number.isFinite(camera.position.x);
|
|
170
|
+
const positionYValid = ((_e = camera.position) === null || _e === void 0 ? void 0 : _e.y) != null && Number.isFinite(camera.position.y);
|
|
171
|
+
const positionZValid = ((_f = camera.position) === null || _f === void 0 ? void 0 : _f.z) != null && Number.isFinite(camera.position.z);
|
|
172
|
+
const upXValid = ((_g = camera.up) === null || _g === void 0 ? void 0 : _g.x) != null && Number.isFinite(camera.up.x);
|
|
173
|
+
const upYValid = ((_h = camera.up) === null || _h === void 0 ? void 0 : _h.y) != null && Number.isFinite(camera.up.y);
|
|
174
|
+
const upZValid = ((_j = camera.up) === null || _j === void 0 ? void 0 : _j.z) != null && Number.isFinite(camera.up.z);
|
|
175
|
+
// Validate up vector has non-zero length
|
|
176
|
+
const upVectorValid = validateVector({ x: (_k = camera === null || camera === void 0 ? void 0 : camera.up) === null || _k === void 0 ? void 0 : _k.x, y: (_l = camera === null || camera === void 0 ? void 0 : camera.up) === null || _l === void 0 ? void 0 : _l.y, z: (_m = camera === null || camera === void 0 ? void 0 : camera.up) === null || _m === void 0 ? void 0 : _m.z }, true);
|
|
177
|
+
return (lookAtXValid &&
|
|
178
|
+
lookAtYValid &&
|
|
179
|
+
lookAtZValid &&
|
|
180
|
+
positionXValid &&
|
|
181
|
+
positionYValid &&
|
|
182
|
+
positionZValid &&
|
|
183
|
+
upXValid &&
|
|
184
|
+
upYValid &&
|
|
185
|
+
upZValid &&
|
|
186
|
+
upVectorValid);
|
|
187
|
+
}
|
|
188
|
+
function validateOrthographicCamera(camera) {
|
|
189
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
190
|
+
const fovHeightValid = camera.fovHeight != null && Number.isFinite(camera.fovHeight);
|
|
191
|
+
const lookAtXValid = ((_a = camera.lookAt) === null || _a === void 0 ? void 0 : _a.x) != null && Number.isFinite(camera.lookAt.x);
|
|
192
|
+
const lookAtYValid = ((_b = camera.lookAt) === null || _b === void 0 ? void 0 : _b.y) != null && Number.isFinite(camera.lookAt.y);
|
|
193
|
+
const lookAtZValid = ((_c = camera.lookAt) === null || _c === void 0 ? void 0 : _c.z) != null && Number.isFinite(camera.lookAt.z);
|
|
194
|
+
const upXValid = ((_d = camera.up) === null || _d === void 0 ? void 0 : _d.x) != null && Number.isFinite(camera.up.x);
|
|
195
|
+
const upYValid = ((_e = camera.up) === null || _e === void 0 ? void 0 : _e.y) != null && Number.isFinite(camera.up.y);
|
|
196
|
+
const upZValid = ((_f = camera.up) === null || _f === void 0 ? void 0 : _f.z) != null && Number.isFinite(camera.up.z);
|
|
197
|
+
const viewVectorXValid = ((_g = camera.viewVector) === null || _g === void 0 ? void 0 : _g.x) != null && Number.isFinite(camera.viewVector.x);
|
|
198
|
+
const viewVectorYValid = ((_h = camera.viewVector) === null || _h === void 0 ? void 0 : _h.y) != null && Number.isFinite(camera.viewVector.y);
|
|
199
|
+
const viewVectorZValid = ((_j = camera.viewVector) === null || _j === void 0 ? void 0 : _j.z) != null && Number.isFinite(camera.viewVector.z);
|
|
200
|
+
// Validate up vector has non-zero length
|
|
201
|
+
const upVectorValid = validateVector({ x: (_k = camera === null || camera === void 0 ? void 0 : camera.up) === null || _k === void 0 ? void 0 : _k.x, y: (_l = camera === null || camera === void 0 ? void 0 : camera.up) === null || _l === void 0 ? void 0 : _l.y, z: (_m = camera === null || camera === void 0 ? void 0 : camera.up) === null || _m === void 0 ? void 0 : _m.z }, true);
|
|
202
|
+
return (fovHeightValid &&
|
|
203
|
+
lookAtXValid &&
|
|
204
|
+
lookAtYValid &&
|
|
205
|
+
lookAtZValid &&
|
|
206
|
+
viewVectorXValid &&
|
|
207
|
+
viewVectorYValid &&
|
|
208
|
+
viewVectorZValid &&
|
|
209
|
+
upXValid &&
|
|
210
|
+
upYValid &&
|
|
211
|
+
upZValid &&
|
|
212
|
+
upVectorValid);
|
|
213
|
+
}
|
|
214
|
+
function validateDimensions(dimensions) {
|
|
215
|
+
const heightValid = (dimensions === null || dimensions === void 0 ? void 0 : dimensions.height) != null &&
|
|
216
|
+
Number.isFinite(dimensions.height) &&
|
|
217
|
+
dimensions.height > 0;
|
|
218
|
+
const widthValid = (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) != null &&
|
|
219
|
+
Number.isFinite(dimensions.width) &&
|
|
220
|
+
dimensions.width > 0;
|
|
221
|
+
return heightValid && widthValid;
|
|
222
|
+
}
|
|
223
|
+
function validateNumber(number) {
|
|
224
|
+
return number != null && Number.isFinite(number);
|
|
225
|
+
}
|
|
226
|
+
function validatePoint(point) {
|
|
227
|
+
const xValid = (point === null || point === void 0 ? void 0 : point.x) != null && Number.isFinite(point.x);
|
|
228
|
+
const yValid = (point === null || point === void 0 ? void 0 : point.y) != null && Number.isFinite(point.y);
|
|
229
|
+
return xValid && yValid;
|
|
230
|
+
}
|
|
231
|
+
function validateVector(vector, verifyNonZeroLength) {
|
|
232
|
+
const xValid = (vector === null || vector === void 0 ? void 0 : vector.x) != null && Number.isFinite(vector.x);
|
|
233
|
+
const yValid = (vector === null || vector === void 0 ? void 0 : vector.y) != null && Number.isFinite(vector.y);
|
|
234
|
+
const zValid = (vector === null || vector === void 0 ? void 0 : vector.z) != null && Number.isFinite(vector.z);
|
|
235
|
+
const vectorComponentsValid = xValid && yValid && zValid;
|
|
236
|
+
if (verifyNonZeroLength) {
|
|
237
|
+
if ((vector === null || vector === void 0 ? void 0 : vector.x) != null && (vector === null || vector === void 0 ? void 0 : vector.y) != null && (vector === null || vector === void 0 ? void 0 : vector.z) != null) {
|
|
238
|
+
const vectorMagnitudeSquared = vector.x * vector.x + vector.y * vector.y + vector.z * vector.z;
|
|
239
|
+
const vectorHasNonZeroLength = vectorMagnitudeSquared !== 0;
|
|
240
|
+
return vectorComponentsValid && vectorHasNonZeroLength;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
// If one or more components are undefined, then the vector does not have non-zero length
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return vectorComponentsValid;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
class WebSocketClientImpl {
|
|
251
|
+
constructor() {
|
|
252
|
+
this.listeners = {};
|
|
253
|
+
this.onMessageDispatcher = new utils.EventDispatcher();
|
|
254
|
+
this.onCloseDispatcher = new utils.EventDispatcher();
|
|
255
|
+
this.addWebSocketListeners = (ws, wsId, resolve, reject) => {
|
|
256
|
+
const onOpen = () => this.onOpen(resolve);
|
|
257
|
+
const onError = () => reject();
|
|
258
|
+
const onClose = (event) => this.handleClose(event, wsId);
|
|
259
|
+
ws.addEventListener('message', this.handleMessage);
|
|
260
|
+
ws.addEventListener('open', onOpen);
|
|
261
|
+
ws.addEventListener('error', onError);
|
|
262
|
+
ws.addEventListener('close', onClose);
|
|
263
|
+
return {
|
|
264
|
+
dispose: () => {
|
|
265
|
+
ws.removeEventListener('message', this.handleMessage);
|
|
266
|
+
ws.removeEventListener('open', onOpen);
|
|
267
|
+
ws.removeEventListener('error', onError);
|
|
268
|
+
ws.removeEventListener('close', onClose);
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
};
|
|
272
|
+
this.handleMessage = (event) => {
|
|
273
|
+
this.onMessageDispatcher.emit(event);
|
|
274
|
+
};
|
|
275
|
+
this.handleClose = (event, webSocketId) => {
|
|
276
|
+
this.onCloseDispatcher.emit(event);
|
|
277
|
+
this.removeWebSocketListeners(webSocketId);
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
close() {
|
|
281
|
+
if (this.webSocket != null) {
|
|
282
|
+
this.webSocket.close();
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async connect(descriptor) {
|
|
286
|
+
const id = utils.UUID.create();
|
|
287
|
+
// Ensure that any existing websocket connection has been closed prior
|
|
288
|
+
// to opening a new one to ensure we don't leave open connections.
|
|
289
|
+
if (this.webSocket != null) {
|
|
290
|
+
this.close();
|
|
291
|
+
}
|
|
292
|
+
this.webSocket = new WebSocket(descriptor.url, descriptor.protocols);
|
|
293
|
+
this.webSocket.binaryType = 'arraybuffer';
|
|
294
|
+
return new Promise((resolve, reject) => {
|
|
295
|
+
if (this.webSocket != null) {
|
|
296
|
+
this.listeners[id] = this.addWebSocketListeners(this.webSocket, id, resolve, reject);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
onMessage(handler) {
|
|
301
|
+
return this.onMessageDispatcher.on(handler);
|
|
302
|
+
}
|
|
303
|
+
onClose(handler) {
|
|
304
|
+
return this.onCloseDispatcher.on(handler);
|
|
305
|
+
}
|
|
306
|
+
send(data) {
|
|
307
|
+
if (this.webSocket != null) {
|
|
308
|
+
this.webSocket.send(data);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
removeWebSocketListeners(webSocketId) {
|
|
312
|
+
var _a;
|
|
313
|
+
(_a = this.listeners[webSocketId]) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
314
|
+
}
|
|
315
|
+
onOpen(resolve) {
|
|
316
|
+
resolve();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* The API client to interact with Vertex's streaming API.
|
|
322
|
+
*/
|
|
323
|
+
class StreamApi {
|
|
324
|
+
constructor(websocket = new WebSocketClientImpl(), opts = {}) {
|
|
325
|
+
var _a;
|
|
326
|
+
this.websocket = websocket;
|
|
327
|
+
this.onResponseDispatcher = new utils.EventDispatcher();
|
|
328
|
+
this.onRequestDispatcher = new utils.EventDispatcher();
|
|
329
|
+
this.onEventDispatcher = new utils.EventDispatcher();
|
|
330
|
+
this.opts = {
|
|
331
|
+
loggingEnabled: (_a = opts.loggingEnabled) !== null && _a !== void 0 ? _a : false,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Initiates a websocket connection to Vertex's streaming API. Returns a
|
|
336
|
+
* promise that resolves once the connection is established and can begin
|
|
337
|
+
* accepting messages.
|
|
338
|
+
*
|
|
339
|
+
* @param descriptor A function that returns a description of how to establish
|
|
340
|
+
* a WS connection.
|
|
341
|
+
* @param settings A configuration to use when initializing the WS connection.
|
|
342
|
+
*/
|
|
343
|
+
async connect(descriptor, settings = {}) {
|
|
344
|
+
const desc = {
|
|
345
|
+
...descriptor,
|
|
346
|
+
url: appendSettingsToUrl(descriptor.url, settings),
|
|
347
|
+
};
|
|
348
|
+
await this.websocket.connect(desc);
|
|
349
|
+
this.messageSubscription = this.websocket.onMessage((message) => {
|
|
350
|
+
this.handleMessage(message);
|
|
351
|
+
});
|
|
352
|
+
return { dispose: () => this.dispose() };
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Closes any open WS connections and disposes of resources.
|
|
356
|
+
*/
|
|
357
|
+
dispose() {
|
|
358
|
+
var _a;
|
|
359
|
+
this.websocket.close();
|
|
360
|
+
(_a = this.messageSubscription) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Adds a callback that is invoked when the client receives a request from the
|
|
364
|
+
* server. Returns a `Disposable` that can be used to remove the listener.
|
|
365
|
+
*
|
|
366
|
+
* @param handler A handler function.
|
|
367
|
+
*/
|
|
368
|
+
onRequest(handler) {
|
|
369
|
+
return this.onRequestDispatcher.on(handler);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Adds a callback that is invoked when the client receives an event from the
|
|
373
|
+
* server. Returns a `Disposable` that can be used to remove the listener.
|
|
374
|
+
*
|
|
375
|
+
* @param handler - A handler function.
|
|
376
|
+
*/
|
|
377
|
+
onEvent(handler) {
|
|
378
|
+
return this.onEventDispatcher.on(handler);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Adds a callback that is invoked when the websocket connection is closed.
|
|
382
|
+
*
|
|
383
|
+
* @param handler A handler function.
|
|
384
|
+
*/
|
|
385
|
+
onClose(handler) {
|
|
386
|
+
return this.websocket.onClose(handler);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Sends a request to initiate a streaming session.
|
|
390
|
+
*
|
|
391
|
+
* The payload accepts an optional `frameCorrelationId` that will be sent
|
|
392
|
+
* back on the frame that is associated to this request. Use `onRequest` to
|
|
393
|
+
* add a callback that'll be invoked when the server sends a request to draw
|
|
394
|
+
* the frame.
|
|
395
|
+
*
|
|
396
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
397
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
398
|
+
* it'll complete when a response is received.
|
|
399
|
+
*
|
|
400
|
+
* @param payload The payload of the request.
|
|
401
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
402
|
+
* Defaults to `true`.
|
|
403
|
+
*/
|
|
404
|
+
startStream(payload, withResponse = true) {
|
|
405
|
+
return this.sendRequest({ startStream: payload }, withResponse);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Sends a request to reconnect to an existing streaming session.
|
|
409
|
+
*
|
|
410
|
+
* The payload accepts an optional `frameCorrelationId` that will be sent
|
|
411
|
+
* back on the frame that is associated to this request. Use `onRequest` to
|
|
412
|
+
* add a callback that'll be invoked when the server sends a request to draw
|
|
413
|
+
* the frame.
|
|
414
|
+
*
|
|
415
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
416
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
417
|
+
* it'll complete when a response is received.
|
|
418
|
+
*
|
|
419
|
+
* @param payload The payload of the request.
|
|
420
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
421
|
+
* Defaults to `true`.
|
|
422
|
+
*/
|
|
423
|
+
async reconnect(payload, withResponse = true) {
|
|
424
|
+
return this.sendRequest({ reconnect: payload }, withResponse);
|
|
425
|
+
}
|
|
426
|
+
async updateStream(payload, withResponse = false) {
|
|
427
|
+
return this.sendRequest({ updateStream: payload }, withResponse);
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Sends a request to signal to the rendering pipeline that an interaction has
|
|
431
|
+
* started. The rendering pipeline will use this as a hint to perform more
|
|
432
|
+
* aggressive rendering optimizations at the expense of rendering quality.
|
|
433
|
+
* Call `endInteraction` to signal to the rendering pipeline that an
|
|
434
|
+
* interaction has finished.
|
|
435
|
+
*
|
|
436
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
437
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
438
|
+
* it'll complete when a response is received.
|
|
439
|
+
*
|
|
440
|
+
* @param data The payload of the request.
|
|
441
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
442
|
+
* Defaults to `true`.
|
|
443
|
+
*/
|
|
444
|
+
beginInteraction(payload = {}, withResponse = true) {
|
|
445
|
+
return this.sendRequest({ beginInteraction: payload }, withResponse);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Sends a request to update the position of the scene's camera.
|
|
449
|
+
*
|
|
450
|
+
* The payload accepts an optional `frameCorrelationId` that will be sent
|
|
451
|
+
* back on the frame that is associated to this request. Use `onRequest` to
|
|
452
|
+
* add a callback that'll be invoked when the server sends a request to draw
|
|
453
|
+
* the frame.
|
|
454
|
+
*
|
|
455
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
456
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
457
|
+
* it'll complete when a response is received.
|
|
458
|
+
*
|
|
459
|
+
* @param payload The payload of the request.
|
|
460
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
461
|
+
* Defaults to `true`.
|
|
462
|
+
*/
|
|
463
|
+
replaceCamera(payload, withResponse = true) {
|
|
464
|
+
// If a camera is provided, verify it is valid
|
|
465
|
+
if (payload.camera != null) {
|
|
466
|
+
const cameraIsValid = validateCamera(payload.camera);
|
|
467
|
+
if (!cameraIsValid) {
|
|
468
|
+
console.warn('Invalid camera provided. Canceling replaceCamera operation.');
|
|
469
|
+
return Promise.resolve({});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return this.sendRequest({ updateCamera: payload }, withResponse);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Sends a request to update the position of the scene's camera as a fly operation
|
|
476
|
+
*
|
|
477
|
+
* The payload accepts an optional `frameCorrelationId` that will be sent
|
|
478
|
+
* back on the frame that is associated to this request. Use `onRequest` to
|
|
479
|
+
* add a callback that'll be invoked when the server sends a request to draw
|
|
480
|
+
* the frame.
|
|
481
|
+
*
|
|
482
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
483
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
484
|
+
* it'll complete when a response is received.
|
|
485
|
+
*
|
|
486
|
+
* @param payload
|
|
487
|
+
* @param withResponse
|
|
488
|
+
*/
|
|
489
|
+
flyTo(payload, withResponse = true) {
|
|
490
|
+
// If a bounding box is provided, verify it is valid
|
|
491
|
+
if (payload.boundingBox != null) {
|
|
492
|
+
const validBoundingBox = validateBoundingBox(payload.boundingBox);
|
|
493
|
+
if (!validBoundingBox) {
|
|
494
|
+
console.warn('Invalid bounding box provided. Canceling flyTo operation.');
|
|
495
|
+
return Promise.resolve({});
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
// If a camera is provided, verify it is valid
|
|
499
|
+
if (payload.camera != null) {
|
|
500
|
+
const cameraIsValid = validateCamera(payload.camera);
|
|
501
|
+
if (!cameraIsValid) {
|
|
502
|
+
console.warn('Invalid camera provided. Canceling flyTo operation.');
|
|
503
|
+
return Promise.resolve({});
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
// If a base camera is provided, verify it is valid
|
|
507
|
+
if (payload.baseCamera != null) {
|
|
508
|
+
const baseCameraIsValid = validateCamera(payload.baseCamera);
|
|
509
|
+
if (!baseCameraIsValid) {
|
|
510
|
+
console.warn('Invalid base camera provided. Canceling flyTo operation.');
|
|
511
|
+
return Promise.resolve({});
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return this.sendRequest({ flyTo: payload }, withResponse);
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Sends a request to update the specified interaction.
|
|
518
|
+
*
|
|
519
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
520
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
521
|
+
* it'll complete when a response is received.
|
|
522
|
+
*
|
|
523
|
+
* @param payload The payload of the request.
|
|
524
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
525
|
+
* Defaults to `true`.
|
|
526
|
+
*/
|
|
527
|
+
updateInteraction(payload, withResponse = true) {
|
|
528
|
+
return this.sendRequest({ updateInteraction: payload }, withResponse);
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Sends a request to update the dimensions of the frame.
|
|
532
|
+
*
|
|
533
|
+
* The payload accepts an optional `frameCorrelationId` that will be sent
|
|
534
|
+
* back on the frame that is associated to this request. Use `onRequest` to
|
|
535
|
+
* add a callback that'll be invoked when the server sends a request to draw
|
|
536
|
+
* the frame.
|
|
537
|
+
*
|
|
538
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
539
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
540
|
+
* it'll complete when a response is received.
|
|
541
|
+
*
|
|
542
|
+
* @param payload The payload of the request.
|
|
543
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
544
|
+
* Defaults to `true`.
|
|
545
|
+
*/
|
|
546
|
+
updateDimensions(payload, withResponse = true) {
|
|
547
|
+
// Verify the provided dimensions are valid
|
|
548
|
+
if (payload.dimensions != null) {
|
|
549
|
+
const validDimensions = validateDimensions(payload.dimensions);
|
|
550
|
+
if (!validDimensions) {
|
|
551
|
+
console.warn('Invalid dimensions provided. Canceling updateDimensions operation.');
|
|
552
|
+
return Promise.resolve({});
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return this.sendRequest({ updateDimensions: payload }, withResponse);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Sends a request to update the cross sectioning planes of the frame.
|
|
559
|
+
*
|
|
560
|
+
* The payload accepts an optional `frameCorrelationId` that will be sent
|
|
561
|
+
* back on the frame that is associated to this request. Use `onRequest` to
|
|
562
|
+
* add a callback that'll be invoked when the server sends a request to draw
|
|
563
|
+
* the frame.
|
|
564
|
+
*
|
|
565
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
566
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
567
|
+
* it'll complete when a response is received.
|
|
568
|
+
*
|
|
569
|
+
* @param payload The payload of the request.
|
|
570
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
571
|
+
* Defaults to `true`.
|
|
572
|
+
*/
|
|
573
|
+
updateCrossSectioning(payload, withResponse = true) {
|
|
574
|
+
var _a, _b;
|
|
575
|
+
// If a section plane is provided, verify it is valid
|
|
576
|
+
const invalidSectionPlane = (_b = (_a = payload.crossSectioning) === null || _a === void 0 ? void 0 : _a.sectionPlanes) === null || _b === void 0 ? void 0 : _b.some((plane) => {
|
|
577
|
+
const validNormal = plane.normal != null && validateVector(plane.normal, true);
|
|
578
|
+
const validOffset = plane.offset != null && validateNumber(plane.offset);
|
|
579
|
+
return !validNormal || !validOffset;
|
|
580
|
+
});
|
|
581
|
+
if (invalidSectionPlane) {
|
|
582
|
+
console.warn('Invalid cross section plane provided. Canceling updateCrossSectioning operation.');
|
|
583
|
+
return Promise.resolve({});
|
|
584
|
+
}
|
|
585
|
+
return this.sendRequest({ updateCrossSectioning: payload }, withResponse);
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Sends a request to set or clear the model view of the frame.
|
|
589
|
+
*
|
|
590
|
+
* The payload accepts an optional `frameCorrelationId` that will be sent
|
|
591
|
+
* back on the frame that is associated to this request. Use `onRequest` to
|
|
592
|
+
* add a callback that'll be invoked when the server sends a request to draw
|
|
593
|
+
* the frame.
|
|
594
|
+
*
|
|
595
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
596
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
597
|
+
* it'll complete when a response is received.
|
|
598
|
+
*
|
|
599
|
+
* @param payload The payload of the request.
|
|
600
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
601
|
+
* Defaults to `true`.
|
|
602
|
+
*/
|
|
603
|
+
updateModelView(payload, withResponse = true) {
|
|
604
|
+
return this.sendRequest({ updateModelView: payload }, withResponse);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Sends a request to perform hit detection.
|
|
608
|
+
*
|
|
609
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
610
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
611
|
+
* it'll complete when a response is received.
|
|
612
|
+
*
|
|
613
|
+
* @param payload The payload of the request.
|
|
614
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
615
|
+
* Defaults to `true`.
|
|
616
|
+
*/
|
|
617
|
+
hitItems(payload, withResponse = true) {
|
|
618
|
+
// If a point is provided, verify it is valid
|
|
619
|
+
if (payload.point != null) {
|
|
620
|
+
const validPoint = validatePoint(payload.point);
|
|
621
|
+
if (!validPoint) {
|
|
622
|
+
console.warn('Invalid point provided. Canceling hitItems operation.');
|
|
623
|
+
return Promise.resolve({});
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
return this.sendRequest({ hitItems: payload }, withResponse);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Sends a request to perform an alteration to a scene. Alterations include
|
|
630
|
+
* changing item visibility and changing the materials of items.
|
|
631
|
+
*
|
|
632
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
633
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
634
|
+
* it'll complete when a response is received.
|
|
635
|
+
*
|
|
636
|
+
* @param payload The payload of the request.
|
|
637
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
638
|
+
* Defaults to `true`.
|
|
639
|
+
*/
|
|
640
|
+
createSceneAlteration(payload, withResponse = true) {
|
|
641
|
+
return this.sendRequest({ createSceneAlteration: payload }, withResponse);
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Sends a request to reset all overrides for a given scene and optionally to
|
|
645
|
+
* reset the camera to that of the base scene.
|
|
646
|
+
*
|
|
647
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
648
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
649
|
+
* it'll complete when a response is received.
|
|
650
|
+
*
|
|
651
|
+
* @param payload The payload of the request.
|
|
652
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
653
|
+
* Defaults to `true`.
|
|
654
|
+
*/
|
|
655
|
+
resetSceneView(payload, withResponse = true) {
|
|
656
|
+
return this.sendRequest({ resetView: payload }, withResponse);
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Sends a request to tell the rendering pipeline that an interaction has
|
|
660
|
+
* ended.
|
|
661
|
+
*
|
|
662
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
663
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
664
|
+
* it'll complete when a response is received.
|
|
665
|
+
*
|
|
666
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
667
|
+
* Defaults to `true`.
|
|
668
|
+
*/
|
|
669
|
+
endInteraction(payload = {}, withResponse = true) {
|
|
670
|
+
return this.sendRequest({ endInteraction: payload }, withResponse);
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Sends a request to sync the clocks between the client and server.
|
|
674
|
+
*
|
|
675
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
676
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
677
|
+
* it'll complete when a response is received.
|
|
678
|
+
*
|
|
679
|
+
* @param payload The request payload.
|
|
680
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
681
|
+
* Defaults to `true`.
|
|
682
|
+
*/
|
|
683
|
+
syncTime(payload, withResponse = true) {
|
|
684
|
+
return this.sendRequest({ syncTime: payload }, withResponse);
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Sends a request to record performance timings that were measured in the
|
|
688
|
+
* client. The server may use these timings as hints to optimize the rendering
|
|
689
|
+
* performance to provide a better experience.
|
|
690
|
+
*
|
|
691
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
692
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
693
|
+
* it'll complete when a response is received.
|
|
694
|
+
*
|
|
695
|
+
* @param payload The request payload
|
|
696
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
697
|
+
* Defaults to `true`.
|
|
698
|
+
*/
|
|
699
|
+
recordPerformance(payload, withResponse = true) {
|
|
700
|
+
return this.sendRequest({ recordPerformance: payload }, withResponse);
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Sends a request to update the current scene view with the state present
|
|
704
|
+
* in the specified scene view state.
|
|
705
|
+
*
|
|
706
|
+
* Use `withResponse` to indicate if the server should reply with a response.
|
|
707
|
+
* If `false`, the returned promise will complete immediately. Otherwise,
|
|
708
|
+
* it'll complete when a response is received.
|
|
709
|
+
*
|
|
710
|
+
* @param payload
|
|
711
|
+
* @param withResponse
|
|
712
|
+
*/
|
|
713
|
+
loadSceneViewState(payload, withResponse = true) {
|
|
714
|
+
return this.sendRequest({ loadSceneViewState: payload }, withResponse);
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Sends a request to get a stencil buffer image for the current scene view.
|
|
718
|
+
*/
|
|
719
|
+
getStencilBuffer(payload, withResponse = true) {
|
|
720
|
+
return this.sendRequest({ getStencilBuffer: payload }, withResponse);
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Sends a request to retrieve a new token. This token can be used to
|
|
724
|
+
* authenticate with other Vertex services.
|
|
725
|
+
*
|
|
726
|
+
* @param withResponse Indicates if the server should reply with a response.
|
|
727
|
+
* @returns A promise that completes with the refreshed token.
|
|
728
|
+
*/
|
|
729
|
+
refreshToken(withResponse = true) {
|
|
730
|
+
return this.sendRequest({ refreshToken: {} }, withResponse);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Acknowledges a successful request by sending a reply back to the server
|
|
734
|
+
* with an optional result body.
|
|
735
|
+
*
|
|
736
|
+
* @param reqId The ID of the received request.
|
|
737
|
+
* @param result A result to reply with.
|
|
738
|
+
*/
|
|
739
|
+
replyResult(reqId, result) {
|
|
740
|
+
this.sendResponse({ requestId: { value: reqId }, ...result });
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Acknowledges a failed request by sending a reply back to the server.
|
|
744
|
+
*
|
|
745
|
+
* @param reqId The ID of the received request.
|
|
746
|
+
* @param error An error to reply with.
|
|
747
|
+
*/
|
|
748
|
+
replyError(reqId, error) {
|
|
749
|
+
this.sendResponse({ requestId: { value: reqId }, error });
|
|
750
|
+
}
|
|
751
|
+
handleMessage(message) {
|
|
752
|
+
const msg = decode(message.data);
|
|
753
|
+
this.log('WS message received', msg);
|
|
754
|
+
if ((msg === null || msg === void 0 ? void 0 : msg.sentAtTime) != null) {
|
|
755
|
+
if (msg.response != null) {
|
|
756
|
+
this.onResponseDispatcher.emit({
|
|
757
|
+
sentAtTime: msg.sentAtTime,
|
|
758
|
+
response: msg.response,
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
if (msg.request != null) {
|
|
762
|
+
this.onRequestDispatcher.emit({
|
|
763
|
+
sentAtTime: msg.sentAtTime,
|
|
764
|
+
request: msg.request,
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
if (msg.event != null) {
|
|
768
|
+
this.onEventDispatcher.emit({
|
|
769
|
+
sentAtTime: msg.sentAtTime,
|
|
770
|
+
event: msg.event,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
onResponse(handler) {
|
|
776
|
+
return this.onResponseDispatcher.on(handler);
|
|
777
|
+
}
|
|
778
|
+
log(msg, ...other) {
|
|
779
|
+
if (this.opts.loggingEnabled) {
|
|
780
|
+
console.debug(msg, ...other);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
sendRequest(req, withResponse) {
|
|
784
|
+
const sentAtTime = currentDateAsProtoTimestamp();
|
|
785
|
+
if (withResponse) {
|
|
786
|
+
const requestId = utils.UUID.create();
|
|
787
|
+
const request = { ...req, requestId: { value: requestId } };
|
|
788
|
+
return new Promise((resolve, reject) => {
|
|
789
|
+
const subscription = this.onResponse((msg) => {
|
|
790
|
+
var _a;
|
|
791
|
+
if (requestId === ((_a = msg.response.requestId) === null || _a === void 0 ? void 0 : _a.value)) {
|
|
792
|
+
if (msg.response.error == null) {
|
|
793
|
+
resolve(msg.response);
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
const { message: summary, details } = msg.response.error;
|
|
797
|
+
reject(new StreamRequestError(requestId, req, summary === null || summary === void 0 ? void 0 : summary.value, details === null || details === void 0 ? void 0 : details.value));
|
|
798
|
+
}
|
|
799
|
+
subscription.dispose();
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
this.sendMessage({ sentAtTime, request });
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
this.sendMessage({ sentAtTime, request: req });
|
|
806
|
+
return Promise.resolve({});
|
|
807
|
+
}
|
|
808
|
+
sendMessage(msg) {
|
|
809
|
+
this.websocket.send(encode(msg));
|
|
810
|
+
this.log('WS message sent', msg);
|
|
811
|
+
}
|
|
812
|
+
sendResponse(response) {
|
|
813
|
+
const sentAtTime = currentDateAsProtoTimestamp();
|
|
814
|
+
this.websocket.send(encode({ sentAtTime, response }));
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function event(req, meta) {
|
|
819
|
+
return {
|
|
820
|
+
sentAtTime: currentDateAsProtoTimestamp(),
|
|
821
|
+
event: {
|
|
822
|
+
...req,
|
|
823
|
+
},
|
|
824
|
+
...meta,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
function animationCompleted(id) {
|
|
828
|
+
const def = {
|
|
829
|
+
animationId: { hex: id },
|
|
830
|
+
};
|
|
831
|
+
return event({
|
|
832
|
+
animationCompleted: {
|
|
833
|
+
...def,
|
|
834
|
+
},
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
var events = /*#__PURE__*/Object.freeze({
|
|
839
|
+
__proto__: null,
|
|
840
|
+
animationCompleted: animationCompleted
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
function request(req, meta) {
|
|
844
|
+
return {
|
|
845
|
+
sentAtTime: currentDateAsProtoTimestamp(),
|
|
846
|
+
...meta,
|
|
847
|
+
request: {
|
|
848
|
+
requestId: req.requestId != null ? { value: req.requestId } : undefined,
|
|
849
|
+
...req.payload,
|
|
850
|
+
},
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function drawFrame(req = {}, meta) {
|
|
854
|
+
const def = {
|
|
855
|
+
sequenceNumber: 1,
|
|
856
|
+
sceneAttributes: {
|
|
857
|
+
camera: {
|
|
858
|
+
position: { x: 0, y: 0, z: 1 },
|
|
859
|
+
lookAt: { x: 0, y: 0, z: 0 },
|
|
860
|
+
up: { x: 0, y: 1, z: 0 },
|
|
861
|
+
},
|
|
862
|
+
visibleBoundingBox: {
|
|
863
|
+
xmin: -1,
|
|
864
|
+
ymin: -1,
|
|
865
|
+
zmin: -1,
|
|
866
|
+
xmax: 1,
|
|
867
|
+
ymax: 1,
|
|
868
|
+
zmax: 1,
|
|
869
|
+
},
|
|
870
|
+
crossSectioning: {
|
|
871
|
+
sectionPlanes: [],
|
|
872
|
+
},
|
|
873
|
+
displayListSummary: {
|
|
874
|
+
visibleSummary: {
|
|
875
|
+
count: 100,
|
|
876
|
+
},
|
|
877
|
+
selectedVisibleSummary: {
|
|
878
|
+
count: 0,
|
|
879
|
+
},
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
imageAttributes: {
|
|
883
|
+
frameDimensions: { width: 200, height: 150 },
|
|
884
|
+
imageRect: { x: 0, y: 0, width: 200, height: 150 },
|
|
885
|
+
scaleFactor: 1,
|
|
886
|
+
},
|
|
887
|
+
frameCorrelationIds: ['123'],
|
|
888
|
+
image: new Uint8Array(),
|
|
889
|
+
};
|
|
890
|
+
return request({
|
|
891
|
+
requestId: req.requestId,
|
|
892
|
+
payload: { drawFrame: utils.Objects.defaults(req.payload, def) },
|
|
893
|
+
}, meta);
|
|
894
|
+
}
|
|
895
|
+
function gracefulReconnect(req = {}, meta) {
|
|
896
|
+
const def = {
|
|
897
|
+
streamId: { hex: utils.UUID.create() },
|
|
898
|
+
timeToReconnectDuration: { seconds: 1, nanos: 0 },
|
|
899
|
+
};
|
|
900
|
+
return request({
|
|
901
|
+
requestId: req.requestId,
|
|
902
|
+
payload: { gracefulReconnection: utils.Objects.defaults(req.payload, def) },
|
|
903
|
+
}, meta);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
var requests = /*#__PURE__*/Object.freeze({
|
|
907
|
+
__proto__: null,
|
|
908
|
+
drawFrame: drawFrame,
|
|
909
|
+
gracefulReconnect: gracefulReconnect
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
function response(res, meta) {
|
|
913
|
+
return {
|
|
914
|
+
sentAtTime: currentDateAsProtoTimestamp(),
|
|
915
|
+
...meta,
|
|
916
|
+
response: {
|
|
917
|
+
requestId: res.requestId != null ? { value: res.requestId } : undefined,
|
|
918
|
+
...res.result,
|
|
919
|
+
},
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
function startStream(res = {}, meta) {
|
|
923
|
+
const def = {
|
|
924
|
+
streamId: { hex: utils.UUID.create() },
|
|
925
|
+
sceneId: { hex: utils.UUID.create() },
|
|
926
|
+
sceneViewId: { hex: utils.UUID.create() },
|
|
927
|
+
sessionId: { hex: utils.UUID.create() },
|
|
928
|
+
jwt: 'jwt',
|
|
929
|
+
token: { token: 'token', expiresIn: new Date().getTime() + 10000 },
|
|
930
|
+
worldOrientation: {
|
|
931
|
+
front: { x: 0, y: 0, z: 1 },
|
|
932
|
+
up: { x: 0, y: 1, z: 0 },
|
|
933
|
+
},
|
|
934
|
+
};
|
|
935
|
+
return response({
|
|
936
|
+
requestId: res.requestId,
|
|
937
|
+
result: { startStream: utils.Objects.defaults(res.result, def) },
|
|
938
|
+
}, meta);
|
|
939
|
+
}
|
|
940
|
+
function syncTime(res = {}, meta) {
|
|
941
|
+
const def = { replyTime: { seconds: 1, nanos: 0 } };
|
|
942
|
+
return response({
|
|
943
|
+
requestId: res.requestId,
|
|
944
|
+
result: { syncTime: utils.Objects.defaults(res.result, def) },
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
function reconnect(res = {}, meta) {
|
|
948
|
+
const def = {
|
|
949
|
+
jwt: 'jwt',
|
|
950
|
+
token: { token: 'token', expiresIn: new Date().getTime() + 10000 },
|
|
951
|
+
};
|
|
952
|
+
return response({
|
|
953
|
+
requestId: res.requestId,
|
|
954
|
+
result: { reconnect: utils.Objects.defaults(res.result, def) },
|
|
955
|
+
}, meta);
|
|
956
|
+
}
|
|
957
|
+
function loadSceneViewState(res = {}, meta) {
|
|
958
|
+
const def = {};
|
|
959
|
+
return response({
|
|
960
|
+
requestId: res.requestId,
|
|
961
|
+
result: { loadSceneViewState: utils.Objects.defaults(res.result, def) },
|
|
962
|
+
}, meta);
|
|
963
|
+
}
|
|
964
|
+
function refreshToken(res = {}, meta) {
|
|
965
|
+
const def = {
|
|
966
|
+
token: { token: 'token', expiresIn: new Date().getTime() + 10000 },
|
|
967
|
+
};
|
|
968
|
+
return response({
|
|
969
|
+
requestId: res.requestId,
|
|
970
|
+
result: { refreshToken: utils.Objects.defaults(res.result, def) },
|
|
971
|
+
}, meta);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
var responses = /*#__PURE__*/Object.freeze({
|
|
975
|
+
__proto__: null,
|
|
976
|
+
startStream: startStream,
|
|
977
|
+
syncTime: syncTime,
|
|
978
|
+
reconnect: reconnect,
|
|
979
|
+
loadSceneViewState: loadSceneViewState,
|
|
980
|
+
refreshToken: refreshToken
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
984
|
+
__proto__: null,
|
|
985
|
+
Events: events,
|
|
986
|
+
Requests: requests,
|
|
987
|
+
Responses: responses
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
class WebSocketClientMock {
|
|
991
|
+
constructor() {
|
|
992
|
+
this.closeHandlers = new Set();
|
|
993
|
+
this.msgHandlers = new Set();
|
|
994
|
+
this.sentMessages = new Array();
|
|
995
|
+
}
|
|
996
|
+
close() {
|
|
997
|
+
this.closeHandlers.forEach((handler) => handler(new CloseEvent('close')));
|
|
998
|
+
}
|
|
999
|
+
connect(descriptor) {
|
|
1000
|
+
return Promise.resolve();
|
|
1001
|
+
}
|
|
1002
|
+
onClose(handler) {
|
|
1003
|
+
this.closeHandlers.add(handler);
|
|
1004
|
+
return { dispose: () => this.closeHandlers.delete(handler) };
|
|
1005
|
+
}
|
|
1006
|
+
onMessage(handler) {
|
|
1007
|
+
this.msgHandlers.add(handler);
|
|
1008
|
+
return { dispose: () => this.msgHandlers.delete(handler) };
|
|
1009
|
+
}
|
|
1010
|
+
send(data) {
|
|
1011
|
+
this.sentMessages.push(data);
|
|
1012
|
+
}
|
|
1013
|
+
reconnect(descriptor) {
|
|
1014
|
+
return Promise.resolve();
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Simulates a websocket message that was sent by the server and received by
|
|
1018
|
+
* the client.
|
|
1019
|
+
*
|
|
1020
|
+
* @param data The websocket message data.
|
|
1021
|
+
*/
|
|
1022
|
+
receiveMessage(data) {
|
|
1023
|
+
this.msgHandlers.forEach((handler) => handler(new MessageEvent('message', { data })));
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Resets the internal state of the mock by clearing any accrued sent messages
|
|
1027
|
+
* and removing all handlers.
|
|
1028
|
+
*/
|
|
1029
|
+
reset() {
|
|
1030
|
+
this.sentMessages = [];
|
|
1031
|
+
this.msgHandlers.clear();
|
|
1032
|
+
this.closeHandlers.clear();
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Returns `true` if there are remaining sent messages..
|
|
1036
|
+
*/
|
|
1037
|
+
hasNextSent() {
|
|
1038
|
+
return this.sentMessages.length > 0;
|
|
1039
|
+
}
|
|
1040
|
+
nextSent(decoder) {
|
|
1041
|
+
const next = this.sentMessages.shift();
|
|
1042
|
+
if (next != null) {
|
|
1043
|
+
if (decoder != null) {
|
|
1044
|
+
return decoder(next);
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
return next;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
else {
|
|
1051
|
+
throw new Error('Sent messages is empty');
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Skips the next N sent messages.
|
|
1056
|
+
*
|
|
1057
|
+
* @example
|
|
1058
|
+
* ```
|
|
1059
|
+
* const ws = new WebSocketClientMock();
|
|
1060
|
+
* ws.send("1");
|
|
1061
|
+
* ws.send("2");
|
|
1062
|
+
* ws.send("3");
|
|
1063
|
+
*
|
|
1064
|
+
* ws.skipSent(2);
|
|
1065
|
+
* ws.nextSent(); // "3"
|
|
1066
|
+
* ```
|
|
1067
|
+
*
|
|
1068
|
+
* @param n The number of sent messages to skip over.
|
|
1069
|
+
*/
|
|
1070
|
+
skipSent(n = 1) {
|
|
1071
|
+
if (n <= this.sentMessages.length) {
|
|
1072
|
+
for (let i = 0; i < n; i++) {
|
|
1073
|
+
this.nextSent();
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
throw new Error(`Cannot skip the next ${n} messages. Sent message queue only has ${this.sentMessages.length} messages.`);
|
|
1078
|
+
}
|
|
1079
|
+
return this;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
exports.Fixtures = index;
|
|
1084
|
+
exports.StreamApi = StreamApi;
|
|
1085
|
+
exports.StreamRequestError = StreamRequestError;
|
|
1086
|
+
exports.WebSocketClientImpl = WebSocketClientImpl;
|
|
1087
|
+
exports.WebSocketClientMock = WebSocketClientMock;
|
|
1088
|
+
exports.appendSettingsToUrl = appendSettingsToUrl;
|
|
1089
|
+
exports.currentDateAsProtoTimestamp = currentDateAsProtoTimestamp;
|
|
1090
|
+
exports.decode = decode;
|
|
1091
|
+
exports.encode = encode;
|
|
1092
|
+
exports.protoToDate = protoToDate;
|
|
1093
|
+
exports.toProtoDuration = toProtoDuration;
|
|
1094
|
+
exports.toProtoTimestamp = toProtoTimestamp;
|
|
1095
|
+
//# sourceMappingURL=bundle.cjs.map
|