@vuu-ui/vuu-data-remote 4.0.0-alpha.8 → 4.0.0-beta.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.
Files changed (39) hide show
  1. package/package.json +12 -12
  2. package/src/ConnectionManager.js +65 -158
  3. package/src/DedicatedWorker.js +1 -4
  4. package/src/LostConnectionHandler.js +89 -0
  5. package/src/VuuAuthProvider.js +78 -0
  6. package/src/VuuAuthenticator.js +36 -0
  7. package/src/VuuDataSource.js +7 -10
  8. package/src/WebSocketConnection.js +1 -8
  9. package/src/authenticate.js +50 -0
  10. package/src/index.js +4 -0
  11. package/src/inlined-worker.js +1 -2805
  12. package/src/server-proxy/array-backed-moving-window.js +12 -17
  13. package/src/server-proxy/server-proxy.js +4 -7
  14. package/src/worker.js +2 -3
  15. package/types/ConnectionManager.d.ts +17 -45
  16. package/types/DedicatedWorker.d.ts +3 -10
  17. package/types/VuuDataSource.d.ts +1 -1
  18. package/types/WebSocketConnection.d.ts +3 -3
  19. package/types/index.d.ts +4 -0
  20. package/types/inlined-worker.d.ts +1 -1
  21. package/types/server-proxy/server-proxy.d.ts +2 -4
  22. package/types/src/ConnectionManager.d.ts +0 -36
  23. package/types/src/DedicatedWorker.d.ts +0 -9
  24. package/types/src/LostConnectionHandler.d.ts +0 -28
  25. package/types/src/VuuAuthProvider.d.ts +0 -39
  26. package/types/src/VuuAuthenticator.d.ts +0 -21
  27. package/types/src/VuuDataSource.d.ts +0 -74
  28. package/types/src/WebSocketConnection.d.ts +0 -54
  29. package/types/src/authenticate.d.ts +0 -15
  30. package/types/src/constants.d.ts +0 -41
  31. package/types/src/data-source.d.ts +0 -6
  32. package/types/src/index.d.ts +0 -11
  33. package/types/src/inlined-worker.d.ts +0 -1
  34. package/types/src/message-utils.d.ts +0 -20
  35. package/types/src/server-proxy/array-backed-moving-window.d.ts +0 -27
  36. package/types/src/server-proxy/messages.d.ts +0 -33
  37. package/types/src/server-proxy/server-proxy.d.ts +0 -68
  38. package/types/src/server-proxy/viewport.d.ts +0 -132
  39. package/types/src/worker.d.ts +0 -1
package/package.json CHANGED
@@ -1,26 +1,24 @@
1
1
  {
2
- "version": "4.0.0-alpha.8",
2
+ "version": "4.0.0-beta.1",
3
3
  "main": "./src/index.js",
4
4
  "author": "heswell",
5
5
  "license": "Apache-2.0",
6
- "type": "module",
7
6
  "scripts": {
8
- "build": "node ../../scripts/run-build-worker.mjs && node ../../scripts/run-build-rslib.ts",
9
- "build:dev": "node ../../scripts/run-build-worker.mjs && node ../../scripts/run-build.mjs -- --dev",
10
- "build:worker": "node ../../scripts/run-build-worker.mjs",
7
+ "build": "node ../../scripts/build-worker.ts && node ../../scripts/run-build-rslib.ts",
8
+ "build:dev": "node ../../scripts/build-worker.ts && node ../../scripts/run-build.mjs -- --dev",
9
+ "build:worker": "node ../../scripts/build-worker.ts",
11
10
  "test": "vitest run",
12
11
  "type-defs": "node ../../scripts/build-type-defs.mjs"
13
12
  },
14
13
  "devDependencies": {
15
- "@vuu-ui/vuu-data-types": "4.0.0-alpha.8",
16
- "@vuu-ui/vuu-table-types": "4.0.0-alpha.8",
17
- "@vuu-ui/vuu-filter-types": "4.0.0-alpha.8",
18
- "@vuu-ui/vuu-protocol-types": "4.0.0-alpha.8"
14
+ "@vuu-ui/vuu-data-types": "4.0.0-beta.1",
15
+ "@vuu-ui/vuu-table-types": "4.0.0-beta.1",
16
+ "@vuu-ui/vuu-filter-types": "4.0.0-beta.1",
17
+ "@vuu-ui/vuu-protocol-types": "4.0.0-beta.1"
19
18
  },
20
19
  "dependencies": {
21
- "@vuu-ui/vuu-data-editing": "4.0.0-alpha.8",
22
- "@vuu-ui/vuu-filter-parser": "4.0.0-alpha.8",
23
- "@vuu-ui/vuu-utils": "4.0.0-alpha.8"
20
+ "@vuu-ui/vuu-filter-parser": "4.0.0-beta.1",
21
+ "@vuu-ui/vuu-utils": "4.0.0-beta.1"
24
22
  },
25
23
  "files": [
26
24
  "README.md",
@@ -30,10 +28,12 @@
30
28
  "exports": {
31
29
  ".": {
32
30
  "import": "./src/index.js",
31
+ "default": "./src/index.js",
33
32
  "types": "./types/index.d.ts"
34
33
  }
35
34
  },
36
35
  "module": "./src/index.js",
37
36
  "name": "@vuu-ui/vuu-data-remote",
37
+ "type": "module",
38
38
  "types": "types/index.d.ts"
39
39
  }
@@ -2,55 +2,20 @@ import { DeferredPromise, EventEmitter, isConnectionQualityMetrics, isRequestRes
2
2
  import { isWebSocketConnectionStatus } from "./WebSocketConnection.js";
3
3
  import { DedicatedWorker } from "./DedicatedWorker.js";
4
4
  import { shouldMessageBeRoutedToDataSource } from "./data-source.js";
5
- const DEFAULT_CONNECTION_ID = "portal";
6
- class ConnectionChannel {
7
- onConnectionStatus;
8
- onConnectionMetrics;
5
+ class ConnectionManager extends EventEmitter {
6
+ static #instance;
9
7
  #connectionStatus = "closed";
10
8
  #deferredServerAPI = new DeferredPromise();
11
9
  #pendingRequests = new Map();
12
10
  #viewports = new Map();
13
11
  #worker;
14
- #serverAPI;
15
- constructor(onConnectionStatus, onConnectionMetrics){
16
- this.onConnectionStatus = onConnectionStatus;
17
- this.onConnectionMetrics = onConnectionMetrics;
12
+ constructor(){
13
+ super();
18
14
  this.#worker = new DedicatedWorker(this.handleMessageFromWorker);
19
- this.#serverAPI = {
20
- subscribe: (message, callback)=>{
21
- if (this.#viewports.get(message.viewport)) throw Error("ConnectionManager attempting to subscribe with an existing viewport id");
22
- this.#viewports.set(message.viewport, {
23
- status: "subscribing",
24
- request: message,
25
- postMessageToClientDataSource: callback
26
- });
27
- this.#worker.send({
28
- type: "subscribe",
29
- ...message
30
- });
31
- },
32
- unsubscribe: (viewport)=>{
33
- this.#worker.send({
34
- type: "unsubscribe",
35
- viewport
36
- });
37
- },
38
- send: (message)=>{
39
- this.#worker.send(message);
40
- },
41
- destroy: (viewportId)=>{
42
- if (viewportId && this.#viewports.has(viewportId)) this.#viewports.delete(viewportId);
43
- },
44
- rpcCall: async (message)=>this.asyncRequest(message),
45
- select: async (selectRequest)=>this.asyncRequest(selectRequest),
46
- getTableList: async ()=>this.asyncRequest({
47
- type: "GET_TABLE_LIST"
48
- }),
49
- getTableSchema: async (table)=>this.asyncRequest({
50
- type: "GET_TABLE_META",
51
- table
52
- })
53
- };
15
+ }
16
+ static get instance() {
17
+ if (!ConnectionManager.#instance) ConnectionManager.#instance = new ConnectionManager();
18
+ return ConnectionManager.#instance;
54
19
  }
55
20
  get connectionStatus() {
56
21
  return this.#connectionStatus;
@@ -58,45 +23,28 @@ class ConnectionChannel {
58
23
  get connected() {
59
24
  return "connected" === this.#connectionStatus || "reconnected" === this.#connectionStatus;
60
25
  }
61
- get serverAPI() {
62
- return this.#deferredServerAPI.promise;
63
- }
64
26
  async connect(options, throwOnRejected = false) {
65
27
  try {
66
28
  const result = await this.#worker.connect(options);
67
- if ("connected" === result.status || "reconnected" === result.status) this.#deferredServerAPI.resolve(this.#serverAPI);
29
+ if ("connected" === result) this.#deferredServerAPI.resolve(this.connectedServerAPI);
68
30
  return result;
69
31
  } catch (err) {
70
- if (throwOnRejected) throw err;
71
- return {
72
- status: "rejected"
73
- };
32
+ if (!throwOnRejected) return "connection-failed";
33
+ throw err;
74
34
  }
75
35
  }
76
36
  disableActiveSubscriptions() {
37
+ console.log("[ConnectionManager] disableActiveSubscriptions");
77
38
  this.#worker.send({
78
39
  type: "disable-all-active"
79
40
  });
80
41
  }
81
42
  enableActiveSubscriptions() {
43
+ console.log("[ConnectionManager] enableActiveSubscriptions");
82
44
  this.#worker.send({
83
45
  type: "enable-all-active"
84
46
  });
85
47
  }
86
- async disconnect() {
87
- try {
88
- this.#worker.send({
89
- type: "disconnect"
90
- });
91
- this.#deferredServerAPI = new DeferredPromise();
92
- return "disconnected";
93
- } catch {
94
- return "rejected";
95
- }
96
- }
97
- destroy() {
98
- this.#worker.terminate();
99
- }
100
48
  handleMessageFromWorker = (message)=>{
101
49
  if (shouldMessageBeRoutedToDataSource(message)) {
102
50
  const viewport = this.#viewports.get(message.clientViewportId);
@@ -104,8 +52,8 @@ class ConnectionChannel {
104
52
  else console.error(`[ConnectionManager] ${message.type} message received, viewport not found`);
105
53
  } else if (isWebSocketConnectionStatus(message)) {
106
54
  this.#connectionStatus = message;
107
- this.onConnectionStatus(message);
108
- } else if (isConnectionQualityMetrics(message)) this.onConnectionMetrics(message);
55
+ this.emit("connection-status", message);
56
+ } else if (isConnectionQualityMetrics(message)) this.emit("connection-metrics", message);
109
57
  else if (isRequestResponse(message)) {
110
58
  const { requestId } = message;
111
59
  if (this.#pendingRequests.has(requestId)) {
@@ -116,112 +64,71 @@ class ConnectionChannel {
116
64
  } else console.warn("%cConnectionManager Unexpected message from the worker", "color:red;font-weight:bold;");
117
65
  }
118
66
  };
67
+ get serverAPI() {
68
+ return this.#deferredServerAPI.promise;
69
+ }
70
+ connectedServerAPI = {
71
+ subscribe: (message, callback)=>{
72
+ if (this.#viewports.get(message.viewport)) throw Error("ConnectionManager attempting to subscribe with an existing viewport id");
73
+ this.#viewports.set(message.viewport, {
74
+ status: "subscribing",
75
+ request: message,
76
+ postMessageToClientDataSource: callback
77
+ });
78
+ this.#worker.send({
79
+ type: "subscribe",
80
+ ...message
81
+ });
82
+ },
83
+ unsubscribe: (viewport)=>{
84
+ this.#worker.send({
85
+ type: "unsubscribe",
86
+ viewport
87
+ });
88
+ },
89
+ send: (message)=>{
90
+ this.#worker.send(message);
91
+ },
92
+ destroy: (viewportId)=>{
93
+ if (viewportId && this.#viewports.has(viewportId)) this.#viewports.delete(viewportId);
94
+ },
95
+ rpcCall: async (message)=>this.asyncRequest(message),
96
+ select: async (selectRequest)=>this.asyncRequest(selectRequest),
97
+ getTableList: async ()=>this.asyncRequest({
98
+ type: "GET_TABLE_LIST"
99
+ }),
100
+ getTableSchema: async (table)=>this.asyncRequest({
101
+ type: "GET_TABLE_META",
102
+ table
103
+ })
104
+ };
119
105
  asyncRequest = (msg)=>{
120
106
  const requestId = uuid();
121
107
  this.#worker.send({
122
108
  requestId,
123
109
  ...msg
124
110
  });
125
- return new Promise((resolve)=>{
111
+ return new Promise((resolve, reject)=>{
126
112
  this.#pendingRequests.set(requestId, {
127
- resolve: (value)=>resolve(value)
113
+ resolve,
114
+ reject
128
115
  });
129
116
  });
130
117
  };
131
- }
132
- class ConnectionManager extends EventEmitter {
133
- static #instance;
134
- #connections = new Map();
135
- #connectionStatusListeners = new Map();
136
- constructor(){
137
- super();
138
- }
139
- static get instance() {
140
- if (!ConnectionManager.#instance) ConnectionManager.#instance = new ConnectionManager();
141
- return ConnectionManager.#instance;
142
- }
143
- getConnection(connectionId = DEFAULT_CONNECTION_ID) {
144
- const existing = this.#connections.get(connectionId);
145
- if (existing) return existing;
146
- const connection = new ConnectionChannel((status)=>{
147
- this.#connectionStatusListeners.get(connectionId)?.forEach((listener)=>listener(status));
148
- if (connectionId === DEFAULT_CONNECTION_ID) this.emit("connection-status", status);
149
- }, (metrics)=>{
150
- if (connectionId === DEFAULT_CONNECTION_ID) this.emit("connection-metrics", metrics);
151
- });
152
- this.#connections.set(connectionId, connection);
153
- return connection;
154
- }
155
- get connectionStatus() {
156
- return this.connectionStatusFor(DEFAULT_CONNECTION_ID);
157
- }
158
- get connected() {
159
- return this.connectedFor(DEFAULT_CONNECTION_ID);
160
- }
161
- connectionStatusFor(connectionId) {
162
- return this.getConnection(connectionId).connectionStatus;
163
- }
164
- connectedFor(connectionId) {
165
- return this.getConnection(connectionId).connected;
166
- }
167
- onConnectionStatus(connectionId, listener) {
168
- const listeners = this.#connectionStatusListeners.get(connectionId) ?? new Set();
169
- listeners.add(listener);
170
- this.#connectionStatusListeners.set(connectionId, listeners);
171
- return ()=>{
172
- listeners.delete(listener);
173
- if (0 === listeners.size) this.#connectionStatusListeners.delete(connectionId);
174
- };
175
- }
176
- async connect(options, throwOnRejected = false) {
177
- return this.connectTo(DEFAULT_CONNECTION_ID, options, throwOnRejected);
178
- }
179
- async connectTo(connectionId, options, throwOnRejected = false) {
180
- const result = await this.connectWithLoginResponseTo(connectionId, options, throwOnRejected);
181
- return "rejected" === result.status ? "connection-failed" : result.status;
182
- }
183
- async connectWithLoginResponseTo(connectionId, options, throwOnRejected = false) {
184
- return this.getConnection(connectionId).connect(options, throwOnRejected);
185
- }
186
- disableActiveSubscriptions() {
187
- for (const connection of this.#connections.values())connection.disableActiveSubscriptions();
188
- }
189
- enableActiveSubscriptions() {
190
- for (const connection of this.#connections.values())connection.enableActiveSubscriptions();
191
- }
192
- disableActiveSubscriptionsFor(connectionId) {
193
- this.getConnection(connectionId).disableActiveSubscriptions();
194
- }
195
- enableActiveSubscriptionsFor(connectionId) {
196
- this.getConnection(connectionId).enableActiveSubscriptions();
197
- }
198
- get serverAPI() {
199
- return this.serverAPIFor(DEFAULT_CONNECTION_ID);
200
- }
201
- serverAPIFor(connectionId) {
202
- return this.getConnection(connectionId).serverAPI;
203
- }
204
118
  async disconnect() {
205
- return this.disconnectFrom(DEFAULT_CONNECTION_ID);
206
- }
207
- async disconnectFrom(connectionId) {
208
- return this.getConnection(connectionId).disconnect();
209
- }
210
- async destroyConnection(connectionId) {
211
- const connection = this.#connections.get(connectionId);
212
- if (connection) {
213
- await connection.disconnect();
214
- connection.destroy();
215
- this.#connections.delete(connectionId);
119
+ try {
120
+ this.#worker.send({
121
+ type: "disconnect"
122
+ });
123
+ this.#deferredServerAPI = new DeferredPromise();
124
+ return "disconnected";
125
+ } catch (err) {
126
+ return "rejected";
216
127
  }
217
- this.#connectionStatusListeners.delete(connectionId);
218
128
  }
219
129
  destroy() {
220
- for (const connection of this.#connections.values())connection.destroy();
221
- this.#connections.clear();
222
- this.#connectionStatusListeners.clear();
130
+ this.#worker.terminate();
223
131
  }
224
132
  }
225
133
  var src_ConnectionManager = ConnectionManager.instance;
226
134
  export default src_ConnectionManager;
227
- export { DEFAULT_CONNECTION_ID };
@@ -21,10 +21,7 @@ class DedicatedWorker {
21
21
  if ("ready" === message.type) {
22
22
  window.clearTimeout(timer);
23
23
  deferredWorker.resolve(worker);
24
- } else if ("connected" === message.type) this.#deferredConnection?.resolve({
25
- loginResponse: message.loginResponse,
26
- status: "connected"
27
- });
24
+ } else if ("connected" === message.type) this.#deferredConnection?.resolve("connected");
28
25
  else if ("connection-failed" === message.type) this.#deferredConnection?.reject(message.reason);
29
26
  else onMessage(message);
30
27
  };
@@ -0,0 +1,89 @@
1
+ function _to_primitive(input, hint) {
2
+ if ("object" !== _type_of(input) || null === input) return input;
3
+ var prim = input[Symbol.toPrimitive];
4
+ if (void 0 !== prim) {
5
+ var res = prim.call(input, hint || "default");
6
+ if ("object" !== _type_of(res)) return res;
7
+ throw new TypeError("@@toPrimitive must return a primitive value.");
8
+ }
9
+ return ("string" === hint ? String : Number)(input);
10
+ }
11
+ function _to_property_key(arg) {
12
+ var key = _to_primitive(arg, "string");
13
+ return "symbol" === _type_of(key) ? key : String(key);
14
+ }
15
+ function _type_of(obj) {
16
+ return obj && "u" > typeof Symbol && obj.constructor === Symbol ? "symbol" : typeof obj;
17
+ }
18
+ let _computedKey;
19
+ class RetryOptionsImpl {
20
+ retryIntervals;
21
+ ind = 0;
22
+ constructor(retryIntervals){
23
+ this.retryIntervals = retryIntervals;
24
+ console.log("[RetryOptionsImpl] constructor");
25
+ }
26
+ next() {
27
+ this.ind = Math.min(this.retryIntervals.length, this.ind + 1);
28
+ }
29
+ get remaining() {
30
+ return this.retryIntervals.length - this.ind;
31
+ }
32
+ get interval() {
33
+ if (this.ind === this.retryIntervals.length) return -1;
34
+ return 1000 * this.retryIntervals[this.ind];
35
+ }
36
+ }
37
+ function RetryOptions(retryIntervals) {
38
+ if (Array.isArray(retryIntervals)) return new RetryOptionsImpl(retryIntervals);
39
+ throw Error("[lostConnectionHandler] RetryOptions, invalid retryIntervals");
40
+ }
41
+ const defaultRetryIntervals = [
42
+ 1,
43
+ 2,
44
+ 3,
45
+ 5,
46
+ 10,
47
+ 30,
48
+ 60,
49
+ 120
50
+ ];
51
+ _computedKey = _to_property_key(Symbol.asyncIterator);
52
+ class RetryGenerator {
53
+ vuuAuth;
54
+ options;
55
+ constructor(vuuAuth, options){
56
+ this.vuuAuth = vuuAuth;
57
+ this.options = options;
58
+ console.log("[RetryGenerator] constructor");
59
+ }
60
+ async *[_computedKey]() {
61
+ let connected = false;
62
+ do {
63
+ await new Promise((resolve)=>setTimeout(resolve, this.options.interval));
64
+ try {
65
+ await this.vuuAuth.login();
66
+ connected = true;
67
+ yield "connected";
68
+ } catch (err) {}
69
+ this.options.next();
70
+ }while (!connected && -1 !== this.options.interval)
71
+ if (!connected) yield "connection-failed";
72
+ }
73
+ }
74
+ class LostConnectionHandler {
75
+ vuuAuth;
76
+ retryIntervals;
77
+ constructor(vuuAuth, retryIntervals = defaultRetryIntervals){
78
+ this.vuuAuth = vuuAuth;
79
+ this.retryIntervals = retryIntervals;
80
+ }
81
+ async reconnect() {
82
+ for await (const result of new RetryGenerator(this.vuuAuth, RetryOptions(this.retryIntervals))){
83
+ console.log(` ... async iterator result = ${result}`);
84
+ if ("connected" === result) return result;
85
+ }
86
+ return "connection-failed";
87
+ }
88
+ }
89
+ export { LostConnectionHandler, RetryGenerator, RetryOptions };
@@ -0,0 +1,78 @@
1
+ import { getCookieValue } from "@vuu-ui/vuu-utils";
2
+ import { parseVuuUserFromToken } from "./authenticate.js";
3
+ class VuuAuthProvider {
4
+ authEndpoint;
5
+ constructor(authEndpoint){
6
+ this.authEndpoint = authEndpoint;
7
+ }
8
+ login = async (username, password)=>{
9
+ const date = new Date();
10
+ const days = 1;
11
+ date.setTime(date.getTime() + 24 * days * 3600000);
12
+ if (username && password) {
13
+ const { token } = await this.getVuuTokenWithUsernameAndPassword(username, password);
14
+ document.cookie = `vuu-auth-user=${username};expires=${date.toUTCString()};path=/`;
15
+ document.cookie = `vuu-auth-password=${password};expires=${date.toUTCString()};path=/`;
16
+ document.cookie = `vuu-auth-token=${token};expires=${date.toUTCString()};path=/`;
17
+ return this.redirectToApplication();
18
+ }
19
+ {
20
+ const userName = getCookieValue("vuu-auth-user");
21
+ const password = getCookieValue("vuu-auth-password");
22
+ if (!userName || !password) return this.redirectToLoginPage();
23
+ {
24
+ const { authorizations, token } = await this.getVuuTokenWithUsernameAndPassword(userName, password);
25
+ document.cookie = `vuu-auth-token=${token};expires=${date.toUTCString()};path=/`;
26
+ return {
27
+ authorizations,
28
+ user: {
29
+ userName
30
+ },
31
+ token
32
+ };
33
+ }
34
+ }
35
+ };
36
+ async getVuuTokenWithUsernameAndPassword(username, password) {
37
+ const response = await fetch(this.authEndpoint, {
38
+ method: "POST",
39
+ credentials: "include",
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ "access-control-allow-origin": location.host
43
+ },
44
+ body: JSON.stringify({
45
+ username,
46
+ password
47
+ })
48
+ });
49
+ if (response.ok) {
50
+ const vuuAuthToken = response.headers.get("vuu-auth-token");
51
+ if ("string" == typeof vuuAuthToken && vuuAuthToken.length > 0) {
52
+ const { authorizations } = parseVuuUserFromToken(vuuAuthToken);
53
+ return {
54
+ authorizations,
55
+ token: vuuAuthToken
56
+ };
57
+ }
58
+ throw Error("Authentication failed auth token not returned by server");
59
+ }
60
+ throw Error(`Authentication failed, ${response.status}`);
61
+ }
62
+ clear() {
63
+ document.cookie = "vuu-auth-user= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
64
+ document.cookie = "vuu-auth-password= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
65
+ document.cookie = "vuu-auth-token= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
66
+ }
67
+ redirectToLoginPage() {
68
+ window.location.href = "login.html";
69
+ }
70
+ redirectToApplication() {
71
+ window.location.href = "index.html";
72
+ }
73
+ logout() {
74
+ this.clear();
75
+ this.redirectToLoginPage();
76
+ }
77
+ }
78
+ export { VuuAuthProvider };
@@ -0,0 +1,36 @@
1
+ import ConnectionManager from "./ConnectionManager.js";
2
+ const VuuAuthTokenIssuePolicy = {
3
+ BearerToken: "bearer-token",
4
+ UsernamePassword: "username-password"
5
+ };
6
+ class VuuAuthenticator {
7
+ authProvider;
8
+ authTokenIssuePolicy;
9
+ websocketUrl;
10
+ constructor({ authProvider, authTokenIssuePolicy = VuuAuthTokenIssuePolicy.BearerToken, websocketUrl }){
11
+ this.authProvider = authProvider;
12
+ this.authTokenIssuePolicy = authTokenIssuePolicy;
13
+ this.websocketUrl = websocketUrl;
14
+ }
15
+ openWebsocketConnection = async (vuuToken)=>{
16
+ await ConnectionManager.connect({
17
+ url: this.websocketUrl,
18
+ token: vuuToken
19
+ }, true);
20
+ };
21
+ login = async ()=>{
22
+ const { authorizations, user, token, websocket = true } = await this.authProvider.login();
23
+ if (token && user) {
24
+ if (websocket) await this.openWebsocketConnection(token);
25
+ return [
26
+ user,
27
+ authorizations
28
+ ];
29
+ }
30
+ throw Error("[VuuAuthenticator] login failed");
31
+ };
32
+ logout = ()=>{
33
+ this.authProvider.logout();
34
+ };
35
+ }
36
+ export { VuuAuthTokenIssuePolicy, VuuAuthenticator };
@@ -16,7 +16,6 @@ class VuuDataSource extends BaseDataSource {
16
16
  bufferSize;
17
17
  server = null;
18
18
  rangeRequest;
19
- #connectionId;
20
19
  #allColumns;
21
20
  #autosubscribeColumns = [];
22
21
  #pendingVisualLink;
@@ -33,13 +32,12 @@ class VuuDataSource extends BaseDataSource {
33
32
  #tableSchema;
34
33
  isRemote = true;
35
34
  table;
36
- constructor({ session, connectionId = "portal", sessionTableMessageColumn, ...props }){
35
+ constructor({ session, sessionTableMessageColumn, ...props }){
37
36
  super(props);
38
37
  const { bufferSize = 100, table, visualLink } = props;
39
38
  if (!table) throw Error("RemoteDataSource constructor called without table");
40
39
  this.bufferSize = bufferSize;
41
40
  this.table = table;
42
- this.#connectionId = connectionId;
43
41
  this.#pendingVisualLink = visualLink;
44
42
  this.#session = session;
45
43
  this.#sessionTableMessageColumn = sessionTableMessageColumn;
@@ -51,15 +49,11 @@ class VuuDataSource extends BaseDataSource {
51
49
  }
52
50
  async subscribe(subscribeProps, callback) {
53
51
  super.subscribe(subscribeProps, callback);
54
- let viewport = subscribeProps.viewport ?? this.viewport;
55
- if (!viewport) {
56
- viewport = uuid();
57
- this.viewport = viewport;
58
- }
52
+ const { viewport = this.viewport || (this.viewport = uuid()) } = subscribeProps;
59
53
  if ("disabled" === this.#status || "disabling" === this.#status || "enabling" === this.#status) return void this.enable(callback);
60
54
  if ("initialising" !== this.#status && "unsubscribed" !== this.#status) throw Error(`[VuuDataSource] invalid status ${this.#status} for subscribe`);
61
55
  this.#status = "subscribing";
62
- this.server = await ConnectionManager.serverAPIFor(this.#connectionId);
56
+ this.server = await ConnectionManager.serverAPI;
63
57
  const { bufferSize } = this;
64
58
  const { columns, ...dataSourceConfig } = combineFilters(this.config);
65
59
  this.server?.subscribe({
@@ -440,7 +434,6 @@ class VuuDataSource extends BaseDataSource {
440
434
  assertExpectedSessionTable(sessionTable, effectiveOverrides?.table);
441
435
  const sessionDataSource = new VuuDataSource({
442
436
  ...sessionDataSourceConfig(this.config, effectiveOverrides?.columns),
443
- connectionId: this.#connectionId,
444
437
  table: sessionTable,
445
438
  viewport: sessionTable.table
446
439
  });
@@ -483,6 +476,10 @@ class VuuDataSource extends BaseDataSource {
483
476
  });
484
477
  }
485
478
  async endEditSession(saveChanges = false, force = false) {
479
+ if ("unsubscribed" === this.#status || !this.server || !this.viewport) {
480
+ if (!saveChanges) return;
481
+ throw Error("Cannot save changes: server or viewport are undefined");
482
+ }
486
483
  const type = "RPC_REQUEST";
487
484
  const rpcName = "endEditSession";
488
485
  const rpcResponse = await this.rpcRequest(saveChanges ? {
@@ -81,14 +81,7 @@ class WebSocketConnection extends EventEmitter {
81
81
  const timer = setTimeout(()=>{
82
82
  throw Error(`Failed to open WebSocket connection to ${url}, timed out after ${connectionTimeout}ms`);
83
83
  }, connectionTimeout);
84
- console.log(`create websocket ${url} ${protocols}`);
85
- try {
86
- this.#ws = new WebSocket(url, protocols);
87
- } catch (e) {
88
- console.error(e);
89
- return;
90
- }
91
- const ws = this.#ws;
84
+ const ws = this.#ws = new WebSocket(url, protocols);
92
85
  ws.onopen = ()=>{
93
86
  this.connectionStatus = "websocket-open";
94
87
  clearTimeout(timer);