@phystack/hub-client 4.4.29

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 (113) hide show
  1. package/.prettierignore +10 -0
  2. package/.prettierrc +10 -0
  3. package/CHANGELOG.md +1202 -0
  4. package/README-MEDIASTREAM.md +124 -0
  5. package/README.md +302 -0
  6. package/dist/constants/constants.d.ts +7 -0
  7. package/dist/constants/constants.d.ts.map +1 -0
  8. package/dist/constants/constants.js +10 -0
  9. package/dist/constants/constants.js.map +1 -0
  10. package/dist/helpers/browser.helper.d.ts +5 -0
  11. package/dist/helpers/browser.helper.d.ts.map +1 -0
  12. package/dist/helpers/browser.helper.js +19 -0
  13. package/dist/helpers/browser.helper.js.map +1 -0
  14. package/dist/helpers/cache.helper.d.ts +6 -0
  15. package/dist/helpers/cache.helper.d.ts.map +1 -0
  16. package/dist/helpers/cache.helper.js +46 -0
  17. package/dist/helpers/cache.helper.js.map +1 -0
  18. package/dist/helpers/date.helper.d.ts +4 -0
  19. package/dist/helpers/date.helper.d.ts.map +1 -0
  20. package/dist/helpers/date.helper.js +13 -0
  21. package/dist/helpers/date.helper.js.map +1 -0
  22. package/dist/helpers/session.helper.d.ts +13 -0
  23. package/dist/helpers/session.helper.d.ts.map +1 -0
  24. package/dist/helpers/session.helper.js +88 -0
  25. package/dist/helpers/session.helper.js.map +1 -0
  26. package/dist/helpers/shorten-look-ups.helper.d.ts +3 -0
  27. package/dist/helpers/shorten-look-ups.helper.d.ts.map +1 -0
  28. package/dist/helpers/shorten-look-ups.helper.js +80 -0
  29. package/dist/helpers/shorten-look-ups.helper.js.map +1 -0
  30. package/dist/helpers/signals-client.helper.d.ts +9 -0
  31. package/dist/helpers/signals-client.helper.d.ts.map +1 -0
  32. package/dist/helpers/signals-client.helper.js +44 -0
  33. package/dist/helpers/signals-client.helper.js.map +1 -0
  34. package/dist/helpers/signals.helper.d.ts +19 -0
  35. package/dist/helpers/signals.helper.d.ts.map +1 -0
  36. package/dist/helpers/signals.helper.js +48 -0
  37. package/dist/helpers/signals.helper.js.map +1 -0
  38. package/dist/helpers/wrtc/browser.d.ts +3 -0
  39. package/dist/helpers/wrtc/browser.d.ts.map +1 -0
  40. package/dist/helpers/wrtc/browser.js +11 -0
  41. package/dist/helpers/wrtc/browser.js.map +1 -0
  42. package/dist/helpers/wrtc/index.d.ts +5 -0
  43. package/dist/helpers/wrtc/index.d.ts.map +1 -0
  44. package/dist/helpers/wrtc/index.js +30 -0
  45. package/dist/helpers/wrtc/index.js.map +1 -0
  46. package/dist/helpers/wrtc/node.d.ts +3 -0
  47. package/dist/helpers/wrtc/node.d.ts.map +1 -0
  48. package/dist/helpers/wrtc/node.js +18 -0
  49. package/dist/helpers/wrtc/node.js.map +1 -0
  50. package/dist/index.d.ts +109 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +1013 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/services/online-status-subscription.service.d.ts +28 -0
  55. package/dist/services/online-status-subscription.service.d.ts.map +1 -0
  56. package/dist/services/online-status-subscription.service.js +96 -0
  57. package/dist/services/online-status-subscription.service.js.map +1 -0
  58. package/dist/services/phyhub-connection.service.d.ts +20 -0
  59. package/dist/services/phyhub-connection.service.d.ts.map +1 -0
  60. package/dist/services/phyhub-connection.service.js +176 -0
  61. package/dist/services/phyhub-connection.service.js.map +1 -0
  62. package/dist/services/signals.service.d.ts +97 -0
  63. package/dist/services/signals.service.d.ts.map +1 -0
  64. package/dist/services/signals.service.js +536 -0
  65. package/dist/services/signals.service.js.map +1 -0
  66. package/dist/services/webrtc/datachannel.d.ts +10 -0
  67. package/dist/services/webrtc/datachannel.d.ts.map +1 -0
  68. package/dist/services/webrtc/datachannel.js +290 -0
  69. package/dist/services/webrtc/datachannel.js.map +1 -0
  70. package/dist/services/webrtc/mediastream.d.ts +10 -0
  71. package/dist/services/webrtc/mediastream.d.ts.map +1 -0
  72. package/dist/services/webrtc/mediastream.js +396 -0
  73. package/dist/services/webrtc/mediastream.js.map +1 -0
  74. package/dist/services/webrtc/peer-connection-ice.d.ts +32 -0
  75. package/dist/services/webrtc/peer-connection-ice.d.ts.map +1 -0
  76. package/dist/services/webrtc/peer-connection-ice.js +483 -0
  77. package/dist/services/webrtc/peer-connection-ice.js.map +1 -0
  78. package/dist/types/signal.types.d.ts +354 -0
  79. package/dist/types/signal.types.d.ts.map +1 -0
  80. package/dist/types/signal.types.js +53 -0
  81. package/dist/types/signal.types.js.map +1 -0
  82. package/dist/types/twin.types.d.ts +705 -0
  83. package/dist/types/twin.types.d.ts.map +1 -0
  84. package/dist/types/twin.types.js +21 -0
  85. package/dist/types/twin.types.js.map +1 -0
  86. package/dist/types/webrtc.types.d.ts +41 -0
  87. package/dist/types/webrtc.types.d.ts.map +1 -0
  88. package/dist/types/webrtc.types.js +3 -0
  89. package/dist/types/webrtc.types.js.map +1 -0
  90. package/package.json +50 -0
  91. package/src/constants/constants.ts +12 -0
  92. package/src/helpers/browser.helper.ts +15 -0
  93. package/src/helpers/cache.helper.ts +52 -0
  94. package/src/helpers/date.helper.ts +8 -0
  95. package/src/helpers/session.helper.ts +96 -0
  96. package/src/helpers/shorten-look-ups.helper.ts +75 -0
  97. package/src/helpers/signals-client.helper.ts +54 -0
  98. package/src/helpers/signals.helper.ts +41 -0
  99. package/src/helpers/wrtc/browser.ts +9 -0
  100. package/src/helpers/wrtc/index.ts +32 -0
  101. package/src/helpers/wrtc/node.ts +16 -0
  102. package/src/index.ts +1429 -0
  103. package/src/services/online-status-subscription.service.ts +127 -0
  104. package/src/services/phyhub-connection.service.ts +213 -0
  105. package/src/services/signals.service.ts +783 -0
  106. package/src/services/webrtc/datachannel.ts +421 -0
  107. package/src/services/webrtc/mediastream.ts +602 -0
  108. package/src/services/webrtc/peer-connection-ice.ts +689 -0
  109. package/src/types/lodash.d.ts +3 -0
  110. package/src/types/signal.types.ts +382 -0
  111. package/src/types/twin.types.ts +803 -0
  112. package/src/types/webrtc.types.ts +48 -0
  113. package/tsconfig.json +45 -0
@@ -0,0 +1,127 @@
1
+ import axios from 'axios';
2
+ const url = 'https://screen.omborigrid.com/is-online.json';
3
+ const getUrl = () => `${url}?r=${Math.random()}`;
4
+
5
+ interface OnlineSubscriptionOptions {
6
+ checkIntervalMs: number;
7
+ checkIntervalMsWhenOfflineMs: number;
8
+ }
9
+
10
+ const defaultOptions = {
11
+ checkIntervalMs: 30 * 1000,
12
+ checkIntervalMsWhenOfflineMs: 10 * 1000,
13
+ };
14
+
15
+ type OnlineStatusSubscriptionListener = (props: GetOnlineStatusRequestResponse) => void;
16
+
17
+ type GetOnlineStatusRequestResponse = {
18
+ isOnline: boolean;
19
+ message?: string;
20
+ };
21
+
22
+ export const getOnlineStatusRequest = (timeoutMs: number) => {
23
+ return new Promise<GetOnlineStatusRequestResponse>((resolve, _reject) => {
24
+ const requestTimeout = setTimeout(
25
+ () =>
26
+ resolve({
27
+ isOnline: false,
28
+ message: 'manual promise timeout',
29
+ }),
30
+ timeoutMs
31
+ );
32
+
33
+ axios
34
+ .get(getUrl())
35
+ .then(response => {
36
+ resolve({
37
+ isOnline: response.data.isOnline,
38
+ message: 'ping success',
39
+ });
40
+ })
41
+ .catch(err =>
42
+ resolve({
43
+ isOnline: false,
44
+ message: `ping error, ${err.message}`,
45
+ })
46
+ )
47
+ .finally(() => clearTimeout(requestTimeout));
48
+ });
49
+ };
50
+
51
+ class OnlineStatusSubscription {
52
+ private onlineCheckTimeout: NodeJS.Timeout | undefined;
53
+ private readonly options: OnlineSubscriptionOptions;
54
+ private activatedAt: number | null = null;
55
+ private listeners: OnlineStatusSubscriptionListener[] = [];
56
+
57
+ public isOnline: boolean | null = null;
58
+
59
+ constructor(options?: Partial<OnlineSubscriptionOptions> | undefined) {
60
+ this.options = { ...defaultOptions, ...options };
61
+ }
62
+
63
+ private getPollingIntervalDuration = () => {
64
+ return this.isOnline ? this.options.checkIntervalMs : this.options.checkIntervalMsWhenOfflineMs;
65
+ };
66
+
67
+ private getOnlineStatus = () => {
68
+ const timeout = this.getPollingIntervalDuration() - 1;
69
+ return getOnlineStatusRequest(timeout);
70
+ };
71
+
72
+ private pollOnlineStatus = () => {
73
+ const startActivatedAt = this.activatedAt;
74
+ this.getOnlineStatus()
75
+ .then(({ isOnline, message }) => {
76
+ if (this.activatedAt && startActivatedAt === this.activatedAt) {
77
+ if (this.isOnline !== isOnline) {
78
+ this.isOnline = isOnline;
79
+ this.emit({ isOnline, message });
80
+ }
81
+ }
82
+ })
83
+ .catch(err => {
84
+ // this is not expected, there should be no error from the function
85
+ console.error(`Error getting online status: ${err}`);
86
+ })
87
+ .finally(() => {
88
+ if (this.activatedAt && startActivatedAt === this.activatedAt) {
89
+ this.onlineCheckTimeout = setTimeout(
90
+ this.pollOnlineStatus,
91
+ this.getPollingIntervalDuration()
92
+ );
93
+ }
94
+ });
95
+ };
96
+
97
+ public start = () => {
98
+ if (!this.activatedAt) {
99
+ this.activatedAt = Date.now();
100
+ this.pollOnlineStatus();
101
+ }
102
+ };
103
+
104
+ public stop = () => {
105
+ if (this.onlineCheckTimeout) {
106
+ clearTimeout(this.onlineCheckTimeout);
107
+ }
108
+ this.activatedAt = null;
109
+ };
110
+
111
+ private emit = (props: GetOnlineStatusRequestResponse) => {
112
+ for (const listener of this.listeners) {
113
+ listener(props);
114
+ }
115
+ };
116
+
117
+ public subscribe = (listener: OnlineStatusSubscriptionListener) => {
118
+ this.listeners = this.listeners.concat([listener]);
119
+ return () => this.unsubscribe(listener);
120
+ };
121
+
122
+ public unsubscribe = (listener: OnlineStatusSubscriptionListener) => {
123
+ this.listeners = this.listeners.filter(activeListener => activeListener !== listener);
124
+ };
125
+ }
126
+
127
+ export default OnlineStatusSubscription;
@@ -0,0 +1,213 @@
1
+ import { Socket } from 'socket.io-client';
2
+ import { get } from 'lodash';
3
+ import { isBrowser } from '../helpers/browser.helper';
4
+ import { getSocketIOWithProxy } from '@phystack/socket.io-proxy';
5
+ interface UrlConfig {
6
+ url: string;
7
+ timeout: number;
8
+ options: Record<string, any>;
9
+ }
10
+
11
+ export class PhyHubConnection {
12
+ private static instance: PhyHubConnection | null = null;
13
+ private phygridSocketSingleton: Socket | null = null;
14
+ private socketUrls: UrlConfig[] = [];
15
+ private instanceId: string | undefined;
16
+ private moduleName: string | undefined;
17
+
18
+ private constructor(
19
+ params: { instanceId?: string; moduleName?: string; dataResidency?: string } = {}
20
+ ) {
21
+ this.instanceId = params.instanceId;
22
+ this.moduleName = params.moduleName;
23
+ this.setSocketUrls(params.dataResidency);
24
+ this.fetchPhygridSocketInstance();
25
+ }
26
+
27
+ private getTopWindow(): Window & typeof globalThis {
28
+ let topWindow: Window & typeof globalThis = window;
29
+ while (topWindow.parent !== topWindow) {
30
+ try {
31
+ topWindow = topWindow.parent as Window & typeof globalThis;
32
+ } catch (e) {
33
+ break;
34
+ }
35
+ }
36
+ return topWindow;
37
+ }
38
+
39
+ private fetchPhygridSocketInstance = () => {
40
+ if (isBrowser) {
41
+ const topWindow = this.getTopWindow();
42
+ if ((topWindow as any).edgeHub) {
43
+ this.phygridSocketSingleton = (topWindow as any).edgeHub;
44
+ } else if ((topWindow as any).phygridSocketSingleton) {
45
+ this.phygridSocketSingleton = (topWindow as any).phygridSocketSingleton;
46
+ }
47
+ }
48
+ };
49
+
50
+ private setSocketUrls(dataResidency: string | undefined = undefined): void {
51
+ // Todo this should be resolved once phyos resolves to correct ip
52
+ if (!isBrowser) {
53
+ this.socketUrls = [{ url: `http://phyos:55000`, timeout: 5000, options: {} }];
54
+ } else {
55
+ this.socketUrls.push({ url: 'https://phyos:55500', timeout: 5000, options: {} });
56
+ // if (dataResidency !== undefined) { // TOOD: tmp disabled since we will need this in mobile apps later
57
+ this.socketUrls.push({
58
+ url: `https://phyhub.${dataResidency || 'eu'}.omborigrid.net:443`,
59
+ timeout: 10000,
60
+ options: {},
61
+ });
62
+ // }
63
+ }
64
+ console.log('socketUrls', this.socketUrls);
65
+ }
66
+
67
+ private async getSocketIoInstance(): Promise<Socket> {
68
+ while (true) {
69
+ // Keep trying until we connect or explicitly throw
70
+ for (const { url, timeout, options } of this.socketUrls) {
71
+ let socket: Socket | null = null;
72
+ try {
73
+ console.info(`Attempting to connect to ${url}...`);
74
+ const auth = { instanceId: this.instanceId, moduleName: this.moduleName };
75
+ socket = await getSocketIOWithProxy(url, {
76
+ ...options,
77
+ auth,
78
+ reconnectionAttempts: 1,
79
+ timeout: timeout,
80
+ debug: true,
81
+ });
82
+
83
+ // Wait for the connection to be established
84
+ await new Promise((resolve, reject) => {
85
+ socket!.on('connect', () => {
86
+ console.info(`Successfully connected to ${url}`);
87
+ resolve(true);
88
+ });
89
+
90
+ socket!.on('connect_error', error => {
91
+ console.info(`Failed to connect to ${url}: ${error.message}`);
92
+ reject(error);
93
+ });
94
+
95
+ // Add timeout for the connection attempt
96
+ setTimeout(() => {
97
+ reject(new Error(`Connection timeout to ${url}`));
98
+ }, timeout);
99
+ });
100
+
101
+ // If we get here, the connection was successful
102
+ return socket; // Exit both the loop and the while(true)
103
+ } catch (error) {
104
+ // console.info(`Failed to connect to ${url}. Trying next option...`);
105
+ // Cleanup the failed socket
106
+ try {
107
+ socket?.disconnect();
108
+ } catch (e) {
109
+ // Ignore cleanup errors
110
+ }
111
+ }
112
+ }
113
+ // console.info('Failed to connect to any socket.io server. Retrying in 1 second...');
114
+ await new Promise(resolve => setTimeout(resolve, 1000));
115
+ }
116
+ }
117
+
118
+ public static getInstance(
119
+ params: { instanceId?: string; moduleName?: string; dataResidency?: string } = {}
120
+ ): PhyHubConnection {
121
+ if (!PhyHubConnection.instance) {
122
+ PhyHubConnection.instance = new PhyHubConnection(params);
123
+ } else if (
124
+ (params.instanceId && PhyHubConnection.instance.instanceId !== params.instanceId) ||
125
+ (params.moduleName && PhyHubConnection.instance.moduleName !== params.moduleName)
126
+ ) {
127
+ // Update instance parameters if they are different
128
+ PhyHubConnection.instance.instanceId = params.instanceId;
129
+ PhyHubConnection.instance.moduleName = params.moduleName;
130
+ if (params.dataResidency) {
131
+ PhyHubConnection.instance.setSocketUrls(params.dataResidency);
132
+ }
133
+ }
134
+ return PhyHubConnection.instance;
135
+ }
136
+
137
+ public async getPhyHubSocket(): Promise<Socket> {
138
+ console.info(`getPhyHubSocket(): Getting phyhub socket`);
139
+
140
+ // Always check top window first
141
+ if (isBrowser) {
142
+ const topWindow = this.getTopWindow();
143
+ console.log('Checking for edgeHub in top window...', {
144
+ hasEdgeHub: !!(topWindow as any).edgeHub,
145
+ hasPhygridSocket: !!(topWindow as any).phygridSocketSingleton,
146
+ });
147
+
148
+ if ((topWindow as any).edgeHub) {
149
+ console.log('Found edgeHub in top window, using it instead of creating new connection');
150
+ this.phygridSocketSingleton = (topWindow as any).edgeHub;
151
+ if (this.phygridSocketSingleton) {
152
+ console.log('Successfully initialized edgeHub socket');
153
+ return this.phygridSocketSingleton;
154
+ }
155
+ }
156
+ if ((topWindow as any).phygridSocketSingleton) {
157
+ console.log('Found existing socket in top window, reusing it');
158
+ this.phygridSocketSingleton = (topWindow as any).phygridSocketSingleton;
159
+ if (this.phygridSocketSingleton) {
160
+ console.log('Successfully initialized existing socket');
161
+ return this.phygridSocketSingleton;
162
+ }
163
+ }
164
+ }
165
+
166
+ // Only proceed with new connection if we haven't found an existing one
167
+ if (!this.phygridSocketSingleton) {
168
+ console.log('No existing socket found, creating new connection...');
169
+ while (true) {
170
+ try {
171
+ const tmpSocket = await this.getSocketIoInstance();
172
+ const PHYHUB_URL = get(tmpSocket, 'io.uri', false);
173
+ tmpSocket.disconnect();
174
+
175
+ if (PHYHUB_URL) {
176
+ const { instanceId, moduleName } = this;
177
+ console.log('PHYHUB_URL', PHYHUB_URL);
178
+ const auth = { instanceId, moduleName };
179
+ console.log('auth', JSON.stringify(auth, null, 2));
180
+ const socket = await getSocketIOWithProxy(PHYHUB_URL, {
181
+ auth,
182
+ });
183
+
184
+ await new Promise((resolve, reject) => {
185
+ socket.on('connect', () => {
186
+ console.info(`Successfully connected to final socket at ${PHYHUB_URL}`);
187
+ if (isBrowser) {
188
+ // Store in top window immediately upon successful connection
189
+ const topWindow = this.getTopWindow();
190
+ (topWindow as any).phygridSocketSingleton = socket;
191
+ }
192
+ this.phygridSocketSingleton = socket;
193
+ resolve(true);
194
+ });
195
+
196
+ socket.on('connect_error', error => {
197
+ this.phygridSocketSingleton = null;
198
+ reject(error);
199
+ });
200
+ });
201
+
202
+ break; // Connection successful
203
+ }
204
+ } catch (error) {
205
+ console.error('Failed to connect to PhyHub', error);
206
+ await new Promise(resolve => setTimeout(resolve, 5000));
207
+ }
208
+ }
209
+ }
210
+
211
+ return this.phygridSocketSingleton as Socket;
212
+ }
213
+ }