@symbo.ls/sdk 3.1.2 → 3.2.3
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.
- package/README.md +2 -2
- package/dist/cjs/config/environment.js +5 -21
- package/dist/cjs/index.js +6 -26
- package/dist/cjs/services/AIService.js +3 -3
- package/dist/cjs/services/CollabService.js +420 -0
- package/dist/cjs/services/CoreService.js +651 -107
- package/dist/cjs/services/SocketService.js +207 -59
- package/dist/cjs/services/index.js +5 -13
- package/dist/cjs/state/RootStateManager.js +86 -0
- package/dist/cjs/state/rootEventBus.js +65 -0
- package/dist/cjs/utils/CollabClient.js +157 -0
- package/dist/cjs/utils/TokenManager.js +62 -27
- package/dist/cjs/utils/jsonDiff.js +103 -0
- package/dist/cjs/utils/services.js +129 -88
- package/dist/cjs/utils/symstoryClient.js +5 -5
- package/dist/esm/config/environment.js +5 -21
- package/dist/esm/index.js +20459 -9286
- package/dist/esm/services/AIService.js +3 -3
- package/dist/esm/services/BasedService.js +5 -21
- package/dist/esm/services/CollabService.js +18028 -0
- package/dist/esm/services/CoreService.js +718 -155
- package/dist/esm/services/SocketService.js +323 -58
- package/dist/esm/services/SymstoryService.js +10 -26
- package/dist/esm/services/index.js +20305 -9158
- package/dist/esm/state/RootStateManager.js +102 -0
- package/dist/esm/state/rootEventBus.js +47 -0
- package/dist/esm/utils/CollabClient.js +17483 -0
- package/dist/esm/utils/TokenManager.js +62 -27
- package/dist/esm/utils/jsonDiff.js +6096 -0
- package/dist/esm/utils/services.js +129 -88
- package/dist/esm/utils/symstoryClient.js +10 -26
- package/dist/node/config/environment.js +5 -21
- package/dist/node/index.js +10 -34
- package/dist/node/services/AIService.js +3 -3
- package/dist/node/services/CollabService.js +401 -0
- package/dist/node/services/CoreService.js +651 -107
- package/dist/node/services/SocketService.js +197 -59
- package/dist/node/services/index.js +5 -13
- package/dist/node/state/RootStateManager.js +57 -0
- package/dist/node/state/rootEventBus.js +46 -0
- package/dist/node/utils/CollabClient.js +128 -0
- package/dist/node/utils/TokenManager.js +62 -27
- package/dist/node/utils/jsonDiff.js +74 -0
- package/dist/node/utils/services.js +129 -88
- package/dist/node/utils/symstoryClient.js +5 -5
- package/package.json +12 -6
- package/src/config/environment.js +5 -19
- package/src/index.js +9 -31
- package/src/services/AIService.js +3 -3
- package/src/services/BasedService.js +1 -0
- package/src/services/CollabService.js +491 -0
- package/src/services/CoreService.js +715 -110
- package/src/services/SocketService.js +227 -59
- package/src/services/index.js +6 -13
- package/src/state/RootStateManager.js +71 -0
- package/src/state/rootEventBus.js +48 -0
- package/src/utils/CollabClient.js +161 -0
- package/src/utils/TokenManager.js +68 -30
- package/src/utils/jsonDiff.js +109 -0
- package/src/utils/services.js +140 -88
- package/src/utils/symstoryClient.js +5 -5
- package/dist/cjs/services/SocketIOService.js +0 -307
- package/dist/esm/services/SocketIOService.js +0 -470
- package/dist/node/services/SocketIOService.js +0 -278
- package/src/services/SocketIOService.js +0 -334
|
@@ -6,18 +6,18 @@ class CoreService extends BaseService {
|
|
|
6
6
|
super(config);
|
|
7
7
|
this._client = null;
|
|
8
8
|
this._initialized = false;
|
|
9
|
-
this.
|
|
9
|
+
this._apiUrl = null;
|
|
10
10
|
this._tokenManager = null;
|
|
11
11
|
}
|
|
12
12
|
init({ context }) {
|
|
13
13
|
try {
|
|
14
14
|
const { appKey, authToken } = context || this._context;
|
|
15
|
-
this.
|
|
16
|
-
if (!this.
|
|
15
|
+
this._apiUrl = environment.apiUrl;
|
|
16
|
+
if (!this._apiUrl) {
|
|
17
17
|
throw new Error("Core service base URL not configured");
|
|
18
18
|
}
|
|
19
19
|
this._tokenManager = getTokenManager({
|
|
20
|
-
apiUrl: this.
|
|
20
|
+
apiUrl: this._apiUrl,
|
|
21
21
|
onTokenRefresh: (tokens) => {
|
|
22
22
|
this.updateContext({ authToken: tokens.accessToken });
|
|
23
23
|
},
|
|
@@ -28,12 +28,12 @@ class CoreService extends BaseService {
|
|
|
28
28
|
console.error("Token management error:", error);
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
|
-
if (authToken) {
|
|
31
|
+
if (authToken && !this._tokenManager.hasTokens()) {
|
|
32
32
|
this._tokenManager.setTokens({ access_token: authToken });
|
|
33
33
|
}
|
|
34
34
|
this._info = {
|
|
35
35
|
config: {
|
|
36
|
-
|
|
36
|
+
apiUrl: this._apiUrl,
|
|
37
37
|
appKey: appKey ? `${appKey.substr(0, 4)}...${appKey.substr(-4)}` : null,
|
|
38
38
|
hasToken: Boolean(authToken)
|
|
39
39
|
}
|
|
@@ -51,11 +51,15 @@ class CoreService extends BaseService {
|
|
|
51
51
|
"register",
|
|
52
52
|
"login",
|
|
53
53
|
"googleAuth",
|
|
54
|
+
"googleAuthCallback",
|
|
54
55
|
"githubAuth",
|
|
55
56
|
"requestPasswordReset",
|
|
56
57
|
"confirmPasswordReset",
|
|
57
58
|
"confirmRegistration",
|
|
58
|
-
"verifyEmail"
|
|
59
|
+
"verifyEmail",
|
|
60
|
+
"listPublicProjects",
|
|
61
|
+
"getPublicProject",
|
|
62
|
+
"getHealthStatus"
|
|
59
63
|
]);
|
|
60
64
|
return !noInitMethods.has(methodName);
|
|
61
65
|
}
|
|
@@ -86,24 +90,34 @@ class CoreService extends BaseService {
|
|
|
86
90
|
authHeader: this._tokenManager.getAuthHeader()
|
|
87
91
|
};
|
|
88
92
|
}
|
|
93
|
+
// Helper method to check if user is authenticated
|
|
94
|
+
isAuthenticated() {
|
|
95
|
+
if (!this._tokenManager) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
return this._tokenManager.hasTokens();
|
|
99
|
+
}
|
|
100
|
+
// Helper method to check if user has valid tokens
|
|
101
|
+
hasValidTokens() {
|
|
102
|
+
if (!this._tokenManager) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
return this._tokenManager.hasTokens() && this._tokenManager.isAccessTokenValid();
|
|
106
|
+
}
|
|
89
107
|
// Helper method to make HTTP requests
|
|
90
108
|
async _request(endpoint, options = {}) {
|
|
91
|
-
const url = `${this.
|
|
92
|
-
const defaultHeaders = {
|
|
93
|
-
|
|
94
|
-
|
|
109
|
+
const url = `${this._apiUrl}/core${endpoint}`;
|
|
110
|
+
const defaultHeaders = {};
|
|
111
|
+
if (!(options.body instanceof FormData)) {
|
|
112
|
+
defaultHeaders["Content-Type"] = "application/json";
|
|
113
|
+
}
|
|
95
114
|
if (this._requiresInit(options.methodName) && this._tokenManager) {
|
|
96
115
|
try {
|
|
97
116
|
const validToken = await this._tokenManager.ensureValidToken();
|
|
98
|
-
console.log(`[CoreService] Token check for ${options.methodName}:`, {
|
|
99
|
-
hasValidToken: Boolean(validToken),
|
|
100
|
-
tokenPreview: validToken ? `${validToken.substring(0, 20)}...` : null
|
|
101
|
-
});
|
|
102
117
|
if (validToken) {
|
|
103
118
|
const authHeader = this._tokenManager.getAuthHeader();
|
|
104
119
|
if (authHeader) {
|
|
105
120
|
defaultHeaders.Authorization = authHeader;
|
|
106
|
-
console.log(`[CoreService] Added auth header for ${options.methodName}`);
|
|
107
121
|
}
|
|
108
122
|
}
|
|
109
123
|
} catch (error) {
|
|
@@ -113,7 +127,6 @@ class CoreService extends BaseService {
|
|
|
113
127
|
const { authToken } = this._context;
|
|
114
128
|
if (authToken) {
|
|
115
129
|
defaultHeaders.Authorization = `Bearer ${authToken}`;
|
|
116
|
-
console.log(`[CoreService] Using context token for ${options.methodName}`);
|
|
117
130
|
}
|
|
118
131
|
}
|
|
119
132
|
try {
|
|
@@ -140,11 +153,15 @@ class CoreService extends BaseService {
|
|
|
140
153
|
// ==================== AUTH METHODS ====================
|
|
141
154
|
async register(userData) {
|
|
142
155
|
try {
|
|
143
|
-
|
|
156
|
+
const response = await this._request("/auth/register", {
|
|
144
157
|
method: "POST",
|
|
145
158
|
body: JSON.stringify(userData),
|
|
146
159
|
methodName: "register"
|
|
147
160
|
});
|
|
161
|
+
if (response.success) {
|
|
162
|
+
return response.data;
|
|
163
|
+
}
|
|
164
|
+
throw new Error(response.message);
|
|
148
165
|
} catch (error) {
|
|
149
166
|
throw new Error(`Registration failed: ${error.message}`);
|
|
150
167
|
}
|
|
@@ -170,7 +187,10 @@ class CoreService extends BaseService {
|
|
|
170
187
|
}
|
|
171
188
|
this.updateContext({ authToken: tokens.accessToken });
|
|
172
189
|
}
|
|
173
|
-
|
|
190
|
+
if (response.success) {
|
|
191
|
+
return response.data;
|
|
192
|
+
}
|
|
193
|
+
throw new Error(response.message);
|
|
174
194
|
} catch (error) {
|
|
175
195
|
throw new Error(`Login failed: ${error.message}`);
|
|
176
196
|
}
|
|
@@ -196,11 +216,15 @@ class CoreService extends BaseService {
|
|
|
196
216
|
}
|
|
197
217
|
async refreshToken(refreshToken) {
|
|
198
218
|
try {
|
|
199
|
-
|
|
219
|
+
const response = await this._request("/auth/refresh", {
|
|
200
220
|
method: "POST",
|
|
201
221
|
body: JSON.stringify({ refreshToken }),
|
|
202
222
|
methodName: "refreshToken"
|
|
203
223
|
});
|
|
224
|
+
if (response.success) {
|
|
225
|
+
return response.data;
|
|
226
|
+
}
|
|
227
|
+
throw new Error(response.message);
|
|
204
228
|
} catch (error) {
|
|
205
229
|
throw new Error(`Token refresh failed: ${error.message}`);
|
|
206
230
|
}
|
|
@@ -226,7 +250,10 @@ class CoreService extends BaseService {
|
|
|
226
250
|
}
|
|
227
251
|
this.updateContext({ authToken: tokens.accessToken });
|
|
228
252
|
}
|
|
229
|
-
|
|
253
|
+
if (response.success) {
|
|
254
|
+
return response.data;
|
|
255
|
+
}
|
|
256
|
+
throw new Error(response.message);
|
|
230
257
|
} catch (error) {
|
|
231
258
|
throw new Error(`Google auth failed: ${error.message}`);
|
|
232
259
|
}
|
|
@@ -252,40 +279,84 @@ class CoreService extends BaseService {
|
|
|
252
279
|
}
|
|
253
280
|
this.updateContext({ authToken: tokens.accessToken });
|
|
254
281
|
}
|
|
255
|
-
|
|
282
|
+
if (response.success) {
|
|
283
|
+
return response.data;
|
|
284
|
+
}
|
|
285
|
+
throw new Error(response.message);
|
|
256
286
|
} catch (error) {
|
|
257
287
|
throw new Error(`GitHub auth failed: ${error.message}`);
|
|
258
288
|
}
|
|
259
289
|
}
|
|
290
|
+
async googleAuthCallback(code, redirectUri) {
|
|
291
|
+
var _a;
|
|
292
|
+
try {
|
|
293
|
+
const response = await this._request("/auth/google/callback", {
|
|
294
|
+
method: "POST",
|
|
295
|
+
body: JSON.stringify({ code, redirectUri }),
|
|
296
|
+
methodName: "googleAuthCallback"
|
|
297
|
+
});
|
|
298
|
+
if (response.success && response.data && response.data.tokens) {
|
|
299
|
+
const { tokens } = response.data;
|
|
300
|
+
const tokenData = {
|
|
301
|
+
access_token: tokens.accessToken,
|
|
302
|
+
refresh_token: tokens.refreshToken,
|
|
303
|
+
expires_in: (_a = tokens.accessTokenExp) == null ? void 0 : _a.expiresIn,
|
|
304
|
+
token_type: "Bearer"
|
|
305
|
+
};
|
|
306
|
+
if (this._tokenManager) {
|
|
307
|
+
this._tokenManager.setTokens(tokenData);
|
|
308
|
+
}
|
|
309
|
+
this.updateContext({ authToken: tokens.accessToken });
|
|
310
|
+
}
|
|
311
|
+
if (response.success) {
|
|
312
|
+
return response.data;
|
|
313
|
+
}
|
|
314
|
+
throw new Error(response.message);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
throw new Error(`Google auth callback failed: ${error.message}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
260
319
|
async requestPasswordReset(email) {
|
|
261
320
|
try {
|
|
262
|
-
|
|
321
|
+
const response = await this._request("/auth/request-password-reset", {
|
|
263
322
|
method: "POST",
|
|
264
323
|
body: JSON.stringify({ email }),
|
|
265
324
|
methodName: "requestPasswordReset"
|
|
266
325
|
});
|
|
326
|
+
if (response.success) {
|
|
327
|
+
return response.data;
|
|
328
|
+
}
|
|
329
|
+
throw new Error(response.message);
|
|
267
330
|
} catch (error) {
|
|
268
331
|
throw new Error(`Password reset request failed: ${error.message}`);
|
|
269
332
|
}
|
|
270
333
|
}
|
|
271
334
|
async confirmPasswordReset(token, password) {
|
|
272
335
|
try {
|
|
273
|
-
|
|
336
|
+
const response = await this._request("/auth/reset-password-confirm", {
|
|
274
337
|
method: "POST",
|
|
275
338
|
body: JSON.stringify({ token, password }),
|
|
276
339
|
methodName: "confirmPasswordReset"
|
|
277
340
|
});
|
|
341
|
+
if (response.success) {
|
|
342
|
+
return response.data;
|
|
343
|
+
}
|
|
344
|
+
throw new Error(response.message);
|
|
278
345
|
} catch (error) {
|
|
279
346
|
throw new Error(`Password reset confirmation failed: ${error.message}`);
|
|
280
347
|
}
|
|
281
348
|
}
|
|
282
349
|
async confirmRegistration(token) {
|
|
283
350
|
try {
|
|
284
|
-
|
|
351
|
+
const response = await this._request("/auth/register-confirmation", {
|
|
285
352
|
method: "POST",
|
|
286
353
|
body: JSON.stringify({ token }),
|
|
287
354
|
methodName: "confirmRegistration"
|
|
288
355
|
});
|
|
356
|
+
if (response.success) {
|
|
357
|
+
return response.data;
|
|
358
|
+
}
|
|
359
|
+
throw new Error(response.message);
|
|
289
360
|
} catch (error) {
|
|
290
361
|
throw new Error(`Registration confirmation failed: ${error.message}`);
|
|
291
362
|
}
|
|
@@ -293,10 +364,14 @@ class CoreService extends BaseService {
|
|
|
293
364
|
async requestPasswordChange() {
|
|
294
365
|
this._requireReady("requestPasswordChange");
|
|
295
366
|
try {
|
|
296
|
-
|
|
367
|
+
const response = await this._request("/auth/request-password-change", {
|
|
297
368
|
method: "POST",
|
|
298
369
|
methodName: "requestPasswordChange"
|
|
299
370
|
});
|
|
371
|
+
if (response.success) {
|
|
372
|
+
return response.data;
|
|
373
|
+
}
|
|
374
|
+
throw new Error(response.message);
|
|
300
375
|
} catch (error) {
|
|
301
376
|
throw new Error(`Password change request failed: ${error.message}`);
|
|
302
377
|
}
|
|
@@ -304,11 +379,15 @@ class CoreService extends BaseService {
|
|
|
304
379
|
async confirmPasswordChange(currentPassword, newPassword, code) {
|
|
305
380
|
this._requireReady("confirmPasswordChange");
|
|
306
381
|
try {
|
|
307
|
-
|
|
382
|
+
const response = await this._request("/auth/confirm-password-change", {
|
|
308
383
|
method: "POST",
|
|
309
384
|
body: JSON.stringify({ currentPassword, newPassword, code }),
|
|
310
385
|
methodName: "confirmPasswordChange"
|
|
311
386
|
});
|
|
387
|
+
if (response.success) {
|
|
388
|
+
return response.data;
|
|
389
|
+
}
|
|
390
|
+
throw new Error(response.message);
|
|
312
391
|
} catch (error) {
|
|
313
392
|
throw new Error(`Password change confirmation failed: ${error.message}`);
|
|
314
393
|
}
|
|
@@ -316,10 +395,14 @@ class CoreService extends BaseService {
|
|
|
316
395
|
async getMe() {
|
|
317
396
|
this._requireReady("getMe");
|
|
318
397
|
try {
|
|
319
|
-
|
|
398
|
+
const response = await this._request("/auth/me", {
|
|
320
399
|
method: "GET",
|
|
321
400
|
methodName: "getMe"
|
|
322
401
|
});
|
|
402
|
+
if (response.success) {
|
|
403
|
+
return response.data;
|
|
404
|
+
}
|
|
405
|
+
throw new Error(response.message);
|
|
323
406
|
} catch (error) {
|
|
324
407
|
throw new Error(`Failed to get user profile: ${error.message}`);
|
|
325
408
|
}
|
|
@@ -347,35 +430,57 @@ class CoreService extends BaseService {
|
|
|
347
430
|
try {
|
|
348
431
|
await this._tokenManager.ensureValidToken();
|
|
349
432
|
} catch (error) {
|
|
350
|
-
|
|
433
|
+
console.warn("[CoreService] Token refresh failed:", error.message);
|
|
434
|
+
if (error.message.includes("401") || error.message.includes("403") || error.message.includes("invalid") || error.message.includes("expired")) {
|
|
435
|
+
this._tokenManager.clearTokens();
|
|
436
|
+
return {
|
|
437
|
+
userId: false,
|
|
438
|
+
authToken: false,
|
|
439
|
+
error: `Authentication failed: ${error.message}`
|
|
440
|
+
};
|
|
441
|
+
}
|
|
351
442
|
return {
|
|
352
443
|
userId: false,
|
|
353
|
-
authToken:
|
|
354
|
-
error: `
|
|
444
|
+
authToken: this._tokenManager.getAccessToken(),
|
|
445
|
+
error: `Network error during token refresh: ${error.message}`,
|
|
446
|
+
hasTokens: true
|
|
355
447
|
};
|
|
356
448
|
}
|
|
357
449
|
}
|
|
450
|
+
const currentAccessToken = this._tokenManager.getAccessToken();
|
|
451
|
+
if (!currentAccessToken) {
|
|
452
|
+
return {
|
|
453
|
+
userId: false,
|
|
454
|
+
authToken: false
|
|
455
|
+
};
|
|
456
|
+
}
|
|
358
457
|
try {
|
|
359
458
|
const currentUser = await this.getMe();
|
|
360
|
-
const userProjects = await this.getUserProjects();
|
|
361
459
|
return {
|
|
362
|
-
userId: currentUser.
|
|
363
|
-
authToken:
|
|
364
|
-
|
|
365
|
-
...currentUser.data,
|
|
366
|
-
projects: (userProjects == null ? void 0 : userProjects.data) || []
|
|
367
|
-
},
|
|
460
|
+
userId: currentUser.user.id,
|
|
461
|
+
authToken: currentAccessToken,
|
|
462
|
+
...currentUser,
|
|
368
463
|
error: null
|
|
369
464
|
};
|
|
370
465
|
} catch (error) {
|
|
371
|
-
|
|
466
|
+
console.warn("[CoreService] Failed to get user data:", error.message);
|
|
467
|
+
if (error.message.includes("401") || error.message.includes("403")) {
|
|
468
|
+
this._tokenManager.clearTokens();
|
|
469
|
+
return {
|
|
470
|
+
userId: false,
|
|
471
|
+
authToken: false,
|
|
472
|
+
error: `Authentication failed: ${error.message}`
|
|
473
|
+
};
|
|
474
|
+
}
|
|
372
475
|
return {
|
|
373
476
|
userId: false,
|
|
374
|
-
authToken:
|
|
375
|
-
error: `Failed to get user data: ${error.message}
|
|
477
|
+
authToken: currentAccessToken,
|
|
478
|
+
error: `Failed to get user data: ${error.message}`,
|
|
479
|
+
hasTokens: true
|
|
376
480
|
};
|
|
377
481
|
}
|
|
378
482
|
} catch (error) {
|
|
483
|
+
console.error("[CoreService] Unexpected error in getStoredAuthState:", error);
|
|
379
484
|
return {
|
|
380
485
|
userId: false,
|
|
381
486
|
authToken: false,
|
|
@@ -387,10 +492,14 @@ class CoreService extends BaseService {
|
|
|
387
492
|
async getUserProfile() {
|
|
388
493
|
this._requireReady("getUserProfile");
|
|
389
494
|
try {
|
|
390
|
-
|
|
495
|
+
const response = await this._request("/users/profile", {
|
|
391
496
|
method: "GET",
|
|
392
497
|
methodName: "getUserProfile"
|
|
393
498
|
});
|
|
499
|
+
if (response.success) {
|
|
500
|
+
return response.data;
|
|
501
|
+
}
|
|
502
|
+
throw new Error(response.message);
|
|
394
503
|
} catch (error) {
|
|
395
504
|
throw new Error(`Failed to get user profile: ${error.message}`);
|
|
396
505
|
}
|
|
@@ -398,11 +507,15 @@ class CoreService extends BaseService {
|
|
|
398
507
|
async updateUserProfile(profileData) {
|
|
399
508
|
this._requireReady("updateUserProfile");
|
|
400
509
|
try {
|
|
401
|
-
|
|
510
|
+
const response = await this._request("/users/profile", {
|
|
402
511
|
method: "PATCH",
|
|
403
512
|
body: JSON.stringify(profileData),
|
|
404
513
|
methodName: "updateUserProfile"
|
|
405
514
|
});
|
|
515
|
+
if (response.success) {
|
|
516
|
+
return response.data;
|
|
517
|
+
}
|
|
518
|
+
throw new Error(response.message);
|
|
406
519
|
} catch (error) {
|
|
407
520
|
throw new Error(`Failed to update user profile: ${error.message}`);
|
|
408
521
|
}
|
|
@@ -410,10 +523,17 @@ class CoreService extends BaseService {
|
|
|
410
523
|
async getUserProjects() {
|
|
411
524
|
this._requireReady("getUserProjects");
|
|
412
525
|
try {
|
|
413
|
-
|
|
526
|
+
const response = await this._request("/users/projects", {
|
|
414
527
|
method: "GET",
|
|
415
528
|
methodName: "getUserProjects"
|
|
416
529
|
});
|
|
530
|
+
if (response.success) {
|
|
531
|
+
return response.data.map((project) => ({
|
|
532
|
+
...project,
|
|
533
|
+
...project.icon && { icon: { src: `${this._apiUrl}/core/files/public/${project.icon.id}/download`, ...project.icon } }
|
|
534
|
+
}));
|
|
535
|
+
}
|
|
536
|
+
throw new Error(response.message);
|
|
417
537
|
} catch (error) {
|
|
418
538
|
throw new Error(`Failed to get user projects: ${error.message}`);
|
|
419
539
|
}
|
|
@@ -424,10 +544,14 @@ class CoreService extends BaseService {
|
|
|
424
544
|
throw new Error("User ID is required");
|
|
425
545
|
}
|
|
426
546
|
try {
|
|
427
|
-
|
|
547
|
+
const response = await this._request(`/users/${userId}`, {
|
|
428
548
|
method: "GET",
|
|
429
549
|
methodName: "getUser"
|
|
430
550
|
});
|
|
551
|
+
if (response.success) {
|
|
552
|
+
return response.data;
|
|
553
|
+
}
|
|
554
|
+
throw new Error(response.message);
|
|
431
555
|
} catch (error) {
|
|
432
556
|
throw new Error(`Failed to get user: ${error.message}`);
|
|
433
557
|
}
|
|
@@ -438,13 +562,17 @@ class CoreService extends BaseService {
|
|
|
438
562
|
throw new Error("Email is required");
|
|
439
563
|
}
|
|
440
564
|
try {
|
|
441
|
-
|
|
565
|
+
const response = await this._request("/auth/user", {
|
|
442
566
|
method: "GET",
|
|
443
567
|
headers: {
|
|
444
568
|
"X-User-Email": email
|
|
445
569
|
},
|
|
446
570
|
methodName: "getUserByEmail"
|
|
447
571
|
});
|
|
572
|
+
if (response.success) {
|
|
573
|
+
return response.data;
|
|
574
|
+
}
|
|
575
|
+
throw new Error(response.message);
|
|
448
576
|
} catch (error) {
|
|
449
577
|
throw new Error(`Failed to get user by email: ${error.message}`);
|
|
450
578
|
}
|
|
@@ -453,50 +581,134 @@ class CoreService extends BaseService {
|
|
|
453
581
|
async createProject(projectData) {
|
|
454
582
|
this._requireReady("createProject");
|
|
455
583
|
try {
|
|
456
|
-
|
|
584
|
+
const response = await this._request("/projects", {
|
|
457
585
|
method: "POST",
|
|
458
586
|
body: JSON.stringify(projectData),
|
|
459
587
|
methodName: "createProject"
|
|
460
588
|
});
|
|
589
|
+
if (response.success) {
|
|
590
|
+
return response.data;
|
|
591
|
+
}
|
|
592
|
+
throw new Error(response.message);
|
|
461
593
|
} catch (error) {
|
|
462
594
|
throw new Error(`Failed to create project: ${error.message}`);
|
|
463
595
|
}
|
|
464
596
|
}
|
|
465
|
-
async getProjects() {
|
|
597
|
+
async getProjects(params = {}) {
|
|
466
598
|
this._requireReady("getProjects");
|
|
467
599
|
try {
|
|
468
|
-
|
|
600
|
+
const queryParams = new URLSearchParams();
|
|
601
|
+
Object.keys(params).forEach((key) => {
|
|
602
|
+
if (params[key] != null) {
|
|
603
|
+
queryParams.append(key, params[key]);
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
const queryString = queryParams.toString();
|
|
607
|
+
const url = `/projects${queryString ? `?${queryString}` : ""}`;
|
|
608
|
+
const response = await this._request(url, {
|
|
469
609
|
method: "GET",
|
|
470
610
|
methodName: "getProjects"
|
|
471
611
|
});
|
|
612
|
+
if (response.success) {
|
|
613
|
+
return response;
|
|
614
|
+
}
|
|
615
|
+
throw new Error(response.message);
|
|
472
616
|
} catch (error) {
|
|
473
617
|
throw new Error(`Failed to get projects: ${error.message}`);
|
|
474
618
|
}
|
|
475
619
|
}
|
|
620
|
+
/**
|
|
621
|
+
* Alias for getProjects for consistency with API naming
|
|
622
|
+
*/
|
|
623
|
+
async listProjects(params = {}) {
|
|
624
|
+
return await this.getProjects(params);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* List only public projects (no authentication required)
|
|
628
|
+
*/
|
|
629
|
+
async listPublicProjects(params = {}) {
|
|
630
|
+
try {
|
|
631
|
+
const queryParams = new URLSearchParams();
|
|
632
|
+
Object.keys(params).forEach((key) => {
|
|
633
|
+
if (params[key] != null) {
|
|
634
|
+
queryParams.append(key, params[key]);
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
const queryString = queryParams.toString();
|
|
638
|
+
const url = `/projects/public${queryString ? `?${queryString}` : ""}`;
|
|
639
|
+
const response = await this._request(url, {
|
|
640
|
+
method: "GET",
|
|
641
|
+
methodName: "listPublicProjects"
|
|
642
|
+
});
|
|
643
|
+
if (response.success) {
|
|
644
|
+
return response.data;
|
|
645
|
+
}
|
|
646
|
+
throw new Error(response.message);
|
|
647
|
+
} catch (error) {
|
|
648
|
+
throw new Error(`Failed to list public projects: ${error.message}`);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
476
651
|
async getProject(projectId) {
|
|
477
652
|
this._requireReady("getProject");
|
|
478
653
|
if (!projectId) {
|
|
479
654
|
throw new Error("Project ID is required");
|
|
480
655
|
}
|
|
481
656
|
try {
|
|
482
|
-
|
|
657
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
483
658
|
method: "GET",
|
|
484
659
|
methodName: "getProject"
|
|
485
660
|
});
|
|
661
|
+
if (response.success) {
|
|
662
|
+
const iconSrc = response.data.icon ? `${this._apiUrl}/core/files/public/${response.data.icon.id}/download` : null;
|
|
663
|
+
return {
|
|
664
|
+
...response.data,
|
|
665
|
+
icon: { src: iconSrc, ...response.data.icon }
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
throw new Error(response.message);
|
|
486
669
|
} catch (error) {
|
|
487
670
|
throw new Error(`Failed to get project: ${error.message}`);
|
|
488
671
|
}
|
|
489
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Get a public project by ID (no authentication required)
|
|
675
|
+
* Corresponds to router.get('/public/:projectId', ProjectController.getPublicProject)
|
|
676
|
+
*/
|
|
677
|
+
async getPublicProject(projectId) {
|
|
678
|
+
if (!projectId) {
|
|
679
|
+
throw new Error("Project ID is required");
|
|
680
|
+
}
|
|
681
|
+
try {
|
|
682
|
+
const response = await this._request(`/projects/public/${projectId}`, {
|
|
683
|
+
method: "GET",
|
|
684
|
+
methodName: "getPublicProject"
|
|
685
|
+
});
|
|
686
|
+
if (response.success) {
|
|
687
|
+
const iconSrc = response.data.icon ? `${this._apiUrl}/core/files/public/${response.data.icon.id}/download` : null;
|
|
688
|
+
return {
|
|
689
|
+
...response.data,
|
|
690
|
+
icon: { src: iconSrc, ...response.data.icon }
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
throw new Error(response.message);
|
|
694
|
+
} catch (error) {
|
|
695
|
+
throw new Error(`Failed to get public project: ${error.message}`);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
490
698
|
async getProjectByKey(key) {
|
|
491
699
|
this._requireReady("getProjectByKey");
|
|
492
700
|
if (!key) {
|
|
493
701
|
throw new Error("Project key is required");
|
|
494
702
|
}
|
|
495
703
|
try {
|
|
496
|
-
|
|
704
|
+
const response = await this._request(`/projects/check-key/${key}`, {
|
|
497
705
|
method: "GET",
|
|
498
706
|
methodName: "getProjectByKey"
|
|
499
707
|
});
|
|
708
|
+
if (response.success) {
|
|
709
|
+
return response.data;
|
|
710
|
+
}
|
|
711
|
+
throw new Error(response.message);
|
|
500
712
|
} catch (error) {
|
|
501
713
|
throw new Error(`Failed to get project by key: ${error.message}`);
|
|
502
714
|
}
|
|
@@ -507,11 +719,15 @@ class CoreService extends BaseService {
|
|
|
507
719
|
throw new Error("Project ID is required");
|
|
508
720
|
}
|
|
509
721
|
try {
|
|
510
|
-
|
|
722
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
511
723
|
method: "PATCH",
|
|
512
724
|
body: JSON.stringify(data),
|
|
513
725
|
methodName: "updateProject"
|
|
514
726
|
});
|
|
727
|
+
if (response.success) {
|
|
728
|
+
return response.data;
|
|
729
|
+
}
|
|
730
|
+
throw new Error(response.message);
|
|
515
731
|
} catch (error) {
|
|
516
732
|
throw new Error(`Failed to update project: ${error.message}`);
|
|
517
733
|
}
|
|
@@ -522,11 +738,15 @@ class CoreService extends BaseService {
|
|
|
522
738
|
throw new Error("Project ID is required");
|
|
523
739
|
}
|
|
524
740
|
try {
|
|
525
|
-
|
|
741
|
+
const response = await this._request(`/projects/${projectId}/components`, {
|
|
526
742
|
method: "PATCH",
|
|
527
743
|
body: JSON.stringify({ components }),
|
|
528
744
|
methodName: "updateProjectComponents"
|
|
529
745
|
});
|
|
746
|
+
if (response.success) {
|
|
747
|
+
return response.data;
|
|
748
|
+
}
|
|
749
|
+
throw new Error(response.message);
|
|
530
750
|
} catch (error) {
|
|
531
751
|
throw new Error(`Failed to update project components: ${error.message}`);
|
|
532
752
|
}
|
|
@@ -537,11 +757,15 @@ class CoreService extends BaseService {
|
|
|
537
757
|
throw new Error("Project ID is required");
|
|
538
758
|
}
|
|
539
759
|
try {
|
|
540
|
-
|
|
760
|
+
const response = await this._request(`/projects/${projectId}/settings`, {
|
|
541
761
|
method: "PATCH",
|
|
542
762
|
body: JSON.stringify({ settings }),
|
|
543
763
|
methodName: "updateProjectSettings"
|
|
544
764
|
});
|
|
765
|
+
if (response.success) {
|
|
766
|
+
return response.data;
|
|
767
|
+
}
|
|
768
|
+
throw new Error(response.message);
|
|
545
769
|
} catch (error) {
|
|
546
770
|
throw new Error(`Failed to update project settings: ${error.message}`);
|
|
547
771
|
}
|
|
@@ -552,11 +776,15 @@ class CoreService extends BaseService {
|
|
|
552
776
|
throw new Error("Project ID is required");
|
|
553
777
|
}
|
|
554
778
|
try {
|
|
555
|
-
|
|
779
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
556
780
|
method: "PATCH",
|
|
557
781
|
body: JSON.stringify({ name }),
|
|
558
782
|
methodName: "updateProjectName"
|
|
559
783
|
});
|
|
784
|
+
if (response.success) {
|
|
785
|
+
return response.data;
|
|
786
|
+
}
|
|
787
|
+
throw new Error(response.message);
|
|
560
788
|
} catch (error) {
|
|
561
789
|
throw new Error(`Failed to update project name: ${error.message}`);
|
|
562
790
|
}
|
|
@@ -567,26 +795,34 @@ class CoreService extends BaseService {
|
|
|
567
795
|
throw new Error("Project ID is required");
|
|
568
796
|
}
|
|
569
797
|
try {
|
|
570
|
-
|
|
798
|
+
const response = await this._request(`/projects/${projectId}/tier`, {
|
|
571
799
|
method: "PATCH",
|
|
572
800
|
body: JSON.stringify({ tier: pkg }),
|
|
573
801
|
methodName: "updateProjectPackage"
|
|
574
802
|
});
|
|
803
|
+
if (response.success) {
|
|
804
|
+
return response.data;
|
|
805
|
+
}
|
|
806
|
+
throw new Error(response.message);
|
|
575
807
|
} catch (error) {
|
|
576
808
|
throw new Error(`Failed to update project package: ${error.message}`);
|
|
577
809
|
}
|
|
578
810
|
}
|
|
579
|
-
async duplicateProject(projectId, newName, newKey) {
|
|
811
|
+
async duplicateProject(projectId, newName, newKey, targetUserId) {
|
|
580
812
|
this._requireReady("duplicateProject");
|
|
581
813
|
if (!projectId) {
|
|
582
814
|
throw new Error("Project ID is required");
|
|
583
815
|
}
|
|
584
816
|
try {
|
|
585
|
-
|
|
817
|
+
const response = await this._request(`/projects/${projectId}/duplicate`, {
|
|
586
818
|
method: "POST",
|
|
587
|
-
body: JSON.stringify({ name: newName, key: newKey }),
|
|
819
|
+
body: JSON.stringify({ name: newName, key: newKey, targetUserId }),
|
|
588
820
|
methodName: "duplicateProject"
|
|
589
821
|
});
|
|
822
|
+
if (response.success) {
|
|
823
|
+
return response.data;
|
|
824
|
+
}
|
|
825
|
+
throw new Error(response.message);
|
|
590
826
|
} catch (error) {
|
|
591
827
|
throw new Error(`Failed to duplicate project: ${error.message}`);
|
|
592
828
|
}
|
|
@@ -597,10 +833,14 @@ class CoreService extends BaseService {
|
|
|
597
833
|
throw new Error("Project ID is required");
|
|
598
834
|
}
|
|
599
835
|
try {
|
|
600
|
-
|
|
836
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
601
837
|
method: "DELETE",
|
|
602
838
|
methodName: "removeProject"
|
|
603
839
|
});
|
|
840
|
+
if (response.success) {
|
|
841
|
+
return response.data;
|
|
842
|
+
}
|
|
843
|
+
throw new Error(response.message);
|
|
604
844
|
} catch (error) {
|
|
605
845
|
throw new Error(`Failed to remove project: ${error.message}`);
|
|
606
846
|
}
|
|
@@ -611,10 +851,14 @@ class CoreService extends BaseService {
|
|
|
611
851
|
throw new Error("Project key is required");
|
|
612
852
|
}
|
|
613
853
|
try {
|
|
614
|
-
|
|
854
|
+
const response = await this._request(`/projects/check-key/${key}`, {
|
|
615
855
|
method: "GET",
|
|
616
856
|
methodName: "checkProjectKeyAvailability"
|
|
617
857
|
});
|
|
858
|
+
if (response.success) {
|
|
859
|
+
return response.data;
|
|
860
|
+
}
|
|
861
|
+
throw new Error(response.message);
|
|
618
862
|
} catch (error) {
|
|
619
863
|
throw new Error(`Failed to check project key availability: ${error.message}`);
|
|
620
864
|
}
|
|
@@ -626,40 +870,62 @@ class CoreService extends BaseService {
|
|
|
626
870
|
throw new Error("Project ID is required");
|
|
627
871
|
}
|
|
628
872
|
try {
|
|
629
|
-
|
|
873
|
+
const response = await this._request(`/projects/${projectId}/members`, {
|
|
630
874
|
method: "GET",
|
|
631
875
|
methodName: "getProjectMembers"
|
|
632
876
|
});
|
|
877
|
+
if (response.success) {
|
|
878
|
+
return response.data;
|
|
879
|
+
}
|
|
880
|
+
throw new Error(response.message);
|
|
633
881
|
} catch (error) {
|
|
634
882
|
throw new Error(`Failed to get project members: ${error.message}`);
|
|
635
883
|
}
|
|
636
884
|
}
|
|
637
|
-
async inviteMember(projectId, email,
|
|
885
|
+
async inviteMember(projectId, email, role = "guest", options = {}) {
|
|
638
886
|
this._requireReady("inviteMember");
|
|
639
|
-
if (!projectId || !email) {
|
|
640
|
-
throw new Error("Project ID and
|
|
887
|
+
if (!projectId || !email || !role) {
|
|
888
|
+
throw new Error("Project ID, email, and role are required");
|
|
641
889
|
}
|
|
890
|
+
const { name, callbackUrl } = options;
|
|
891
|
+
const defaultCallbackUrl = typeof window === "undefined" ? "https://app.symbols.com/accept-invite" : `${window.location.origin}/accept-invite`;
|
|
642
892
|
try {
|
|
643
|
-
|
|
893
|
+
const requestBody = {
|
|
894
|
+
email,
|
|
895
|
+
role,
|
|
896
|
+
callbackUrl: callbackUrl || defaultCallbackUrl
|
|
897
|
+
};
|
|
898
|
+
if (name) {
|
|
899
|
+
requestBody.name = name;
|
|
900
|
+
}
|
|
901
|
+
const response = await this._request(`/projects/${projectId}/invite`, {
|
|
644
902
|
method: "POST",
|
|
645
|
-
body: JSON.stringify(
|
|
903
|
+
body: JSON.stringify(requestBody),
|
|
646
904
|
methodName: "inviteMember"
|
|
647
905
|
});
|
|
906
|
+
if (response.success) {
|
|
907
|
+
return response.data;
|
|
908
|
+
}
|
|
909
|
+
throw new Error(response.message);
|
|
648
910
|
} catch (error) {
|
|
649
911
|
throw new Error(`Failed to invite member: ${error.message}`);
|
|
650
912
|
}
|
|
651
913
|
}
|
|
652
|
-
async acceptInvite(
|
|
914
|
+
async acceptInvite(token) {
|
|
653
915
|
this._requireReady("acceptInvite");
|
|
654
|
-
if (!
|
|
655
|
-
throw new Error("
|
|
916
|
+
if (!token) {
|
|
917
|
+
throw new Error("Invitation token is required");
|
|
656
918
|
}
|
|
657
919
|
try {
|
|
658
|
-
|
|
920
|
+
const response = await this._request("/projects/accept-invite", {
|
|
659
921
|
method: "POST",
|
|
660
922
|
body: JSON.stringify({ token }),
|
|
661
923
|
methodName: "acceptInvite"
|
|
662
924
|
});
|
|
925
|
+
if (response.success) {
|
|
926
|
+
return response.data;
|
|
927
|
+
}
|
|
928
|
+
throw new Error(response.message);
|
|
663
929
|
} catch (error) {
|
|
664
930
|
throw new Error(`Failed to accept invite: ${error.message}`);
|
|
665
931
|
}
|
|
@@ -670,11 +936,15 @@ class CoreService extends BaseService {
|
|
|
670
936
|
throw new Error("Project ID, member ID, and role are required");
|
|
671
937
|
}
|
|
672
938
|
try {
|
|
673
|
-
|
|
939
|
+
const response = await this._request(`/projects/${projectId}/members/${memberId}`, {
|
|
674
940
|
method: "PATCH",
|
|
675
941
|
body: JSON.stringify({ role }),
|
|
676
942
|
methodName: "updateMemberRole"
|
|
677
943
|
});
|
|
944
|
+
if (response.success) {
|
|
945
|
+
return response.data;
|
|
946
|
+
}
|
|
947
|
+
throw new Error(response.message);
|
|
678
948
|
} catch (error) {
|
|
679
949
|
throw new Error(`Failed to update member role: ${error.message}`);
|
|
680
950
|
}
|
|
@@ -685,10 +955,14 @@ class CoreService extends BaseService {
|
|
|
685
955
|
throw new Error("Project ID and member ID are required");
|
|
686
956
|
}
|
|
687
957
|
try {
|
|
688
|
-
|
|
958
|
+
const response = await this._request(`/projects/${projectId}/members/${memberId}`, {
|
|
689
959
|
method: "DELETE",
|
|
690
960
|
methodName: "removeMember"
|
|
691
961
|
});
|
|
962
|
+
if (response.success) {
|
|
963
|
+
return response.data;
|
|
964
|
+
}
|
|
965
|
+
throw new Error(response.message);
|
|
692
966
|
} catch (error) {
|
|
693
967
|
throw new Error(`Failed to remove member: ${error.message}`);
|
|
694
968
|
}
|
|
@@ -698,10 +972,14 @@ class CoreService extends BaseService {
|
|
|
698
972
|
this._requireReady("getAvailableLibraries");
|
|
699
973
|
const queryParams = new URLSearchParams(params).toString();
|
|
700
974
|
try {
|
|
701
|
-
|
|
975
|
+
const response = await this._request(`/projects/libraries/available?${queryParams}`, {
|
|
702
976
|
method: "GET",
|
|
703
977
|
methodName: "getAvailableLibraries"
|
|
704
978
|
});
|
|
979
|
+
if (response.success) {
|
|
980
|
+
return response.data;
|
|
981
|
+
}
|
|
982
|
+
throw new Error(response.message);
|
|
705
983
|
} catch (error) {
|
|
706
984
|
throw new Error(`Failed to get available libraries: ${error.message}`);
|
|
707
985
|
}
|
|
@@ -712,10 +990,14 @@ class CoreService extends BaseService {
|
|
|
712
990
|
throw new Error("Project ID is required");
|
|
713
991
|
}
|
|
714
992
|
try {
|
|
715
|
-
|
|
993
|
+
const response = await this._request(`/projects/${projectId}/libraries`, {
|
|
716
994
|
method: "GET",
|
|
717
995
|
methodName: "getProjectLibraries"
|
|
718
996
|
});
|
|
997
|
+
if (response.success) {
|
|
998
|
+
return response.data;
|
|
999
|
+
}
|
|
1000
|
+
throw new Error(response.message);
|
|
719
1001
|
} catch (error) {
|
|
720
1002
|
throw new Error(`Failed to get project libraries: ${error.message}`);
|
|
721
1003
|
}
|
|
@@ -726,11 +1008,15 @@ class CoreService extends BaseService {
|
|
|
726
1008
|
throw new Error("Project ID and library IDs are required");
|
|
727
1009
|
}
|
|
728
1010
|
try {
|
|
729
|
-
|
|
1011
|
+
const response = await this._request(`/projects/${projectId}/libraries`, {
|
|
730
1012
|
method: "POST",
|
|
731
1013
|
body: JSON.stringify({ libraryIds }),
|
|
732
1014
|
methodName: "addProjectLibraries"
|
|
733
1015
|
});
|
|
1016
|
+
if (response.success) {
|
|
1017
|
+
return response.data;
|
|
1018
|
+
}
|
|
1019
|
+
throw new Error(response.message);
|
|
734
1020
|
} catch (error) {
|
|
735
1021
|
throw new Error(`Failed to add project libraries: ${error.message}`);
|
|
736
1022
|
}
|
|
@@ -741,11 +1027,15 @@ class CoreService extends BaseService {
|
|
|
741
1027
|
throw new Error("Project ID and library IDs are required");
|
|
742
1028
|
}
|
|
743
1029
|
try {
|
|
744
|
-
|
|
1030
|
+
const response = await this._request(`/projects/${projectId}/libraries`, {
|
|
745
1031
|
method: "DELETE",
|
|
746
1032
|
body: JSON.stringify({ libraryIds }),
|
|
747
1033
|
methodName: "removeProjectLibraries"
|
|
748
1034
|
});
|
|
1035
|
+
if (response.success) {
|
|
1036
|
+
return response.data;
|
|
1037
|
+
}
|
|
1038
|
+
throw new Error(response.message);
|
|
749
1039
|
} catch (error) {
|
|
750
1040
|
throw new Error(`Failed to remove project libraries: ${error.message}`);
|
|
751
1041
|
}
|
|
@@ -765,19 +1055,28 @@ class CoreService extends BaseService {
|
|
|
765
1055
|
formData.append("tags", JSON.stringify(options.tags));
|
|
766
1056
|
}
|
|
767
1057
|
if (options.visibility) {
|
|
768
|
-
formData.append("visibility", options.visibility);
|
|
1058
|
+
formData.append("visibility", options.visibility || "public");
|
|
769
1059
|
}
|
|
770
1060
|
if (options.metadata) {
|
|
771
1061
|
formData.append("metadata", JSON.stringify(options.metadata));
|
|
772
1062
|
}
|
|
773
1063
|
try {
|
|
774
|
-
|
|
1064
|
+
const response = await this._request("/files/upload", {
|
|
775
1065
|
method: "POST",
|
|
776
1066
|
body: formData,
|
|
777
1067
|
headers: {},
|
|
778
1068
|
// Let browser set Content-Type for FormData
|
|
779
1069
|
methodName: "uploadFile"
|
|
780
1070
|
});
|
|
1071
|
+
if (!response.success) {
|
|
1072
|
+
throw new Error(response.message);
|
|
1073
|
+
}
|
|
1074
|
+
return {
|
|
1075
|
+
id: response.data.id,
|
|
1076
|
+
src: `${this._apiUrl}/core/files/public/${response.data.id}/download`,
|
|
1077
|
+
success: true,
|
|
1078
|
+
message: response.message
|
|
1079
|
+
};
|
|
781
1080
|
} catch (error) {
|
|
782
1081
|
throw new Error(`File upload failed: ${error.message}`);
|
|
783
1082
|
}
|
|
@@ -791,13 +1090,17 @@ class CoreService extends BaseService {
|
|
|
791
1090
|
formData.append("icon", iconFile);
|
|
792
1091
|
formData.append("projectId", projectId);
|
|
793
1092
|
try {
|
|
794
|
-
|
|
1093
|
+
const response = await this._request("/files/upload-project-icon", {
|
|
795
1094
|
method: "POST",
|
|
796
1095
|
body: formData,
|
|
797
1096
|
headers: {},
|
|
798
1097
|
// Let browser set Content-Type for FormData
|
|
799
1098
|
methodName: "updateProjectIcon"
|
|
800
1099
|
});
|
|
1100
|
+
if (response.success) {
|
|
1101
|
+
return response.data;
|
|
1102
|
+
}
|
|
1103
|
+
throw new Error(response.message);
|
|
801
1104
|
} catch (error) {
|
|
802
1105
|
throw new Error(`Failed to update project icon: ${error.message}`);
|
|
803
1106
|
}
|
|
@@ -816,7 +1119,7 @@ class CoreService extends BaseService {
|
|
|
816
1119
|
throw new Error("Project ID is required for checkout");
|
|
817
1120
|
}
|
|
818
1121
|
try {
|
|
819
|
-
|
|
1122
|
+
const response = await this._request("/payments/checkout", {
|
|
820
1123
|
method: "POST",
|
|
821
1124
|
body: JSON.stringify({
|
|
822
1125
|
projectId,
|
|
@@ -827,6 +1130,10 @@ class CoreService extends BaseService {
|
|
|
827
1130
|
}),
|
|
828
1131
|
methodName: "checkout"
|
|
829
1132
|
});
|
|
1133
|
+
if (response.success) {
|
|
1134
|
+
return response.data;
|
|
1135
|
+
}
|
|
1136
|
+
throw new Error(response.message);
|
|
830
1137
|
} catch (error) {
|
|
831
1138
|
throw new Error(`Failed to checkout: ${error.message}`);
|
|
832
1139
|
}
|
|
@@ -837,10 +1144,14 @@ class CoreService extends BaseService {
|
|
|
837
1144
|
throw new Error("Project ID is required");
|
|
838
1145
|
}
|
|
839
1146
|
try {
|
|
840
|
-
|
|
1147
|
+
const response = await this._request(`/payments/subscription/${projectId}`, {
|
|
841
1148
|
method: "GET",
|
|
842
1149
|
methodName: "getSubscriptionStatus"
|
|
843
1150
|
});
|
|
1151
|
+
if (response.success) {
|
|
1152
|
+
return response.data;
|
|
1153
|
+
}
|
|
1154
|
+
throw new Error(response.message);
|
|
844
1155
|
} catch (error) {
|
|
845
1156
|
throw new Error(`Failed to get subscription status: ${error.message}`);
|
|
846
1157
|
}
|
|
@@ -852,11 +1163,15 @@ class CoreService extends BaseService {
|
|
|
852
1163
|
throw new Error("Domain is required");
|
|
853
1164
|
}
|
|
854
1165
|
try {
|
|
855
|
-
|
|
1166
|
+
const response = await this._request("/dns/records", {
|
|
856
1167
|
method: "POST",
|
|
857
1168
|
body: JSON.stringify({ domain, ...options }),
|
|
858
1169
|
methodName: "createDnsRecord"
|
|
859
1170
|
});
|
|
1171
|
+
if (response.success) {
|
|
1172
|
+
return response.data;
|
|
1173
|
+
}
|
|
1174
|
+
throw new Error(response.message);
|
|
860
1175
|
} catch (error) {
|
|
861
1176
|
throw new Error(`Failed to create DNS record: ${error.message}`);
|
|
862
1177
|
}
|
|
@@ -867,10 +1182,14 @@ class CoreService extends BaseService {
|
|
|
867
1182
|
throw new Error("Domain is required");
|
|
868
1183
|
}
|
|
869
1184
|
try {
|
|
870
|
-
|
|
1185
|
+
const response = await this._request(`/dns/records/${domain}`, {
|
|
871
1186
|
method: "GET",
|
|
872
1187
|
methodName: "getDnsRecord"
|
|
873
1188
|
});
|
|
1189
|
+
if (response.success) {
|
|
1190
|
+
return response.data;
|
|
1191
|
+
}
|
|
1192
|
+
throw new Error(response.message);
|
|
874
1193
|
} catch (error) {
|
|
875
1194
|
throw new Error(`Failed to get DNS record: ${error.message}`);
|
|
876
1195
|
}
|
|
@@ -881,10 +1200,14 @@ class CoreService extends BaseService {
|
|
|
881
1200
|
throw new Error("Domain is required");
|
|
882
1201
|
}
|
|
883
1202
|
try {
|
|
884
|
-
|
|
1203
|
+
const response = await this._request(`/dns/records/${domain}`, {
|
|
885
1204
|
method: "DELETE",
|
|
886
1205
|
methodName: "removeDnsRecord"
|
|
887
1206
|
});
|
|
1207
|
+
if (response.success) {
|
|
1208
|
+
return response.data;
|
|
1209
|
+
}
|
|
1210
|
+
throw new Error(response.message);
|
|
888
1211
|
} catch (error) {
|
|
889
1212
|
throw new Error(`Failed to remove DNS record: ${error.message}`);
|
|
890
1213
|
}
|
|
@@ -895,7 +1218,7 @@ class CoreService extends BaseService {
|
|
|
895
1218
|
throw new Error("Project key is required");
|
|
896
1219
|
}
|
|
897
1220
|
try {
|
|
898
|
-
|
|
1221
|
+
const response = await this._request("/dns/project-domains", {
|
|
899
1222
|
method: "POST",
|
|
900
1223
|
body: JSON.stringify({
|
|
901
1224
|
projectKey,
|
|
@@ -904,6 +1227,10 @@ class CoreService extends BaseService {
|
|
|
904
1227
|
}),
|
|
905
1228
|
methodName: "setProjectDomains"
|
|
906
1229
|
});
|
|
1230
|
+
if (response.success) {
|
|
1231
|
+
return response.data;
|
|
1232
|
+
}
|
|
1233
|
+
throw new Error(response.message);
|
|
907
1234
|
} catch (error) {
|
|
908
1235
|
throw new Error(`Failed to set project domains: ${error.message}`);
|
|
909
1236
|
}
|
|
@@ -911,10 +1238,14 @@ class CoreService extends BaseService {
|
|
|
911
1238
|
// ==================== UTILITY METHODS ====================
|
|
912
1239
|
async getHealthStatus() {
|
|
913
1240
|
try {
|
|
914
|
-
|
|
1241
|
+
const response = await this._request("/health", {
|
|
915
1242
|
method: "GET",
|
|
916
1243
|
methodName: "getHealthStatus"
|
|
917
1244
|
});
|
|
1245
|
+
if (response.success) {
|
|
1246
|
+
return response.data;
|
|
1247
|
+
}
|
|
1248
|
+
throw new Error(response.message);
|
|
918
1249
|
} catch (error) {
|
|
919
1250
|
throw new Error(`Failed to get health status: ${error.message}`);
|
|
920
1251
|
}
|
|
@@ -948,7 +1279,10 @@ class CoreService extends BaseService {
|
|
|
948
1279
|
}),
|
|
949
1280
|
methodName: "applyProjectChanges"
|
|
950
1281
|
});
|
|
951
|
-
|
|
1282
|
+
if (response.success) {
|
|
1283
|
+
return response.data;
|
|
1284
|
+
}
|
|
1285
|
+
throw new Error(response.message);
|
|
952
1286
|
} catch (error) {
|
|
953
1287
|
throw new Error(`Failed to apply project changes: ${error.message}`);
|
|
954
1288
|
}
|
|
@@ -964,17 +1298,23 @@ class CoreService extends BaseService {
|
|
|
964
1298
|
}
|
|
965
1299
|
const {
|
|
966
1300
|
branch = "main",
|
|
1301
|
+
version = "latest",
|
|
967
1302
|
includeHistory = false
|
|
968
1303
|
} = options;
|
|
969
1304
|
const queryParams = new URLSearchParams({
|
|
970
1305
|
branch,
|
|
1306
|
+
version,
|
|
971
1307
|
includeHistory: includeHistory.toString()
|
|
972
1308
|
}).toString();
|
|
973
1309
|
try {
|
|
974
|
-
|
|
1310
|
+
const response = await this._request(`/projects/${projectId}/data?${queryParams}`, {
|
|
975
1311
|
method: "GET",
|
|
976
1312
|
methodName: "getProjectData"
|
|
977
1313
|
});
|
|
1314
|
+
if (response.success) {
|
|
1315
|
+
return response.data;
|
|
1316
|
+
}
|
|
1317
|
+
throw new Error(response.message);
|
|
978
1318
|
} catch (error) {
|
|
979
1319
|
throw new Error(`Failed to get project data: ${error.message}`);
|
|
980
1320
|
}
|
|
@@ -998,10 +1338,14 @@ class CoreService extends BaseService {
|
|
|
998
1338
|
limit: limit.toString()
|
|
999
1339
|
}).toString();
|
|
1000
1340
|
try {
|
|
1001
|
-
|
|
1341
|
+
const response = await this._request(`/projects/${projectId}/versions?${queryParams}`, {
|
|
1002
1342
|
method: "GET",
|
|
1003
1343
|
methodName: "getProjectVersions"
|
|
1004
1344
|
});
|
|
1345
|
+
if (response.success) {
|
|
1346
|
+
return response.data;
|
|
1347
|
+
}
|
|
1348
|
+
throw new Error(response.message);
|
|
1005
1349
|
} catch (error) {
|
|
1006
1350
|
throw new Error(`Failed to get project versions: ${error.message}`);
|
|
1007
1351
|
}
|
|
@@ -1024,7 +1368,7 @@ class CoreService extends BaseService {
|
|
|
1024
1368
|
type = "patch"
|
|
1025
1369
|
} = options;
|
|
1026
1370
|
try {
|
|
1027
|
-
|
|
1371
|
+
const response = await this._request(`/projects/${projectId}/restore`, {
|
|
1028
1372
|
method: "POST",
|
|
1029
1373
|
body: JSON.stringify({
|
|
1030
1374
|
version,
|
|
@@ -1034,6 +1378,10 @@ class CoreService extends BaseService {
|
|
|
1034
1378
|
}),
|
|
1035
1379
|
methodName: "restoreProjectVersion"
|
|
1036
1380
|
});
|
|
1381
|
+
if (response.success) {
|
|
1382
|
+
return response.data;
|
|
1383
|
+
}
|
|
1384
|
+
throw new Error(response.message);
|
|
1037
1385
|
} catch (error) {
|
|
1038
1386
|
throw new Error(`Failed to restore project version: ${error.message}`);
|
|
1039
1387
|
}
|
|
@@ -1126,11 +1474,15 @@ class CoreService extends BaseService {
|
|
|
1126
1474
|
throw new Error("Source branch, target branch, and title are required");
|
|
1127
1475
|
}
|
|
1128
1476
|
try {
|
|
1129
|
-
|
|
1477
|
+
const response = await this._request(`/projects/${projectId}/pull-requests`, {
|
|
1130
1478
|
method: "POST",
|
|
1131
1479
|
body: JSON.stringify(pullRequestData),
|
|
1132
1480
|
methodName: "createPullRequest"
|
|
1133
1481
|
});
|
|
1482
|
+
if (response.success) {
|
|
1483
|
+
return response.data;
|
|
1484
|
+
}
|
|
1485
|
+
throw new Error(response.message);
|
|
1134
1486
|
} catch (error) {
|
|
1135
1487
|
throw new Error(`Failed to create pull request: ${error.message}`);
|
|
1136
1488
|
}
|
|
@@ -1162,10 +1514,14 @@ class CoreService extends BaseService {
|
|
|
1162
1514
|
queryParams.append("target", target);
|
|
1163
1515
|
}
|
|
1164
1516
|
try {
|
|
1165
|
-
|
|
1517
|
+
const response = await this._request(`/projects/${projectId}/pull-requests?${queryParams.toString()}`, {
|
|
1166
1518
|
method: "GET",
|
|
1167
1519
|
methodName: "listPullRequests"
|
|
1168
1520
|
});
|
|
1521
|
+
if (response.success) {
|
|
1522
|
+
return response.data;
|
|
1523
|
+
}
|
|
1524
|
+
throw new Error(response.message);
|
|
1169
1525
|
} catch (error) {
|
|
1170
1526
|
throw new Error(`Failed to list pull requests: ${error.message}`);
|
|
1171
1527
|
}
|
|
@@ -1182,10 +1538,14 @@ class CoreService extends BaseService {
|
|
|
1182
1538
|
throw new Error("Pull request ID is required");
|
|
1183
1539
|
}
|
|
1184
1540
|
try {
|
|
1185
|
-
|
|
1541
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}`, {
|
|
1186
1542
|
method: "GET",
|
|
1187
1543
|
methodName: "getPullRequest"
|
|
1188
1544
|
});
|
|
1545
|
+
if (response.success) {
|
|
1546
|
+
return response.data;
|
|
1547
|
+
}
|
|
1548
|
+
throw new Error(response.message);
|
|
1189
1549
|
} catch (error) {
|
|
1190
1550
|
throw new Error(`Failed to get pull request: ${error.message}`);
|
|
1191
1551
|
}
|
|
@@ -1206,11 +1566,15 @@ class CoreService extends BaseService {
|
|
|
1206
1566
|
throw new Error(`Invalid review status. Must be one of: ${validStatuses.join(", ")}`);
|
|
1207
1567
|
}
|
|
1208
1568
|
try {
|
|
1209
|
-
|
|
1569
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}/review`, {
|
|
1210
1570
|
method: "POST",
|
|
1211
1571
|
body: JSON.stringify(reviewData),
|
|
1212
1572
|
methodName: "reviewPullRequest"
|
|
1213
1573
|
});
|
|
1574
|
+
if (response.success) {
|
|
1575
|
+
return response.data;
|
|
1576
|
+
}
|
|
1577
|
+
throw new Error(response.message);
|
|
1214
1578
|
} catch (error) {
|
|
1215
1579
|
throw new Error(`Failed to review pull request: ${error.message}`);
|
|
1216
1580
|
}
|
|
@@ -1230,11 +1594,15 @@ class CoreService extends BaseService {
|
|
|
1230
1594
|
throw new Error("Comment value is required");
|
|
1231
1595
|
}
|
|
1232
1596
|
try {
|
|
1233
|
-
|
|
1597
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}/comment`, {
|
|
1234
1598
|
method: "POST",
|
|
1235
1599
|
body: JSON.stringify(commentData),
|
|
1236
1600
|
methodName: "addPullRequestComment"
|
|
1237
1601
|
});
|
|
1602
|
+
if (response.success) {
|
|
1603
|
+
return response.data;
|
|
1604
|
+
}
|
|
1605
|
+
throw new Error(response.message);
|
|
1238
1606
|
} catch (error) {
|
|
1239
1607
|
throw new Error(`Failed to add pull request comment: ${error.message}`);
|
|
1240
1608
|
}
|
|
@@ -1255,7 +1623,10 @@ class CoreService extends BaseService {
|
|
|
1255
1623
|
method: "POST",
|
|
1256
1624
|
methodName: "mergePullRequest"
|
|
1257
1625
|
});
|
|
1258
|
-
|
|
1626
|
+
if (response.success) {
|
|
1627
|
+
return response.data;
|
|
1628
|
+
}
|
|
1629
|
+
throw new Error(response.message);
|
|
1259
1630
|
} catch (error) {
|
|
1260
1631
|
if (error.message.includes("conflicts") || error.message.includes("409")) {
|
|
1261
1632
|
throw new Error(`Pull request has merge conflicts: ${error.message}`);
|
|
@@ -1275,10 +1646,14 @@ class CoreService extends BaseService {
|
|
|
1275
1646
|
throw new Error("Pull request ID is required");
|
|
1276
1647
|
}
|
|
1277
1648
|
try {
|
|
1278
|
-
|
|
1649
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}/diff`, {
|
|
1279
1650
|
method: "GET",
|
|
1280
1651
|
methodName: "getPullRequestDiff"
|
|
1281
1652
|
});
|
|
1653
|
+
if (response.success) {
|
|
1654
|
+
return response.data;
|
|
1655
|
+
}
|
|
1656
|
+
throw new Error(response.message);
|
|
1282
1657
|
} catch (error) {
|
|
1283
1658
|
throw new Error(`Failed to get pull request diff: ${error.message}`);
|
|
1284
1659
|
}
|
|
@@ -1392,10 +1767,14 @@ class CoreService extends BaseService {
|
|
|
1392
1767
|
throw new Error("Project ID is required");
|
|
1393
1768
|
}
|
|
1394
1769
|
try {
|
|
1395
|
-
|
|
1770
|
+
const response = await this._request(`/projects/${projectId}/branches`, {
|
|
1396
1771
|
method: "GET",
|
|
1397
1772
|
methodName: "listBranches"
|
|
1398
1773
|
});
|
|
1774
|
+
if (response.success) {
|
|
1775
|
+
return response.data;
|
|
1776
|
+
}
|
|
1777
|
+
throw new Error(response.message);
|
|
1399
1778
|
} catch (error) {
|
|
1400
1779
|
throw new Error(`Failed to list branches: ${error.message}`);
|
|
1401
1780
|
}
|
|
@@ -1413,11 +1792,15 @@ class CoreService extends BaseService {
|
|
|
1413
1792
|
}
|
|
1414
1793
|
const { name, source = "main" } = branchData;
|
|
1415
1794
|
try {
|
|
1416
|
-
|
|
1795
|
+
const response = await this._request(`/projects/${projectId}/branches`, {
|
|
1417
1796
|
method: "POST",
|
|
1418
1797
|
body: JSON.stringify({ name, source }),
|
|
1419
1798
|
methodName: "createBranch"
|
|
1420
1799
|
});
|
|
1800
|
+
if (response.success) {
|
|
1801
|
+
return response.data;
|
|
1802
|
+
}
|
|
1803
|
+
throw new Error(response.message);
|
|
1421
1804
|
} catch (error) {
|
|
1422
1805
|
throw new Error(`Failed to create branch: ${error.message}`);
|
|
1423
1806
|
}
|
|
@@ -1437,10 +1820,14 @@ class CoreService extends BaseService {
|
|
|
1437
1820
|
throw new Error("Cannot delete main branch");
|
|
1438
1821
|
}
|
|
1439
1822
|
try {
|
|
1440
|
-
|
|
1823
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}`, {
|
|
1441
1824
|
method: "DELETE",
|
|
1442
1825
|
methodName: "deleteBranch"
|
|
1443
1826
|
});
|
|
1827
|
+
if (response.success) {
|
|
1828
|
+
return response.data;
|
|
1829
|
+
}
|
|
1830
|
+
throw new Error(response.message);
|
|
1444
1831
|
} catch (error) {
|
|
1445
1832
|
throw new Error(`Failed to delete branch: ${error.message}`);
|
|
1446
1833
|
}
|
|
@@ -1463,11 +1850,15 @@ class CoreService extends BaseService {
|
|
|
1463
1850
|
throw new Error("Cannot rename main branch");
|
|
1464
1851
|
}
|
|
1465
1852
|
try {
|
|
1466
|
-
|
|
1853
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}/rename`, {
|
|
1467
1854
|
method: "POST",
|
|
1468
1855
|
body: JSON.stringify({ newName }),
|
|
1469
1856
|
methodName: "renameBranch"
|
|
1470
1857
|
});
|
|
1858
|
+
if (response.success) {
|
|
1859
|
+
return response.data;
|
|
1860
|
+
}
|
|
1861
|
+
throw new Error(response.message);
|
|
1471
1862
|
} catch (error) {
|
|
1472
1863
|
throw new Error(`Failed to rename branch: ${error.message}`);
|
|
1473
1864
|
}
|
|
@@ -1475,7 +1866,7 @@ class CoreService extends BaseService {
|
|
|
1475
1866
|
/**
|
|
1476
1867
|
* Get changes/diff for a branch compared to another version
|
|
1477
1868
|
*/
|
|
1478
|
-
async getBranchChanges(projectId, branchName, options = {}) {
|
|
1869
|
+
async getBranchChanges(projectId, branchName = "main", options = {}) {
|
|
1479
1870
|
this._requireReady("getBranchChanges");
|
|
1480
1871
|
if (!projectId) {
|
|
1481
1872
|
throw new Error("Project ID is required");
|
|
@@ -1497,10 +1888,14 @@ class CoreService extends BaseService {
|
|
|
1497
1888
|
const queryString = queryParams.toString();
|
|
1498
1889
|
const url = `/projects/${projectId}/branches/${encodeURIComponent(branchName)}/changes${queryString ? `?${queryString}` : ""}`;
|
|
1499
1890
|
try {
|
|
1500
|
-
|
|
1891
|
+
const response = await this._request(url, {
|
|
1501
1892
|
method: "GET",
|
|
1502
1893
|
methodName: "getBranchChanges"
|
|
1503
1894
|
});
|
|
1895
|
+
if (response.success) {
|
|
1896
|
+
return response.data;
|
|
1897
|
+
}
|
|
1898
|
+
throw new Error(response.message);
|
|
1504
1899
|
} catch (error) {
|
|
1505
1900
|
throw new Error(`Failed to get branch changes: ${error.message}`);
|
|
1506
1901
|
}
|
|
@@ -1531,11 +1926,15 @@ class CoreService extends BaseService {
|
|
|
1531
1926
|
...changes && { changes }
|
|
1532
1927
|
};
|
|
1533
1928
|
try {
|
|
1534
|
-
|
|
1929
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}/merge`, {
|
|
1535
1930
|
method: "POST",
|
|
1536
1931
|
body: JSON.stringify(requestBody),
|
|
1537
1932
|
methodName: "mergeBranch"
|
|
1538
1933
|
});
|
|
1934
|
+
if (response.success) {
|
|
1935
|
+
return response.data;
|
|
1936
|
+
}
|
|
1937
|
+
throw new Error(response.message);
|
|
1539
1938
|
} catch (error) {
|
|
1540
1939
|
if (error.message.includes("conflicts") || error.message.includes("409")) {
|
|
1541
1940
|
throw new Error(`Merge conflicts detected: ${error.message}`);
|
|
@@ -1555,10 +1954,14 @@ class CoreService extends BaseService {
|
|
|
1555
1954
|
throw new Error("Branch name is required");
|
|
1556
1955
|
}
|
|
1557
1956
|
try {
|
|
1558
|
-
|
|
1957
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}/reset`, {
|
|
1559
1958
|
method: "POST",
|
|
1560
1959
|
methodName: "resetBranch"
|
|
1561
1960
|
});
|
|
1961
|
+
if (response.success) {
|
|
1962
|
+
return response.data;
|
|
1963
|
+
}
|
|
1964
|
+
throw new Error(response.message);
|
|
1562
1965
|
} catch (error) {
|
|
1563
1966
|
throw new Error(`Failed to reset branch: ${error.message}`);
|
|
1564
1967
|
}
|
|
@@ -1576,11 +1979,15 @@ class CoreService extends BaseService {
|
|
|
1576
1979
|
}
|
|
1577
1980
|
const { version, branch = "main" } = publishData;
|
|
1578
1981
|
try {
|
|
1579
|
-
|
|
1982
|
+
const response = await this._request(`/projects/${projectId}/publish`, {
|
|
1580
1983
|
method: "POST",
|
|
1581
1984
|
body: JSON.stringify({ version, branch }),
|
|
1582
1985
|
methodName: "publishVersion"
|
|
1583
1986
|
});
|
|
1987
|
+
if (response.success) {
|
|
1988
|
+
return response.data;
|
|
1989
|
+
}
|
|
1990
|
+
throw new Error(response.message);
|
|
1584
1991
|
} catch (error) {
|
|
1585
1992
|
throw new Error(`Failed to publish version: ${error.message}`);
|
|
1586
1993
|
}
|
|
@@ -1706,6 +2113,143 @@ class CoreService extends BaseService {
|
|
|
1706
2113
|
}
|
|
1707
2114
|
return await this.deleteBranch(projectId, branchName);
|
|
1708
2115
|
}
|
|
2116
|
+
// ==================== ADMIN METHODS ====================
|
|
2117
|
+
/**
|
|
2118
|
+
* Get admin users list with comprehensive filtering and search capabilities
|
|
2119
|
+
* Requires admin or super_admin global role
|
|
2120
|
+
*/
|
|
2121
|
+
async getAdminUsers(params = {}) {
|
|
2122
|
+
this._requireReady("getAdminUsers");
|
|
2123
|
+
const {
|
|
2124
|
+
emails,
|
|
2125
|
+
ids,
|
|
2126
|
+
query,
|
|
2127
|
+
status,
|
|
2128
|
+
page = 1,
|
|
2129
|
+
limit = 50,
|
|
2130
|
+
sort = { field: "createdAt", order: "desc" }
|
|
2131
|
+
} = params;
|
|
2132
|
+
const queryParams = new URLSearchParams();
|
|
2133
|
+
if (emails) {
|
|
2134
|
+
queryParams.append("emails", emails);
|
|
2135
|
+
}
|
|
2136
|
+
if (ids) {
|
|
2137
|
+
queryParams.append("ids", ids);
|
|
2138
|
+
}
|
|
2139
|
+
if (query) {
|
|
2140
|
+
queryParams.append("query", query);
|
|
2141
|
+
}
|
|
2142
|
+
if (status) {
|
|
2143
|
+
queryParams.append("status", status);
|
|
2144
|
+
}
|
|
2145
|
+
if (page) {
|
|
2146
|
+
queryParams.append("page", page.toString());
|
|
2147
|
+
}
|
|
2148
|
+
if (limit) {
|
|
2149
|
+
queryParams.append("limit", limit.toString());
|
|
2150
|
+
}
|
|
2151
|
+
if (sort && sort.field) {
|
|
2152
|
+
queryParams.append("sort[field]", sort.field);
|
|
2153
|
+
queryParams.append("sort[order]", sort.order || "desc");
|
|
2154
|
+
}
|
|
2155
|
+
const queryString = queryParams.toString();
|
|
2156
|
+
const url = `/users/admin/users${queryString ? `?${queryString}` : ""}`;
|
|
2157
|
+
try {
|
|
2158
|
+
const response = await this._request(url, {
|
|
2159
|
+
method: "GET",
|
|
2160
|
+
methodName: "getAdminUsers"
|
|
2161
|
+
});
|
|
2162
|
+
if (response.success) {
|
|
2163
|
+
return response.data;
|
|
2164
|
+
}
|
|
2165
|
+
throw new Error(response.message);
|
|
2166
|
+
} catch (error) {
|
|
2167
|
+
throw new Error(`Failed to get admin users: ${error.message}`);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* Assign projects to a specific user
|
|
2172
|
+
* Requires admin or super_admin global role
|
|
2173
|
+
*/
|
|
2174
|
+
async assignProjectsToUser(userId, options = {}) {
|
|
2175
|
+
this._requireReady("assignProjectsToUser");
|
|
2176
|
+
if (!userId) {
|
|
2177
|
+
throw new Error("User ID is required");
|
|
2178
|
+
}
|
|
2179
|
+
const {
|
|
2180
|
+
projectIds,
|
|
2181
|
+
role = "guest"
|
|
2182
|
+
} = options;
|
|
2183
|
+
const requestBody = {
|
|
2184
|
+
userId,
|
|
2185
|
+
role
|
|
2186
|
+
};
|
|
2187
|
+
if (projectIds && Array.isArray(projectIds)) {
|
|
2188
|
+
requestBody.projectIds = projectIds;
|
|
2189
|
+
}
|
|
2190
|
+
try {
|
|
2191
|
+
const response = await this._request("/assign-projects", {
|
|
2192
|
+
method: "POST",
|
|
2193
|
+
body: JSON.stringify(requestBody),
|
|
2194
|
+
methodName: "assignProjectsToUser"
|
|
2195
|
+
});
|
|
2196
|
+
if (response.success) {
|
|
2197
|
+
return response.data;
|
|
2198
|
+
}
|
|
2199
|
+
throw new Error(response.message);
|
|
2200
|
+
} catch (error) {
|
|
2201
|
+
throw new Error(`Failed to assign projects to user: ${error.message}`);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Helper method for admin users search
|
|
2206
|
+
*/
|
|
2207
|
+
async searchAdminUsers(searchQuery, options = {}) {
|
|
2208
|
+
return await this.getAdminUsers({
|
|
2209
|
+
query: searchQuery,
|
|
2210
|
+
...options
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
/**
|
|
2214
|
+
* Helper method to get admin users by email list
|
|
2215
|
+
*/
|
|
2216
|
+
async getAdminUsersByEmails(emails, options = {}) {
|
|
2217
|
+
const emailList = Array.isArray(emails) ? emails.join(",") : emails;
|
|
2218
|
+
return await this.getAdminUsers({
|
|
2219
|
+
emails: emailList,
|
|
2220
|
+
...options
|
|
2221
|
+
});
|
|
2222
|
+
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Helper method to get admin users by ID list
|
|
2225
|
+
*/
|
|
2226
|
+
async getAdminUsersByIds(ids, options = {}) {
|
|
2227
|
+
const idList = Array.isArray(ids) ? ids.join(",") : ids;
|
|
2228
|
+
return await this.getAdminUsers({
|
|
2229
|
+
ids: idList,
|
|
2230
|
+
...options
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2233
|
+
/**
|
|
2234
|
+
* Helper method to assign specific projects to a user with a specific role
|
|
2235
|
+
*/
|
|
2236
|
+
async assignSpecificProjectsToUser(userId, projectIds, role = "guest") {
|
|
2237
|
+
if (!Array.isArray(projectIds) || projectIds.length === 0) {
|
|
2238
|
+
throw new Error("Project IDs must be a non-empty array");
|
|
2239
|
+
}
|
|
2240
|
+
return await this.assignProjectsToUser(userId, {
|
|
2241
|
+
projectIds,
|
|
2242
|
+
role
|
|
2243
|
+
});
|
|
2244
|
+
}
|
|
2245
|
+
/**
|
|
2246
|
+
* Helper method to assign all projects to a user with a specific role
|
|
2247
|
+
*/
|
|
2248
|
+
async assignAllProjectsToUser(userId, role = "guest") {
|
|
2249
|
+
return await this.assignProjectsToUser(userId, {
|
|
2250
|
+
role
|
|
2251
|
+
});
|
|
2252
|
+
}
|
|
1709
2253
|
// Cleanup
|
|
1710
2254
|
destroy() {
|
|
1711
2255
|
if (this._tokenManager) {
|