@sprucelabs/mercury-client 42.0.556 → 42.0.558

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 (174) hide show
  1. package/build/esm/.spruce/errors/errors.types.d.ts +324 -0
  2. package/build/esm/.spruce/errors/errors.types.js +1 -0
  3. package/build/esm/.spruce/errors/mercuryClient/connectionFailed.schema.d.ts +3 -0
  4. package/build/esm/.spruce/errors/mercuryClient/connectionFailed.schema.js +25 -0
  5. package/build/esm/.spruce/errors/mercuryClient/invalidEventSignature.schema.d.ts +3 -0
  6. package/build/esm/.spruce/errors/mercuryClient/invalidEventSignature.schema.js +25 -0
  7. package/build/esm/.spruce/errors/mercuryClient/invalidPayload.schema.d.ts +3 -0
  8. package/build/esm/.spruce/errors/mercuryClient/invalidPayload.schema.js +19 -0
  9. package/build/esm/.spruce/errors/mercuryClient/invalidProtocol.schema.d.ts +3 -0
  10. package/build/esm/.spruce/errors/mercuryClient/invalidProtocol.schema.js +19 -0
  11. package/build/esm/.spruce/errors/mercuryClient/missingTestCacheDir.schema.d.ts +3 -0
  12. package/build/esm/.spruce/errors/mercuryClient/missingTestCacheDir.schema.js +12 -0
  13. package/build/esm/.spruce/errors/mercuryClient/mustCreateEvent.schema.d.ts +3 -0
  14. package/build/esm/.spruce/errors/mercuryClient/mustCreateEvent.schema.js +19 -0
  15. package/build/esm/.spruce/errors/mercuryClient/mustHandleLocally.schema.d.ts +3 -0
  16. package/build/esm/.spruce/errors/mercuryClient/mustHandleLocally.schema.js +19 -0
  17. package/build/esm/.spruce/errors/mercuryClient/notConnected.schema.d.ts +3 -0
  18. package/build/esm/.spruce/errors/mercuryClient/notConnected.schema.js +25 -0
  19. package/build/esm/.spruce/errors/mercuryClient/timeout.schema.d.ts +3 -0
  20. package/build/esm/.spruce/errors/mercuryClient/timeout.schema.js +35 -0
  21. package/build/esm/.spruce/errors/mercuryClient/unauthorizedAccess.schema.d.ts +3 -0
  22. package/build/esm/.spruce/errors/mercuryClient/unauthorizedAccess.schema.js +41 -0
  23. package/build/esm/.spruce/errors/mercuryClient/unauthorizedTarget.schema.d.ts +3 -0
  24. package/build/esm/.spruce/errors/mercuryClient/unauthorizedTarget.schema.js +38 -0
  25. package/build/esm/.spruce/errors/mercuryClient/unexpectedPayload.schema.d.ts +3 -0
  26. package/build/esm/.spruce/errors/mercuryClient/unexpectedPayload.schema.js +19 -0
  27. package/build/esm/.spruce/errors/mercuryClient/unknownError.schema.d.ts +3 -0
  28. package/build/esm/.spruce/errors/mercuryClient/unknownError.schema.js +12 -0
  29. package/build/esm/.spruce/errors/options.types.d.ts +40 -0
  30. package/build/esm/.spruce/errors/options.types.js +1 -0
  31. package/build/esm/.spruce/event-cache.json +1 -0
  32. package/build/esm/.spruce/schemas/fields/fieldClassMap.d.ts +2 -0
  33. package/build/esm/.spruce/schemas/fields/fieldClassMap.js +5 -0
  34. package/build/esm/.spruce/schemas/fields/fields.types.d.ts +1 -0
  35. package/build/esm/.spruce/schemas/fields/fields.types.js +3 -0
  36. package/build/esm/.spruce/schemas/schemas.types.d.ts +1 -0
  37. package/build/esm/.spruce/schemas/schemas.types.js +3 -0
  38. package/build/esm/.spruce/settings.json +26 -0
  39. package/build/esm/clients/MercuryClientFactory.d.ts +26 -0
  40. package/build/esm/clients/MercuryClientFactory.js +96 -0
  41. package/build/esm/clients/MercurySocketIoClient.d.ts +89 -0
  42. package/build/esm/clients/MercurySocketIoClient.js +605 -0
  43. package/build/esm/clients/MercuryTestClient.d.ts +57 -0
  44. package/build/esm/clients/MercuryTestClient.js +389 -0
  45. package/build/esm/clients/MutableContractClient.d.ts +10 -0
  46. package/build/esm/clients/MutableContractClient.js +43 -0
  47. package/build/esm/clients/statusChangePayloadSchema.d.ts +103 -0
  48. package/build/esm/clients/statusChangePayloadSchema.js +45 -0
  49. package/build/esm/constants.d.ts +1 -0
  50. package/build/esm/constants.js +1 -0
  51. package/build/esm/errors/SpruceError.d.ts +5 -0
  52. package/build/esm/errors/SpruceError.js +66 -0
  53. package/build/esm/errors/connectionFailed.builder.d.ts +16 -0
  54. package/build/esm/errors/connectionFailed.builder.js +16 -0
  55. package/build/esm/errors/invalidEventSignature.builder.d.ts +15 -0
  56. package/build/esm/errors/invalidEventSignature.builder.js +15 -0
  57. package/build/esm/errors/invalidPayload.builder.d.ts +12 -0
  58. package/build/esm/errors/invalidPayload.builder.js +12 -0
  59. package/build/esm/errors/invalidProtocol.builder.d.ts +12 -0
  60. package/build/esm/errors/invalidProtocol.builder.js +12 -0
  61. package/build/esm/errors/missingTestCacheDir.builder.d.ts +7 -0
  62. package/build/esm/errors/missingTestCacheDir.builder.js +7 -0
  63. package/build/esm/errors/mustCreateEvent.builder.d.ts +11 -0
  64. package/build/esm/errors/mustCreateEvent.builder.js +11 -0
  65. package/build/esm/errors/mustHandleLocally.builder.d.ts +11 -0
  66. package/build/esm/errors/mustHandleLocally.builder.js +11 -0
  67. package/build/esm/errors/notConnected.builder.d.ts +16 -0
  68. package/build/esm/errors/notConnected.builder.js +16 -0
  69. package/build/esm/errors/timeout.builder.d.ts +22 -0
  70. package/build/esm/errors/timeout.builder.js +22 -0
  71. package/build/esm/errors/unauthorizedAccess.builder.d.ts +57 -0
  72. package/build/esm/errors/unauthorizedAccess.builder.js +39 -0
  73. package/build/esm/errors/unexpectedPayload.builder.d.ts +12 -0
  74. package/build/esm/errors/unexpectedPayload.builder.js +12 -0
  75. package/build/esm/errors/unknownError.builder.d.ts +6 -0
  76. package/build/esm/errors/unknownError.builder.js +6 -0
  77. package/build/esm/index.d.ts +6 -0
  78. package/build/esm/index.js +6 -0
  79. package/build/esm/tests/AbstractClientTest.d.ts +31 -0
  80. package/build/esm/tests/AbstractClientTest.js +212 -0
  81. package/build/esm/tests/constants.d.ts +9 -0
  82. package/build/esm/tests/constants.js +11 -0
  83. package/build/esm/types/client.types.d.ts +30 -0
  84. package/build/esm/types/client.types.js +1 -0
  85. package/build/esm/utilities/socketIoEventUtil.utility.d.ts +5 -0
  86. package/build/esm/utilities/socketIoEventUtil.utility.js +9 -0
  87. package/package.json +12 -12
  88. package/build/__tests__/behavioral/AuthenticatingAndReauthenticating.test.d.ts +0 -21
  89. package/build/__tests__/behavioral/AuthenticatingAndReauthenticating.test.js +0 -287
  90. package/build/__tests__/behavioral/AuthenticatingAndReauthenticating.test.js.map +0 -1
  91. package/build/__tests__/behavioral/DisablingPermissionChecksWhenEmittingLocally.test.d.ts +0 -7
  92. package/build/__tests__/behavioral/DisablingPermissionChecksWhenEmittingLocally.test.js +0 -49
  93. package/build/__tests__/behavioral/DisablingPermissionChecksWhenEmittingLocally.test.js.map +0 -1
  94. package/build/__tests__/behavioral/EmittingAndFlatteningResponses.test.d.ts +0 -52
  95. package/build/__tests__/behavioral/EmittingAndFlatteningResponses.test.js +0 -123
  96. package/build/__tests__/behavioral/EmittingAndFlatteningResponses.test.js.map +0 -1
  97. package/build/__tests__/behavioral/EmittingConnectionChangeInTests.test.d.ts +0 -9
  98. package/build/__tests__/behavioral/EmittingConnectionChangeInTests.test.js +0 -103
  99. package/build/__tests__/behavioral/EmittingConnectionChangeInTests.test.js.map +0 -1
  100. package/build/__tests__/behavioral/LocallyHandlingAuthenticateDelaysConnect.test.d.ts +0 -7
  101. package/build/__tests__/behavioral/LocallyHandlingAuthenticateDelaysConnect.test.js +0 -91
  102. package/build/__tests__/behavioral/LocallyHandlingAuthenticateDelaysConnect.test.js.map +0 -1
  103. package/build/__tests__/behavioral/MercuryClientFactory.test.d.ts +0 -7
  104. package/build/__tests__/behavioral/MercuryClientFactory.test.js +0 -85
  105. package/build/__tests__/behavioral/MercuryClientFactory.test.js.map +0 -1
  106. package/build/__tests__/behavioral/ProxyingEvents.test.d.ts +0 -11
  107. package/build/__tests__/behavioral/ProxyingEvents.test.js +0 -99
  108. package/build/__tests__/behavioral/ProxyingEvents.test.js.map +0 -1
  109. package/build/__tests__/behavioral/ReconnectingAutomatically.test.d.ts +0 -33
  110. package/build/__tests__/behavioral/ReconnectingAutomatically.test.js +0 -390
  111. package/build/__tests__/behavioral/ReconnectingAutomatically.test.js.map +0 -1
  112. package/build/__tests__/behavioral/RequiringLocalListeners.test.d.ts +0 -7
  113. package/build/__tests__/behavioral/RequiringLocalListeners.test.js +0 -65
  114. package/build/__tests__/behavioral/RequiringLocalListeners.test.js.map +0 -1
  115. package/build/__tests__/behavioral/SettingNamespacesThatMustBeHandledLocally.test.d.ts +0 -9
  116. package/build/__tests__/behavioral/SettingNamespacesThatMustBeHandledLocally.test.js +0 -66
  117. package/build/__tests__/behavioral/SettingNamespacesThatMustBeHandledLocally.test.js.map +0 -1
  118. package/build/__tests__/behavioral/SimulatingEventsForTesting.test.d.ts +0 -51
  119. package/build/__tests__/behavioral/SimulatingEventsForTesting.test.js +0 -821
  120. package/build/__tests__/behavioral/SimulatingEventsForTesting.test.js.map +0 -1
  121. package/build/__tests__/behavioral/TestClientSpeedTests.test.d.ts +0 -7
  122. package/build/__tests__/behavioral/TestClientSpeedTests.test.js +0 -44
  123. package/build/__tests__/behavioral/TestClientSpeedTests.test.js.map +0 -1
  124. package/build/__tests__/behavioral/TestingWithDefaultContracts.test.d.ts +0 -7
  125. package/build/__tests__/behavioral/TestingWithDefaultContracts.test.js +0 -56
  126. package/build/__tests__/behavioral/TestingWithDefaultContracts.test.js.map +0 -1
  127. package/build/__tests__/behavioral/TurningOffAListener.test.d.ts +0 -16
  128. package/build/__tests__/behavioral/TurningOffAListener.test.js +0 -126
  129. package/build/__tests__/behavioral/TurningOffAListener.test.js.map +0 -1
  130. package/build/__tests__/behavioral/UsingMercuryClient.test.d.ts +0 -45
  131. package/build/__tests__/behavioral/UsingMercuryClient.test.js +0 -662
  132. package/build/__tests__/behavioral/UsingMercuryClient.test.js.map +0 -1
  133. /package/build/{.spruce → esm/.spruce}/errors/errors.types.js.map +0 -0
  134. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/connectionFailed.schema.js.map +0 -0
  135. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/invalidEventSignature.schema.js.map +0 -0
  136. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/invalidPayload.schema.js.map +0 -0
  137. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/invalidProtocol.schema.js.map +0 -0
  138. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/missingTestCacheDir.schema.js.map +0 -0
  139. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/mustCreateEvent.schema.js.map +0 -0
  140. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/mustHandleLocally.schema.js.map +0 -0
  141. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/notConnected.schema.js.map +0 -0
  142. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/timeout.schema.js.map +0 -0
  143. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/unauthorizedAccess.schema.js.map +0 -0
  144. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/unauthorizedTarget.schema.js.map +0 -0
  145. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/unexpectedPayload.schema.js.map +0 -0
  146. /package/build/{.spruce → esm/.spruce}/errors/mercuryClient/unknownError.schema.js.map +0 -0
  147. /package/build/{.spruce → esm/.spruce}/errors/options.types.js.map +0 -0
  148. /package/build/{.spruce → esm/.spruce}/schemas/fields/fieldClassMap.js.map +0 -0
  149. /package/build/{.spruce → esm/.spruce}/schemas/fields/fields.types.js.map +0 -0
  150. /package/build/{.spruce → esm/.spruce}/schemas/schemas.types.js.map +0 -0
  151. /package/build/{clients → esm/clients}/MercuryClientFactory.js.map +0 -0
  152. /package/build/{clients → esm/clients}/MercurySocketIoClient.js.map +0 -0
  153. /package/build/{clients → esm/clients}/MercuryTestClient.js.map +0 -0
  154. /package/build/{clients → esm/clients}/MutableContractClient.js.map +0 -0
  155. /package/build/{clients → esm/clients}/statusChangePayloadSchema.js.map +0 -0
  156. /package/build/{constants.js.map → esm/constants.js.map} +0 -0
  157. /package/build/{errors → esm/errors}/SpruceError.js.map +0 -0
  158. /package/build/{errors → esm/errors}/connectionFailed.builder.js.map +0 -0
  159. /package/build/{errors → esm/errors}/invalidEventSignature.builder.js.map +0 -0
  160. /package/build/{errors → esm/errors}/invalidPayload.builder.js.map +0 -0
  161. /package/build/{errors → esm/errors}/invalidProtocol.builder.js.map +0 -0
  162. /package/build/{errors → esm/errors}/missingTestCacheDir.builder.js.map +0 -0
  163. /package/build/{errors → esm/errors}/mustCreateEvent.builder.js.map +0 -0
  164. /package/build/{errors → esm/errors}/mustHandleLocally.builder.js.map +0 -0
  165. /package/build/{errors → esm/errors}/notConnected.builder.js.map +0 -0
  166. /package/build/{errors → esm/errors}/timeout.builder.js.map +0 -0
  167. /package/build/{errors → esm/errors}/unauthorizedAccess.builder.js.map +0 -0
  168. /package/build/{errors → esm/errors}/unexpectedPayload.builder.js.map +0 -0
  169. /package/build/{errors → esm/errors}/unknownError.builder.js.map +0 -0
  170. /package/build/{index.js.map → esm/index.js.map} +0 -0
  171. /package/build/{tests → esm/tests}/AbstractClientTest.js.map +0 -0
  172. /package/build/{tests → esm/tests}/constants.js.map +0 -0
  173. /package/build/{types → esm/types}/client.types.js.map +0 -0
  174. /package/build/{utilities → esm/utilities}/socketIoEventUtil.utility.js.map +0 -0
@@ -0,0 +1,605 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ import AbstractSpruceError from '@sprucelabs/error';
22
+ import { SchemaError, validateSchemaValues, } from '@sprucelabs/schema';
23
+ import { eventContractUtil, eventResponseUtil, eventNameUtil, } from '@sprucelabs/spruce-event-utils';
24
+ import { buildLog } from '@sprucelabs/spruce-skill-utils';
25
+ import { io } from 'socket.io-client';
26
+ import SpruceError from '../errors/SpruceError.js';
27
+ import socketIoEventUtil from '../utilities/socketIoEventUtil.utility.js';
28
+ class MercurySocketIoClient {
29
+ get eventContract() {
30
+ return this._eventContract;
31
+ }
32
+ set eventContract(contract) {
33
+ this._eventContract = contract;
34
+ }
35
+ constructor(options) {
36
+ this.log = buildLog('MercurySocketIoClient');
37
+ this.proxyToken = null;
38
+ this.listenerMap = new WeakMap();
39
+ this.isReAuthing = false;
40
+ this.reconnectPromise = null;
41
+ this.connectionRetriesRemaining = 5;
42
+ this.registeredListeners = [];
43
+ this.allowNextEventToBeAuthenticate = false;
44
+ this.shouldAutoRegisterListeners = true;
45
+ this.isManuallyDisconnected = false;
46
+ this.isReconnecting = false;
47
+ this.skipWaitIfReconnecting = false;
48
+ this.shouldRegisterProxyOnReconnect = false;
49
+ const { host, eventContract, emitTimeoutMs, reconnectDelayMs, shouldReconnect, maxEmitRetries = 5, connectionRetries } = options, ioOptions = __rest(options, ["host", "eventContract", "emitTimeoutMs", "reconnectDelayMs", "shouldReconnect", "maxEmitRetries", "connectionRetries"]);
50
+ this.host = host;
51
+ this.ioOptions = Object.assign(Object.assign({}, ioOptions), { withCredentials: false });
52
+ this.eventContract = eventContract;
53
+ this.emitTimeoutMs = emitTimeoutMs !== null && emitTimeoutMs !== void 0 ? emitTimeoutMs : 30000;
54
+ this.reconnectDelayMs = reconnectDelayMs !== null && reconnectDelayMs !== void 0 ? reconnectDelayMs : 5000;
55
+ this.shouldReconnect = shouldReconnect !== null && shouldReconnect !== void 0 ? shouldReconnect : true;
56
+ this.id = new Date().getTime().toString();
57
+ this.maxEmitRetries = maxEmitRetries;
58
+ this.connectionRetriesRemaining = connectionRetries !== null && connectionRetries !== void 0 ? connectionRetries : 5;
59
+ this.connectionRetries = connectionRetries !== null && connectionRetries !== void 0 ? connectionRetries : 5;
60
+ }
61
+ connect() {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ this.socket = MercurySocketIoClient.io(this.host, this.ioOptions);
64
+ this.emitStatusChange('connecting');
65
+ yield new Promise((resolve, reject) => {
66
+ var _a, _b;
67
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('connect', () => {
68
+ var _a, _b;
69
+ this.connectionRetriesRemaining = this.connectionRetries;
70
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
71
+ if (!this.isReconnecting) {
72
+ this.emitStatusChange('connected');
73
+ }
74
+ if (this.shouldReconnect) {
75
+ (_b = this.socket) === null || _b === void 0 ? void 0 : _b.once('disconnect', (opts) => __awaiter(this, void 0, void 0, function* () {
76
+ this.log.error('Mercury disconnected, reason:', opts);
77
+ yield this.attemptReconnectAfterDelay();
78
+ }));
79
+ }
80
+ this.attachConnectError();
81
+ resolve(undefined);
82
+ });
83
+ (_b = this.socket) === null || _b === void 0 ? void 0 : _b.on('timeout', () => {
84
+ reject(new SpruceError({
85
+ code: 'TIMEOUT',
86
+ eventName: 'connect',
87
+ timeoutMs: 20000,
88
+ friendlyMessage: `Uh Oh! I'm having trouble reaching HQ! Double check you have good internet and try again. In the meantime I'll try some things on my side and see what I can do. 🤞`,
89
+ }));
90
+ });
91
+ this.attachConnectError(reject, resolve);
92
+ });
93
+ });
94
+ }
95
+ emitStatusChange(status) {
96
+ //@ts-ignore
97
+ void this.emit('connection-status-change', {
98
+ payload: {
99
+ status,
100
+ },
101
+ });
102
+ }
103
+ attachConnectError(reject, resolve) {
104
+ var _a;
105
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('connect_error', (err) => __awaiter(this, void 0, void 0, function* () {
106
+ var _a;
107
+ const error = this.mapSocketErrorToSpruceError(err);
108
+ //@ts-ignore
109
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
110
+ this.log.error('Failed to connect to Mercury', error.message);
111
+ this.log.error('Connection retries left', `${this.connectionRetriesRemaining}`);
112
+ if (this.connectionRetriesRemaining === 0) {
113
+ reject === null || reject === void 0 ? void 0 : reject(error);
114
+ return;
115
+ }
116
+ try {
117
+ this.isReconnecting = false;
118
+ yield this.attemptReconnectAfterDelay();
119
+ resolve === null || resolve === void 0 ? void 0 : resolve();
120
+ }
121
+ catch (err) {
122
+ //@ts-ignore
123
+ reject === null || reject === void 0 ? void 0 : reject(err);
124
+ }
125
+ }));
126
+ }
127
+ attemptReconnectAfterDelay() {
128
+ return __awaiter(this, arguments, void 0, function* (retriesLeft = this.maxEmitRetries) {
129
+ if (this.isManuallyDisconnected) {
130
+ this.isReconnecting = false;
131
+ return;
132
+ }
133
+ if (this.isReconnecting) {
134
+ return;
135
+ }
136
+ this.emitStatusChange('disconnected');
137
+ delete this.authPromise;
138
+ this.isReconnecting = true;
139
+ this.proxyToken = null;
140
+ this.reconnectPromise = new Promise((resolve, reject) => {
141
+ if (this.lastAuthOptions) {
142
+ this.isReAuthing = true;
143
+ }
144
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
145
+ yield this.reconnect(resolve, reject, retriesLeft);
146
+ }), this.reconnectDelayMs);
147
+ });
148
+ return this.reconnectPromise;
149
+ });
150
+ }
151
+ reconnect(resolve, reject, retriesLeft) {
152
+ return __awaiter(this, void 0, void 0, function* () {
153
+ var _a;
154
+ try {
155
+ this.connectionRetriesRemaining--;
156
+ const key = new Date().getTime();
157
+ this.reconnectKey = key;
158
+ yield this.connect();
159
+ if (this.reconnectKey !== key) {
160
+ return;
161
+ }
162
+ if (this.isManuallyDisconnected) {
163
+ this.isReconnecting = false;
164
+ return;
165
+ }
166
+ this.skipWaitIfReconnecting = true;
167
+ if (this.lastAuthOptions) {
168
+ yield this.authenticate(this.lastAuthOptions);
169
+ }
170
+ if (this.isManuallyDisconnected) {
171
+ this.isReconnecting = false;
172
+ return;
173
+ }
174
+ if (this.shouldRegisterProxyOnReconnect) {
175
+ yield this.registerProxyToken();
176
+ }
177
+ if (this.isManuallyDisconnected) {
178
+ this.isReconnecting = false;
179
+ return;
180
+ }
181
+ yield this.reRegisterAllListeners();
182
+ this.emitStatusChange('connected');
183
+ this.isReAuthing = false;
184
+ this.isReconnecting = false;
185
+ this.skipWaitIfReconnecting = false;
186
+ resolve();
187
+ }
188
+ catch (err) {
189
+ ;
190
+ ((_a = console.error) !== null && _a !== void 0 ? _a : console.log)(err.message);
191
+ this.isReconnecting = false;
192
+ this.skipWaitIfReconnecting = false;
193
+ retriesLeft = retriesLeft - 1;
194
+ if ((err.options.code === 'TIMEOUT' ||
195
+ err.options.code === 'CONNECTION_FAILED') &&
196
+ retriesLeft > 0) {
197
+ yield this.attemptReconnectAfterDelay(retriesLeft)
198
+ .then(resolve)
199
+ .catch(reject);
200
+ }
201
+ else {
202
+ this.lastAuthOptions = undefined;
203
+ reject(err);
204
+ }
205
+ }
206
+ });
207
+ }
208
+ waitIfReconnecting() {
209
+ return __awaiter(this, void 0, void 0, function* () {
210
+ yield this.reconnectPromise;
211
+ });
212
+ }
213
+ reRegisterAllListeners() {
214
+ return __awaiter(this, void 0, void 0, function* () {
215
+ const listeners = this.registeredListeners;
216
+ this.registeredListeners = [];
217
+ const all = Promise.all(listeners.map((listener) => this.on(listener[0], listener[1])));
218
+ yield all;
219
+ });
220
+ }
221
+ mapSocketErrorToSpruceError(err) {
222
+ var _a;
223
+ const originalError = new Error((_a = err.message) !== null && _a !== void 0 ? _a : err);
224
+ if (err.stack) {
225
+ originalError.stack = err.stack;
226
+ }
227
+ //@ts-ignore
228
+ originalError.socketError = err;
229
+ switch (err.message) {
230
+ case 'timeout':
231
+ return new SpruceError({
232
+ code: 'TIMEOUT',
233
+ eventName: 'connect',
234
+ timeoutMs: 10000,
235
+ });
236
+ case 'xhr poll error':
237
+ return new SpruceError({
238
+ code: 'CONNECTION_FAILED',
239
+ host: this.host,
240
+ statusCode: +err.description || 503,
241
+ originalError,
242
+ });
243
+ default:
244
+ return new SpruceError({
245
+ code: 'UNKNOWN_ERROR',
246
+ originalError,
247
+ friendlyMessage: `Something went wrong when working with socketio`,
248
+ });
249
+ }
250
+ }
251
+ emit(eventName, targetAndPayload, cb) {
252
+ return __awaiter(this, void 0, void 0, function* () {
253
+ const isLocalEvent = this.isEventLocal(eventName);
254
+ if (isLocalEvent) {
255
+ return this.handleLocalEmit(eventName, targetAndPayload);
256
+ }
257
+ return this._emit(this.maxEmitRetries, eventName, targetAndPayload, cb);
258
+ });
259
+ }
260
+ handleLocalEmit(eventName, targetAndPayload) {
261
+ const listeners = this.registeredListeners.filter((r) => r[0] === eventName);
262
+ for (const listener of listeners) {
263
+ const cb = listener === null || listener === void 0 ? void 0 : listener[1];
264
+ cb === null || cb === void 0 ? void 0 : cb({
265
+ //@ts-ignore
266
+ payload: targetAndPayload === null || targetAndPayload === void 0 ? void 0 : targetAndPayload.payload,
267
+ });
268
+ }
269
+ return {
270
+ responses: [],
271
+ totalContracts: 0,
272
+ totalErrors: 0,
273
+ totalResponses: 0,
274
+ };
275
+ }
276
+ emitAndFlattenResponses(eventName, payload, cb) {
277
+ return __awaiter(this, void 0, void 0, function* () {
278
+ const results = yield this.emit(eventName, payload, cb);
279
+ const { payloads, errors } = eventResponseUtil.getAllResponsePayloadsAndErrors(results, SpruceError);
280
+ if (errors === null || errors === void 0 ? void 0 : errors[0]) {
281
+ throw errors[0];
282
+ }
283
+ return payloads;
284
+ });
285
+ }
286
+ _emit(retriesRemaining, eventName, payload, cb) {
287
+ return __awaiter(this, void 0, void 0, function* () {
288
+ var _a;
289
+ if (!this.skipWaitIfReconnecting) {
290
+ yield this.waitIfReconnecting();
291
+ }
292
+ if (!this.allowNextEventToBeAuthenticate &&
293
+ eventName === authenticateFqen) {
294
+ throw new SchemaError({
295
+ code: 'INVALID_PARAMETERS',
296
+ parameters: ['eventName'],
297
+ friendlyMessage: `You can't emit '${authenticateFqen}' event directly. Use client.authenticate() so all your auth is preserved.`,
298
+ });
299
+ }
300
+ else if (eventName === authenticateFqen) {
301
+ this.allowNextEventToBeAuthenticate = false;
302
+ }
303
+ if (this.isManuallyDisconnected) {
304
+ throw new SpruceError({
305
+ code: 'NOT_CONNECTED',
306
+ action: 'emit',
307
+ fqen: eventName,
308
+ });
309
+ }
310
+ this.assertValidEmitTargetAndPayload(eventName, payload);
311
+ const responseEventName = eventNameUtil.generateResponseEventName(eventName);
312
+ const singleResponsePromises = [];
313
+ const singleResponseHandler = (response) => __awaiter(this, void 0, void 0, function* () {
314
+ if (cb) {
315
+ let resolve;
316
+ singleResponsePromises.push(new Promise((r) => {
317
+ resolve = r;
318
+ }));
319
+ yield cb(eventResponseUtil.mutatingMapSingleResonseErrorsToSpruceErrors(response, SpruceError));
320
+ //@ts-ignore
321
+ resolve();
322
+ }
323
+ });
324
+ if (cb) {
325
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.on(responseEventName, singleResponseHandler);
326
+ }
327
+ const args = [];
328
+ if (payload || this.proxyToken) {
329
+ const p = Object.assign({}, payload);
330
+ if (eventName !== authenticateFqen &&
331
+ this.proxyToken &&
332
+ !p.source) {
333
+ p.source = {
334
+ proxyToken: this.proxyToken,
335
+ };
336
+ }
337
+ args.push(p);
338
+ }
339
+ const results = yield new Promise((resolve, reject) => {
340
+ var _a;
341
+ try {
342
+ const emitTimeout = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
343
+ var _a;
344
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.off(responseEventName, singleResponseHandler);
345
+ if (retriesRemaining == 0) {
346
+ const err = new SpruceError({
347
+ code: 'TIMEOUT',
348
+ eventName,
349
+ timeoutMs: this.emitTimeoutMs,
350
+ isConnected: this.isSocketConnected(),
351
+ totalRetries: this.maxEmitRetries,
352
+ });
353
+ reject(err);
354
+ return;
355
+ }
356
+ retriesRemaining--;
357
+ try {
358
+ if (eventName === authenticateFqen &&
359
+ this.authRawResults) {
360
+ resolve(this.authRawResults);
361
+ return;
362
+ }
363
+ this.allowNextEventToBeAuthenticate = true;
364
+ //@ts-ignore
365
+ const results = yield this._emit(retriesRemaining, eventName, payload, cb);
366
+ //@ts-ignore
367
+ resolve(results);
368
+ }
369
+ catch (err) {
370
+ reject(err);
371
+ }
372
+ }), this.emitTimeoutMs);
373
+ args.push((results) => {
374
+ var _a;
375
+ clearTimeout(emitTimeout);
376
+ this.handleConfirmPinResponse(eventName, results);
377
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.off(responseEventName, singleResponseHandler);
378
+ resolve(results);
379
+ });
380
+ const ioName = socketIoEventUtil.toSocketName(eventName);
381
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.emit(ioName, ...args);
382
+ }
383
+ catch (err) {
384
+ reject(err);
385
+ }
386
+ });
387
+ yield Promise.all(singleResponsePromises);
388
+ return eventResponseUtil.mutatingMapAggregateResponseErrorsToSpruceErrors(results, SpruceError);
389
+ });
390
+ }
391
+ assertValidEmitTargetAndPayload(eventName, payload) {
392
+ const signature = this.getEventSignatureByName(eventName);
393
+ if (signature.emitPayloadSchema) {
394
+ try {
395
+ validateSchemaValues(signature.emitPayloadSchema, payload !== null && payload !== void 0 ? payload : {});
396
+ }
397
+ catch (err) {
398
+ throw new SpruceError({
399
+ code: 'INVALID_PAYLOAD',
400
+ originalError: err,
401
+ eventName,
402
+ });
403
+ }
404
+ }
405
+ else if (payload && this.eventContract) {
406
+ throw new SpruceError({
407
+ code: 'UNEXPECTED_PAYLOAD',
408
+ eventName,
409
+ });
410
+ }
411
+ }
412
+ handleConfirmPinResponse(eventName, results) {
413
+ var _a, _b;
414
+ const payload = (_b = (_a = results === null || results === void 0 ? void 0 : results.responses) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.payload;
415
+ if (eventName.search('confirm-pin') === 0 && (payload === null || payload === void 0 ? void 0 : payload.person)) {
416
+ this.lastAuthOptions = { token: payload.token };
417
+ this.auth = {
418
+ person: payload.person,
419
+ };
420
+ }
421
+ }
422
+ getEventSignatureByName(eventName) {
423
+ if (!this.eventContract) {
424
+ return {};
425
+ }
426
+ return eventContractUtil.getSignatureByName(this.eventContract, eventName);
427
+ }
428
+ setShouldAutoRegisterListeners(should) {
429
+ this.shouldAutoRegisterListeners = should;
430
+ }
431
+ on(eventName, cb) {
432
+ return __awaiter(this, void 0, void 0, function* () {
433
+ var _a, _b, _c;
434
+ this.registeredListeners.push([eventName, cb]);
435
+ const isLocalEvent = this.isEventLocal(eventName);
436
+ if (isLocalEvent) {
437
+ return;
438
+ }
439
+ if (!isLocalEvent && this.shouldAutoRegisterListeners) {
440
+ //@ts-ignore
441
+ const results = yield this.emit('register-listeners::v2020_12_25', {
442
+ payload: { events: [{ eventName }] },
443
+ });
444
+ if (results.totalErrors > 0) {
445
+ const options = (_b = (_a = results.responses[0].errors) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 'UNKNOWN_ERROR';
446
+ throw AbstractSpruceError.parse(options, SpruceError);
447
+ }
448
+ }
449
+ const listener = (targetAndPayload, ioCallback) => __awaiter(this, void 0, void 0, function* () {
450
+ if (cb) {
451
+ try {
452
+ const results = yield cb(targetAndPayload);
453
+ if (ioCallback) {
454
+ ioCallback(results);
455
+ }
456
+ }
457
+ catch (err) {
458
+ let thisErr = err;
459
+ if (ioCallback) {
460
+ if (!(err instanceof AbstractSpruceError)) {
461
+ thisErr = new SpruceError({
462
+ //@ts-ignore
463
+ code: 'LISTENER_ERROR',
464
+ fqen: eventName,
465
+ friendlyMessage: err.message,
466
+ originalError: err,
467
+ });
468
+ }
469
+ ioCallback({ errors: [thisErr.toObject()] });
470
+ }
471
+ }
472
+ }
473
+ });
474
+ this.listenerMap.set(cb, listener);
475
+ (_c = this.socket) === null || _c === void 0 ? void 0 : _c.on(eventName,
476
+ //@ts-ignore
477
+ listener);
478
+ });
479
+ }
480
+ isEventLocal(eventName) {
481
+ return eventName === 'connection-status-change';
482
+ }
483
+ off(eventName, cb) {
484
+ return __awaiter(this, void 0, void 0, function* () {
485
+ this.removeLocalListener(cb, eventName);
486
+ return new Promise((resolve, reject) => {
487
+ var _a;
488
+ if (!this.socket || !this.auth || this.isEventLocal(eventName)) {
489
+ resolve(0);
490
+ return;
491
+ }
492
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.emit('unregister-listeners::v2020_12_25', {
493
+ payload: {
494
+ fullyQualifiedEventNames: [eventName],
495
+ },
496
+ }, (results) => {
497
+ if (results.totalErrors > 0) {
498
+ const err = AbstractSpruceError.parse(results.responses[0].errors[0], SpruceError);
499
+ reject(err);
500
+ }
501
+ else {
502
+ resolve(results.responses[0].payload.unregisterCount);
503
+ }
504
+ });
505
+ });
506
+ });
507
+ }
508
+ removeLocalListener(cb, eventName) {
509
+ var _a, _b;
510
+ const listener = this.listenerMap.get(cb);
511
+ if (listener) {
512
+ this.listenerMap.delete(cb);
513
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.off(eventName, listener);
514
+ }
515
+ else {
516
+ (_b = this.socket) === null || _b === void 0 ? void 0 : _b.removeAllListeners(eventName);
517
+ }
518
+ }
519
+ getId() {
520
+ return this.id;
521
+ }
522
+ disconnect() {
523
+ return __awaiter(this, void 0, void 0, function* () {
524
+ var _a;
525
+ this.isManuallyDisconnected = true;
526
+ if (this.isSocketConnected()) {
527
+ //@ts-ignore
528
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
529
+ yield new Promise((resolve) => {
530
+ var _a, _b;
531
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.once('disconnect', () => {
532
+ this.socket = undefined;
533
+ resolve(undefined);
534
+ });
535
+ (_b = this.socket) === null || _b === void 0 ? void 0 : _b.disconnect();
536
+ });
537
+ }
538
+ return;
539
+ });
540
+ }
541
+ authenticate(options) {
542
+ return __awaiter(this, void 0, void 0, function* () {
543
+ var _a, _b;
544
+ const { skillId, apiKey, token } = options;
545
+ if (this.authPromise) {
546
+ yield this.authPromise;
547
+ return {
548
+ skill: (_a = this.auth) === null || _a === void 0 ? void 0 : _a.skill,
549
+ person: (_b = this.auth) === null || _b === void 0 ? void 0 : _b.person,
550
+ };
551
+ }
552
+ this.lastAuthOptions = options;
553
+ this.allowNextEventToBeAuthenticate = true;
554
+ //@ts-ignore
555
+ this.authPromise = this.emit('authenticate::v2020_12_25', {
556
+ payload: {
557
+ skillId,
558
+ apiKey,
559
+ token,
560
+ },
561
+ });
562
+ const results = yield this.authPromise;
563
+ //@ts-ignore
564
+ const { auth } = eventResponseUtil.getFirstResponseOrThrow(results);
565
+ this.authRawResults = results;
566
+ this.auth = auth;
567
+ return {
568
+ skill: auth.skill,
569
+ person: auth.person,
570
+ };
571
+ });
572
+ }
573
+ isAuthenticated() {
574
+ return !!this.auth;
575
+ }
576
+ isConnected() {
577
+ return !this.isReAuthing && this.isSocketConnected();
578
+ }
579
+ isSocketConnected() {
580
+ var _a, _b;
581
+ return (_b = (_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected) !== null && _b !== void 0 ? _b : false;
582
+ }
583
+ getProxyToken() {
584
+ return this.proxyToken;
585
+ }
586
+ setProxyToken(token) {
587
+ this.proxyToken = token;
588
+ }
589
+ registerProxyToken() {
590
+ return __awaiter(this, void 0, void 0, function* () {
591
+ const results = yield this.emit('register-proxy-token::v2020_12_25');
592
+ //@ts-ignore
593
+ const { token } = eventResponseUtil.getFirstResponseOrThrow(results);
594
+ this.setProxyToken(token);
595
+ this.shouldRegisterProxyOnReconnect = true;
596
+ return token;
597
+ });
598
+ }
599
+ getIsTestClient() {
600
+ return false;
601
+ }
602
+ }
603
+ MercurySocketIoClient.io = io;
604
+ export default MercurySocketIoClient;
605
+ export const authenticateFqen = 'authenticate::v2020_12_25';
@@ -0,0 +1,57 @@
1
+ import { AbstractEventEmitter } from '@sprucelabs/mercury-event-emitter';
2
+ import { EventContract, EventName, MercuryAggregateResponse, SkillEventContract, SpruceSchemas } from '@sprucelabs/mercury-types';
3
+ import { Schema } from '@sprucelabs/schema';
4
+ import MutableContractClient from './MutableContractClient';
5
+ declare class InternalEmitter<Contract extends EventContract> extends AbstractEventEmitter<Contract> {
6
+ doesHandleEvent(eventName: string): boolean;
7
+ protected validateEmitPayload(schema: Schema | undefined | null, actualPayload: any, eventName: string): void;
8
+ mixinOnlyUniqueSignatures(contract: EventContract): void;
9
+ overrideSignatures(contract: EventContract): void;
10
+ getContract(): SpruceSchemas.Mercury.v2020_12_25.EventContract;
11
+ setContract(contract: Contract): void;
12
+ }
13
+ export default class MercuryTestClient<
14
+ /** @ts-ignore */
15
+ Contract extends EventContract = SkillEventContract> extends MutableContractClient<Contract> {
16
+ private static emitter;
17
+ private _isConnected;
18
+ private isConnectedToApi;
19
+ private connectPromise?;
20
+ private static shouldCheckPermissionsOnLocalEvents;
21
+ private shouldHandleAuthenticateLocallyIfListenerSet;
22
+ private static namespacesThatHaveToBeHandledLocally;
23
+ private shouldWaitForDelayedConnectIfAuthing;
24
+ private static shouldRequireLocalListeners;
25
+ protected get eventContract(): Contract;
26
+ protected set eventContract(contract: Contract);
27
+ static setShouldCheckPermissionsOnLocalEvents(should: boolean): void;
28
+ static setNamespacesThatMustBeHandledLocally(namespaces: string[]): void;
29
+ static getNamespacesThatMustBeHandledLocally(): string[];
30
+ constructor(options: Record<string, any> & {
31
+ host: string;
32
+ eventContract?: Contract;
33
+ });
34
+ /** @ts-ignore */
35
+ static getInternalEmitter(contract?: EventContract): InternalEmitter<SkillEventContract>;
36
+ off(eventName: EventName<Contract>, cb?: any): Promise<number>;
37
+ static mixinContract(contract: EventContract): void;
38
+ mixinContract(contract: EventContract): void;
39
+ doesHandleEvent(eventName: string): boolean;
40
+ on(...args: any[]): Promise<void>;
41
+ emit(...args: any[]): Promise<MercuryAggregateResponse<any>>;
42
+ private shouldHandleEventLocally;
43
+ private handleEventLocally;
44
+ private assertValidEventSignature;
45
+ private optionallyCheckPermissions;
46
+ private buildSource;
47
+ private connectIfNotConnected;
48
+ private delayedConnectAndAuth;
49
+ connect(): Promise<void>;
50
+ isConnected(): boolean;
51
+ disconnect(): Promise<void>;
52
+ static reset(): void;
53
+ getIsTestClient(): boolean;
54
+ static setShouldRequireLocalListeners(shouldRequire: boolean): void;
55
+ static getShouldRequireLocalListeners(): boolean;
56
+ }
57
+ export {};