oneentry 1.0.176 → 1.0.177

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 (197) hide show
  1. package/README.md +12 -5
  2. package/changelog.md +116 -0
  3. package/dist/admins/adminsApi.js +2 -9
  4. package/dist/admins/adminsInterfaces.d.ts +5 -5
  5. package/dist/admins/adminsSchemas.d.ts +4 -4
  6. package/dist/admins/adminsSchemas.js +2 -2
  7. package/dist/attribute-sets/attributeSetsApi.d.ts +1 -1
  8. package/dist/attribute-sets/attributeSetsApi.js +4 -4
  9. package/dist/attribute-sets/attributeSetsInterfaces.d.ts +65 -14
  10. package/dist/attribute-sets/attributeSetsSchemas.d.ts +8 -6
  11. package/dist/attribute-sets/attributeSetsSchemas.js +6 -9
  12. package/dist/auth-provider/authProviderApi.d.ts +4 -4
  13. package/dist/auth-provider/authProviderApi.js +90 -23
  14. package/dist/auth-provider/authProviderSchemas.d.ts +1 -0
  15. package/dist/auth-provider/authProviderSchemas.js +1 -0
  16. package/dist/auth-provider/authProvidersInterfaces.d.ts +8 -6
  17. package/dist/base/asyncModules.d.ts +62 -1
  18. package/dist/base/asyncModules.js +219 -37
  19. package/dist/base/stateModule.d.ts +2 -0
  20. package/dist/base/stateModule.js +22 -12
  21. package/dist/base/syncModules.d.ts +18 -10
  22. package/dist/base/syncModules.js +100 -29
  23. package/dist/base/utils.d.ts +26 -21
  24. package/dist/base/validation.d.ts +3 -3
  25. package/dist/base/validation.js +6 -7
  26. package/dist/blocks/blocksApi.d.ts +20 -17
  27. package/dist/blocks/blocksApi.js +82 -64
  28. package/dist/blocks/blocksInterfaces.d.ts +8 -8
  29. package/dist/discounts/discountsApi.d.ts +9 -7
  30. package/dist/discounts/discountsApi.js +16 -13
  31. package/dist/discounts/discountsInterfaces.d.ts +14 -10
  32. package/dist/events/eventsApi.d.ts +3 -3
  33. package/dist/events/eventsApi.js +3 -3
  34. package/dist/events/eventsInterfaces.d.ts +10 -14
  35. package/dist/file-uploading/fileUploadingApi.d.ts +4 -4
  36. package/dist/file-uploading/fileUploadingApi.js +13 -5
  37. package/dist/file-uploading/fileUploadingInterfaces.d.ts +5 -6
  38. package/dist/filters/filtersApi.js +2 -2
  39. package/dist/forms/formsApi.js +2 -2
  40. package/dist/forms/formsInterfaces.d.ts +1 -3
  41. package/dist/forms/formsSchemas.d.ts +3 -6
  42. package/dist/forms/formsSchemas.js +2 -4
  43. package/dist/forms-data/formsDataApi.d.ts +16 -0
  44. package/dist/forms-data/formsDataApi.js +32 -5
  45. package/dist/forms-data/formsDataInterfaces.d.ts +17 -13
  46. package/dist/general-types/generalTypesInterfaces.d.ts +1 -1
  47. package/dist/index.d.ts +7 -6
  48. package/dist/index.js +50 -7
  49. package/dist/integration-collections/integrationCollectionsApi.d.ts +15 -4
  50. package/dist/integration-collections/integrationCollectionsApi.js +41 -14
  51. package/dist/integration-collections/integrationCollectionsInterfaces.d.ts +8 -9
  52. package/dist/integration-collections/integrationCollectionsSchemas.d.ts +0 -2
  53. package/dist/integration-collections/integrationCollectionsSchemas.js +0 -1
  54. package/dist/menus/menusApi.js +1 -1
  55. package/dist/orders/ordersApi.d.ts +1 -13
  56. package/dist/orders/ordersApi.js +21 -42
  57. package/dist/orders/ordersInterfaces.d.ts +21 -14
  58. package/dist/pages/pagesApi.d.ts +6 -5
  59. package/dist/pages/pagesApi.js +44 -31
  60. package/dist/pages/pagesInterfaces.d.ts +18 -15
  61. package/dist/pages/pagesSchemas.d.ts +0 -3
  62. package/dist/pages/pagesSchemas.js +0 -1
  63. package/dist/payments/paymentsApi.d.ts +10 -11
  64. package/dist/payments/paymentsApi.js +22 -18
  65. package/dist/payments/paymentsInterfaces.d.ts +12 -14
  66. package/dist/payments/paymentsSchemas.d.ts +21 -20
  67. package/dist/payments/paymentsSchemas.js +5 -8
  68. package/dist/product-statuses/productStatusesApi.d.ts +1 -1
  69. package/dist/product-statuses/productStatusesApi.js +3 -3
  70. package/dist/product-statuses/productStatusesInterfaces.d.ts +1 -4
  71. package/dist/products/productsApi.d.ts +38 -58
  72. package/dist/products/productsApi.js +59 -72
  73. package/dist/products/productsInterfaces.d.ts +48 -85
  74. package/dist/search/searchApi.d.ts +1 -1
  75. package/dist/search/searchApi.js +4 -3
  76. package/dist/sitemap/sitemapInterfaces.d.ts +10 -6
  77. package/dist/subscriptions/subscriptionsApi.d.ts +1 -1
  78. package/dist/subscriptions/subscriptionsApi.js +1 -1
  79. package/dist/subscriptions/subscriptionsInterfaces.d.ts +1 -1
  80. package/dist/system/systemApi.d.ts +2 -0
  81. package/dist/system/systemApi.js +2 -0
  82. package/dist/system/systemInterfaces.d.ts +2 -0
  83. package/dist/templates/templatesApi.d.ts +2 -2
  84. package/dist/templates/templatesApi.js +12 -11
  85. package/dist/templates/templatesInterfaces.d.ts +2 -2
  86. package/dist/templates-preview/templatesPreviewApi.js +2 -2
  87. package/dist/templates-preview/templatesPreviewInterfaces.d.ts +23 -13
  88. package/dist/templates-preview/templatesPreviewSchemas.d.ts +7 -0
  89. package/dist/templates-preview/templatesPreviewSchemas.js +2 -0
  90. package/dist/user-groups/userGroupsApi.js +5 -5
  91. package/dist/user-groups/userGroupsSchemas.d.ts +4 -4
  92. package/dist/users/usersApi.d.ts +1 -1
  93. package/dist/users/usersApi.js +28 -15
  94. package/dist/users/usersInterfaces.d.ts +2 -9
  95. package/dist/web-socket/lazySocket.d.ts +6 -5
  96. package/dist/web-socket/lazySocket.js +212 -15
  97. package/dist/web-socket/wsApi.d.ts +7 -4
  98. package/dist/web-socket/wsApi.js +49 -12
  99. package/dist/web-socket/wsInterfaces.d.ts +41 -4
  100. package/esm/admins/adminsApi.js +2 -9
  101. package/esm/admins/adminsInterfaces.d.ts +5 -5
  102. package/esm/admins/adminsSchemas.d.ts +4 -4
  103. package/esm/admins/adminsSchemas.js +2 -2
  104. package/esm/attribute-sets/attributeSetsApi.d.ts +1 -1
  105. package/esm/attribute-sets/attributeSetsApi.js +4 -4
  106. package/esm/attribute-sets/attributeSetsInterfaces.d.ts +65 -14
  107. package/esm/attribute-sets/attributeSetsSchemas.d.ts +8 -6
  108. package/esm/attribute-sets/attributeSetsSchemas.js +6 -9
  109. package/esm/auth-provider/authProviderApi.d.ts +4 -4
  110. package/esm/auth-provider/authProviderApi.js +90 -23
  111. package/esm/auth-provider/authProviderSchemas.d.ts +1 -0
  112. package/esm/auth-provider/authProviderSchemas.js +1 -0
  113. package/esm/auth-provider/authProvidersInterfaces.d.ts +8 -6
  114. package/esm/base/asyncModules.d.ts +62 -1
  115. package/esm/base/asyncModules.js +219 -37
  116. package/esm/base/stateModule.d.ts +2 -0
  117. package/esm/base/stateModule.js +22 -12
  118. package/esm/base/syncModules.d.ts +18 -10
  119. package/esm/base/syncModules.js +99 -29
  120. package/esm/base/utils.d.ts +26 -21
  121. package/esm/base/validation.d.ts +3 -3
  122. package/esm/base/validation.js +6 -7
  123. package/esm/blocks/blocksApi.d.ts +20 -17
  124. package/esm/blocks/blocksApi.js +82 -64
  125. package/esm/blocks/blocksInterfaces.d.ts +8 -8
  126. package/esm/discounts/discountsApi.d.ts +9 -7
  127. package/esm/discounts/discountsApi.js +16 -13
  128. package/esm/discounts/discountsInterfaces.d.ts +14 -10
  129. package/esm/events/eventsApi.d.ts +3 -3
  130. package/esm/events/eventsApi.js +3 -3
  131. package/esm/events/eventsInterfaces.d.ts +10 -14
  132. package/esm/file-uploading/fileUploadingApi.d.ts +4 -4
  133. package/esm/file-uploading/fileUploadingApi.js +13 -5
  134. package/esm/file-uploading/fileUploadingInterfaces.d.ts +5 -6
  135. package/esm/filters/filtersApi.js +2 -2
  136. package/esm/forms/formsApi.js +2 -2
  137. package/esm/forms/formsInterfaces.d.ts +1 -3
  138. package/esm/forms/formsSchemas.d.ts +3 -6
  139. package/esm/forms/formsSchemas.js +2 -4
  140. package/esm/forms-data/formsDataApi.d.ts +16 -0
  141. package/esm/forms-data/formsDataApi.js +32 -5
  142. package/esm/forms-data/formsDataInterfaces.d.ts +17 -13
  143. package/esm/general-types/generalTypesInterfaces.d.ts +1 -1
  144. package/esm/index.d.ts +7 -6
  145. package/esm/index.js +50 -7
  146. package/esm/integration-collections/integrationCollectionsApi.d.ts +15 -4
  147. package/esm/integration-collections/integrationCollectionsApi.js +41 -14
  148. package/esm/integration-collections/integrationCollectionsInterfaces.d.ts +8 -9
  149. package/esm/integration-collections/integrationCollectionsSchemas.d.ts +0 -2
  150. package/esm/integration-collections/integrationCollectionsSchemas.js +0 -1
  151. package/esm/menus/menusApi.js +1 -1
  152. package/esm/orders/ordersApi.d.ts +1 -13
  153. package/esm/orders/ordersApi.js +21 -42
  154. package/esm/orders/ordersInterfaces.d.ts +21 -14
  155. package/esm/pages/pagesApi.d.ts +6 -5
  156. package/esm/pages/pagesApi.js +44 -31
  157. package/esm/pages/pagesInterfaces.d.ts +18 -15
  158. package/esm/pages/pagesSchemas.d.ts +0 -3
  159. package/esm/pages/pagesSchemas.js +0 -1
  160. package/esm/payments/paymentsApi.d.ts +10 -11
  161. package/esm/payments/paymentsApi.js +22 -18
  162. package/esm/payments/paymentsInterfaces.d.ts +12 -14
  163. package/esm/payments/paymentsSchemas.d.ts +21 -20
  164. package/esm/payments/paymentsSchemas.js +5 -8
  165. package/esm/product-statuses/productStatusesApi.d.ts +1 -1
  166. package/esm/product-statuses/productStatusesApi.js +3 -3
  167. package/esm/product-statuses/productStatusesInterfaces.d.ts +1 -4
  168. package/esm/products/productsApi.d.ts +38 -58
  169. package/esm/products/productsApi.js +59 -72
  170. package/esm/products/productsInterfaces.d.ts +48 -85
  171. package/esm/search/searchApi.d.ts +1 -1
  172. package/esm/search/searchApi.js +4 -3
  173. package/esm/sitemap/sitemapInterfaces.d.ts +10 -6
  174. package/esm/subscriptions/subscriptionsApi.d.ts +1 -1
  175. package/esm/subscriptions/subscriptionsApi.js +1 -1
  176. package/esm/subscriptions/subscriptionsInterfaces.d.ts +1 -1
  177. package/esm/system/systemApi.d.ts +2 -0
  178. package/esm/system/systemApi.js +2 -0
  179. package/esm/system/systemInterfaces.d.ts +2 -0
  180. package/esm/templates/templatesApi.d.ts +2 -2
  181. package/esm/templates/templatesApi.js +11 -10
  182. package/esm/templates/templatesInterfaces.d.ts +2 -2
  183. package/esm/templates-preview/templatesPreviewApi.js +2 -2
  184. package/esm/templates-preview/templatesPreviewInterfaces.d.ts +23 -13
  185. package/esm/templates-preview/templatesPreviewSchemas.d.ts +7 -0
  186. package/esm/templates-preview/templatesPreviewSchemas.js +2 -0
  187. package/esm/user-groups/userGroupsApi.js +5 -5
  188. package/esm/user-groups/userGroupsSchemas.d.ts +4 -4
  189. package/esm/users/usersApi.d.ts +1 -1
  190. package/esm/users/usersApi.js +28 -15
  191. package/esm/users/usersInterfaces.d.ts +2 -9
  192. package/esm/web-socket/lazySocket.d.ts +6 -5
  193. package/esm/web-socket/lazySocket.js +212 -15
  194. package/esm/web-socket/wsApi.d.ts +7 -4
  195. package/esm/web-socket/wsApi.js +49 -12
  196. package/esm/web-socket/wsInterfaces.d.ts +41 -4
  197. package/package.json +2 -2
@@ -8,11 +8,12 @@ import type { Socket } from 'socket.io-client';
8
8
  * queued and replayed onto the real socket as soon as the chunk resolves, and every later
9
9
  * call passes straight through.
10
10
  * @param {() => Promise<Socket>} createSocket - Loads Socket.io and creates the socket.
11
- * @returns {Socket} Stand-in usable exactly like the socket it will become.
11
+ * @returns {Socket} Stand-in usable like the socket it will become.
12
12
  * @description Listener registration is what matters for ordering, and it is safe: the queue is
13
13
  * replayed in the same tick the socket is created, before the connection can deliver anything.
14
- * The one visible difference is that methods returning a value (e.g. `listeners()`) cannot answer
15
- * before the chunk arrives — they return the proxy instead. Reading state (`id`, `connected`, …)
16
- * is accurate, and awaiting `socket.io` or other nested objects is only possible once loaded.
14
+ * Before the chunk arrives: `emitWithAck` returns a Promise settled by the real socket,
15
+ * `hasListeners`/`listeners` answer from the queued listeners, `socket.io.on(…)` and `volatile` are
16
+ * queued, assignments (e.g. `socket.auth = …`) are applied to the real socket, and other properties
17
+ * read `undefined`. A failed chunk load is reported to the `connect_error` listeners.
17
18
  */
18
- export default function createLazySocket(createSocket: () => Promise<Socket>): Socket;
19
+ export default function createLazySocket<S extends Socket = Socket>(createSocket: () => Promise<S>): S;
@@ -7,9 +7,41 @@ const PENDING_STATE = {
7
7
  id: undefined,
8
8
  connected: false,
9
9
  disconnected: true,
10
- active: false,
10
+ // A socket created with `autoConnect` is active from the start
11
+ active: true,
11
12
  recovered: false,
12
13
  };
14
+ /**
15
+ * Socket methods that may be called before the real socket exists: they are queued and replayed.
16
+ * @description Any other property read early answers `undefined`. Queuing every name used to put
17
+ * `toJSON` (read by `JSON.stringify`) into the queue, and its replay threw and lost every listener.
18
+ */
19
+ const QUEUEABLE = new Set([
20
+ 'on',
21
+ 'once',
22
+ 'off',
23
+ 'addListener',
24
+ 'removeListener',
25
+ 'removeAllListeners',
26
+ 'onAny',
27
+ 'prependAny',
28
+ 'offAny',
29
+ 'onAnyOutgoing',
30
+ 'prependAnyOutgoing',
31
+ 'offAnyOutgoing',
32
+ 'emit',
33
+ 'send',
34
+ 'connect',
35
+ 'open',
36
+ 'disconnect',
37
+ 'close',
38
+ 'compress',
39
+ 'timeout',
40
+ ]);
41
+ /**
42
+ * Methods of `socket.io` (the Manager) that may be called before the real socket exists.
43
+ */
44
+ const IO_QUEUEABLE = new Set(['on', 'once', 'off', 'reconnection']);
13
45
  /**
14
46
  * Wraps a not-yet-loaded Socket.io socket in a synchronous stand-in.
15
47
  *
@@ -19,30 +51,108 @@ const PENDING_STATE = {
19
51
  * queued and replayed onto the real socket as soon as the chunk resolves, and every later
20
52
  * call passes straight through.
21
53
  * @param {() => Promise<Socket>} createSocket - Loads Socket.io and creates the socket.
22
- * @returns {Socket} Stand-in usable exactly like the socket it will become.
54
+ * @returns {Socket} Stand-in usable like the socket it will become.
23
55
  * @description Listener registration is what matters for ordering, and it is safe: the queue is
24
56
  * replayed in the same tick the socket is created, before the connection can deliver anything.
25
- * The one visible difference is that methods returning a value (e.g. `listeners()`) cannot answer
26
- * before the chunk arrives — they return the proxy instead. Reading state (`id`, `connected`, …)
27
- * is accurate, and awaiting `socket.io` or other nested objects is only possible once loaded.
57
+ * Before the chunk arrives: `emitWithAck` returns a Promise settled by the real socket,
58
+ * `hasListeners`/`listeners` answer from the queued listeners, `socket.io.on(…)` and `volatile` are
59
+ * queued, assignments (e.g. `socket.auth = …`) are applied to the real socket, and other properties
60
+ * read `undefined`. A failed chunk load is reported to the `connect_error` listeners.
28
61
  */
29
62
  export default function createLazySocket(createSocket) {
30
63
  let socket;
64
+ let loadError;
31
65
  const queued = [];
66
+ const pendingProps = new Map();
67
+ // The listeners the queue leaves registered, `off`/`removeAllListeners` applied in order
68
+ const queuedListeners = (event) => {
69
+ let listeners = [];
70
+ for (const { target, method, args } of queued) {
71
+ if (target !== 'socket')
72
+ continue;
73
+ if (method === 'on' || method === 'once' || method === 'addListener') {
74
+ listeners.push({
75
+ event: args[0],
76
+ fn: args[1],
77
+ });
78
+ }
79
+ else if (method === 'off' || method === 'removeListener') {
80
+ // `off()` without arguments removes every listener, as in Socket.io
81
+ listeners = listeners.filter((l) => (args.length > 0 && l.event !== args[0]) ||
82
+ (args.length > 1 && l.fn !== args[1]));
83
+ }
84
+ else if (method === 'removeAllListeners') {
85
+ listeners = listeners.filter((l) => args.length > 0 && l.event !== args[0]);
86
+ }
87
+ }
88
+ return listeners
89
+ .filter((l) => event === undefined || l.event === event)
90
+ .map((l) => l.fn);
91
+ };
32
92
  const loading = createSocket().then((created) => {
93
+ // Assigned first: a listener running during the replay already reaches the real socket
94
+ socket = created;
95
+ for (const [property, value] of pendingProps) {
96
+ created[property] = value;
97
+ }
98
+ pendingProps.clear();
33
99
  // Replay before returning: the connection cannot emit anything until this tick ends,
34
- // so no event registered through the proxy can be missed.
35
- for (const { method, args } of queued) {
36
- created[method](...args);
100
+ // so no event registered through the proxy can be missed. One failing call must not
101
+ // drop the rest of the queue.
102
+ for (const { target, method, args } of queued) {
103
+ try {
104
+ const owner = target === 'io' ? created.io : created;
105
+ if (method === 'volatile') {
106
+ void owner.volatile;
107
+ }
108
+ else if (method === 'emitWithAck') {
109
+ // Replayed in its place in the queue: a `timeout()` queued before it is its own flag
110
+ const { resolve, reject } = args.pop();
111
+ owner.emitWithAck(...args).then(resolve, reject);
112
+ }
113
+ else {
114
+ owner[method](...args);
115
+ }
116
+ }
117
+ catch (error) {
118
+ // eslint-disable-next-line no-undef, no-console
119
+ console.error(`OneEntry SDK: socket.${method}() failed`, error);
120
+ }
37
121
  }
38
122
  queued.length = 0;
39
- socket = created;
40
123
  return created;
41
124
  });
42
- // A failed chunk load must not surface as an unhandled rejection
125
+ // A failed chunk load must not surface as an unhandled rejection: it goes to the
126
+ // `connect_error` listeners, the place Socket.io reports a connection that cannot open
43
127
  loading.catch((error) => {
44
- // eslint-disable-next-line no-undef, no-console
45
- console.error('OneEntry SDK: failed to load socket.io-client', error);
128
+ loadError = error;
129
+ const listeners = queuedListeners('connect_error');
130
+ for (const { method, args } of queued) {
131
+ if (method === 'emitWithAck') {
132
+ args[args.length - 1].reject(error);
133
+ }
134
+ }
135
+ queued.length = 0;
136
+ if (listeners.length === 0) {
137
+ // eslint-disable-next-line no-undef, no-console
138
+ console.error('OneEntry SDK: could not create the socket', error);
139
+ }
140
+ for (const listener of listeners) {
141
+ listener(error);
142
+ }
143
+ });
144
+ const ioProxy = new Proxy({}, {
145
+ get(_target, property) {
146
+ if (typeof property === 'string' && IO_QUEUEABLE.has(property)) {
147
+ return (...args) => {
148
+ if (!loadError) {
149
+ queued.push({ target: 'io', method: property, args });
150
+ }
151
+ return ioProxy;
152
+ };
153
+ }
154
+ return undefined;
155
+ },
46
156
  });
47
157
  const proxy = new Proxy({}, {
48
158
  get(_target, property) {
@@ -54,13 +164,100 @@ export default function createLazySocket(createSocket) {
54
164
  if (property === 'then' || typeof property === 'symbol') {
55
165
  return undefined;
56
166
  }
167
+ if (pendingProps.has(property)) {
168
+ return pendingProps.get(property);
169
+ }
170
+ if (property === 'active') {
171
+ // Active until a queued disconnect or a failed load, as the real socket would be
172
+ // The last queued connect/disconnect decides, as on the real socket
173
+ const last = [...queued]
174
+ .reverse()
175
+ .find(({ target, method }) => target === 'socket' &&
176
+ ['disconnect', 'close', 'connect', 'open'].includes(method));
177
+ return (!loadError &&
178
+ !(last && (last.method === 'disconnect' || last.method === 'close')));
179
+ }
57
180
  if (property in PENDING_STATE) {
58
181
  return PENDING_STATE[property];
59
182
  }
60
- return (...args) => {
61
- queued.push({ method: property, args });
183
+ if (property === 'io') {
184
+ return ioProxy;
185
+ }
186
+ if (property === 'volatile') {
187
+ if (!loadError) {
188
+ queued.push({ target: 'socket', method: 'volatile', args: [] });
189
+ }
62
190
  return proxy;
63
- };
191
+ }
192
+ if (property === 'emitWithAck') {
193
+ return (...args) => loadError
194
+ ? Promise.reject(loadError)
195
+ : new Promise((resolve, reject) => {
196
+ queued.push({
197
+ target: 'socket',
198
+ method: 'emitWithAck',
199
+ args: [...args, { resolve, reject }],
200
+ });
201
+ });
202
+ }
203
+ if (property === 'hasListeners') {
204
+ return (event) => queuedListeners(event).length > 0;
205
+ }
206
+ if (property === 'listeners') {
207
+ return (event) => queuedListeners(event);
208
+ }
209
+ if (typeof property === 'string' && QUEUEABLE.has(property)) {
210
+ return (...args) => {
211
+ if (loadError &&
212
+ (property === 'on' || property === 'once') &&
213
+ args[0] === 'connect_error') {
214
+ // Registered after the load already failed: report it straight away
215
+ args[1](loadError);
216
+ }
217
+ else if (!loadError) {
218
+ queued.push({ target: 'socket', method: property, args });
219
+ }
220
+ return proxy;
221
+ };
222
+ }
223
+ return undefined;
224
+ },
225
+ set(_target, property, value) {
226
+ if (socket) {
227
+ return Reflect.set(socket, property, value);
228
+ }
229
+ pendingProps.set(property, value);
230
+ return true;
231
+ },
232
+ has(_target, property) {
233
+ if (socket) {
234
+ return property in socket;
235
+ }
236
+ return (typeof property === 'string' &&
237
+ (property in PENDING_STATE ||
238
+ QUEUEABLE.has(property) ||
239
+ [
240
+ 'io',
241
+ 'volatile',
242
+ 'emitWithAck',
243
+ 'hasListeners',
244
+ 'listeners',
245
+ ].includes(property) ||
246
+ pendingProps.has(property)));
247
+ },
248
+ ownKeys() {
249
+ return socket ? Reflect.ownKeys(socket) : [];
250
+ },
251
+ getOwnPropertyDescriptor(_target, property) {
252
+ if (!socket) {
253
+ return undefined;
254
+ }
255
+ const descriptor = Reflect.getOwnPropertyDescriptor(socket, property);
256
+ // The proxy target holds none of these keys, so they must be reported configurable
257
+ return descriptor ? { ...descriptor, configurable: true } : undefined;
258
+ },
259
+ getPrototypeOf() {
260
+ return socket ? Reflect.getPrototypeOf(socket) : Object.prototype;
64
261
  },
65
262
  });
66
263
  return proxy;
@@ -1,7 +1,7 @@
1
1
  import type { Socket } from 'socket.io-client';
2
2
  import AsyncModules from '../base/asyncModules.js';
3
3
  import type StateModule from '../base/stateModule.js';
4
- import type { IWS } from './wsInterfaces.js';
4
+ import type { IWS, IWsServerEvents } from './wsInterfaces.js';
5
5
  /**
6
6
  * Controllers for working with users
7
7
  * @handle /api/content/ws
@@ -17,11 +17,14 @@ export default class WsApi extends AsyncModules implements IWS {
17
17
  /**
18
18
  * Creates an instance of an object Socket.io with a connection.
19
19
  * @handleName connect
20
- * @returns {Socket} Returns a Socket instance.
21
- * @description Creates an instance of an object Socket.io with a connection. This method requires user authorization.
20
+ * @returns {Socket<IWsServerEvents>} Returns a Socket instance.
21
+ * @description Opens a Socket.io connection. Without a signed-in user the socket is a guest and
22
+ * receives only notifications sent to everyone; personal ones need `AuthProvider.auth` first.
23
+ * The current access token is sent on every (re)connection, so a refreshed token is picked up.
24
+ * Every call opens a separate connection.
22
25
  * Socket.io is imported on demand, so projects that never open a socket do not bundle it; the returned
23
26
  * value is usable immediately either way (see `createLazySocket`).
24
27
  * @see {@link https://js-sdk.oneentry.cloud/docs/web-socket/connect connect} documentation.
25
28
  */
26
- connect(): Socket;
29
+ connect(): Socket<IWsServerEvents>;
27
30
  }
@@ -16,28 +16,65 @@ export default class WsApi extends AsyncModules {
16
16
  /**
17
17
  * Creates an instance of an object Socket.io with a connection.
18
18
  * @handleName connect
19
- * @returns {Socket} Returns a Socket instance.
20
- * @description Creates an instance of an object Socket.io with a connection. This method requires user authorization.
19
+ * @returns {Socket<IWsServerEvents>} Returns a Socket instance.
20
+ * @description Opens a Socket.io connection. Without a signed-in user the socket is a guest and
21
+ * receives only notifications sent to everyone; personal ones need `AuthProvider.auth` first.
22
+ * The current access token is sent on every (re)connection, so a refreshed token is picked up.
23
+ * Every call opens a separate connection.
21
24
  * Socket.io is imported on demand, so projects that never open a socket do not bundle it; the returned
22
25
  * value is usable immediately either way (see `createLazySocket`).
23
26
  * @see {@link https://js-sdk.oneentry.cloud/docs/web-socket/connect connect} documentation.
24
27
  */
25
28
  connect() {
26
- if (!this.state.accessToken) {
27
- // eslint-disable-next-line no-undef, no-console
28
- console.error('User is unauthorized');
29
- }
30
29
  return createLazySocket(async () => {
30
+ var _a;
31
31
  const { io } = await import('socket.io-client');
32
- return io(this.state.url, {
32
+ // A session restored from a refresh token has no access token until its first
33
+ // request: the socket went out as a guest. Obtain it first, as REST calls do.
34
+ if (!this.state.accessToken &&
35
+ this._canRefresh() &&
36
+ !this.state.customAuth) {
37
+ await this.refreshToken();
38
+ }
39
+ // A path in the project URL (a reverse proxy prefix) belongs to the socket path:
40
+ // passed in the URL, Socket.io read it as a namespace and answered "Invalid namespace"
41
+ // A proxy path (`/oneentry`) resolves against the page
42
+ // `''` (the site root proxy) must not resolve to the current page's path
43
+ const base = new URL(this.state.url || '/', (_a = globalThis.location) === null || _a === void 0 ? void 0 : _a.href);
44
+ const path = base.pathname.replace(/\/+$/, '') + '/api/content/ws';
45
+ // The platform registers a user only with both the bearer and `x-device-metadata`;
46
+ // without the latter every SDK socket was a guest. Read on each (re)connection so a
47
+ // refreshed token is used, and no `Bearer undefined` for a guest.
48
+ const headers = () => ({
49
+ ...(this.state.accessToken
50
+ ? { Authorization: 'Bearer ' + this.state.accessToken }
51
+ : {}),
52
+ 'x-app-token': this.state.token,
53
+ 'x-device-metadata': this._getDeviceMetadata(),
54
+ });
55
+ const socket = io(base.origin, {
33
56
  autoConnect: true,
34
- path: '/api/content/ws',
57
+ path,
35
58
  transports: ['websocket'],
36
- extraHeaders: {
37
- Authorization: 'Bearer ' + this.state.accessToken,
38
- 'x-app-token': this.state.token,
39
- },
59
+ // Browsers drop `extraHeaders` on a WebSocket: the same data goes in the
60
+ // handshake `auth` payload as well
61
+ extraHeaders: headers(),
62
+ auth: (cb) => cb({
63
+ token: this.state.accessToken,
64
+ appToken: this.state.token,
65
+ deviceMetadata: this._getDeviceMetadata(),
66
+ }),
40
67
  });
68
+ // Every connection — automatic reconnection or a manual `socket.connect()` after
69
+ // `disconnect()` — goes through `Manager.open`, which builds the transport from
70
+ // `opts`: refresh the headers there, or a sign-in after the first connect never reached it
71
+ const manager = socket.io;
72
+ const open = manager.open.bind(manager);
73
+ manager.open = (...args) => {
74
+ manager.opts.extraHeaders = headers();
75
+ return open(...args);
76
+ };
77
+ return socket;
41
78
  });
42
79
  }
43
80
  }
@@ -1,4 +1,39 @@
1
1
  import type { Socket } from 'socket.io-client';
2
+ /**
3
+ * @interface IWsNotificationAttribute
4
+ * @property {string} identifier - Attribute marker. Example: "title".
5
+ * @property {string} type - Attribute type. Example: "string".
6
+ * @property {unknown} value - Attribute value as the platform sent it.
7
+ * @description An attribute carried by a notification.
8
+ */
9
+ interface IWsNotificationAttribute {
10
+ identifier: string;
11
+ type: string;
12
+ value: unknown;
13
+ }
14
+ /**
15
+ * @interface IWsNotification
16
+ * @property {string} message - Notification text; an empty string when the event has none.
17
+ * @property {string} [type] - What the notification is about. Example: "product", "order", "user", "form", "refund".
18
+ * @property {IWsNotificationAttribute[]} [attributes] - Attributes selected for the notification in the event settings.
19
+ * @description Payload of the `notification` event. Fields beyond `message` depend on the event
20
+ * (`product`, `order`, `user`, `formData`, …) and are typed `unknown` until checked.
21
+ */
22
+ interface IWsNotification {
23
+ message: string;
24
+ type?: string;
25
+ attributes?: IWsNotificationAttribute[];
26
+ [key: string]: unknown;
27
+ }
28
+ /**
29
+ * @interface IWsServerEvents
30
+ * @property {function(IWsNotification): void} notification - Event notification sent by the platform.
31
+ * @description Events the platform sends over the socket. Other event names stay untyped.
32
+ */
33
+ interface IWsServerEvents {
34
+ notification: (payload: IWsNotification) => void;
35
+ [event: string]: (...args: any[]) => void;
36
+ }
2
37
  /**
3
38
  * @interface IWS
4
39
  * @description This interface defines a method for establishing a WebSocket connection.
@@ -7,10 +42,12 @@ interface IWS {
7
42
  /**
8
43
  * Creates an instance of an object Socket.io with a connection.
9
44
  * @handleName connect
10
- * @returns {Socket} Returns a Socket instance.
11
- * @description Creates an instance of an object Socket.io with a connection. This method requires user authorization.
45
+ * @returns {Socket<IWsServerEvents>} Returns a Socket instance.
46
+ * @description Opens a Socket.io connection. Without a signed-in user the socket is a guest and
47
+ * receives only notifications sent to everyone; personal ones need `AuthProvider.auth` first.
48
+ * Every call opens a separate connection.
12
49
  * @see For more information about configuring the {@link https://js-sdk.oneentry.cloud/docs/category/authprovider authorization module}, see the documentation in the {@link https://js-sdk.oneentry.cloud/docs/category/authprovider configuration settings section of the SDK}.
13
50
  */
14
- connect(): Socket;
51
+ connect(): Socket<IWsServerEvents>;
15
52
  }
16
- export type { IWS };
53
+ export type { IWS, IWsNotification, IWsNotificationAttribute, IWsServerEvents };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oneentry",
3
- "version": "1.0.176",
3
+ "version": "1.0.177",
4
4
  "description": "OneEntry NPM package",
5
5
  "main": "dist/index.js",
6
6
  "module": "esm/index.js",
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "scripts": {
50
50
  "prepublishOnly": "node ../scripts/smoke-pack.js --files-only",
51
- "postpublish": "node ../scripts/verify-published.js --named defineOneEntry --expect 1.0.176"
51
+ "postpublish": "node ../scripts/verify-published.js --named defineOneEntry --expect 1.0.177"
52
52
  },
53
53
  "sideEffects": false,
54
54
  "files": [