@blocklet/payment-broker-client 1.20.17

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 (157) hide show
  1. package/examples/README.md +277 -0
  2. package/examples/browser/README.md +119 -0
  3. package/examples/browser/simple-example.js +223 -0
  4. package/examples/nodejs/README.md +180 -0
  5. package/examples/nodejs/deploy-example.mjs +200 -0
  6. package/examples/nodejs/package.json +30 -0
  7. package/lib/adapters/config/browser.d.ts +12 -0
  8. package/lib/adapters/config/browser.d.ts.map +1 -0
  9. package/lib/adapters/config/browser.js +48 -0
  10. package/lib/adapters/config/browser.js.map +1 -0
  11. package/lib/adapters/config/node.d.ts +13 -0
  12. package/lib/adapters/config/node.d.ts.map +1 -0
  13. package/lib/adapters/config/node.js +62 -0
  14. package/lib/adapters/config/node.js.map +1 -0
  15. package/lib/adapters/http/browser.d.ts +12 -0
  16. package/lib/adapters/http/browser.d.ts.map +1 -0
  17. package/lib/adapters/http/browser.js +50 -0
  18. package/lib/adapters/http/browser.js.map +1 -0
  19. package/lib/adapters/http/node.d.ts +12 -0
  20. package/lib/adapters/http/node.d.ts.map +1 -0
  21. package/lib/adapters/http/node.js +30 -0
  22. package/lib/adapters/http/node.js.map +1 -0
  23. package/lib/browser/adapters/config/browser.d.ts +12 -0
  24. package/lib/browser/adapters/config/browser.d.ts.map +1 -0
  25. package/lib/browser/adapters/config/node.d.ts +13 -0
  26. package/lib/browser/adapters/config/node.d.ts.map +1 -0
  27. package/lib/browser/adapters/http/browser.d.ts +12 -0
  28. package/lib/browser/adapters/http/browser.d.ts.map +1 -0
  29. package/lib/browser/adapters/http/node.d.ts +12 -0
  30. package/lib/browser/adapters/http/node.d.ts.map +1 -0
  31. package/lib/browser/browser/factory.d.ts +19 -0
  32. package/lib/browser/browser/factory.d.ts.map +1 -0
  33. package/lib/browser/browser/index.d.ts +9 -0
  34. package/lib/browser/browser/index.d.ts.map +1 -0
  35. package/lib/browser/core/client.d.ts +29 -0
  36. package/lib/browser/core/client.d.ts.map +1 -0
  37. package/lib/browser/core/deployment.d.ts +20 -0
  38. package/lib/browser/core/deployment.d.ts.map +1 -0
  39. package/lib/browser/core/errors.d.ts +15 -0
  40. package/lib/browser/core/errors.d.ts.map +1 -0
  41. package/lib/browser/core/index.d.ts +10 -0
  42. package/lib/browser/core/index.d.ts.map +1 -0
  43. package/lib/browser/core/interfaces.d.ts +24 -0
  44. package/lib/browser/core/interfaces.d.ts.map +1 -0
  45. package/lib/browser/core/logger.d.ts +8 -0
  46. package/lib/browser/core/logger.d.ts.map +1 -0
  47. package/lib/browser/core/polling.d.ts +23 -0
  48. package/lib/browser/core/polling.d.ts.map +1 -0
  49. package/lib/browser/core/session.d.ts +31 -0
  50. package/lib/browser/core/session.d.ts.map +1 -0
  51. package/lib/browser/core/types.d.ts +175 -0
  52. package/lib/browser/core/types.d.ts.map +1 -0
  53. package/lib/browser/core/utils.d.ts +27 -0
  54. package/lib/browser/core/utils.d.ts.map +1 -0
  55. package/lib/browser/factory.d.ts +19 -0
  56. package/lib/browser/factory.d.ts.map +1 -0
  57. package/lib/browser/factory.js +30 -0
  58. package/lib/browser/factory.js.map +1 -0
  59. package/lib/browser/index.d.ts +8 -0
  60. package/lib/browser/index.d.ts.map +1 -0
  61. package/lib/browser/index.js +973 -0
  62. package/lib/browser/index.js.map +1 -0
  63. package/lib/browser/node/factory.d.ts +9 -0
  64. package/lib/browser/node/factory.d.ts.map +1 -0
  65. package/lib/browser/node/index.d.ts +8 -0
  66. package/lib/browser/node/index.d.ts.map +1 -0
  67. package/lib/core/client.d.ts +29 -0
  68. package/lib/core/client.d.ts.map +1 -0
  69. package/lib/core/client.js +150 -0
  70. package/lib/core/client.js.map +1 -0
  71. package/lib/core/deployment.d.ts +20 -0
  72. package/lib/core/deployment.d.ts.map +1 -0
  73. package/lib/core/deployment.js +184 -0
  74. package/lib/core/deployment.js.map +1 -0
  75. package/lib/core/errors.d.ts +15 -0
  76. package/lib/core/errors.d.ts.map +1 -0
  77. package/lib/core/errors.js +21 -0
  78. package/lib/core/errors.js.map +1 -0
  79. package/lib/core/index.d.ts +10 -0
  80. package/lib/core/index.d.ts.map +1 -0
  81. package/lib/core/index.js +32 -0
  82. package/lib/core/index.js.map +1 -0
  83. package/lib/core/interfaces.d.ts +24 -0
  84. package/lib/core/interfaces.d.ts.map +1 -0
  85. package/lib/core/interfaces.js +4 -0
  86. package/lib/core/interfaces.js.map +1 -0
  87. package/lib/core/logger.d.ts +8 -0
  88. package/lib/core/logger.d.ts.map +1 -0
  89. package/lib/core/logger.js +39 -0
  90. package/lib/core/logger.js.map +1 -0
  91. package/lib/core/polling.d.ts +23 -0
  92. package/lib/core/polling.d.ts.map +1 -0
  93. package/lib/core/polling.js +97 -0
  94. package/lib/core/polling.js.map +1 -0
  95. package/lib/core/session.d.ts +31 -0
  96. package/lib/core/session.d.ts.map +1 -0
  97. package/lib/core/session.js +202 -0
  98. package/lib/core/session.js.map +1 -0
  99. package/lib/core/types.d.ts +175 -0
  100. package/lib/core/types.d.ts.map +1 -0
  101. package/lib/core/types.js +48 -0
  102. package/lib/core/types.js.map +1 -0
  103. package/lib/core/utils.d.ts +27 -0
  104. package/lib/core/utils.d.ts.map +1 -0
  105. package/lib/core/utils.js +181 -0
  106. package/lib/core/utils.js.map +1 -0
  107. package/lib/index.d.ts +484 -0
  108. package/lib/index.d.ts.map +1 -0
  109. package/lib/index.esm.js +969 -0
  110. package/lib/index.esm.js.map +1 -0
  111. package/lib/index.js +984 -0
  112. package/lib/index.js.map +1 -0
  113. package/lib/node/adapters/config/browser.d.ts +12 -0
  114. package/lib/node/adapters/config/browser.d.ts.map +1 -0
  115. package/lib/node/adapters/config/node.d.ts +13 -0
  116. package/lib/node/adapters/config/node.d.ts.map +1 -0
  117. package/lib/node/adapters/http/browser.d.ts +12 -0
  118. package/lib/node/adapters/http/browser.d.ts.map +1 -0
  119. package/lib/node/adapters/http/node.d.ts +12 -0
  120. package/lib/node/adapters/http/node.d.ts.map +1 -0
  121. package/lib/node/browser/factory.d.ts +19 -0
  122. package/lib/node/browser/factory.d.ts.map +1 -0
  123. package/lib/node/browser/index.d.ts +9 -0
  124. package/lib/node/browser/index.d.ts.map +1 -0
  125. package/lib/node/core/client.d.ts +29 -0
  126. package/lib/node/core/client.d.ts.map +1 -0
  127. package/lib/node/core/deployment.d.ts +20 -0
  128. package/lib/node/core/deployment.d.ts.map +1 -0
  129. package/lib/node/core/errors.d.ts +15 -0
  130. package/lib/node/core/errors.d.ts.map +1 -0
  131. package/lib/node/core/index.d.ts +10 -0
  132. package/lib/node/core/index.d.ts.map +1 -0
  133. package/lib/node/core/interfaces.d.ts +24 -0
  134. package/lib/node/core/interfaces.d.ts.map +1 -0
  135. package/lib/node/core/logger.d.ts +8 -0
  136. package/lib/node/core/logger.d.ts.map +1 -0
  137. package/lib/node/core/polling.d.ts +23 -0
  138. package/lib/node/core/polling.d.ts.map +1 -0
  139. package/lib/node/core/session.d.ts +31 -0
  140. package/lib/node/core/session.d.ts.map +1 -0
  141. package/lib/node/core/types.d.ts +175 -0
  142. package/lib/node/core/types.d.ts.map +1 -0
  143. package/lib/node/core/utils.d.ts +27 -0
  144. package/lib/node/core/utils.d.ts.map +1 -0
  145. package/lib/node/factory.d.ts +9 -0
  146. package/lib/node/factory.d.ts.map +1 -0
  147. package/lib/node/factory.js +34 -0
  148. package/lib/node/factory.js.map +1 -0
  149. package/lib/node/index.d.ts +8 -0
  150. package/lib/node/index.d.ts.map +1 -0
  151. package/lib/node/index.js +984 -0
  152. package/lib/node/index.js.map +1 -0
  153. package/lib/node/node/factory.d.ts +9 -0
  154. package/lib/node/node/factory.d.ts.map +1 -0
  155. package/lib/node/node/index.d.ts +8 -0
  156. package/lib/node/node/index.d.ts.map +1 -0
  157. package/package.json +98 -0
package/lib/index.js ADDED
@@ -0,0 +1,984 @@
1
+ 'use strict';
2
+
3
+ /* eslint-disable import/prefer-default-export */
4
+ // Deployment step constants
5
+ const STEPS = {
6
+ PAYMENT_PENDING: 'payment_pending',
7
+ PAYMENT_COMPLETED: 'payment_completed',
8
+ INSTALLATION_STARTING: 'installation_starting',
9
+ INSTALLATION_COMPLETED: 'installation_completed',
10
+ SERVICE_STARTING: 'service_starting',
11
+ SERVICE_READY: 'service_ready',
12
+ ACCESS_PREPARING: 'access_preparing',
13
+ ACCESS_READY: 'access_ready',
14
+ };
15
+ const DEFAULT_CONFIG = {
16
+ timeout: 300000, // 5 minutes
17
+ polling: {
18
+ interval: 3000, // 3 seconds
19
+ maxAttempts: 100,
20
+ backoffStrategy: 'linear',
21
+ },
22
+ };
23
+ const API_ENDPOINTS = {
24
+ createCheckout: '/api/checkout-sessions/start',
25
+ paymentPage: '/checkout/pay/{id}',
26
+ orderStatus: '/api/vendors/order/{id}/status',
27
+ orderDetail: '/api/vendors/order/{id}/detail',
28
+ vendors: '/api/sessions/{id}/vendors',
29
+ };
30
+ const DEPLOYMENT_STEPS = {
31
+ CREATING_SESSION: 'creating_session',
32
+ WAITING_PAYMENT: 'waiting_payment',
33
+ INSTALLING: 'installing',
34
+ STARTING_SERVICE: 'starting_service',
35
+ GETTING_URLS: 'getting_urls',
36
+ COMPLETED: 'completed',
37
+ };
38
+ const ERROR_CODES = {
39
+ NETWORK_ERROR: 'NETWORK_ERROR',
40
+ TIMEOUT_ERROR: 'TIMEOUT_ERROR',
41
+ PAYMENT_ERROR: 'PAYMENT_ERROR',
42
+ VALIDATION_ERROR: 'VALIDATION_ERROR',
43
+ SESSION_ERROR: 'SESSION_ERROR',
44
+ DEPLOYMENT_ERROR: 'DEPLOYMENT_ERROR',
45
+ UNKNOWN_ERROR: 'UNKNOWN_ERROR',
46
+ };
47
+
48
+ /* eslint-disable import/prefer-default-export */
49
+ function createDeploymentError(message, code, options) {
50
+ const error = new Error(message);
51
+ error.code = code;
52
+ error.step = options?.step;
53
+ error.sessionId = options?.sessionId;
54
+ error.paymentUrl = options?.paymentUrl;
55
+ error.linkId = options?.linkId;
56
+ error.timestamp = new Date().toISOString();
57
+ error.details = options?.details;
58
+ error.recovery = options?.recovery;
59
+ return error;
60
+ }
61
+ function isDeploymentError(error) {
62
+ return error && typeof error === 'object' && 'code' in error;
63
+ }
64
+
65
+ /* eslint-disable import/prefer-default-export */
66
+ const httpUtils = {
67
+ async request(url, options = {}) {
68
+ const response = await fetch(url, {
69
+ ...options,
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ ...options.headers,
73
+ },
74
+ });
75
+ if (!response.ok) {
76
+ throw createDeploymentError(`HTTP ${response.status}: ${response.statusText}`, 'NETWORK_ERROR', {
77
+ details: { status: response.status, statusText: response.statusText },
78
+ recovery: {
79
+ canRetry: response.status >= 500, // Server errors can be retried
80
+ suggestions: response.status === 404
81
+ ? ['Check if the URL is correct', 'Verify the service is running']
82
+ : ['Check your network connection', 'Try again later'],
83
+ },
84
+ });
85
+ }
86
+ return response.json();
87
+ },
88
+ get(url, headers) {
89
+ return this.request(url, { method: 'GET', headers });
90
+ },
91
+ post(url, data, headers) {
92
+ return this.request(url, {
93
+ method: 'POST',
94
+ body: data ? JSON.stringify(data) : undefined,
95
+ headers,
96
+ });
97
+ },
98
+ put(url, data, headers) {
99
+ return this.request(url, {
100
+ method: 'PUT',
101
+ body: data ? JSON.stringify(data) : undefined,
102
+ headers,
103
+ });
104
+ },
105
+ delete(url, headers) {
106
+ return this.request(url, { method: 'DELETE', headers });
107
+ },
108
+ };
109
+ const urlUtils = {
110
+ join(...parts) {
111
+ return parts
112
+ .map((part, index) => {
113
+ if (index === 0) {
114
+ return part.replace(/\/+$/, '');
115
+ }
116
+ return part.replace(/^\/+/, '').replace(/\/+$/, '');
117
+ })
118
+ .filter(Boolean)
119
+ .join('/');
120
+ },
121
+ addParams(url, params) {
122
+ const urlObj = new URL(url);
123
+ Object.entries(params).forEach(([key, value]) => {
124
+ if (value !== undefined && value !== null) {
125
+ urlObj.searchParams.set(key, String(value));
126
+ }
127
+ });
128
+ return urlObj.toString();
129
+ },
130
+ replaceParams(url, params) {
131
+ let result = url;
132
+ Object.entries(params).forEach(([key, value]) => {
133
+ result = result.replace(`:${key}`, value);
134
+ });
135
+ return result;
136
+ },
137
+ isValidUrl(url) {
138
+ try {
139
+ // eslint-disable-next-line no-new
140
+ new URL(url);
141
+ return true;
142
+ }
143
+ catch {
144
+ return false;
145
+ }
146
+ },
147
+ };
148
+ const timeUtils = {
149
+ formatDuration(ms) {
150
+ const seconds = Math.floor(ms / 1000);
151
+ const minutes = Math.floor(seconds / 60);
152
+ const hours = Math.floor(minutes / 60);
153
+ if (hours > 0) {
154
+ return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
155
+ }
156
+ if (minutes > 0) {
157
+ return `${minutes}m ${seconds % 60}s`;
158
+ }
159
+ return `${seconds}s`;
160
+ },
161
+ sleep(ms) {
162
+ return new Promise((resolve) => {
163
+ setTimeout(resolve, ms);
164
+ });
165
+ },
166
+ timeout(promise, ms) {
167
+ return Promise.race([
168
+ promise,
169
+ new Promise((_, reject) => {
170
+ setTimeout(() => reject(createDeploymentError('Operation timed out', 'TIMEOUT_ERROR', {
171
+ recovery: {
172
+ canRetry: true,
173
+ suggestions: ['Try again with a longer timeout', 'Check your network connection'],
174
+ },
175
+ })), ms);
176
+ }),
177
+ ]);
178
+ },
179
+ now() {
180
+ return new Date().toISOString();
181
+ },
182
+ };
183
+ const objectUtils = {
184
+ deepMerge(target, ...sources) {
185
+ if (!sources.length)
186
+ return target;
187
+ const source = sources.shift();
188
+ if (this.isObject(target) && this.isObject(source)) {
189
+ Object.keys(source).forEach((key) => {
190
+ if (this.isObject(source[key])) {
191
+ if (!target[key])
192
+ Object.assign(target, { [key]: {} });
193
+ this.deepMerge(target[key], source[key]);
194
+ }
195
+ else {
196
+ Object.assign(target, { [key]: source[key] });
197
+ }
198
+ });
199
+ }
200
+ return this.deepMerge(target, ...sources);
201
+ },
202
+ isObject(item) {
203
+ return item && typeof item === 'object' && !Array.isArray(item);
204
+ },
205
+ pick(obj, keys) {
206
+ const result = {};
207
+ keys.forEach((key) => {
208
+ if (key in obj) {
209
+ result[key] = obj[key];
210
+ }
211
+ });
212
+ return result;
213
+ },
214
+ omit(obj, keys) {
215
+ const result = { ...obj };
216
+ keys.forEach((key) => {
217
+ delete result[key];
218
+ });
219
+ return result;
220
+ },
221
+ deepClone(obj) {
222
+ if (obj === null || typeof obj !== 'object') {
223
+ return obj;
224
+ }
225
+ if (obj instanceof Date) {
226
+ return new Date(obj.getTime());
227
+ }
228
+ if (obj instanceof Array) {
229
+ return obj.map((item) => this.deepClone(item));
230
+ }
231
+ if (typeof obj === 'object') {
232
+ const cloned = {};
233
+ Object.keys(obj).forEach((key) => {
234
+ cloned[key] = this.deepClone(obj[key]);
235
+ });
236
+ return cloned;
237
+ }
238
+ return obj;
239
+ },
240
+ };
241
+
242
+ /* eslint-disable import/prefer-default-export */
243
+ // Internal debug logger - only logs when BROKER_CLIENT_DEBUG=true
244
+ const isDebugEnabled = (() => {
245
+ try {
246
+ return typeof process !== 'undefined' && process.env?.BROKER_CLIENT_DEBUG === 'true';
247
+ }
248
+ catch {
249
+ // In browser environments, check localStorage or global variables
250
+ return typeof window !== 'undefined' && window.BROKER_CLIENT_DEBUG === 'true';
251
+ }
252
+ })();
253
+ const logger = {
254
+ debug: (message, data) => {
255
+ if (isDebugEnabled) {
256
+ // eslint-disable-next-line no-console
257
+ console.log(`[BROKER-CLIENT-DEBUG] ${message}`, data ? JSON.stringify(data) : '');
258
+ }
259
+ },
260
+ info: (message, data) => {
261
+ if (isDebugEnabled) {
262
+ // eslint-disable-next-line no-console
263
+ console.log(`[BROKER-CLIENT-DEBUG] ${message}`, data ? JSON.stringify(data) : '');
264
+ }
265
+ },
266
+ warn: (message, data) => {
267
+ if (isDebugEnabled) {
268
+ console.warn(`[BROKER-CLIENT-DEBUG] ${message}`, data ? JSON.stringify(data) : '');
269
+ }
270
+ },
271
+ error: (message, data) => {
272
+ if (isDebugEnabled) {
273
+ console.error(`[BROKER-CLIENT-DEBUG] ${message}`, data ? JSON.stringify(data) : '');
274
+ }
275
+ },
276
+ };
277
+
278
+ /* eslint-disable import/prefer-default-export */
279
+ class SessionManager {
280
+ constructor(config, deps) {
281
+ this.config = config;
282
+ this.deps = deps;
283
+ }
284
+ async getConfigInfo() {
285
+ if (this.cachedConfig) {
286
+ return this.cachedConfig;
287
+ }
288
+ const blockletInfo = await this.deps.configProvider.getBlockletInfo();
289
+ const paymentLinkKey = this.config.paymentLinkKey || 'PAYMENT_LINK_ID';
290
+ const linkId = blockletInfo[paymentLinkKey];
291
+ if (!linkId) {
292
+ throw createDeploymentError(`Payment link ID not found using key '${paymentLinkKey}' in blocklet configuration`, 'VALIDATION_ERROR', {
293
+ step: 'creating_session',
294
+ recovery: {
295
+ canRetry: false,
296
+ suggestions: [
297
+ `Make sure ${paymentLinkKey} is set in the environment`,
298
+ 'Check if the Payment Kit is properly configured',
299
+ 'Verify the paymentLinkKey configuration is correct',
300
+ ],
301
+ },
302
+ });
303
+ }
304
+ const paymentKitDid = 'z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk';
305
+ let mountPoint = '/';
306
+ if (blockletInfo.componentMountPoints && Array.isArray(blockletInfo.componentMountPoints)) {
307
+ const paymentKitComponent = blockletInfo.componentMountPoints.find((component) => component.did === paymentKitDid || component.appId === paymentKitDid);
308
+ if (paymentKitComponent?.mountPoint) {
309
+ mountPoint = paymentKitComponent.mountPoint;
310
+ }
311
+ }
312
+ this.cachedConfig = { linkId, mountPoint, paymentKitDid };
313
+ logger.info('Configuration processed', this.cachedConfig);
314
+ return this.cachedConfig;
315
+ }
316
+ /**
317
+ * Get linkId
318
+ */
319
+ async getLinkId() {
320
+ const { linkId } = await this.getConfigInfo();
321
+ return linkId;
322
+ }
323
+ /**
324
+ * Get mountPoint
325
+ */
326
+ async getMountPoint() {
327
+ const { mountPoint } = await this.getConfigInfo();
328
+ return mountPoint;
329
+ }
330
+ /**
331
+ * Get paymentKitDid
332
+ */
333
+ async getPaymentKitDid() {
334
+ const { paymentKitDid } = await this.getConfigInfo();
335
+ return paymentKitDid;
336
+ }
337
+ async checkCacheCheckoutId(checkoutId) {
338
+ try {
339
+ if (!checkoutId) {
340
+ return '';
341
+ }
342
+ // API_ENDPOINTS already includes /api prefix
343
+ const orderStatusUrl = urlUtils.join(this.config.baseUrl, API_ENDPOINTS.orderStatus.replace('{id}', checkoutId));
344
+ const response = await this.deps.httpClient.get(orderStatusUrl);
345
+ if (response.error) {
346
+ throw new Error(response.error);
347
+ }
348
+ // Check payment status
349
+ const isPaid = response.payment_status === 'paid';
350
+ return isPaid ? checkoutId : '';
351
+ }
352
+ catch {
353
+ return '';
354
+ }
355
+ }
356
+ async createSession(options = {}) {
357
+ const { linkId, mountPoint, paymentKitDid } = await this.getConfigInfo();
358
+ logger.info('Creating payment session', { linkId, mountPoint, paymentKitDid });
359
+ try {
360
+ // Build URL - API_ENDPOINTS already includes /api prefix
361
+ const url = urlUtils.join(this.config.baseUrl, API_ENDPOINTS.createCheckout, linkId);
362
+ const { needShortUrl = true, page_info: pageInfo } = options;
363
+ const payload = {
364
+ needShortUrl,
365
+ metadata: {
366
+ page_info: {
367
+ has_vendor: true,
368
+ ...pageInfo,
369
+ },
370
+ },
371
+ };
372
+ const response = await timeUtils.timeout(this.deps.httpClient.post(url, payload), this.config.timeout || 30000);
373
+ const session = {
374
+ id: response.checkoutSession.id,
375
+ paymentUrl: response.paymentUrl,
376
+ status: 'pending',
377
+ linkId,
378
+ vendorDid: paymentKitDid,
379
+ createdAt: timeUtils.now(),
380
+ updatedAt: timeUtils.now(),
381
+ expiresAt: new Date(Date.now() + (this.config.timeout || 300000)).toISOString(),
382
+ currency: 'USD',
383
+ };
384
+ logger.info('Session created successfully', { sessionId: session.id });
385
+ return session;
386
+ }
387
+ catch (error) {
388
+ logger.error('Failed to create session', { error: error.message, linkId });
389
+ throw createDeploymentError(`Failed to create session: ${error.message}`, 'SESSION_ERROR', {
390
+ step: 'creating_session',
391
+ linkId,
392
+ details: { originalError: error },
393
+ recovery: {
394
+ canRetry: true,
395
+ suggestions: ['Check your network connection', 'Verify the Payment Kit service is available'],
396
+ },
397
+ });
398
+ }
399
+ }
400
+ async getSessionStatus(sessionId) {
401
+ logger.debug('Getting session status', { sessionId });
402
+ try {
403
+ // API_ENDPOINTS already includes /api prefix
404
+ const url = urlUtils.join(this.config.baseUrl, API_ENDPOINTS.orderStatus.replace('{id}', sessionId));
405
+ const response = await timeUtils.timeout(this.deps.httpClient.get(url), this.config.timeout || 30000);
406
+ logger.debug('Session status retrieved', { sessionId, status: response.payment_status });
407
+ return response;
408
+ }
409
+ catch (error) {
410
+ logger.error('Failed to get session status', { error: error.message, sessionId });
411
+ throw createDeploymentError(`Failed to get session status: ${error.message}`, 'SESSION_ERROR', {
412
+ sessionId,
413
+ recovery: {
414
+ canRetry: true,
415
+ suggestions: ['Check your network connection', 'Verify the session ID is correct'],
416
+ },
417
+ });
418
+ }
419
+ }
420
+ waitForPayment(sessionId) {
421
+ logger.info('Waiting for payment completion', { sessionId });
422
+ return this.deps.pollingManager.poll({
423
+ checkCondition: async () => {
424
+ const status = await this.getSessionStatus(sessionId);
425
+ if (status.payment_status === 'paid') {
426
+ logger.info('Payment completed', { sessionId });
427
+ return status.vendors || true;
428
+ }
429
+ if (status.payment_status === 'expired' || status.payment_status === 'cancelled') {
430
+ throw createDeploymentError(`Payment ${status.payment_status}`, 'SESSION_ERROR', {
431
+ sessionId,
432
+ recovery: {
433
+ canRetry: status.payment_status === 'expired',
434
+ suggestions: status.payment_status === 'expired'
435
+ ? ['Create a new payment session', 'Try the deployment again']
436
+ : ['Payment was cancelled', 'Start a new deployment if needed'],
437
+ },
438
+ });
439
+ }
440
+ return false;
441
+ },
442
+ stepName: 'waiting for payment',
443
+ maxAttempts: this.config.polling?.maxAttempts || 100,
444
+ interval: this.config.polling?.interval || 3000,
445
+ });
446
+ }
447
+ async getOrderDetails(sessionId) {
448
+ logger.debug('Getting order details', { sessionId });
449
+ try {
450
+ // API_ENDPOINTS already includes /api prefix
451
+ const url = urlUtils.join(this.config.baseUrl, API_ENDPOINTS.orderDetail.replace('{id}', sessionId));
452
+ const response = await timeUtils.timeout(this.deps.httpClient.get(url), this.config.timeout || 30000);
453
+ logger.debug('Order details retrieved', { sessionId });
454
+ return response;
455
+ }
456
+ catch (error) {
457
+ logger.error('Failed to get order details', { error: error.message, sessionId });
458
+ throw createDeploymentError(`Failed to get order details: ${error.message}`, 'SESSION_ERROR', {
459
+ sessionId,
460
+ recovery: {
461
+ canRetry: true,
462
+ suggestions: ['Check your network connection', 'Verify the session is still active'],
463
+ },
464
+ });
465
+ }
466
+ }
467
+ }
468
+
469
+ /* eslint-disable import/prefer-default-export */
470
+ /**
471
+ * Unified DeploymentManager class
472
+ * Uses dependency injection to support different environment implementations
473
+ */
474
+ class DeploymentManager {
475
+ constructor(config, deps) {
476
+ this.config = config;
477
+ this.deps = deps;
478
+ this.installationStarted = false;
479
+ this.serviceStartCallbackCalled = false;
480
+ this.currentDeployment = null;
481
+ }
482
+ async startDeployment(sessionId, options) {
483
+ this.currentDeployment = {
484
+ sessionId,
485
+ startTime: timeUtils.now(),
486
+ };
487
+ this.installationStarted = false;
488
+ this.serviceStartCallbackCalled = false;
489
+ logger.info('Starting deployment', { sessionId });
490
+ try {
491
+ await this.waitForPaymentCompletion(sessionId, options);
492
+ const vendors = await this.waitForInstallation(sessionId, options);
493
+ await this.waitForServiceStartup(vendors, options);
494
+ const result = await this.getFinalUrls(sessionId, vendors, options);
495
+ this.currentDeployment.result = result;
496
+ logger.info('Deployment completed successfully', { sessionId, duration: result.duration });
497
+ return result;
498
+ }
499
+ catch (error) {
500
+ logger.error('Deployment failed', { sessionId, error: error.message });
501
+ this.currentDeployment.error = error;
502
+ options.onError?.(error, 'getting_urls'); // Call onError
503
+ throw error;
504
+ }
505
+ }
506
+ async waitForPaymentCompletion(sessionId, options) {
507
+ logger.info('Waiting for payment to be marked as paid', { sessionId });
508
+ await this.deps.pollingManager.poll({
509
+ checkCondition: async () => {
510
+ // API_ENDPOINTS already includes /api prefix
511
+ const orderStatusUrl = urlUtils.join(this.config.baseUrl, API_ENDPOINTS.orderStatus.replace('{id}', sessionId));
512
+ const response = await this.deps.httpClient.get(orderStatusUrl);
513
+ if (response.session_status === 'complete') {
514
+ const vendors = response.vendors || [];
515
+ await options.hooks?.[STEPS.PAYMENT_COMPLETED]?.({
516
+ sessionId,
517
+ vendors,
518
+ });
519
+ return true;
520
+ }
521
+ return false;
522
+ },
523
+ stepName: 'waiting_payment',
524
+ });
525
+ }
526
+ waitForInstallation(sessionId, options) {
527
+ logger.info('Waiting for installation to start', { sessionId });
528
+ return this.deps.pollingManager.poll({
529
+ checkCondition: async () => {
530
+ // API_ENDPOINTS already includes /api prefix
531
+ const url = urlUtils.join(this.config.baseUrl, API_ENDPOINTS.orderStatus.replace('{id}', sessionId));
532
+ const response = await this.deps.httpClient.get(url);
533
+ const vendors = response.vendors || [];
534
+ if (vendors.length === 0) {
535
+ return false;
536
+ }
537
+ if (vendors.length > 0 && !this.installationStarted) {
538
+ this.installationStarted = true;
539
+ await options.hooks?.[STEPS.INSTALLATION_STARTING]?.({
540
+ vendors,
541
+ });
542
+ }
543
+ // Check if all vendors meet conditions: progress >= 80 and appUrl exists
544
+ const isInstalled = vendors.every((vendor) => vendor.progress >= 80 && vendor.appUrl);
545
+ if (isInstalled) {
546
+ const avgProgress = vendors.reduce((sum, v) => sum + v.progress, 0) / vendors.length;
547
+ await options.hooks?.[STEPS.INSTALLATION_COMPLETED]?.({
548
+ vendors,
549
+ progress: Math.round(avgProgress),
550
+ });
551
+ return vendors;
552
+ }
553
+ return false;
554
+ },
555
+ stepName: 'installation_started',
556
+ });
557
+ }
558
+ async waitForServiceStartup(vendors, options) {
559
+ logger.info('Services starting', { vendorCount: vendors.length });
560
+ // Since we don't need to check service status, we can directly call the callbacks
561
+ await options.hooks?.[STEPS.SERVICE_STARTING]?.({
562
+ vendors,
563
+ });
564
+ // Wait a brief moment for services to initialize
565
+ await new Promise((resolve) => {
566
+ setTimeout(resolve, 2000);
567
+ });
568
+ logger.info('Services started successfully');
569
+ await options.hooks?.[STEPS.SERVICE_READY]?.({
570
+ vendors,
571
+ });
572
+ }
573
+ async getFinalUrls(sessionId, runningVendors, options) {
574
+ try {
575
+ await options.hooks?.[STEPS.ACCESS_PREPARING]?.({
576
+ sessionId,
577
+ });
578
+ // API_ENDPOINTS already includes /api prefix
579
+ const orderDetailUrl = urlUtils.join(this.config.baseUrl, API_ENDPOINTS.orderDetail.replace('{id}', sessionId));
580
+ const data = await this.deps.httpClient.get(orderDetailUrl);
581
+ if (data.vendors.length === 0) {
582
+ throw createDeploymentError('No vendors found in order details', 'DEPLOYMENT_ERROR', {
583
+ step: 'getting_urls',
584
+ sessionId,
585
+ recovery: {
586
+ canRetry: true,
587
+ suggestions: ['Wait a moment and try again', 'Check if the deployment completed successfully'],
588
+ },
589
+ });
590
+ }
591
+ // Wait 3 seconds like in the original code
592
+ await timeUtils.sleep(3000);
593
+ // Return the URLs from the API response, fallback to running vendor data
594
+ const apiVendor = data.vendors[0];
595
+ const primaryVendor = runningVendors[0];
596
+ const endTime = timeUtils.now();
597
+ const duration = this.currentDeployment.startTime
598
+ ? new Date(endTime).getTime() - new Date(this.currentDeployment.startTime).getTime()
599
+ : 0;
600
+ const result = {
601
+ success: true,
602
+ sessionId,
603
+ appUrl: apiVendor?.appUrl || primaryVendor?.appUrl,
604
+ dashboardUrl: apiVendor?.dashboardUrl || primaryVendor?.dashboardUrl,
605
+ homeUrl: apiVendor?.homeUrl || primaryVendor?.homeUrl,
606
+ token: apiVendor?.token || primaryVendor?.token,
607
+ subscriptionUrl: data.subscriptionUrl,
608
+ vendors: data.vendors || runningVendors,
609
+ duration,
610
+ startTime: this.currentDeployment.startTime || timeUtils.now(),
611
+ endTime,
612
+ metadata: data.metadata,
613
+ data: data.data,
614
+ };
615
+ await options.hooks?.[STEPS.ACCESS_READY]?.({
616
+ sessionId,
617
+ appUrl: result.appUrl,
618
+ dashboardUrl: result.dashboardUrl,
619
+ homeUrl: result.homeUrl,
620
+ subscriptionUrl: result.subscriptionUrl,
621
+ });
622
+ return result;
623
+ }
624
+ catch (error) {
625
+ logger.error('Failed to get final URLs', { sessionId, error: error.message });
626
+ // If getting details fails, use the appUrl of running vendor
627
+ return {
628
+ success: true,
629
+ sessionId,
630
+ appUrl: runningVendors[0]?.appUrl || null,
631
+ dashboardUrl: runningVendors[0]?.dashboardUrl || null,
632
+ homeUrl: runningVendors[0]?.homeUrl || null,
633
+ token: runningVendors[0]?.token || null,
634
+ duration: this.currentDeployment.startTime
635
+ ? new Date().getTime() - new Date(this.currentDeployment.startTime).getTime()
636
+ : 0,
637
+ };
638
+ }
639
+ }
640
+ }
641
+
642
+ /**
643
+ * Unified BrokerClient class
644
+ * Uses dependency injection to support different environment implementations
645
+ */
646
+ class BrokerClient {
647
+ constructor(config, dependencies) {
648
+ this.isDeploying = false;
649
+ this.currentDeployment = null;
650
+ this.validateConfig(config);
651
+ this.config = objectUtils.deepMerge({}, DEFAULT_CONFIG, config);
652
+ this.sessionManager = new SessionManager(this.config, dependencies);
653
+ this.deploymentManager = new DeploymentManager(this.config, dependencies);
654
+ }
655
+ async deploy(options) {
656
+ if (this.isDeploying) {
657
+ throw createDeploymentError('Deployment already in progress', 'VALIDATION_ERROR');
658
+ }
659
+ this.isDeploying = true;
660
+ this.currentDeployment = {
661
+ sessionId: '', // Will be set after session creation
662
+ startTime: timeUtils.now(),
663
+ };
664
+ try {
665
+ let sessionId;
666
+ let paymentUrl = options.cachedPaymentUrl;
667
+ // Check cached checkout session
668
+ if (options.cachedCheckoutId) {
669
+ logger.info('Checking cached checkout session', { cachedCheckoutId: options.cachedCheckoutId });
670
+ const cachedCheckoutId = await this.sessionManager.checkCacheCheckoutId(options.cachedCheckoutId);
671
+ if (cachedCheckoutId) {
672
+ sessionId = cachedCheckoutId;
673
+ logger.info('Using cached session', { sessionId });
674
+ // Build payment URL if not cached
675
+ if (!paymentUrl) {
676
+ const mountPoint = await this.sessionManager.getMountPoint();
677
+ const basePath = `${this.config.baseUrl}${mountPoint}`;
678
+ paymentUrl = `${basePath}/checkout/pay/${sessionId}`;
679
+ }
680
+ await options.hooks?.[STEPS.PAYMENT_PENDING]?.({
681
+ sessionId,
682
+ paymentUrl,
683
+ isResuming: true,
684
+ });
685
+ }
686
+ }
687
+ // Create new session if no valid cached session
688
+ if (!sessionId) {
689
+ logger.info('Creating new checkout session');
690
+ const linkId = await this.sessionManager.getLinkId();
691
+ const session = await this.sessionManager.createSession(options);
692
+ sessionId = session.id;
693
+ paymentUrl = session.paymentUrl;
694
+ await options.hooks?.[STEPS.PAYMENT_PENDING]?.({
695
+ sessionId: session.id,
696
+ paymentUrl: session.paymentUrl,
697
+ linkId,
698
+ isResuming: false,
699
+ });
700
+ }
701
+ this.currentDeployment.sessionId = sessionId;
702
+ const result = await this.deploymentManager.startDeployment(sessionId, options);
703
+ return result;
704
+ }
705
+ catch (error) {
706
+ this.isDeploying = false;
707
+ if (this.currentDeployment) {
708
+ if (isDeploymentError(error)) {
709
+ this.currentDeployment.error = error;
710
+ }
711
+ else {
712
+ this.currentDeployment.error = createDeploymentError(error.message, 'UNKNOWN_ERROR', {
713
+ sessionId: this.currentDeployment.sessionId,
714
+ details: { originalError: error },
715
+ recovery: {
716
+ canRetry: true,
717
+ suggestions: ['Check your network connection', 'Verify the baseUrl is correct'],
718
+ },
719
+ });
720
+ }
721
+ }
722
+ if (options.onError) {
723
+ const deploymentError = isDeploymentError(error) ? error : this.currentDeployment?.error;
724
+ if (deploymentError) {
725
+ options.onError(deploymentError, deploymentError.step);
726
+ }
727
+ }
728
+ throw error;
729
+ }
730
+ }
731
+ createSession(options = {}) {
732
+ return this.sessionManager.createSession(options);
733
+ }
734
+ getSessionStatus(sessionId) {
735
+ return this.sessionManager.getSessionStatus(sessionId);
736
+ }
737
+ cancelDeployment() {
738
+ if (this.isDeploying) {
739
+ logger.info('Cancelling deployment');
740
+ this.isDeploying = false;
741
+ // Note: Actual cancellation would need to be implemented in deployment manager
742
+ }
743
+ }
744
+ getDeploymentStatus() {
745
+ const result = this.currentDeployment?.result;
746
+ const error = this.currentDeployment?.error;
747
+ const sessionId = this.currentDeployment?.sessionId;
748
+ const startTime = this.currentDeployment?.startTime;
749
+ return {
750
+ isDeploying: this.isDeploying,
751
+ result,
752
+ error,
753
+ sessionId,
754
+ duration: startTime ? new Date().getTime() - new Date(startTime).getTime() : 0,
755
+ };
756
+ }
757
+ updateConfig(newConfig) {
758
+ this.config = objectUtils.deepMerge(this.config, newConfig);
759
+ // Note: In a real implementation, we might need to recreate the dependencies
760
+ // For now, we assume the dependencies remain the same
761
+ }
762
+ getConfig() {
763
+ return this.config;
764
+ }
765
+ validateConfig(config) {
766
+ if (!config.baseUrl) {
767
+ throw createDeploymentError('baseUrl is required in configuration', 'VALIDATION_ERROR');
768
+ }
769
+ try {
770
+ // eslint-disable-next-line no-new
771
+ new URL(config.baseUrl);
772
+ }
773
+ catch {
774
+ throw createDeploymentError('Invalid baseUrl format', 'VALIDATION_ERROR');
775
+ }
776
+ }
777
+ }
778
+
779
+ /* eslint-disable import/prefer-default-export */
780
+ class PollingManager {
781
+ constructor(options = {}) {
782
+ this.baseInterval = 1000;
783
+ this.maxAttempts = 60;
784
+ this.backoffStrategy = 'linear';
785
+ this.baseInterval = options.baseInterval || 1000;
786
+ this.maxAttempts = options.maxAttempts || 60;
787
+ this.backoffStrategy = options.backoffStrategy || 'linear';
788
+ }
789
+ async poll(options) {
790
+ const { checkCondition, stepName = 'polling', interval = this.baseInterval, maxAttempts = this.maxAttempts, backoffStrategy = this.backoffStrategy, onProgress, } = options;
791
+ for (let attempts = 1; attempts <= maxAttempts; attempts++) {
792
+ try {
793
+ logger.debug(`${stepName} - Attempt ${attempts}/${maxAttempts}`);
794
+ // eslint-disable-next-line no-await-in-loop
795
+ const result = await checkCondition();
796
+ if (result !== null && result !== false && result !== undefined) {
797
+ logger.debug(`${stepName} - Success on attempt ${attempts}`);
798
+ return result;
799
+ }
800
+ onProgress?.(attempts, maxAttempts);
801
+ if (attempts < maxAttempts) {
802
+ const waitTime = this.calculateWaitTime(attempts, interval, backoffStrategy);
803
+ logger.debug(`${stepName} - Waiting ${waitTime}ms before next attempt`);
804
+ // eslint-disable-next-line no-await-in-loop
805
+ await timeUtils.sleep(waitTime);
806
+ }
807
+ }
808
+ catch (error) {
809
+ logger.error(`${stepName} - Error on attempt ${attempts}:`, error.message);
810
+ if (attempts === maxAttempts) {
811
+ throw createDeploymentError(`${stepName} failed after ${maxAttempts} attempts: ${error.message}`, 'TIMEOUT_ERROR');
812
+ }
813
+ const waitTime = this.calculateWaitTime(attempts, interval, backoffStrategy);
814
+ // eslint-disable-next-line no-await-in-loop
815
+ await timeUtils.sleep(waitTime);
816
+ }
817
+ }
818
+ throw createDeploymentError(`${stepName} timed out after ${maxAttempts} attempts`, 'TIMEOUT_ERROR');
819
+ }
820
+ calculateWaitTime(attempt, baseInterval, strategy) {
821
+ switch (strategy) {
822
+ case 'linear':
823
+ return baseInterval;
824
+ case 'exponential':
825
+ return Math.min(baseInterval * 2 ** (attempt - 1), 30000);
826
+ default:
827
+ return baseInterval;
828
+ }
829
+ }
830
+ pollWithTimeout(options, timeoutMs) {
831
+ return Promise.race([
832
+ this.poll(options),
833
+ new Promise((_, reject) => {
834
+ setTimeout(() => reject(createDeploymentError('Polling timed out', 'TIMEOUT_ERROR')), timeoutMs);
835
+ }),
836
+ ]);
837
+ }
838
+ async pollBatch(items, checkCondition, options = {}) {
839
+ const completed = [];
840
+ const remaining = [...items];
841
+ while (remaining.length > 0) {
842
+ const batchPromises = remaining.map(async (item) => {
843
+ const isComplete = await checkCondition(item);
844
+ return { item, isComplete };
845
+ });
846
+ // eslint-disable-next-line no-await-in-loop
847
+ const results = await Promise.all(batchPromises);
848
+ results.forEach(({ item, isComplete }) => {
849
+ if (isComplete) {
850
+ completed.push(item);
851
+ const index = remaining.indexOf(item);
852
+ if (index > -1) {
853
+ remaining.splice(index, 1);
854
+ }
855
+ }
856
+ });
857
+ if (remaining.length > 0) {
858
+ // eslint-disable-next-line no-await-in-loop
859
+ await timeUtils.sleep(options.interval || this.baseInterval);
860
+ }
861
+ }
862
+ return completed;
863
+ }
864
+ }
865
+
866
+ /* eslint-disable import/prefer-default-export */
867
+ /**
868
+ * Node.js HTTP client implementation
869
+ * Uses httpUtils and automatically adds Authorization header
870
+ */
871
+ class NodeHttpClient {
872
+ constructor(authToken) {
873
+ this.authToken = authToken;
874
+ }
875
+ get(url) {
876
+ const headers = {};
877
+ if (this.authToken) {
878
+ headers.Authorization = `Bearer ${this.authToken}`;
879
+ }
880
+ return httpUtils.get(url, headers);
881
+ }
882
+ post(url, data) {
883
+ const headers = {};
884
+ if (this.authToken) {
885
+ headers.Authorization = `Bearer ${this.authToken}`;
886
+ }
887
+ return httpUtils.post(url, data, headers);
888
+ }
889
+ }
890
+
891
+ /* eslint-disable import/prefer-default-export */
892
+ /**
893
+ * Node.js configuration provider implementation
894
+ * Gets raw blocklet information from API endpoints
895
+ */
896
+ class NodeConfigProvider {
897
+ constructor(config) {
898
+ this.config = config;
899
+ }
900
+ async getBlockletInfo() {
901
+ if (this.cachedBlockletInfo) {
902
+ return this.cachedBlockletInfo;
903
+ }
904
+ logger.info('Getting blocklet info from baseUrl', { baseUrl: this.config.baseUrl });
905
+ try {
906
+ // Try to get info from /__blocklet__.js endpoint
907
+ const blockletInfoUrl = urlUtils.join(this.config.baseUrl, '__blocklet__.js?type=json');
908
+ logger.info('Getting blocklet info from __blocklet__.js', { blockletInfoUrl });
909
+ const response = await httpUtils.get(blockletInfoUrl);
910
+ if (response.PAYMENT_LINK_ID) {
911
+ this.cachedBlockletInfo = response;
912
+ logger.info('Blocklet info found from __blocklet__.js', { hasPaymentLinkId: true });
913
+ return this.cachedBlockletInfo;
914
+ }
915
+ // Fallback to env API if not found in blocklet info
916
+ const envUrl = urlUtils.join(this.config.baseUrl, 'api/env');
917
+ const envResponse = await httpUtils.get(envUrl);
918
+ if (envResponse.PAYMENT_LINK_ID) {
919
+ this.cachedBlockletInfo = envResponse;
920
+ logger.info('Blocklet info found from /api/env', { hasPaymentLinkId: true });
921
+ return this.cachedBlockletInfo;
922
+ }
923
+ throw new Error('PAYMENT_LINK_ID not found in any API endpoint');
924
+ }
925
+ catch (error) {
926
+ logger.error('Failed to get blocklet info', { error });
927
+ throw createDeploymentError(`Failed to get blocklet info from ${this.config.baseUrl}: ${error.message}`, 'VALIDATION_ERROR', {
928
+ step: 'creating_session',
929
+ details: { originalError: error },
930
+ recovery: {
931
+ canRetry: true,
932
+ suggestions: [
933
+ 'Check if the baseUrl is correct and accessible',
934
+ 'Verify the service is running and configured properly',
935
+ 'Ensure PAYMENT_LINK_ID is set in the environment',
936
+ ],
937
+ },
938
+ });
939
+ }
940
+ }
941
+ }
942
+
943
+ /* eslint-disable import/prefer-default-export */
944
+ /**
945
+ * Creates a Node.js specific BrokerClient instance
946
+ * @param config - Partial configuration for the broker client
947
+ * @returns Configured BrokerClient instance with Node.js dependencies
948
+ */
949
+ function createNodeBrokerClient(config) {
950
+ // Validate required Node.js specific config
951
+ if (!config.authToken) {
952
+ throw new Error('authToken is required for Node.js BrokerClient');
953
+ }
954
+ const fullConfig = { ...config };
955
+ // Create HTTP client with auth token
956
+ const httpClient = new NodeHttpClient(fullConfig.authToken);
957
+ // Create dependencies for Node.js environment
958
+ const dependencies = {
959
+ httpClient,
960
+ configProvider: new NodeConfigProvider(fullConfig),
961
+ pollingManager: new PollingManager({
962
+ baseInterval: fullConfig.polling?.interval || 3000,
963
+ maxAttempts: fullConfig.polling?.maxAttempts || 100,
964
+ backoffStrategy: fullConfig.polling?.backoffStrategy || 'linear',
965
+ }),
966
+ };
967
+ return new BrokerClient(fullConfig, dependencies);
968
+ }
969
+
970
+ exports.API_ENDPOINTS = API_ENDPOINTS;
971
+ exports.BrokerClient = createNodeBrokerClient;
972
+ exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
973
+ exports.DEPLOYMENT_STEPS = DEPLOYMENT_STEPS;
974
+ exports.ERROR_CODES = ERROR_CODES;
975
+ exports.PollingManager = PollingManager;
976
+ exports.STEPS = STEPS;
977
+ exports.createDeploymentError = createDeploymentError;
978
+ exports.httpUtils = httpUtils;
979
+ exports.isDeploymentError = isDeploymentError;
980
+ exports.logger = logger;
981
+ exports.objectUtils = objectUtils;
982
+ exports.timeUtils = timeUtils;
983
+ exports.urlUtils = urlUtils;
984
+ //# sourceMappingURL=index.js.map