@symbo.ls/sdk 2.34.6 → 2.34.7

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 (42) hide show
  1. package/dist/cjs/index.js +24 -0
  2. package/dist/cjs/services/BranchService.js +4 -4
  3. package/dist/cjs/services/IntegrationService.js +538 -0
  4. package/dist/cjs/services/MetricsService.js +62 -0
  5. package/dist/cjs/services/PaymentService.js +1 -1
  6. package/dist/cjs/services/PullRequestService.js +8 -6
  7. package/dist/cjs/services/WaitlistService.js +148 -0
  8. package/dist/cjs/services/index.js +13 -1
  9. package/dist/cjs/utils/services.js +26 -1
  10. package/dist/esm/index.js +751 -12
  11. package/dist/esm/services/BranchService.js +4 -4
  12. package/dist/esm/services/IntegrationService.js +1319 -0
  13. package/dist/esm/services/MetricsService.js +843 -0
  14. package/dist/esm/services/PaymentService.js +1 -1
  15. package/dist/esm/services/PullRequestService.js +8 -6
  16. package/dist/esm/services/WaitlistService.js +929 -0
  17. package/dist/esm/services/index.js +708 -12
  18. package/dist/esm/utils/services.js +26 -1
  19. package/dist/node/index.js +32 -2
  20. package/dist/node/services/BranchService.js +4 -4
  21. package/dist/node/services/IntegrationService.js +519 -0
  22. package/dist/node/services/MetricsService.js +43 -0
  23. package/dist/node/services/PaymentService.js +1 -1
  24. package/dist/node/services/PullRequestService.js +8 -6
  25. package/dist/node/services/WaitlistService.js +129 -0
  26. package/dist/node/services/index.js +13 -1
  27. package/dist/node/utils/services.js +26 -1
  28. package/package.json +8 -7
  29. package/src/index.js +40 -13
  30. package/src/services/BranchService.js +5 -5
  31. package/src/services/IntegrationService.js +548 -0
  32. package/src/services/MetricsService.js +40 -0
  33. package/src/services/PaymentService.js +1 -1
  34. package/src/services/PullRequestService.js +6 -6
  35. package/src/services/WaitlistService.js +130 -0
  36. package/src/services/index.js +16 -2
  37. package/src/services/tests/FileService/createFileFormData.test.js +74 -0
  38. package/src/services/tests/FileService/getFileUrl.test.js +69 -0
  39. package/src/services/tests/FileService/uploadMultipleFiles.test.js +111 -0
  40. package/src/services/tests/FileService/validateFile.test.js +63 -0
  41. package/src/services/tests/PlanService/getActivePlans.test.js +0 -2
  42. package/src/utils/services.js +29 -1
@@ -128,7 +128,7 @@ class PaymentService extends BaseService {
128
128
  status: status.status
129
129
  };
130
130
  } catch (error) {
131
- throw new Error(`Failed to get subscription details: ${error.message}`);
131
+ throw new Error(`Failed to get subscription details: ${error.message}`, { cause: error });
132
132
  }
133
133
  }
134
134
  /**
@@ -182,7 +182,7 @@ class PullRequestService extends BaseService {
182
182
  throw new Error(response.message);
183
183
  } catch (error) {
184
184
  if (error.message.includes("conflicts") || error.message.includes("409")) {
185
- throw new Error(`Pull request has merge conflicts: ${error.message}`);
185
+ throw new Error(`Pull request has merge conflicts: ${error.message}`, { cause: error });
186
186
  }
187
187
  throw new Error(`Failed to merge pull request: ${error.message}`, { cause: error });
188
188
  }
@@ -299,7 +299,8 @@ class PullRequestService extends BaseService {
299
299
  return ((_a = prData == null ? void 0 : prData.data) == null ? void 0 : _a.canMerge) || false;
300
300
  } catch (error) {
301
301
  throw new Error(
302
- `Failed to check pull request mergeability: ${error.message}`
302
+ `Failed to check pull request mergeability: ${error.message}`,
303
+ { cause: error }
303
304
  );
304
305
  }
305
306
  }
@@ -325,7 +326,8 @@ class PullRequestService extends BaseService {
325
326
  };
326
327
  } catch (error) {
327
328
  throw new Error(
328
- `Failed to get pull request status summary: ${error.message}`
329
+ `Failed to get pull request status summary: ${error.message}`,
330
+ { cause: error }
329
331
  );
330
332
  }
331
333
  }
@@ -419,7 +421,7 @@ class PullRequestService extends BaseService {
419
421
  });
420
422
  return stats;
421
423
  } catch (error) {
422
- throw new Error(`Failed to get pull request stats: ${error.message}`);
424
+ throw new Error(`Failed to get pull request stats: ${error.message}`, { cause: error });
423
425
  }
424
426
  }
425
427
  /**
@@ -446,7 +448,7 @@ class PullRequestService extends BaseService {
446
448
  }
447
449
  throw new Error(response.message);
448
450
  } catch (error) {
449
- throw new Error(`Failed to close pull request: ${error.message}`);
451
+ throw new Error(`Failed to close pull request: ${error.message}`, { cause: error });
450
452
  }
451
453
  }
452
454
  /**
@@ -473,7 +475,7 @@ class PullRequestService extends BaseService {
473
475
  }
474
476
  throw new Error(response.message);
475
477
  } catch (error) {
476
- throw new Error(`Failed to reopen pull request: ${error.message}`);
478
+ throw new Error(`Failed to reopen pull request: ${error.message}`, { cause: error });
477
479
  }
478
480
  }
479
481
  }
@@ -0,0 +1,129 @@
1
+ import { BaseService } from "./BaseService.js";
2
+ class WaitlistService extends BaseService {
3
+ // ==================== WAITLIST METHODS ====================
4
+ /**
5
+ * Join a waitlist campaign (public).
6
+ *
7
+ * Mirrors: POST /waitlist (WaitlistController.join)
8
+ */
9
+ async joinWaitlist(data = {}) {
10
+ this._requireReady("joinWaitlist");
11
+ if (!data || typeof data !== "object") {
12
+ throw new Error("Waitlist join payload is required");
13
+ }
14
+ if (!data.email) {
15
+ throw new Error("Email is required");
16
+ }
17
+ try {
18
+ const response = await this._request("/waitlist", {
19
+ method: "POST",
20
+ body: JSON.stringify(data),
21
+ methodName: "joinWaitlist"
22
+ });
23
+ if (response.success) {
24
+ return response.data;
25
+ }
26
+ throw new Error(response.message);
27
+ } catch (error) {
28
+ throw new Error(`Failed to join waitlist: ${error.message}`, { cause: error });
29
+ }
30
+ }
31
+ /**
32
+ * List waitlist entries (admin).
33
+ *
34
+ * Mirrors: GET /waitlist (WaitlistController.list)
35
+ */
36
+ async listWaitlistEntries(options = {}) {
37
+ this._requireReady("listWaitlistEntries");
38
+ const {
39
+ campaignKey,
40
+ status,
41
+ search,
42
+ page,
43
+ limit
44
+ } = options || {};
45
+ const queryParams = new URLSearchParams();
46
+ if (campaignKey != null) {
47
+ queryParams.append("campaignKey", String(campaignKey));
48
+ }
49
+ if (status != null) {
50
+ queryParams.append("status", String(status));
51
+ }
52
+ if (search != null) {
53
+ queryParams.append("search", String(search));
54
+ }
55
+ if (page != null) {
56
+ queryParams.append("page", String(page));
57
+ }
58
+ if (limit != null) {
59
+ queryParams.append("limit", String(limit));
60
+ }
61
+ const queryString = queryParams.toString();
62
+ const url = `/waitlist${queryString ? `?${queryString}` : ""}`;
63
+ try {
64
+ const response = await this._request(url, {
65
+ method: "GET",
66
+ methodName: "listWaitlistEntries"
67
+ });
68
+ if (response.success) {
69
+ return response.data;
70
+ }
71
+ throw new Error(response.message);
72
+ } catch (error) {
73
+ throw new Error(`Failed to list waitlist entries: ${error.message}`, { cause: error });
74
+ }
75
+ }
76
+ /**
77
+ * Update a waitlist entry (admin).
78
+ *
79
+ * Mirrors: PATCH /waitlist/:id (WaitlistController.update)
80
+ */
81
+ async updateWaitlistEntry(id, update = {}) {
82
+ this._requireReady("updateWaitlistEntry");
83
+ if (!id) {
84
+ throw new Error("Waitlist entry ID is required");
85
+ }
86
+ if (!update || typeof update !== "object") {
87
+ throw new Error("Update payload is required");
88
+ }
89
+ try {
90
+ const response = await this._request(`/waitlist/${id}`, {
91
+ method: "PATCH",
92
+ body: JSON.stringify(update),
93
+ methodName: "updateWaitlistEntry"
94
+ });
95
+ if (response.success) {
96
+ return response.data;
97
+ }
98
+ throw new Error(response.message);
99
+ } catch (error) {
100
+ throw new Error(`Failed to update waitlist entry: ${error.message}`, { cause: error });
101
+ }
102
+ }
103
+ /**
104
+ * Send an invitation email for a waitlist entry (admin).
105
+ *
106
+ * Mirrors: POST /waitlist/:id/invite (WaitlistController.invite)
107
+ */
108
+ async inviteWaitlistEntry(id) {
109
+ this._requireReady("inviteWaitlistEntry");
110
+ if (!id) {
111
+ throw new Error("Waitlist entry ID is required");
112
+ }
113
+ try {
114
+ const response = await this._request(`/waitlist/${id}/invite`, {
115
+ method: "POST",
116
+ methodName: "inviteWaitlistEntry"
117
+ });
118
+ if (response.success) {
119
+ return response.data;
120
+ }
121
+ throw new Error(response.message);
122
+ } catch (error) {
123
+ throw new Error(`Failed to invite waitlist entry: ${error.message}`, { cause: error });
124
+ }
125
+ }
126
+ }
127
+ export {
128
+ WaitlistService
129
+ };
@@ -11,6 +11,9 @@ import { PullRequestService } from "./PullRequestService.js";
11
11
  import { AdminService } from "./AdminService.js";
12
12
  import { ScreenshotService } from "./ScreenshotService.js";
13
13
  import { TrackingService } from "./TrackingService.js";
14
+ import { WaitlistService } from "./WaitlistService.js";
15
+ import { MetricsService } from "./MetricsService.js";
16
+ import { IntegrationService } from "./IntegrationService.js";
14
17
  const createService = (ServiceClass, config) => new ServiceClass(config);
15
18
  const createAuthService = (config) => createService(AuthService, config);
16
19
  const createCollabService = (config) => createService(CollabService, config);
@@ -25,6 +28,9 @@ const createPullRequestService = (config) => createService(PullRequestService, c
25
28
  const createAdminService = (config) => createService(AdminService, config);
26
29
  const createScreenshotService = (config) => createService(ScreenshotService, config);
27
30
  const createTrackingService = (config) => createService(TrackingService, config);
31
+ const createWaitlistService = (config) => createService(WaitlistService, config);
32
+ const createMetricsService = (config) => createService(MetricsService, config);
33
+ const createIntegrationService = (config) => createService(IntegrationService, config);
28
34
  export {
29
35
  AdminService,
30
36
  AuthService,
@@ -32,6 +38,8 @@ export {
32
38
  CollabService,
33
39
  DnsService,
34
40
  FileService,
41
+ IntegrationService,
42
+ MetricsService,
35
43
  PaymentService,
36
44
  PlanService,
37
45
  ProjectService,
@@ -39,17 +47,21 @@ export {
39
47
  ScreenshotService,
40
48
  SubscriptionService,
41
49
  TrackingService,
50
+ WaitlistService,
42
51
  createAdminService,
43
52
  createAuthService,
44
53
  createBranchService,
45
54
  createCollabService,
46
55
  createDnsService,
47
56
  createFileService,
57
+ createIntegrationService,
58
+ createMetricsService,
48
59
  createPaymentService,
49
60
  createPlanService,
50
61
  createProjectService,
51
62
  createPullRequestService,
52
63
  createScreenshotService,
53
64
  createSubscriptionService,
54
- createTrackingService
65
+ createTrackingService,
66
+ createWaitlistService
55
67
  };
@@ -272,7 +272,32 @@ const SERVICE_METHODS = {
272
272
  flushQueue: "tracking",
273
273
  getClient: "tracking",
274
274
  isEnabled: "tracking",
275
- isInitialized: "tracking"
275
+ isInitialized: "tracking",
276
+ // Waitlist methods
277
+ joinWaitlist: "waitlist",
278
+ listWaitlistEntries: "waitlist",
279
+ updateWaitlistEntry: "waitlist",
280
+ inviteWaitlistEntry: "waitlist",
281
+ // Metrics methods
282
+ getContributions: "metrics",
283
+ // Integration methods
284
+ integrationWhoami: "integration",
285
+ listIntegrations: "integration",
286
+ createIntegration: "integration",
287
+ updateIntegration: "integration",
288
+ createIntegrationApiKey: "integration",
289
+ listIntegrationApiKeys: "integration",
290
+ revokeIntegrationApiKey: "integration",
291
+ createIntegrationWebhook: "integration",
292
+ listIntegrationWebhooks: "integration",
293
+ updateIntegrationWebhook: "integration",
294
+ deleteIntegrationWebhook: "integration",
295
+ listIntegrationWebhookDeliveries: "integration",
296
+ replayIntegrationWebhookDelivery: "integration",
297
+ listGitHubConnectors: "integration",
298
+ createGitHubConnector: "integration",
299
+ updateGitHubConnector: "integration",
300
+ deleteGitHubConnector: "integration"
276
301
  };
277
302
  export {
278
303
  SERVICE_METHODS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/sdk",
3
- "version": "2.34.6",
3
+ "version": "2.34.7",
4
4
  "type": "module",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -43,15 +43,16 @@
43
43
  "test:update-project": "cross-env NODE_ENV=$NODE_ENV npx tape integration-tests/index.js integration-tests/update-project/*.test.js | tap-spec",
44
44
  "test:favorite-project": "cross-env NODE_ENV=$NODE_ENV npx tape integration-tests/index.js integration-tests/favorite-project/*.test.js | tap-spec",
45
45
  "test:collab": "cross-env NODE_ENV=$NODE_ENV npx tape integration-tests/index.js integration-tests/collab/*.test.js | tap-spec",
46
- "test:user": "cross-env NODE_ENV=$NODE_ENV npx tape integration-tests/index.js integration-tests/user/*.test.js | tap-spec"
46
+ "test:user": "cross-env NODE_ENV=$NODE_ENV npx tape integration-tests/index.js integration-tests/user/*.test.js | tap-spec",
47
+ "test:unit-all": "cross-env NODE_ENV=$NODE_ENV npx tape src/services/tests/**/*.test.js | tap-spec"
47
48
  },
48
49
  "dependencies": {
49
- "@domql/element": "^2.34.6",
50
- "@domql/utils": "^2.34.6",
50
+ "@domql/element": "^2.34.7",
51
+ "@domql/utils": "^2.34.7",
51
52
  "@grafana/faro-web-sdk": "^1.19.0",
52
53
  "@grafana/faro-web-tracing": "^1.19.0",
53
- "@symbo.ls/router": "^2.34.6",
54
- "@symbo.ls/socket": "^2.34.6",
54
+ "@symbo.ls/router": "^2.34.7",
55
+ "@symbo.ls/socket": "^2.34.7",
55
56
  "acorn": "^8.14.0",
56
57
  "acorn-walk": "^8.3.4",
57
58
  "dexie": "^4.0.11",
@@ -74,5 +75,5 @@
74
75
  "tap-spec": "^5.0.0",
75
76
  "tape": "^5.9.0"
76
77
  },
77
- "gitHead": "d0ceab62f9a7fd775f741821b28efb4facf3b4fb"
78
+ "gitHead": "dc0a8d8734cf5720ecad250b62f0eb4ad2b87590"
78
79
  }
package/src/index.js CHANGED
@@ -11,7 +11,10 @@ import {
11
11
  createAdminService,
12
12
  createSubscriptionService,
13
13
  createScreenshotService,
14
- createTrackingService
14
+ createTrackingService,
15
+ createWaitlistService,
16
+ createMetricsService,
17
+ createIntegrationService
15
18
  } from './services/index.js'
16
19
 
17
20
  import { SERVICE_METHODS } from './utils/services.js'
@@ -29,7 +32,7 @@ export const isLocalhost = () => {
29
32
  }
30
33
 
31
34
  export class SDK {
32
- constructor(options = {}) {
35
+ constructor (options = {}) {
33
36
  this._services = new Map()
34
37
  this._context = {}
35
38
  this._options = this._validateOptions(options)
@@ -45,7 +48,7 @@ export class SDK {
45
48
  }
46
49
 
47
50
  // Initialize SDK with context
48
- async initialize(context = {}) {
51
+ async initialize (context = {}) {
49
52
  this._context = {
50
53
  ...this._context,
51
54
  ...context
@@ -145,6 +148,27 @@ export class SDK {
145
148
  context: this._context,
146
149
  options: this._options
147
150
  })
151
+ ),
152
+ this._initService(
153
+ 'waitlist',
154
+ createWaitlistService({
155
+ context: this._context,
156
+ options: this._options
157
+ })
158
+ ),
159
+ this._initService(
160
+ 'metrics',
161
+ createMetricsService({
162
+ context: this._context,
163
+ options: this._options
164
+ })
165
+ ),
166
+ this._initService(
167
+ 'integration',
168
+ createIntegrationService({
169
+ context: this._context,
170
+ options: this._options
171
+ })
148
172
  )
149
173
  ])
150
174
 
@@ -152,7 +176,7 @@ export class SDK {
152
176
  }
153
177
 
154
178
  // Private helper to initialize a service
155
- async _initService(name, service) {
179
+ async _initService (name, service) {
156
180
  // Add service reference to context for inter-service communication
157
181
  this._context.services = {
158
182
  ...this._context.services,
@@ -168,7 +192,7 @@ export class SDK {
168
192
  this._services.set(name, service)
169
193
  }
170
194
 
171
- _validateOptions(options) {
195
+ _validateOptions (options) {
172
196
  const onLocalhost = isLocalhost()
173
197
  const hasGrafanaUrl = Boolean(environment.grafanaUrl)
174
198
  const defaults = {
@@ -180,7 +204,7 @@ export class SDK {
180
204
  debug: false,
181
205
  tracking: {
182
206
  // Force-disabled on localhost or when no Grafana URL is configured
183
- enabled: onLocalhost ? false : (hasGrafanaUrl ? environment.features.trackingEnabled : false),
207
+ enabled: onLocalhost ? false : (hasGrafanaUrl ? environment.features.trackingEnabled : false)
184
208
  }
185
209
  }
186
210
 
@@ -202,7 +226,7 @@ export class SDK {
202
226
  }
203
227
 
204
228
  // Get service instance
205
- getService(name) {
229
+ getService (name) {
206
230
  if (!this._services.has(name)) {
207
231
  throw new Error(`Service '${name}' not found`)
208
232
  }
@@ -210,7 +234,7 @@ export class SDK {
210
234
  }
211
235
 
212
236
  // Update context
213
- updateContext(newContext) {
237
+ updateContext (newContext) {
214
238
  // Do not persist authToken in SDK context; TokenManager is the source of truth
215
239
  const { ...sanitized } = newContext || {}
216
240
 
@@ -226,7 +250,7 @@ export class SDK {
226
250
  }
227
251
 
228
252
  // Check if SDK is ready
229
- isReady() {
253
+ isReady () {
230
254
  const sdkServices = Array.from(this._services.values())
231
255
  return (
232
256
  sdkServices.length > 0 &&
@@ -235,7 +259,7 @@ export class SDK {
235
259
  }
236
260
 
237
261
  // Get SDK status
238
- getStatus() {
262
+ getStatus () {
239
263
  return {
240
264
  ready: this.isReady(),
241
265
  services: Array.from(this._services.entries()).map(([name, service]) => ({
@@ -247,7 +271,7 @@ export class SDK {
247
271
  }
248
272
 
249
273
  // Create proxy methods for direct service access
250
- _createServiceProxies() {
274
+ _createServiceProxies () {
251
275
  for (const [methodName, serviceName] of Object.entries(SERVICE_METHODS)) {
252
276
  // Skip if method already exists on SDK
253
277
  if (!this[methodName]) {
@@ -269,7 +293,7 @@ export class SDK {
269
293
  * Destroys all services and cleans up resources
270
294
  * @returns {Promise<boolean>} Returns true when cleanup is complete
271
295
  */
272
- async destroy() {
296
+ async destroy () {
273
297
  try {
274
298
  // Call destroy on all services
275
299
  const destroyPromises = Array.from(this._services.entries())
@@ -308,7 +332,10 @@ export {
308
332
  createPullRequestService,
309
333
  createAdminService,
310
334
  createSubscriptionService,
311
- createTrackingService
335
+ createTrackingService,
336
+ createWaitlistService,
337
+ createMetricsService,
338
+ createIntegrationService
312
339
  } from './services/index.js'
313
340
 
314
341
  // Export environment configuration
@@ -218,7 +218,7 @@ export class BranchService extends BaseService {
218
218
  error.message.includes('conflicts') ||
219
219
  error.message.includes('409')
220
220
  ) {
221
- throw new Error(`Merge conflicts detected: ${error.message}`)
221
+ throw new Error(`Merge conflicts detected: ${error.message}`, { cause: error })
222
222
  }
223
223
  throw new Error(`Failed to merge branch: ${error.message}`, { cause: error })
224
224
  }
@@ -468,7 +468,7 @@ export class BranchService extends BaseService {
468
468
 
469
469
  return branchStatuses
470
470
  } catch (error) {
471
- throw new Error(`Failed to get branches with status: ${error.message}`)
471
+ throw new Error(`Failed to get branches with status: ${error.message}`, { cause: error })
472
472
  }
473
473
  }
474
474
 
@@ -505,7 +505,7 @@ export class BranchService extends BaseService {
505
505
  }
506
506
 
507
507
  // Check for valid characters (alphanumeric, hyphens, underscores)
508
- if (!/^[a-zA-Z0-9-_]+$/.test(branchName)) {
508
+ if (!/^[a-zA-Z0-9-_]+$/u.test(branchName)) {
509
509
  return {
510
510
  isValid: false,
511
511
  error: 'Branch name can only contain letters, numbers, hyphens, and underscores'
@@ -530,7 +530,7 @@ export class BranchService extends BaseService {
530
530
  .trim()
531
531
  .toLowerCase()
532
532
  .replace(/[^a-z0-9-_]/gu, '-')
533
- .replace(/-+/g, '-')
534
- .replace(/^-|-$/g, '')
533
+ .replace(/-+/gu, '-')
534
+ .replace(/^-|-$/gu, '')
535
535
  }
536
536
  }