@symbo.ls/sdk 2.32.2 → 2.32.5

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 (90) hide show
  1. package/dist/cjs/config/environment.js +43 -8
  2. package/dist/cjs/index.js +12 -4
  3. package/dist/cjs/services/AdminService.js +4 -4
  4. package/dist/cjs/services/AuthService.js +36 -149
  5. package/dist/cjs/services/BaseService.js +5 -18
  6. package/dist/cjs/services/BranchService.js +10 -10
  7. package/dist/cjs/services/CollabService.js +94 -61
  8. package/dist/cjs/services/CoreService.js +19 -19
  9. package/dist/cjs/services/DnsService.js +4 -4
  10. package/dist/cjs/services/FileService.js +2 -2
  11. package/dist/cjs/services/PaymentService.js +2 -2
  12. package/dist/cjs/services/PlanService.js +12 -12
  13. package/dist/cjs/services/ProjectService.js +45 -35
  14. package/dist/cjs/services/PullRequestService.js +7 -7
  15. package/dist/cjs/services/ScreenshotService.js +304 -0
  16. package/dist/cjs/services/SubscriptionService.js +14 -14
  17. package/dist/cjs/services/index.js +4 -0
  18. package/dist/cjs/utils/TokenManager.js +16 -5
  19. package/dist/cjs/utils/changePreprocessor.js +134 -0
  20. package/dist/cjs/utils/jsonDiff.js +46 -4
  21. package/dist/cjs/utils/ordering.js +274 -0
  22. package/dist/cjs/utils/services.js +14 -1
  23. package/dist/esm/config/environment.js +43 -8
  24. package/dist/esm/index.js +1099 -417
  25. package/dist/esm/services/AdminService.js +68 -35
  26. package/dist/esm/services/AuthService.js +100 -168
  27. package/dist/esm/services/BaseService.js +64 -31
  28. package/dist/esm/services/BranchService.js +74 -41
  29. package/dist/esm/services/CollabService.js +570 -97
  30. package/dist/esm/services/CoreService.js +83 -50
  31. package/dist/esm/services/DnsService.js +68 -35
  32. package/dist/esm/services/FileService.js +66 -33
  33. package/dist/esm/services/PaymentService.js +66 -33
  34. package/dist/esm/services/PlanService.js +76 -43
  35. package/dist/esm/services/ProjectService.js +547 -66
  36. package/dist/esm/services/PullRequestService.js +71 -38
  37. package/dist/esm/services/ScreenshotService.js +992 -0
  38. package/dist/esm/services/SubscriptionService.js +78 -45
  39. package/dist/esm/services/index.js +1076 -412
  40. package/dist/esm/utils/CollabClient.js +89 -12
  41. package/dist/esm/utils/TokenManager.js +16 -5
  42. package/dist/esm/utils/changePreprocessor.js +442 -0
  43. package/dist/esm/utils/jsonDiff.js +46 -4
  44. package/dist/esm/utils/ordering.js +256 -0
  45. package/dist/esm/utils/services.js +14 -1
  46. package/dist/node/config/environment.js +43 -8
  47. package/dist/node/index.js +14 -5
  48. package/dist/node/services/AdminService.js +4 -4
  49. package/dist/node/services/AuthService.js +36 -139
  50. package/dist/node/services/BaseService.js +5 -18
  51. package/dist/node/services/BranchService.js +10 -10
  52. package/dist/node/services/CollabService.js +95 -62
  53. package/dist/node/services/CoreService.js +19 -19
  54. package/dist/node/services/DnsService.js +4 -4
  55. package/dist/node/services/FileService.js +2 -2
  56. package/dist/node/services/PaymentService.js +2 -2
  57. package/dist/node/services/PlanService.js +12 -12
  58. package/dist/node/services/ProjectService.js +45 -35
  59. package/dist/node/services/PullRequestService.js +7 -7
  60. package/dist/node/services/ScreenshotService.js +285 -0
  61. package/dist/node/services/SubscriptionService.js +14 -14
  62. package/dist/node/services/index.js +4 -0
  63. package/dist/node/utils/TokenManager.js +16 -5
  64. package/dist/node/utils/changePreprocessor.js +115 -0
  65. package/dist/node/utils/jsonDiff.js +46 -4
  66. package/dist/node/utils/ordering.js +255 -0
  67. package/dist/node/utils/services.js +14 -1
  68. package/package.json +7 -6
  69. package/src/config/environment.js +48 -9
  70. package/src/index.js +38 -22
  71. package/src/services/AdminService.js +4 -4
  72. package/src/services/AuthService.js +42 -175
  73. package/src/services/BaseService.js +7 -24
  74. package/src/services/BranchService.js +10 -10
  75. package/src/services/CollabService.js +115 -74
  76. package/src/services/CoreService.js +19 -19
  77. package/src/services/DnsService.js +4 -4
  78. package/src/services/FileService.js +2 -2
  79. package/src/services/PaymentService.js +2 -2
  80. package/src/services/PlanService.js +12 -12
  81. package/src/services/ProjectService.js +50 -35
  82. package/src/services/PullRequestService.js +7 -7
  83. package/src/services/ScreenshotService.js +258 -0
  84. package/src/services/SubscriptionService.js +14 -14
  85. package/src/services/index.js +6 -1
  86. package/src/utils/TokenManager.js +19 -5
  87. package/src/utils/changePreprocessor.js +139 -0
  88. package/src/utils/jsonDiff.js +40 -5
  89. package/src/utils/ordering.js +244 -0
  90. package/src/utils/services.js +15 -1
@@ -0,0 +1,256 @@
1
+ // src/utils/ordering.js
2
+ function isObjectLike(val) {
3
+ return val && typeof val === "object" && !Array.isArray(val);
4
+ }
5
+ function normalizePath(path) {
6
+ if (Array.isArray(path)) {
7
+ return path;
8
+ }
9
+ if (typeof path === "string") {
10
+ return [path];
11
+ }
12
+ return [];
13
+ }
14
+ function getParentPathsFromTuples(tuples = []) {
15
+ const seen = /* @__PURE__ */ new Set();
16
+ const parents = [];
17
+ const META_KEYS = /* @__PURE__ */ new Set([
18
+ "style",
19
+ "class",
20
+ "text",
21
+ "html",
22
+ "content",
23
+ "data",
24
+ "attr",
25
+ "state",
26
+ "scope",
27
+ "define",
28
+ "on",
29
+ "extend",
30
+ "extends",
31
+ "childExtend",
32
+ "childExtends",
33
+ "children",
34
+ "component",
35
+ "context",
36
+ "tag",
37
+ "key",
38
+ "__order",
39
+ "if"
40
+ ]);
41
+ for (let i = 0; i < tuples.length; i++) {
42
+ const tuple = tuples[i];
43
+ if (!Array.isArray(tuple) || tuple.length < 2) {
44
+ continue;
45
+ }
46
+ const path = normalizePath(tuple[1]);
47
+ if (!path.length) {
48
+ continue;
49
+ }
50
+ if (path[0] === "schema") {
51
+ continue;
52
+ }
53
+ const immediateParent = path.slice(0, -1);
54
+ if (immediateParent.length) {
55
+ const key = JSON.stringify(immediateParent);
56
+ if (!seen.has(key)) {
57
+ seen.add(key);
58
+ parents.push(immediateParent);
59
+ }
60
+ }
61
+ const last = path[path.length - 1];
62
+ if (META_KEYS.has(last) && path.length >= 2) {
63
+ const containerParent = path.slice(0, -2);
64
+ if (containerParent.length) {
65
+ const key2 = JSON.stringify(containerParent);
66
+ if (!seen.has(key2)) {
67
+ seen.add(key2);
68
+ parents.push(containerParent);
69
+ }
70
+ }
71
+ }
72
+ for (let j = 0; j < path.length; j++) {
73
+ const seg = path[j];
74
+ if (!META_KEYS.has(seg)) {
75
+ continue;
76
+ }
77
+ const containerParent2 = path.slice(0, j);
78
+ if (!containerParent2.length) {
79
+ continue;
80
+ }
81
+ const key3 = JSON.stringify(containerParent2);
82
+ if (!seen.has(key3)) {
83
+ seen.add(key3);
84
+ parents.push(containerParent2);
85
+ }
86
+ }
87
+ }
88
+ return parents;
89
+ }
90
+ function computeOrdersFromState(root, parentPaths = []) {
91
+ if (!root || typeof root.getByPath !== "function") {
92
+ return [];
93
+ }
94
+ const orders = [];
95
+ const EXCLUDE_KEYS = /* @__PURE__ */ new Set(["__order"]);
96
+ for (let i = 0; i < parentPaths.length; i++) {
97
+ const parentPath = parentPaths[i];
98
+ const obj = (() => {
99
+ try {
100
+ return root.getByPath(parentPath);
101
+ } catch {
102
+ return null;
103
+ }
104
+ })();
105
+ if (!isObjectLike(obj)) {
106
+ continue;
107
+ }
108
+ const keys = Object.keys(obj).filter((k) => !EXCLUDE_KEYS.has(k));
109
+ orders.push({ path: parentPath, keys });
110
+ }
111
+ return orders;
112
+ }
113
+ function normaliseSchemaCode(code) {
114
+ if (typeof code !== "string" || !code.length) {
115
+ return "";
116
+ }
117
+ return code.replaceAll("/////n", "\n").replaceAll("/////tilde", "`");
118
+ }
119
+ function parseExportedObject(code) {
120
+ const src = normaliseSchemaCode(code);
121
+ if (!src) {
122
+ return null;
123
+ }
124
+ const body = src.replace(/^\s*export\s+default\s*/u, "return ");
125
+ try {
126
+ return new Function(body)();
127
+ } catch {
128
+ return null;
129
+ }
130
+ }
131
+ function extractTopLevelKeysFromCode(code) {
132
+ const obj = parseExportedObject(code);
133
+ if (!obj || typeof obj !== "object") {
134
+ return [];
135
+ }
136
+ return Object.keys(obj);
137
+ }
138
+ function computeOrdersForTuples(root, tuples = []) {
139
+ const pendingChildrenByContainer = /* @__PURE__ */ new Map();
140
+ for (let i = 0; i < tuples.length; i++) {
141
+ const t = tuples[i];
142
+ if (!Array.isArray(t)) {
143
+ continue;
144
+ }
145
+ const [action, path] = t;
146
+ const p = normalizePath(path);
147
+ if (!Array.isArray(p) || p.length < 3) {
148
+ continue;
149
+ }
150
+ if (p[0] === "schema") {
151
+ continue;
152
+ }
153
+ const [typeName, containerKey, childKey] = p;
154
+ const containerPath = [typeName, containerKey];
155
+ const key = JSON.stringify(containerPath);
156
+ if (!pendingChildrenByContainer.has(key)) {
157
+ pendingChildrenByContainer.set(key, /* @__PURE__ */ new Set());
158
+ }
159
+ if (action === "update" || action === "set") {
160
+ pendingChildrenByContainer.get(key).add(childKey);
161
+ }
162
+ }
163
+ const preferredOrderMap = /* @__PURE__ */ new Map();
164
+ for (let i = 0; i < tuples.length; i++) {
165
+ const t = tuples[i];
166
+ if (!Array.isArray(t)) {
167
+ continue;
168
+ }
169
+ const [action, path, value] = t;
170
+ const p = normalizePath(path);
171
+ if (action !== "update" || !Array.isArray(p) || p.length < 3) {
172
+ continue;
173
+ }
174
+ if (p[0] !== "schema") {
175
+ continue;
176
+ }
177
+ const [, type, key] = p;
178
+ const containerPath = [type, key];
179
+ const uses = value && Array.isArray(value.uses) ? value.uses : null;
180
+ const code = value && value.code;
181
+ const obj = (() => {
182
+ try {
183
+ return root && typeof root.getByPath === "function" ? root.getByPath(containerPath) : null;
184
+ } catch {
185
+ return null;
186
+ }
187
+ })();
188
+ if (!obj) {
189
+ continue;
190
+ }
191
+ const present = new Set(Object.keys(obj));
192
+ const EXCLUDE_KEYS = /* @__PURE__ */ new Set(["__order"]);
193
+ const codeKeys = extractTopLevelKeysFromCode(code);
194
+ let resolved = [];
195
+ const pendingKey = JSON.stringify(containerPath);
196
+ const pendingChildren = pendingChildrenByContainer.get(pendingKey) || /* @__PURE__ */ new Set();
197
+ const eligible = /* @__PURE__ */ new Set([...present, ...pendingChildren]);
198
+ if (Array.isArray(codeKeys) && codeKeys.length) {
199
+ resolved = codeKeys.filter((k) => eligible.has(k) && !EXCLUDE_KEYS.has(k));
200
+ }
201
+ if (Array.isArray(uses) && uses.length) {
202
+ for (let u = 0; u < uses.length; u++) {
203
+ const keyName = uses[u];
204
+ if (eligible.has(keyName) && !EXCLUDE_KEYS.has(keyName) && !resolved.includes(keyName)) {
205
+ resolved.push(keyName);
206
+ }
207
+ }
208
+ }
209
+ if (pendingChildren.size) {
210
+ for (const child of pendingChildren) {
211
+ if (!EXCLUDE_KEYS.has(child) && !resolved.includes(child)) {
212
+ resolved.push(child);
213
+ }
214
+ }
215
+ }
216
+ if (resolved.length) {
217
+ preferredOrderMap.set(JSON.stringify(containerPath), { path: containerPath, keys: resolved });
218
+ }
219
+ }
220
+ const parents = getParentPathsFromTuples(tuples);
221
+ const orders = [];
222
+ const seen = /* @__PURE__ */ new Set();
223
+ preferredOrderMap.forEach((v) => {
224
+ const k = JSON.stringify(v.path);
225
+ if (!seen.has(k)) {
226
+ seen.add(k);
227
+ orders.push(v);
228
+ }
229
+ });
230
+ const fallbackOrders = computeOrdersFromState(root, parents);
231
+ for (let i = 0; i < fallbackOrders.length; i++) {
232
+ const v = fallbackOrders[i];
233
+ const k = JSON.stringify(v.path);
234
+ if (seen.has(k)) {
235
+ continue;
236
+ }
237
+ const pending = pendingChildrenByContainer.get(k);
238
+ if (pending && pending.size) {
239
+ const existing = new Set(v.keys);
240
+ for (const child of pending) {
241
+ if (existing.has(child)) {
242
+ continue;
243
+ }
244
+ v.keys.push(child);
245
+ }
246
+ }
247
+ seen.add(k);
248
+ orders.push(v);
249
+ }
250
+ return orders;
251
+ }
252
+ export {
253
+ computeOrdersForTuples,
254
+ computeOrdersFromState,
255
+ getParentPathsFromTuples
256
+ };
@@ -224,7 +224,20 @@ var SERVICE_METHODS = {
224
224
  promoteToAdmin: "admin",
225
225
  demoteFromAdmin: "admin",
226
226
  // Utility methods
227
- getHealthStatus: "core"
227
+ getHealthStatus: "core",
228
+ // Screenshot methods
229
+ createScreenshotProject: "screenshot",
230
+ getProjectScreenshots: "screenshot",
231
+ reprocessProjectScreenshots: "screenshot",
232
+ recreateProjectScreenshots: "screenshot",
233
+ deleteProjectScreenshots: "screenshot",
234
+ getThumbnailCandidate: "screenshot",
235
+ updateProjectThumbnail: "screenshot",
236
+ getPageScreenshot: "screenshot",
237
+ getComponentScreenshot: "screenshot",
238
+ getScreenshotByKey: "screenshot",
239
+ getQueueStatistics: "screenshot",
240
+ refreshThumbnail: "screenshot"
228
241
  };
229
242
  export {
230
243
  SERVICE_METHODS
@@ -23,18 +23,28 @@ const CONFIG = {
23
23
  // For based api
24
24
  basedOrg: "symbols",
25
25
  // For based api
26
- githubClientId: "Ov23liHxyWFBxS8f1gnF",
26
+ githubClientId: "Ov23liAFrsR0StbAO6PO",
27
27
  // For github api
28
28
  // Environment-specific feature toggles (override common)
29
29
  features: {
30
30
  betaFeatures: true
31
31
  // Enable beta features in local dev
32
- }
32
+ },
33
+ typesenseCollectionName: "docs",
34
+ typesenseApiKey: "vZya3L2zpq8L6iI5WWMUZJZABvT63VDb",
35
+ typesenseHost: "localhost",
36
+ typesensePort: "8108",
37
+ typesenseProtocol: "http"
33
38
  },
34
39
  development: {
35
40
  socketUrl: "https://dev.api.symbols.app",
36
41
  apiUrl: "https://dev.api.symbols.app",
37
- githubClientId: "Ov23liHxyWFBxS8f1gnF"
42
+ githubClientId: "Ov23liHxyWFBxS8f1gnF",
43
+ typesenseCollectionName: "docs",
44
+ typesenseApiKey: "awmcVpbWqZi9IUgmvslp1C5LKDU8tMjA",
45
+ typesenseHost: "tl2qpnwxev4cjm36p-1.a1.typesense.net",
46
+ typesensePort: "443",
47
+ typesenseProtocol: "https"
38
48
  },
39
49
  testing: {
40
50
  socketUrl: "https://test.api.symbols.app",
@@ -42,12 +52,22 @@ const CONFIG = {
42
52
  basedEnv: "testing",
43
53
  basedProject: "platform-v2-sm",
44
54
  basedOrg: "symbols",
45
- githubClientId: "Ov23liHxyWFBxS8f1gnF"
55
+ githubClientId: "Ov23liHxyWFBxS8f1gnF",
56
+ typesenseCollectionName: "docs",
57
+ typesenseApiKey: "awmcVpbWqZi9IUgmvslp1C5LKDU8tMjA",
58
+ typesenseHost: "tl2qpnwxev4cjm36p-1.a1.typesense.net",
59
+ typesensePort: "443",
60
+ typesenseProtocol: "https"
46
61
  },
47
62
  upcoming: {
48
63
  socketUrl: "https://upcoming.api.symbols.app",
49
64
  apiUrl: "https://upcoming.api.symbols.app",
50
- githubClientId: "Ov23liWF7NvdZ056RV5J"
65
+ githubClientId: "Ov23liWF7NvdZ056RV5J",
66
+ typesenseCollectionName: "docs",
67
+ typesenseApiKey: "awmcVpbWqZi9IUgmvslp1C5LKDU8tMjA",
68
+ typesenseHost: "tl2qpnwxev4cjm36p-1.a1.typesense.net",
69
+ typesensePort: "443",
70
+ typesenseProtocol: "https"
51
71
  },
52
72
  staging: {
53
73
  socketUrl: "https://staging.api.symbols.app",
@@ -55,7 +75,12 @@ const CONFIG = {
55
75
  basedEnv: "staging",
56
76
  basedProject: "platform-v2-sm",
57
77
  basedOrg: "symbols",
58
- githubClientId: "Ov23ligwZDQVD0VfuWNa"
78
+ githubClientId: "Ov23ligwZDQVD0VfuWNa",
79
+ typesenseCollectionName: "docs",
80
+ typesenseApiKey: "awmcVpbWqZi9IUgmvslp1C5LKDU8tMjA",
81
+ typesenseHost: "tl2qpnwxev4cjm36p-1.a1.typesense.net",
82
+ typesensePort: "443",
83
+ typesenseProtocol: "https"
59
84
  },
60
85
  production: {
61
86
  socketUrl: "https://api.symbols.app",
@@ -63,7 +88,12 @@ const CONFIG = {
63
88
  basedEnv: "production",
64
89
  basedProject: "platform-v2-sm",
65
90
  basedOrg: "symbols",
66
- githubClientId: "Ov23liFAlOEIXtX3dBtR"
91
+ githubClientId: "Ov23liFAlOEIXtX3dBtR",
92
+ typesenseCollectionName: "docs",
93
+ typesenseApiKey: "awmcVpbWqZi9IUgmvslp1C5LKDU8tMjA",
94
+ typesenseHost: "tl2qpnwxev4cjm36p-1.a1.typesense.net",
95
+ typesensePort: "443",
96
+ typesenseProtocol: "https"
67
97
  }
68
98
  };
69
99
  const getEnvironment = () => {
@@ -86,6 +116,11 @@ const getConfig = () => {
86
116
  basedProject: process.env.SYMBOLS_APP_BASED_PROJECT || envConfig.basedProject,
87
117
  basedOrg: process.env.SYMBOLS_APP_BASED_ORG || envConfig.basedOrg,
88
118
  githubClientId: process.env.SYMBOLS_APP_GITHUB_CLIENT_ID || envConfig.githubClientId,
119
+ typesenseCollectionName: process.env.TYPESENSE_COLLECTION_NAME || envConfig.typesenseCollectionName,
120
+ typesenseApiKey: process.env.TYPESENSE_API_KEY || envConfig.typesenseApiKey,
121
+ typesenseHost: process.env.TYPESENSE_HOST || envConfig.typesenseHost,
122
+ typesensePort: process.env.TYPESENSE_PORT || envConfig.typesensePort,
123
+ typesenseProtocol: process.env.TYPESENSE_PROTOCOL || envConfig.typesenseProtocol,
89
124
  isDevelopment: isDevelopment(env),
90
125
  isTesting: env === "testing",
91
126
  isStaging: env === "staging",
@@ -105,7 +140,7 @@ const getConfig = () => {
105
140
  );
106
141
  }
107
142
  if (finalConfig.isDevelopment) {
108
- console.log(
143
+ console.warn(
109
144
  "environment in SDK:",
110
145
  env || process.env.NODE_ENV || process.env.NODE_ENV
111
146
  );
@@ -10,15 +10,18 @@ import {
10
10
  createBranchService,
11
11
  createPullRequestService,
12
12
  createAdminService,
13
- createSubscriptionService
13
+ createSubscriptionService,
14
+ createScreenshotService
14
15
  } from "./services/index.js";
15
16
  import { SERVICE_METHODS } from "./utils/services.js";
16
17
  import environment from "./config/environment.js";
18
+ import { rootBus } from "./state/rootEventBus.js";
17
19
  class SDK {
18
20
  constructor(options = {}) {
19
21
  this._services = /* @__PURE__ */ new Map();
20
22
  this._context = {};
21
23
  this._options = this._validateOptions(options);
24
+ this.rootBus = rootBus;
22
25
  this._createServiceProxies();
23
26
  }
24
27
  // Initialize SDK with context
@@ -112,6 +115,13 @@ class SDK {
112
115
  context: this._context,
113
116
  options: this._options
114
117
  })
118
+ ),
119
+ this._initService(
120
+ "screenshot",
121
+ createScreenshotService({
122
+ context: this._context,
123
+ options: this._options
124
+ })
115
125
  )
116
126
  ]);
117
127
  return this;
@@ -149,9 +159,10 @@ class SDK {
149
159
  }
150
160
  // Update context
151
161
  updateContext(newContext) {
162
+ const { authToken, ...sanitized } = newContext || {};
152
163
  this._context = {
153
164
  ...this._context,
154
- ...newContext
165
+ ...sanitized
155
166
  };
156
167
  for (const service of this._services.values()) {
157
168
  service.updateContext(this._context);
@@ -160,9 +171,7 @@ class SDK {
160
171
  // Check if SDK is ready
161
172
  isReady() {
162
173
  const sdkServices = Array.from(this._services.values());
163
- return sdkServices.length > 0 && sdkServices.every(
164
- (service) => service.isReady()
165
- );
174
+ return sdkServices.length > 0 && sdkServices.every((service) => service.isReady());
166
175
  }
167
176
  // Get SDK status
168
177
  getStatus() {
@@ -51,7 +51,7 @@ class AdminService extends BaseService {
51
51
  }
52
52
  throw new Error(response.message);
53
53
  } catch (error) {
54
- throw new Error(`Failed to get admin users: ${error.message}`);
54
+ throw new Error(`Failed to get admin users: ${error.message}`, { cause: error });
55
55
  }
56
56
  }
57
57
  /**
@@ -82,7 +82,7 @@ class AdminService extends BaseService {
82
82
  }
83
83
  throw new Error(response.message);
84
84
  } catch (error) {
85
- throw new Error(`Failed to assign projects to user: ${error.message}`);
85
+ throw new Error(`Failed to assign projects to user: ${error.message}`, { cause: error });
86
86
  }
87
87
  }
88
88
  /**
@@ -111,7 +111,7 @@ class AdminService extends BaseService {
111
111
  if ((_a = error.message) == null ? void 0 : _a.includes("Duplicate")) {
112
112
  throw new Error("Username already exists");
113
113
  }
114
- throw new Error(`Failed to update user: ${error.message}`);
114
+ throw new Error(`Failed to update user: ${error.message}`, { cause: error });
115
115
  }
116
116
  }
117
117
  // ==================== ADMIN HELPER METHODS ====================
@@ -241,7 +241,7 @@ class AdminService extends BaseService {
241
241
  });
242
242
  return stats;
243
243
  } catch (error) {
244
- throw new Error(`Failed to get user stats: ${error.message}`);
244
+ throw new Error(`Failed to get user stats: ${error.message}`, { cause: error });
245
245
  }
246
246
  }
247
247
  /**