@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
|
@@ -7,7 +7,7 @@ export class CoreService extends BaseService {
|
|
|
7
7
|
super(config)
|
|
8
8
|
this._client = null
|
|
9
9
|
this._initialized = false
|
|
10
|
-
this.
|
|
10
|
+
this._apiUrl = null
|
|
11
11
|
this._tokenManager = null
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -16,15 +16,15 @@ export class CoreService extends BaseService {
|
|
|
16
16
|
const { appKey, authToken } = context || this._context
|
|
17
17
|
|
|
18
18
|
// Get base URL from environment config
|
|
19
|
-
this.
|
|
19
|
+
this._apiUrl = environment.apiUrl
|
|
20
20
|
|
|
21
|
-
if (!this.
|
|
21
|
+
if (!this._apiUrl) {
|
|
22
22
|
throw new Error('Core service base URL not configured')
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// Initialize token manager
|
|
26
26
|
this._tokenManager = getTokenManager({
|
|
27
|
-
apiUrl: this.
|
|
27
|
+
apiUrl: this._apiUrl,
|
|
28
28
|
onTokenRefresh: (tokens) => {
|
|
29
29
|
// Update context with new token
|
|
30
30
|
this.updateContext({ authToken: tokens.accessToken })
|
|
@@ -38,15 +38,14 @@ export class CoreService extends BaseService {
|
|
|
38
38
|
}
|
|
39
39
|
})
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
if (authToken) {
|
|
41
|
+
if (authToken && !this._tokenManager.hasTokens()) {
|
|
43
42
|
this._tokenManager.setTokens({ access_token: authToken })
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
// Store masked configuration info
|
|
47
46
|
this._info = {
|
|
48
47
|
config: {
|
|
49
|
-
|
|
48
|
+
apiUrl: this._apiUrl,
|
|
50
49
|
appKey: appKey ? `${appKey.substr(0, 4)}...${appKey.substr(-4)}` : null,
|
|
51
50
|
hasToken: Boolean(authToken)
|
|
52
51
|
}
|
|
@@ -66,11 +65,15 @@ export class CoreService extends BaseService {
|
|
|
66
65
|
'register',
|
|
67
66
|
'login',
|
|
68
67
|
'googleAuth',
|
|
68
|
+
'googleAuthCallback',
|
|
69
69
|
'githubAuth',
|
|
70
70
|
'requestPasswordReset',
|
|
71
71
|
'confirmPasswordReset',
|
|
72
72
|
'confirmRegistration',
|
|
73
|
-
'verifyEmail'
|
|
73
|
+
'verifyEmail',
|
|
74
|
+
'listPublicProjects',
|
|
75
|
+
'getPublicProject',
|
|
76
|
+
'getHealthStatus'
|
|
74
77
|
])
|
|
75
78
|
return !noInitMethods.has(methodName)
|
|
76
79
|
}
|
|
@@ -106,12 +109,31 @@ export class CoreService extends BaseService {
|
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
|
|
112
|
+
// Helper method to check if user is authenticated
|
|
113
|
+
isAuthenticated () {
|
|
114
|
+
if (!this._tokenManager) {
|
|
115
|
+
return false
|
|
116
|
+
}
|
|
117
|
+
return this._tokenManager.hasTokens()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Helper method to check if user has valid tokens
|
|
121
|
+
hasValidTokens () {
|
|
122
|
+
if (!this._tokenManager) {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
return this._tokenManager.hasTokens() && this._tokenManager.isAccessTokenValid()
|
|
126
|
+
}
|
|
127
|
+
|
|
109
128
|
// Helper method to make HTTP requests
|
|
110
129
|
async _request (endpoint, options = {}) {
|
|
111
|
-
const url = `${this.
|
|
130
|
+
const url = `${this._apiUrl}/core${endpoint}`
|
|
131
|
+
|
|
132
|
+
const defaultHeaders = {}
|
|
112
133
|
|
|
113
|
-
|
|
114
|
-
|
|
134
|
+
// Only set Content-Type for JSON requests, not for FormData
|
|
135
|
+
if (!(options.body instanceof FormData)) {
|
|
136
|
+
defaultHeaders['Content-Type'] = 'application/json'
|
|
115
137
|
}
|
|
116
138
|
|
|
117
139
|
// Use TokenManager for automatic token management
|
|
@@ -119,16 +141,11 @@ export class CoreService extends BaseService {
|
|
|
119
141
|
try {
|
|
120
142
|
// Ensure we have a valid token (will refresh if needed)
|
|
121
143
|
const validToken = await this._tokenManager.ensureValidToken()
|
|
122
|
-
console.log(`[CoreService] Token check for ${options.methodName}:`, {
|
|
123
|
-
hasValidToken: Boolean(validToken),
|
|
124
|
-
tokenPreview: validToken ? `${validToken.substring(0, 20)}...` : null
|
|
125
|
-
})
|
|
126
144
|
|
|
127
145
|
if (validToken) {
|
|
128
146
|
const authHeader = this._tokenManager.getAuthHeader()
|
|
129
147
|
if (authHeader) {
|
|
130
148
|
defaultHeaders.Authorization = authHeader
|
|
131
|
-
console.log(`[CoreService] Added auth header for ${options.methodName}`)
|
|
132
149
|
}
|
|
133
150
|
}
|
|
134
151
|
} catch (error) {
|
|
@@ -139,7 +156,6 @@ export class CoreService extends BaseService {
|
|
|
139
156
|
const { authToken } = this._context
|
|
140
157
|
if (authToken) {
|
|
141
158
|
defaultHeaders.Authorization = `Bearer ${authToken}`
|
|
142
|
-
console.log(`[CoreService] Using context token for ${options.methodName}`)
|
|
143
159
|
}
|
|
144
160
|
}
|
|
145
161
|
|
|
@@ -172,11 +188,15 @@ export class CoreService extends BaseService {
|
|
|
172
188
|
|
|
173
189
|
async register (userData) {
|
|
174
190
|
try {
|
|
175
|
-
|
|
191
|
+
const response = await this._request('/auth/register', {
|
|
176
192
|
method: 'POST',
|
|
177
193
|
body: JSON.stringify(userData),
|
|
178
194
|
methodName: 'register'
|
|
179
195
|
})
|
|
196
|
+
if (response.success) {
|
|
197
|
+
return response.data
|
|
198
|
+
}
|
|
199
|
+
throw new Error(response.message)
|
|
180
200
|
} catch (error) {
|
|
181
201
|
throw new Error(`Registration failed: ${error.message}`)
|
|
182
202
|
}
|
|
@@ -209,7 +229,10 @@ export class CoreService extends BaseService {
|
|
|
209
229
|
this.updateContext({ authToken: tokens.accessToken })
|
|
210
230
|
}
|
|
211
231
|
|
|
212
|
-
|
|
232
|
+
if (response.success) {
|
|
233
|
+
return response.data
|
|
234
|
+
}
|
|
235
|
+
throw new Error(response.message)
|
|
213
236
|
} catch (error) {
|
|
214
237
|
throw new Error(`Login failed: ${error.message}`)
|
|
215
238
|
}
|
|
@@ -242,11 +265,15 @@ export class CoreService extends BaseService {
|
|
|
242
265
|
|
|
243
266
|
async refreshToken (refreshToken) {
|
|
244
267
|
try {
|
|
245
|
-
|
|
268
|
+
const response = await this._request('/auth/refresh', {
|
|
246
269
|
method: 'POST',
|
|
247
270
|
body: JSON.stringify({ refreshToken }),
|
|
248
271
|
methodName: 'refreshToken'
|
|
249
272
|
})
|
|
273
|
+
if (response.success) {
|
|
274
|
+
return response.data
|
|
275
|
+
}
|
|
276
|
+
throw new Error(response.message)
|
|
250
277
|
} catch (error) {
|
|
251
278
|
throw new Error(`Token refresh failed: ${error.message}`)
|
|
252
279
|
}
|
|
@@ -279,7 +306,10 @@ export class CoreService extends BaseService {
|
|
|
279
306
|
this.updateContext({ authToken: tokens.accessToken })
|
|
280
307
|
}
|
|
281
308
|
|
|
282
|
-
|
|
309
|
+
if (response.success) {
|
|
310
|
+
return response.data
|
|
311
|
+
}
|
|
312
|
+
throw new Error(response.message)
|
|
283
313
|
} catch (error) {
|
|
284
314
|
throw new Error(`Google auth failed: ${error.message}`)
|
|
285
315
|
}
|
|
@@ -312,19 +342,62 @@ export class CoreService extends BaseService {
|
|
|
312
342
|
this.updateContext({ authToken: tokens.accessToken })
|
|
313
343
|
}
|
|
314
344
|
|
|
315
|
-
|
|
345
|
+
if (response.success) {
|
|
346
|
+
return response.data
|
|
347
|
+
}
|
|
348
|
+
throw new Error(response.message)
|
|
316
349
|
} catch (error) {
|
|
317
350
|
throw new Error(`GitHub auth failed: ${error.message}`)
|
|
318
351
|
}
|
|
319
352
|
}
|
|
320
353
|
|
|
354
|
+
async googleAuthCallback (code, redirectUri) {
|
|
355
|
+
try {
|
|
356
|
+
const response = await this._request('/auth/google/callback', {
|
|
357
|
+
method: 'POST',
|
|
358
|
+
body: JSON.stringify({ code, redirectUri }),
|
|
359
|
+
methodName: 'googleAuthCallback'
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
// Handle new response format: response.data.tokens
|
|
363
|
+
if (response.success && response.data && response.data.tokens) {
|
|
364
|
+
const { tokens } = response.data
|
|
365
|
+
const tokenData = {
|
|
366
|
+
access_token: tokens.accessToken,
|
|
367
|
+
refresh_token: tokens.refreshToken,
|
|
368
|
+
expires_in: tokens.accessTokenExp?.expiresIn,
|
|
369
|
+
token_type: 'Bearer'
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Set tokens in TokenManager
|
|
373
|
+
if (this._tokenManager) {
|
|
374
|
+
this._tokenManager.setTokens(tokenData)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Update context for backward compatibility
|
|
378
|
+
this.updateContext({ authToken: tokens.accessToken })
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (response.success) {
|
|
382
|
+
return response.data
|
|
383
|
+
}
|
|
384
|
+
throw new Error(response.message)
|
|
385
|
+
} catch (error) {
|
|
386
|
+
throw new Error(`Google auth callback failed: ${error.message}`)
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
321
390
|
async requestPasswordReset (email) {
|
|
322
391
|
try {
|
|
323
|
-
|
|
392
|
+
const response = await this._request('/auth/request-password-reset', {
|
|
324
393
|
method: 'POST',
|
|
325
394
|
body: JSON.stringify({ email }),
|
|
326
395
|
methodName: 'requestPasswordReset'
|
|
327
396
|
})
|
|
397
|
+
if (response.success) {
|
|
398
|
+
return response.data
|
|
399
|
+
}
|
|
400
|
+
throw new Error(response.message)
|
|
328
401
|
} catch (error) {
|
|
329
402
|
throw new Error(`Password reset request failed: ${error.message}`)
|
|
330
403
|
}
|
|
@@ -332,11 +405,15 @@ export class CoreService extends BaseService {
|
|
|
332
405
|
|
|
333
406
|
async confirmPasswordReset (token, password) {
|
|
334
407
|
try {
|
|
335
|
-
|
|
408
|
+
const response = await this._request('/auth/reset-password-confirm', {
|
|
336
409
|
method: 'POST',
|
|
337
410
|
body: JSON.stringify({ token, password }),
|
|
338
411
|
methodName: 'confirmPasswordReset'
|
|
339
412
|
})
|
|
413
|
+
if (response.success) {
|
|
414
|
+
return response.data
|
|
415
|
+
}
|
|
416
|
+
throw new Error(response.message)
|
|
340
417
|
} catch (error) {
|
|
341
418
|
throw new Error(`Password reset confirmation failed: ${error.message}`)
|
|
342
419
|
}
|
|
@@ -344,11 +421,15 @@ export class CoreService extends BaseService {
|
|
|
344
421
|
|
|
345
422
|
async confirmRegistration (token) {
|
|
346
423
|
try {
|
|
347
|
-
|
|
424
|
+
const response = await this._request('/auth/register-confirmation', {
|
|
348
425
|
method: 'POST',
|
|
349
426
|
body: JSON.stringify({ token }),
|
|
350
427
|
methodName: 'confirmRegistration'
|
|
351
428
|
})
|
|
429
|
+
if (response.success) {
|
|
430
|
+
return response.data
|
|
431
|
+
}
|
|
432
|
+
throw new Error(response.message)
|
|
352
433
|
} catch (error) {
|
|
353
434
|
throw new Error(`Registration confirmation failed: ${error.message}`)
|
|
354
435
|
}
|
|
@@ -357,10 +438,14 @@ export class CoreService extends BaseService {
|
|
|
357
438
|
async requestPasswordChange () {
|
|
358
439
|
this._requireReady('requestPasswordChange')
|
|
359
440
|
try {
|
|
360
|
-
|
|
441
|
+
const response = await this._request('/auth/request-password-change', {
|
|
361
442
|
method: 'POST',
|
|
362
443
|
methodName: 'requestPasswordChange'
|
|
363
444
|
})
|
|
445
|
+
if (response.success) {
|
|
446
|
+
return response.data
|
|
447
|
+
}
|
|
448
|
+
throw new Error(response.message)
|
|
364
449
|
} catch (error) {
|
|
365
450
|
throw new Error(`Password change request failed: ${error.message}`)
|
|
366
451
|
}
|
|
@@ -369,11 +454,15 @@ export class CoreService extends BaseService {
|
|
|
369
454
|
async confirmPasswordChange (currentPassword, newPassword, code) {
|
|
370
455
|
this._requireReady('confirmPasswordChange')
|
|
371
456
|
try {
|
|
372
|
-
|
|
457
|
+
const response = await this._request('/auth/confirm-password-change', {
|
|
373
458
|
method: 'POST',
|
|
374
459
|
body: JSON.stringify({ currentPassword, newPassword, code }),
|
|
375
460
|
methodName: 'confirmPasswordChange'
|
|
376
461
|
})
|
|
462
|
+
if (response.success) {
|
|
463
|
+
return response.data
|
|
464
|
+
}
|
|
465
|
+
throw new Error(response.message)
|
|
377
466
|
} catch (error) {
|
|
378
467
|
throw new Error(`Password change confirmation failed: ${error.message}`)
|
|
379
468
|
}
|
|
@@ -382,10 +471,14 @@ export class CoreService extends BaseService {
|
|
|
382
471
|
async getMe () {
|
|
383
472
|
this._requireReady('getMe')
|
|
384
473
|
try {
|
|
385
|
-
|
|
474
|
+
const response = await this._request('/auth/me', {
|
|
386
475
|
method: 'GET',
|
|
387
476
|
methodName: 'getMe'
|
|
388
477
|
})
|
|
478
|
+
if (response.success) {
|
|
479
|
+
return response.data
|
|
480
|
+
}
|
|
481
|
+
throw new Error(response.message)
|
|
389
482
|
} catch (error) {
|
|
390
483
|
throw new Error(`Failed to get user profile: ${error.message}`)
|
|
391
484
|
}
|
|
@@ -418,40 +511,70 @@ export class CoreService extends BaseService {
|
|
|
418
511
|
try {
|
|
419
512
|
await this._tokenManager.ensureValidToken()
|
|
420
513
|
} catch (error) {
|
|
421
|
-
|
|
422
|
-
|
|
514
|
+
console.warn('[CoreService] Token refresh failed:', error.message)
|
|
515
|
+
// Only clear tokens if it's definitely an auth error, not a network error
|
|
516
|
+
if (error.message.includes('401') || error.message.includes('403') ||
|
|
517
|
+
error.message.includes('invalid') || error.message.includes('expired')) {
|
|
518
|
+
this._tokenManager.clearTokens()
|
|
519
|
+
return {
|
|
520
|
+
userId: false,
|
|
521
|
+
authToken: false,
|
|
522
|
+
error: `Authentication failed: ${error.message}`
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
// For network errors, keep tokens and return what we have
|
|
423
526
|
return {
|
|
424
527
|
userId: false,
|
|
425
|
-
authToken:
|
|
426
|
-
error: `
|
|
528
|
+
authToken: this._tokenManager.getAccessToken(),
|
|
529
|
+
error: `Network error during token refresh: ${error.message}`,
|
|
530
|
+
hasTokens: true
|
|
427
531
|
}
|
|
428
532
|
}
|
|
429
533
|
}
|
|
430
534
|
|
|
535
|
+
// Check if we have a valid token now
|
|
536
|
+
const currentAccessToken = this._tokenManager.getAccessToken()
|
|
537
|
+
if (!currentAccessToken) {
|
|
538
|
+
return {
|
|
539
|
+
userId: false,
|
|
540
|
+
authToken: false
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
431
544
|
// Get current user data if we have valid tokens
|
|
545
|
+
// Be more lenient with API failures - don't immediately clear tokens
|
|
432
546
|
try {
|
|
433
547
|
const currentUser = await this.getMe()
|
|
434
|
-
const userProjects = await this.getUserProjects()
|
|
435
548
|
|
|
436
549
|
return {
|
|
437
|
-
userId: currentUser.
|
|
438
|
-
authToken:
|
|
439
|
-
|
|
440
|
-
...currentUser.data,
|
|
441
|
-
projects: userProjects?.data || []
|
|
442
|
-
},
|
|
550
|
+
userId: currentUser.user.id,
|
|
551
|
+
authToken: currentAccessToken,
|
|
552
|
+
...currentUser,
|
|
443
553
|
error: null
|
|
444
554
|
}
|
|
445
555
|
} catch (error) {
|
|
446
|
-
|
|
447
|
-
|
|
556
|
+
console.warn('[CoreService] Failed to get user data:', error.message)
|
|
557
|
+
|
|
558
|
+
// Only clear tokens if it's an auth error (401, 403), not network errors
|
|
559
|
+
if (error.message.includes('401') || error.message.includes('403')) {
|
|
560
|
+
this._tokenManager.clearTokens()
|
|
561
|
+
return {
|
|
562
|
+
userId: false,
|
|
563
|
+
authToken: false,
|
|
564
|
+
error: `Authentication failed: ${error.message}`
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// For other errors (network, 500, etc.), keep tokens but return minimal state
|
|
448
569
|
return {
|
|
449
570
|
userId: false,
|
|
450
|
-
authToken:
|
|
451
|
-
error: `Failed to get user data: ${error.message}
|
|
571
|
+
authToken: currentAccessToken,
|
|
572
|
+
error: `Failed to get user data: ${error.message}`,
|
|
573
|
+
hasTokens: true
|
|
452
574
|
}
|
|
453
575
|
}
|
|
454
576
|
} catch (error) {
|
|
577
|
+
console.error('[CoreService] Unexpected error in getStoredAuthState:', error)
|
|
455
578
|
return {
|
|
456
579
|
userId: false,
|
|
457
580
|
authToken: false,
|
|
@@ -465,10 +588,14 @@ export class CoreService extends BaseService {
|
|
|
465
588
|
async getUserProfile () {
|
|
466
589
|
this._requireReady('getUserProfile')
|
|
467
590
|
try {
|
|
468
|
-
|
|
591
|
+
const response = await this._request('/users/profile', {
|
|
469
592
|
method: 'GET',
|
|
470
593
|
methodName: 'getUserProfile'
|
|
471
594
|
})
|
|
595
|
+
if (response.success) {
|
|
596
|
+
return response.data
|
|
597
|
+
}
|
|
598
|
+
throw new Error(response.message)
|
|
472
599
|
} catch (error) {
|
|
473
600
|
throw new Error(`Failed to get user profile: ${error.message}`)
|
|
474
601
|
}
|
|
@@ -477,11 +604,15 @@ export class CoreService extends BaseService {
|
|
|
477
604
|
async updateUserProfile (profileData) {
|
|
478
605
|
this._requireReady('updateUserProfile')
|
|
479
606
|
try {
|
|
480
|
-
|
|
607
|
+
const response = await this._request('/users/profile', {
|
|
481
608
|
method: 'PATCH',
|
|
482
609
|
body: JSON.stringify(profileData),
|
|
483
610
|
methodName: 'updateUserProfile'
|
|
484
611
|
})
|
|
612
|
+
if (response.success) {
|
|
613
|
+
return response.data
|
|
614
|
+
}
|
|
615
|
+
throw new Error(response.message)
|
|
485
616
|
} catch (error) {
|
|
486
617
|
throw new Error(`Failed to update user profile: ${error.message}`)
|
|
487
618
|
}
|
|
@@ -490,10 +621,17 @@ export class CoreService extends BaseService {
|
|
|
490
621
|
async getUserProjects () {
|
|
491
622
|
this._requireReady('getUserProjects')
|
|
492
623
|
try {
|
|
493
|
-
|
|
624
|
+
const response = await this._request('/users/projects', {
|
|
494
625
|
method: 'GET',
|
|
495
626
|
methodName: 'getUserProjects'
|
|
496
627
|
})
|
|
628
|
+
if (response.success) {
|
|
629
|
+
return response.data.map(project => ({
|
|
630
|
+
...project,
|
|
631
|
+
...(project.icon && { icon: { src: `${this._apiUrl}/core/files/public/${project.icon.id}/download`, ...project.icon } })
|
|
632
|
+
}))
|
|
633
|
+
}
|
|
634
|
+
throw new Error(response.message)
|
|
497
635
|
} catch (error) {
|
|
498
636
|
throw new Error(`Failed to get user projects: ${error.message}`)
|
|
499
637
|
}
|
|
@@ -505,10 +643,14 @@ export class CoreService extends BaseService {
|
|
|
505
643
|
throw new Error('User ID is required')
|
|
506
644
|
}
|
|
507
645
|
try {
|
|
508
|
-
|
|
646
|
+
const response = await this._request(`/users/${userId}`, {
|
|
509
647
|
method: 'GET',
|
|
510
648
|
methodName: 'getUser'
|
|
511
649
|
})
|
|
650
|
+
if (response.success) {
|
|
651
|
+
return response.data
|
|
652
|
+
}
|
|
653
|
+
throw new Error(response.message)
|
|
512
654
|
} catch (error) {
|
|
513
655
|
throw new Error(`Failed to get user: ${error.message}`)
|
|
514
656
|
}
|
|
@@ -520,13 +662,17 @@ export class CoreService extends BaseService {
|
|
|
520
662
|
throw new Error('Email is required')
|
|
521
663
|
}
|
|
522
664
|
try {
|
|
523
|
-
|
|
665
|
+
const response = await this._request('/auth/user', {
|
|
524
666
|
method: 'GET',
|
|
525
667
|
headers: {
|
|
526
668
|
'X-User-Email': email
|
|
527
669
|
},
|
|
528
670
|
methodName: 'getUserByEmail'
|
|
529
671
|
})
|
|
672
|
+
if (response.success) {
|
|
673
|
+
return response.data
|
|
674
|
+
}
|
|
675
|
+
throw new Error(response.message)
|
|
530
676
|
} catch (error) {
|
|
531
677
|
throw new Error(`Failed to get user by email: ${error.message}`)
|
|
532
678
|
}
|
|
@@ -537,53 +683,148 @@ export class CoreService extends BaseService {
|
|
|
537
683
|
async createProject (projectData) {
|
|
538
684
|
this._requireReady('createProject')
|
|
539
685
|
try {
|
|
540
|
-
|
|
686
|
+
const response = await this._request('/projects', {
|
|
541
687
|
method: 'POST',
|
|
542
688
|
body: JSON.stringify(projectData),
|
|
543
689
|
methodName: 'createProject'
|
|
544
690
|
})
|
|
691
|
+
if (response.success) {
|
|
692
|
+
return response.data
|
|
693
|
+
}
|
|
694
|
+
throw new Error(response.message)
|
|
545
695
|
} catch (error) {
|
|
546
696
|
throw new Error(`Failed to create project: ${error.message}`)
|
|
547
697
|
}
|
|
548
698
|
}
|
|
549
699
|
|
|
550
|
-
async getProjects () {
|
|
700
|
+
async getProjects (params = {}) {
|
|
551
701
|
this._requireReady('getProjects')
|
|
552
702
|
try {
|
|
553
|
-
|
|
703
|
+
const queryParams = new URLSearchParams()
|
|
704
|
+
|
|
705
|
+
// Add query parameters
|
|
706
|
+
Object.keys(params).forEach(key => {
|
|
707
|
+
if (params[key] != null) {
|
|
708
|
+
queryParams.append(key, params[key])
|
|
709
|
+
}
|
|
710
|
+
})
|
|
711
|
+
|
|
712
|
+
const queryString = queryParams.toString()
|
|
713
|
+
const url = `/projects${queryString ? `?${queryString}` : ''}`
|
|
714
|
+
|
|
715
|
+
const response = await this._request(url, {
|
|
554
716
|
method: 'GET',
|
|
555
717
|
methodName: 'getProjects'
|
|
556
718
|
})
|
|
719
|
+
if (response.success) {
|
|
720
|
+
return response
|
|
721
|
+
}
|
|
722
|
+
throw new Error(response.message)
|
|
557
723
|
} catch (error) {
|
|
558
724
|
throw new Error(`Failed to get projects: ${error.message}`)
|
|
559
725
|
}
|
|
560
726
|
}
|
|
561
727
|
|
|
728
|
+
/**
|
|
729
|
+
* Alias for getProjects for consistency with API naming
|
|
730
|
+
*/
|
|
731
|
+
async listProjects (params = {}) {
|
|
732
|
+
return await this.getProjects(params)
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* List only public projects (no authentication required)
|
|
737
|
+
*/
|
|
738
|
+
async listPublicProjects (params = {}) {
|
|
739
|
+
try {
|
|
740
|
+
const queryParams = new URLSearchParams()
|
|
741
|
+
|
|
742
|
+
// Add query parameters
|
|
743
|
+
Object.keys(params).forEach(key => {
|
|
744
|
+
if (params[key] != null) {
|
|
745
|
+
queryParams.append(key, params[key])
|
|
746
|
+
}
|
|
747
|
+
})
|
|
748
|
+
|
|
749
|
+
const queryString = queryParams.toString()
|
|
750
|
+
const url = `/projects/public${queryString ? `?${queryString}` : ''}`
|
|
751
|
+
|
|
752
|
+
const response = await this._request(url, {
|
|
753
|
+
method: 'GET',
|
|
754
|
+
methodName: 'listPublicProjects'
|
|
755
|
+
})
|
|
756
|
+
if (response.success) {
|
|
757
|
+
return response.data
|
|
758
|
+
}
|
|
759
|
+
throw new Error(response.message)
|
|
760
|
+
} catch (error) {
|
|
761
|
+
throw new Error(`Failed to list public projects: ${error.message}`)
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
562
765
|
async getProject (projectId) {
|
|
563
766
|
this._requireReady('getProject')
|
|
564
767
|
if (!projectId) {
|
|
565
768
|
throw new Error('Project ID is required')
|
|
566
769
|
}
|
|
567
770
|
try {
|
|
568
|
-
|
|
771
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
569
772
|
method: 'GET',
|
|
570
773
|
methodName: 'getProject'
|
|
571
774
|
})
|
|
775
|
+
if (response.success) {
|
|
776
|
+
const iconSrc = response.data.icon ? `${this._apiUrl}/core/files/public/${response.data.icon.id}/download` : null
|
|
777
|
+
return {
|
|
778
|
+
...response.data,
|
|
779
|
+
icon: { src: iconSrc, ...response.data.icon }
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
throw new Error(response.message)
|
|
572
783
|
} catch (error) {
|
|
573
784
|
throw new Error(`Failed to get project: ${error.message}`)
|
|
574
785
|
}
|
|
575
786
|
}
|
|
576
787
|
|
|
788
|
+
/**
|
|
789
|
+
* Get a public project by ID (no authentication required)
|
|
790
|
+
* Corresponds to router.get('/public/:projectId', ProjectController.getPublicProject)
|
|
791
|
+
*/
|
|
792
|
+
async getPublicProject (projectId) {
|
|
793
|
+
if (!projectId) {
|
|
794
|
+
throw new Error('Project ID is required')
|
|
795
|
+
}
|
|
796
|
+
try {
|
|
797
|
+
const response = await this._request(`/projects/public/${projectId}`, {
|
|
798
|
+
method: 'GET',
|
|
799
|
+
methodName: 'getPublicProject'
|
|
800
|
+
})
|
|
801
|
+
if (response.success) {
|
|
802
|
+
const iconSrc = response.data.icon ? `${this._apiUrl}/core/files/public/${response.data.icon.id}/download` : null
|
|
803
|
+
return {
|
|
804
|
+
...response.data,
|
|
805
|
+
icon: { src: iconSrc, ...response.data.icon }
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
throw new Error(response.message)
|
|
809
|
+
} catch (error) {
|
|
810
|
+
throw new Error(`Failed to get public project: ${error.message}`)
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
577
814
|
async getProjectByKey (key) {
|
|
578
815
|
this._requireReady('getProjectByKey')
|
|
579
816
|
if (!key) {
|
|
580
817
|
throw new Error('Project key is required')
|
|
581
818
|
}
|
|
582
819
|
try {
|
|
583
|
-
|
|
820
|
+
const response = await this._request(`/projects/check-key/${key}`, {
|
|
584
821
|
method: 'GET',
|
|
585
822
|
methodName: 'getProjectByKey'
|
|
586
823
|
})
|
|
824
|
+
if (response.success) {
|
|
825
|
+
return response.data
|
|
826
|
+
}
|
|
827
|
+
throw new Error(response.message)
|
|
587
828
|
} catch (error) {
|
|
588
829
|
throw new Error(`Failed to get project by key: ${error.message}`)
|
|
589
830
|
}
|
|
@@ -595,11 +836,15 @@ export class CoreService extends BaseService {
|
|
|
595
836
|
throw new Error('Project ID is required')
|
|
596
837
|
}
|
|
597
838
|
try {
|
|
598
|
-
|
|
839
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
599
840
|
method: 'PATCH',
|
|
600
841
|
body: JSON.stringify(data),
|
|
601
842
|
methodName: 'updateProject'
|
|
602
843
|
})
|
|
844
|
+
if (response.success) {
|
|
845
|
+
return response.data
|
|
846
|
+
}
|
|
847
|
+
throw new Error(response.message)
|
|
603
848
|
} catch (error) {
|
|
604
849
|
throw new Error(`Failed to update project: ${error.message}`)
|
|
605
850
|
}
|
|
@@ -611,11 +856,15 @@ export class CoreService extends BaseService {
|
|
|
611
856
|
throw new Error('Project ID is required')
|
|
612
857
|
}
|
|
613
858
|
try {
|
|
614
|
-
|
|
859
|
+
const response = await this._request(`/projects/${projectId}/components`, {
|
|
615
860
|
method: 'PATCH',
|
|
616
861
|
body: JSON.stringify({ components }),
|
|
617
862
|
methodName: 'updateProjectComponents'
|
|
618
863
|
})
|
|
864
|
+
if (response.success) {
|
|
865
|
+
return response.data
|
|
866
|
+
}
|
|
867
|
+
throw new Error(response.message)
|
|
619
868
|
} catch (error) {
|
|
620
869
|
throw new Error(`Failed to update project components: ${error.message}`)
|
|
621
870
|
}
|
|
@@ -627,11 +876,15 @@ export class CoreService extends BaseService {
|
|
|
627
876
|
throw new Error('Project ID is required')
|
|
628
877
|
}
|
|
629
878
|
try {
|
|
630
|
-
|
|
879
|
+
const response = await this._request(`/projects/${projectId}/settings`, {
|
|
631
880
|
method: 'PATCH',
|
|
632
881
|
body: JSON.stringify({ settings }),
|
|
633
882
|
methodName: 'updateProjectSettings'
|
|
634
883
|
})
|
|
884
|
+
if (response.success) {
|
|
885
|
+
return response.data
|
|
886
|
+
}
|
|
887
|
+
throw new Error(response.message)
|
|
635
888
|
} catch (error) {
|
|
636
889
|
throw new Error(`Failed to update project settings: ${error.message}`)
|
|
637
890
|
}
|
|
@@ -643,11 +896,15 @@ export class CoreService extends BaseService {
|
|
|
643
896
|
throw new Error('Project ID is required')
|
|
644
897
|
}
|
|
645
898
|
try {
|
|
646
|
-
|
|
899
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
647
900
|
method: 'PATCH',
|
|
648
901
|
body: JSON.stringify({ name }),
|
|
649
902
|
methodName: 'updateProjectName'
|
|
650
903
|
})
|
|
904
|
+
if (response.success) {
|
|
905
|
+
return response.data
|
|
906
|
+
}
|
|
907
|
+
throw new Error(response.message)
|
|
651
908
|
} catch (error) {
|
|
652
909
|
throw new Error(`Failed to update project name: ${error.message}`)
|
|
653
910
|
}
|
|
@@ -659,27 +916,35 @@ export class CoreService extends BaseService {
|
|
|
659
916
|
throw new Error('Project ID is required')
|
|
660
917
|
}
|
|
661
918
|
try {
|
|
662
|
-
|
|
919
|
+
const response = await this._request(`/projects/${projectId}/tier`, {
|
|
663
920
|
method: 'PATCH',
|
|
664
921
|
body: JSON.stringify({ tier: pkg }),
|
|
665
922
|
methodName: 'updateProjectPackage'
|
|
666
923
|
})
|
|
924
|
+
if (response.success) {
|
|
925
|
+
return response.data
|
|
926
|
+
}
|
|
927
|
+
throw new Error(response.message)
|
|
667
928
|
} catch (error) {
|
|
668
929
|
throw new Error(`Failed to update project package: ${error.message}`)
|
|
669
930
|
}
|
|
670
931
|
}
|
|
671
932
|
|
|
672
|
-
async duplicateProject (projectId, newName, newKey) {
|
|
933
|
+
async duplicateProject (projectId, newName, newKey, targetUserId) {
|
|
673
934
|
this._requireReady('duplicateProject')
|
|
674
935
|
if (!projectId) {
|
|
675
936
|
throw new Error('Project ID is required')
|
|
676
937
|
}
|
|
677
938
|
try {
|
|
678
|
-
|
|
939
|
+
const response = await this._request(`/projects/${projectId}/duplicate`, {
|
|
679
940
|
method: 'POST',
|
|
680
|
-
body: JSON.stringify({ name: newName, key: newKey }),
|
|
941
|
+
body: JSON.stringify({ name: newName, key: newKey, targetUserId }),
|
|
681
942
|
methodName: 'duplicateProject'
|
|
682
943
|
})
|
|
944
|
+
if (response.success) {
|
|
945
|
+
return response.data
|
|
946
|
+
}
|
|
947
|
+
throw new Error(response.message)
|
|
683
948
|
} catch (error) {
|
|
684
949
|
throw new Error(`Failed to duplicate project: ${error.message}`)
|
|
685
950
|
}
|
|
@@ -691,10 +956,14 @@ export class CoreService extends BaseService {
|
|
|
691
956
|
throw new Error('Project ID is required')
|
|
692
957
|
}
|
|
693
958
|
try {
|
|
694
|
-
|
|
959
|
+
const response = await this._request(`/projects/${projectId}`, {
|
|
695
960
|
method: 'DELETE',
|
|
696
961
|
methodName: 'removeProject'
|
|
697
962
|
})
|
|
963
|
+
if (response.success) {
|
|
964
|
+
return response.data
|
|
965
|
+
}
|
|
966
|
+
throw new Error(response.message)
|
|
698
967
|
} catch (error) {
|
|
699
968
|
throw new Error(`Failed to remove project: ${error.message}`)
|
|
700
969
|
}
|
|
@@ -706,10 +975,14 @@ export class CoreService extends BaseService {
|
|
|
706
975
|
throw new Error('Project key is required')
|
|
707
976
|
}
|
|
708
977
|
try {
|
|
709
|
-
|
|
978
|
+
const response = await this._request(`/projects/check-key/${key}`, {
|
|
710
979
|
method: 'GET',
|
|
711
980
|
methodName: 'checkProjectKeyAvailability'
|
|
712
981
|
})
|
|
982
|
+
if (response.success) {
|
|
983
|
+
return response.data
|
|
984
|
+
}
|
|
985
|
+
throw new Error(response.message)
|
|
713
986
|
} catch (error) {
|
|
714
987
|
throw new Error(`Failed to check project key availability: ${error.message}`)
|
|
715
988
|
}
|
|
@@ -723,42 +996,73 @@ export class CoreService extends BaseService {
|
|
|
723
996
|
throw new Error('Project ID is required')
|
|
724
997
|
}
|
|
725
998
|
try {
|
|
726
|
-
|
|
999
|
+
const response = await this._request(`/projects/${projectId}/members`, {
|
|
727
1000
|
method: 'GET',
|
|
728
1001
|
methodName: 'getProjectMembers'
|
|
729
1002
|
})
|
|
1003
|
+
if (response.success) {
|
|
1004
|
+
return response.data
|
|
1005
|
+
}
|
|
1006
|
+
throw new Error(response.message)
|
|
730
1007
|
} catch (error) {
|
|
731
1008
|
throw new Error(`Failed to get project members: ${error.message}`)
|
|
732
1009
|
}
|
|
733
1010
|
}
|
|
734
1011
|
|
|
735
|
-
async inviteMember (projectId, email,
|
|
1012
|
+
async inviteMember (projectId, email, role = 'guest', options = {}) {
|
|
736
1013
|
this._requireReady('inviteMember')
|
|
737
|
-
if (!projectId || !email) {
|
|
738
|
-
throw new Error('Project ID and
|
|
1014
|
+
if (!projectId || !email || !role) {
|
|
1015
|
+
throw new Error('Project ID, email, and role are required')
|
|
739
1016
|
}
|
|
1017
|
+
|
|
1018
|
+
const { name, callbackUrl } = options
|
|
1019
|
+
|
|
1020
|
+
// Default callbackUrl if not provided
|
|
1021
|
+
const defaultCallbackUrl = typeof window === 'undefined'
|
|
1022
|
+
? 'https://app.symbols.com/accept-invite'
|
|
1023
|
+
: `${window.location.origin}/accept-invite`
|
|
1024
|
+
|
|
740
1025
|
try {
|
|
741
|
-
|
|
1026
|
+
const requestBody = {
|
|
1027
|
+
email,
|
|
1028
|
+
role,
|
|
1029
|
+
callbackUrl: callbackUrl || defaultCallbackUrl
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
// Add optional name if provided
|
|
1033
|
+
if (name) {
|
|
1034
|
+
requestBody.name = name
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
const response = await this._request(`/projects/${projectId}/invite`, {
|
|
742
1038
|
method: 'POST',
|
|
743
|
-
body: JSON.stringify(
|
|
1039
|
+
body: JSON.stringify(requestBody),
|
|
744
1040
|
methodName: 'inviteMember'
|
|
745
1041
|
})
|
|
1042
|
+
if (response.success) {
|
|
1043
|
+
return response.data
|
|
1044
|
+
}
|
|
1045
|
+
throw new Error(response.message)
|
|
746
1046
|
} catch (error) {
|
|
747
1047
|
throw new Error(`Failed to invite member: ${error.message}`)
|
|
748
1048
|
}
|
|
749
1049
|
}
|
|
750
1050
|
|
|
751
|
-
async acceptInvite (
|
|
1051
|
+
async acceptInvite (token) {
|
|
752
1052
|
this._requireReady('acceptInvite')
|
|
753
|
-
if (!
|
|
754
|
-
throw new Error('
|
|
1053
|
+
if (!token) {
|
|
1054
|
+
throw new Error('Invitation token is required')
|
|
755
1055
|
}
|
|
756
1056
|
try {
|
|
757
|
-
|
|
1057
|
+
const response = await this._request('/projects/accept-invite', {
|
|
758
1058
|
method: 'POST',
|
|
759
1059
|
body: JSON.stringify({ token }),
|
|
760
1060
|
methodName: 'acceptInvite'
|
|
761
1061
|
})
|
|
1062
|
+
if (response.success) {
|
|
1063
|
+
return response.data
|
|
1064
|
+
}
|
|
1065
|
+
throw new Error(response.message)
|
|
762
1066
|
} catch (error) {
|
|
763
1067
|
throw new Error(`Failed to accept invite: ${error.message}`)
|
|
764
1068
|
}
|
|
@@ -770,11 +1074,15 @@ export class CoreService extends BaseService {
|
|
|
770
1074
|
throw new Error('Project ID, member ID, and role are required')
|
|
771
1075
|
}
|
|
772
1076
|
try {
|
|
773
|
-
|
|
1077
|
+
const response = await this._request(`/projects/${projectId}/members/${memberId}`, {
|
|
774
1078
|
method: 'PATCH',
|
|
775
1079
|
body: JSON.stringify({ role }),
|
|
776
1080
|
methodName: 'updateMemberRole'
|
|
777
1081
|
})
|
|
1082
|
+
if (response.success) {
|
|
1083
|
+
return response.data
|
|
1084
|
+
}
|
|
1085
|
+
throw new Error(response.message)
|
|
778
1086
|
} catch (error) {
|
|
779
1087
|
throw new Error(`Failed to update member role: ${error.message}`)
|
|
780
1088
|
}
|
|
@@ -786,10 +1094,14 @@ export class CoreService extends BaseService {
|
|
|
786
1094
|
throw new Error('Project ID and member ID are required')
|
|
787
1095
|
}
|
|
788
1096
|
try {
|
|
789
|
-
|
|
1097
|
+
const response = await this._request(`/projects/${projectId}/members/${memberId}`, {
|
|
790
1098
|
method: 'DELETE',
|
|
791
1099
|
methodName: 'removeMember'
|
|
792
1100
|
})
|
|
1101
|
+
if (response.success) {
|
|
1102
|
+
return response.data
|
|
1103
|
+
}
|
|
1104
|
+
throw new Error(response.message)
|
|
793
1105
|
} catch (error) {
|
|
794
1106
|
throw new Error(`Failed to remove member: ${error.message}`)
|
|
795
1107
|
}
|
|
@@ -801,10 +1113,14 @@ export class CoreService extends BaseService {
|
|
|
801
1113
|
this._requireReady('getAvailableLibraries')
|
|
802
1114
|
const queryParams = new URLSearchParams(params).toString()
|
|
803
1115
|
try {
|
|
804
|
-
|
|
1116
|
+
const response = await this._request(`/projects/libraries/available?${queryParams}`, {
|
|
805
1117
|
method: 'GET',
|
|
806
1118
|
methodName: 'getAvailableLibraries'
|
|
807
1119
|
})
|
|
1120
|
+
if (response.success) {
|
|
1121
|
+
return response.data
|
|
1122
|
+
}
|
|
1123
|
+
throw new Error(response.message)
|
|
808
1124
|
} catch (error) {
|
|
809
1125
|
throw new Error(`Failed to get available libraries: ${error.message}`)
|
|
810
1126
|
}
|
|
@@ -816,10 +1132,14 @@ export class CoreService extends BaseService {
|
|
|
816
1132
|
throw new Error('Project ID is required')
|
|
817
1133
|
}
|
|
818
1134
|
try {
|
|
819
|
-
|
|
1135
|
+
const response = await this._request(`/projects/${projectId}/libraries`, {
|
|
820
1136
|
method: 'GET',
|
|
821
1137
|
methodName: 'getProjectLibraries'
|
|
822
1138
|
})
|
|
1139
|
+
if (response.success) {
|
|
1140
|
+
return response.data
|
|
1141
|
+
}
|
|
1142
|
+
throw new Error(response.message)
|
|
823
1143
|
} catch (error) {
|
|
824
1144
|
throw new Error(`Failed to get project libraries: ${error.message}`)
|
|
825
1145
|
}
|
|
@@ -831,11 +1151,15 @@ export class CoreService extends BaseService {
|
|
|
831
1151
|
throw new Error('Project ID and library IDs are required')
|
|
832
1152
|
}
|
|
833
1153
|
try {
|
|
834
|
-
|
|
1154
|
+
const response = await this._request(`/projects/${projectId}/libraries`, {
|
|
835
1155
|
method: 'POST',
|
|
836
1156
|
body: JSON.stringify({ libraryIds }),
|
|
837
1157
|
methodName: 'addProjectLibraries'
|
|
838
1158
|
})
|
|
1159
|
+
if (response.success) {
|
|
1160
|
+
return response.data
|
|
1161
|
+
}
|
|
1162
|
+
throw new Error(response.message)
|
|
839
1163
|
} catch (error) {
|
|
840
1164
|
throw new Error(`Failed to add project libraries: ${error.message}`)
|
|
841
1165
|
}
|
|
@@ -847,11 +1171,15 @@ export class CoreService extends BaseService {
|
|
|
847
1171
|
throw new Error('Project ID and library IDs are required')
|
|
848
1172
|
}
|
|
849
1173
|
try {
|
|
850
|
-
|
|
1174
|
+
const response = await this._request(`/projects/${projectId}/libraries`, {
|
|
851
1175
|
method: 'DELETE',
|
|
852
1176
|
body: JSON.stringify({ libraryIds }),
|
|
853
1177
|
methodName: 'removeProjectLibraries'
|
|
854
1178
|
})
|
|
1179
|
+
if (response.success) {
|
|
1180
|
+
return response.data
|
|
1181
|
+
}
|
|
1182
|
+
throw new Error(response.message)
|
|
855
1183
|
} catch (error) {
|
|
856
1184
|
throw new Error(`Failed to remove project libraries: ${error.message}`)
|
|
857
1185
|
}
|
|
@@ -868,19 +1196,30 @@ export class CoreService extends BaseService {
|
|
|
868
1196
|
const formData = new FormData()
|
|
869
1197
|
formData.append('file', file)
|
|
870
1198
|
|
|
871
|
-
// Add optional parameters
|
|
1199
|
+
// Add optional parameters only if they exist
|
|
872
1200
|
if (options.projectId) {formData.append('projectId', options.projectId)}
|
|
873
1201
|
if (options.tags) {formData.append('tags', JSON.stringify(options.tags))}
|
|
874
|
-
if (options.visibility) {formData.append('visibility', options.visibility)}
|
|
1202
|
+
if (options.visibility) {formData.append('visibility', options.visibility || 'public')}
|
|
875
1203
|
if (options.metadata) {formData.append('metadata', JSON.stringify(options.metadata))}
|
|
876
1204
|
|
|
877
1205
|
try {
|
|
878
|
-
|
|
1206
|
+
const response = await this._request('/files/upload', {
|
|
879
1207
|
method: 'POST',
|
|
880
1208
|
body: formData,
|
|
881
1209
|
headers: {}, // Let browser set Content-Type for FormData
|
|
882
1210
|
methodName: 'uploadFile'
|
|
883
1211
|
})
|
|
1212
|
+
|
|
1213
|
+
if (!response.success) {
|
|
1214
|
+
throw new Error(response.message)
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
return {
|
|
1218
|
+
id: response.data.id,
|
|
1219
|
+
src: `${this._apiUrl}/core/files/public/${response.data.id}/download`,
|
|
1220
|
+
success: true,
|
|
1221
|
+
message: response.message
|
|
1222
|
+
}
|
|
884
1223
|
} catch (error) {
|
|
885
1224
|
throw new Error(`File upload failed: ${error.message}`)
|
|
886
1225
|
}
|
|
@@ -897,12 +1236,16 @@ export class CoreService extends BaseService {
|
|
|
897
1236
|
formData.append('projectId', projectId)
|
|
898
1237
|
|
|
899
1238
|
try {
|
|
900
|
-
|
|
1239
|
+
const response = await this._request('/files/upload-project-icon', {
|
|
901
1240
|
method: 'POST',
|
|
902
1241
|
body: formData,
|
|
903
1242
|
headers: {}, // Let browser set Content-Type for FormData
|
|
904
1243
|
methodName: 'updateProjectIcon'
|
|
905
1244
|
})
|
|
1245
|
+
if (response.success) {
|
|
1246
|
+
return response.data
|
|
1247
|
+
}
|
|
1248
|
+
throw new Error(response.message)
|
|
906
1249
|
} catch (error) {
|
|
907
1250
|
throw new Error(`Failed to update project icon: ${error.message}`)
|
|
908
1251
|
}
|
|
@@ -925,7 +1268,7 @@ export class CoreService extends BaseService {
|
|
|
925
1268
|
}
|
|
926
1269
|
|
|
927
1270
|
try {
|
|
928
|
-
|
|
1271
|
+
const response = await this._request('/payments/checkout', {
|
|
929
1272
|
method: 'POST',
|
|
930
1273
|
body: JSON.stringify({
|
|
931
1274
|
projectId,
|
|
@@ -936,6 +1279,10 @@ export class CoreService extends BaseService {
|
|
|
936
1279
|
}),
|
|
937
1280
|
methodName: 'checkout'
|
|
938
1281
|
})
|
|
1282
|
+
if (response.success) {
|
|
1283
|
+
return response.data
|
|
1284
|
+
}
|
|
1285
|
+
throw new Error(response.message)
|
|
939
1286
|
} catch (error) {
|
|
940
1287
|
throw new Error(`Failed to checkout: ${error.message}`)
|
|
941
1288
|
}
|
|
@@ -947,10 +1294,14 @@ export class CoreService extends BaseService {
|
|
|
947
1294
|
throw new Error('Project ID is required')
|
|
948
1295
|
}
|
|
949
1296
|
try {
|
|
950
|
-
|
|
1297
|
+
const response = await this._request(`/payments/subscription/${projectId}`, {
|
|
951
1298
|
method: 'GET',
|
|
952
1299
|
methodName: 'getSubscriptionStatus'
|
|
953
1300
|
})
|
|
1301
|
+
if (response.success) {
|
|
1302
|
+
return response.data
|
|
1303
|
+
}
|
|
1304
|
+
throw new Error(response.message)
|
|
954
1305
|
} catch (error) {
|
|
955
1306
|
throw new Error(`Failed to get subscription status: ${error.message}`)
|
|
956
1307
|
}
|
|
@@ -964,11 +1315,15 @@ export class CoreService extends BaseService {
|
|
|
964
1315
|
throw new Error('Domain is required')
|
|
965
1316
|
}
|
|
966
1317
|
try {
|
|
967
|
-
|
|
1318
|
+
const response = await this._request('/dns/records', {
|
|
968
1319
|
method: 'POST',
|
|
969
1320
|
body: JSON.stringify({ domain, ...options }),
|
|
970
1321
|
methodName: 'createDnsRecord'
|
|
971
1322
|
})
|
|
1323
|
+
if (response.success) {
|
|
1324
|
+
return response.data
|
|
1325
|
+
}
|
|
1326
|
+
throw new Error(response.message)
|
|
972
1327
|
} catch (error) {
|
|
973
1328
|
throw new Error(`Failed to create DNS record: ${error.message}`)
|
|
974
1329
|
}
|
|
@@ -980,10 +1335,14 @@ export class CoreService extends BaseService {
|
|
|
980
1335
|
throw new Error('Domain is required')
|
|
981
1336
|
}
|
|
982
1337
|
try {
|
|
983
|
-
|
|
1338
|
+
const response = await this._request(`/dns/records/${domain}`, {
|
|
984
1339
|
method: 'GET',
|
|
985
1340
|
methodName: 'getDnsRecord'
|
|
986
1341
|
})
|
|
1342
|
+
if (response.success) {
|
|
1343
|
+
return response.data
|
|
1344
|
+
}
|
|
1345
|
+
throw new Error(response.message)
|
|
987
1346
|
} catch (error) {
|
|
988
1347
|
throw new Error(`Failed to get DNS record: ${error.message}`)
|
|
989
1348
|
}
|
|
@@ -995,10 +1354,14 @@ export class CoreService extends BaseService {
|
|
|
995
1354
|
throw new Error('Domain is required')
|
|
996
1355
|
}
|
|
997
1356
|
try {
|
|
998
|
-
|
|
1357
|
+
const response = await this._request(`/dns/records/${domain}`, {
|
|
999
1358
|
method: 'DELETE',
|
|
1000
1359
|
methodName: 'removeDnsRecord'
|
|
1001
1360
|
})
|
|
1361
|
+
if (response.success) {
|
|
1362
|
+
return response.data
|
|
1363
|
+
}
|
|
1364
|
+
throw new Error(response.message)
|
|
1002
1365
|
} catch (error) {
|
|
1003
1366
|
throw new Error(`Failed to remove DNS record: ${error.message}`)
|
|
1004
1367
|
}
|
|
@@ -1010,7 +1373,7 @@ export class CoreService extends BaseService {
|
|
|
1010
1373
|
throw new Error('Project key is required')
|
|
1011
1374
|
}
|
|
1012
1375
|
try {
|
|
1013
|
-
|
|
1376
|
+
const response = await this._request('/dns/project-domains', {
|
|
1014
1377
|
method: 'POST',
|
|
1015
1378
|
body: JSON.stringify({
|
|
1016
1379
|
projectKey,
|
|
@@ -1019,6 +1382,10 @@ export class CoreService extends BaseService {
|
|
|
1019
1382
|
}),
|
|
1020
1383
|
methodName: 'setProjectDomains'
|
|
1021
1384
|
})
|
|
1385
|
+
if (response.success) {
|
|
1386
|
+
return response.data
|
|
1387
|
+
}
|
|
1388
|
+
throw new Error(response.message)
|
|
1022
1389
|
} catch (error) {
|
|
1023
1390
|
throw new Error(`Failed to set project domains: ${error.message}`)
|
|
1024
1391
|
}
|
|
@@ -1028,10 +1395,14 @@ export class CoreService extends BaseService {
|
|
|
1028
1395
|
|
|
1029
1396
|
async getHealthStatus () {
|
|
1030
1397
|
try {
|
|
1031
|
-
|
|
1398
|
+
const response = await this._request('/health', {
|
|
1032
1399
|
method: 'GET',
|
|
1033
1400
|
methodName: 'getHealthStatus'
|
|
1034
1401
|
})
|
|
1402
|
+
if (response.success) {
|
|
1403
|
+
return response.data
|
|
1404
|
+
}
|
|
1405
|
+
throw new Error(response.message)
|
|
1035
1406
|
} catch (error) {
|
|
1036
1407
|
throw new Error(`Failed to get health status: ${error.message}`)
|
|
1037
1408
|
}
|
|
@@ -1070,7 +1441,10 @@ export class CoreService extends BaseService {
|
|
|
1070
1441
|
methodName: 'applyProjectChanges'
|
|
1071
1442
|
})
|
|
1072
1443
|
|
|
1073
|
-
|
|
1444
|
+
if (response.success) {
|
|
1445
|
+
return response.data
|
|
1446
|
+
}
|
|
1447
|
+
throw new Error(response.message)
|
|
1074
1448
|
} catch (error) {
|
|
1075
1449
|
throw new Error(`Failed to apply project changes: ${error.message}`)
|
|
1076
1450
|
}
|
|
@@ -1088,19 +1462,25 @@ export class CoreService extends BaseService {
|
|
|
1088
1462
|
|
|
1089
1463
|
const {
|
|
1090
1464
|
branch = 'main',
|
|
1465
|
+
version = 'latest',
|
|
1091
1466
|
includeHistory = false
|
|
1092
1467
|
} = options
|
|
1093
1468
|
|
|
1094
1469
|
const queryParams = new URLSearchParams({
|
|
1095
1470
|
branch,
|
|
1471
|
+
version,
|
|
1096
1472
|
includeHistory: includeHistory.toString()
|
|
1097
1473
|
}).toString()
|
|
1098
1474
|
|
|
1099
1475
|
try {
|
|
1100
|
-
|
|
1476
|
+
const response = await this._request(`/projects/${projectId}/data?${queryParams}`, {
|
|
1101
1477
|
method: 'GET',
|
|
1102
1478
|
methodName: 'getProjectData'
|
|
1103
1479
|
})
|
|
1480
|
+
if (response.success) {
|
|
1481
|
+
return response.data
|
|
1482
|
+
}
|
|
1483
|
+
throw new Error(response.message)
|
|
1104
1484
|
} catch (error) {
|
|
1105
1485
|
throw new Error(`Failed to get project data: ${error.message}`)
|
|
1106
1486
|
}
|
|
@@ -1128,10 +1508,14 @@ export class CoreService extends BaseService {
|
|
|
1128
1508
|
}).toString()
|
|
1129
1509
|
|
|
1130
1510
|
try {
|
|
1131
|
-
|
|
1511
|
+
const response = await this._request(`/projects/${projectId}/versions?${queryParams}`, {
|
|
1132
1512
|
method: 'GET',
|
|
1133
1513
|
methodName: 'getProjectVersions'
|
|
1134
1514
|
})
|
|
1515
|
+
if (response.success) {
|
|
1516
|
+
return response.data
|
|
1517
|
+
}
|
|
1518
|
+
throw new Error(response.message)
|
|
1135
1519
|
} catch (error) {
|
|
1136
1520
|
throw new Error(`Failed to get project versions: ${error.message}`)
|
|
1137
1521
|
}
|
|
@@ -1157,7 +1541,7 @@ export class CoreService extends BaseService {
|
|
|
1157
1541
|
} = options
|
|
1158
1542
|
|
|
1159
1543
|
try {
|
|
1160
|
-
|
|
1544
|
+
const response = await this._request(`/projects/${projectId}/restore`, {
|
|
1161
1545
|
method: 'POST',
|
|
1162
1546
|
body: JSON.stringify({
|
|
1163
1547
|
version,
|
|
@@ -1167,6 +1551,10 @@ export class CoreService extends BaseService {
|
|
|
1167
1551
|
}),
|
|
1168
1552
|
methodName: 'restoreProjectVersion'
|
|
1169
1553
|
})
|
|
1554
|
+
if (response.success) {
|
|
1555
|
+
return response.data
|
|
1556
|
+
}
|
|
1557
|
+
throw new Error(response.message)
|
|
1170
1558
|
} catch (error) {
|
|
1171
1559
|
throw new Error(`Failed to restore project version: ${error.message}`)
|
|
1172
1560
|
}
|
|
@@ -1277,11 +1665,15 @@ export class CoreService extends BaseService {
|
|
|
1277
1665
|
}
|
|
1278
1666
|
|
|
1279
1667
|
try {
|
|
1280
|
-
|
|
1668
|
+
const response = await this._request(`/projects/${projectId}/pull-requests`, {
|
|
1281
1669
|
method: 'POST',
|
|
1282
1670
|
body: JSON.stringify(pullRequestData),
|
|
1283
1671
|
methodName: 'createPullRequest'
|
|
1284
1672
|
})
|
|
1673
|
+
if (response.success) {
|
|
1674
|
+
return response.data
|
|
1675
|
+
}
|
|
1676
|
+
throw new Error(response.message)
|
|
1285
1677
|
} catch (error) {
|
|
1286
1678
|
throw new Error(`Failed to create pull request: ${error.message}`)
|
|
1287
1679
|
}
|
|
@@ -1314,10 +1706,14 @@ export class CoreService extends BaseService {
|
|
|
1314
1706
|
if (target) {queryParams.append('target', target)}
|
|
1315
1707
|
|
|
1316
1708
|
try {
|
|
1317
|
-
|
|
1709
|
+
const response = await this._request(`/projects/${projectId}/pull-requests?${queryParams.toString()}`, {
|
|
1318
1710
|
method: 'GET',
|
|
1319
1711
|
methodName: 'listPullRequests'
|
|
1320
1712
|
})
|
|
1713
|
+
if (response.success) {
|
|
1714
|
+
return response.data
|
|
1715
|
+
}
|
|
1716
|
+
throw new Error(response.message)
|
|
1321
1717
|
} catch (error) {
|
|
1322
1718
|
throw new Error(`Failed to list pull requests: ${error.message}`)
|
|
1323
1719
|
}
|
|
@@ -1336,10 +1732,14 @@ export class CoreService extends BaseService {
|
|
|
1336
1732
|
}
|
|
1337
1733
|
|
|
1338
1734
|
try {
|
|
1339
|
-
|
|
1735
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}`, {
|
|
1340
1736
|
method: 'GET',
|
|
1341
1737
|
methodName: 'getPullRequest'
|
|
1342
1738
|
})
|
|
1739
|
+
if (response.success) {
|
|
1740
|
+
return response.data
|
|
1741
|
+
}
|
|
1742
|
+
throw new Error(response.message)
|
|
1343
1743
|
} catch (error) {
|
|
1344
1744
|
throw new Error(`Failed to get pull request: ${error.message}`)
|
|
1345
1745
|
}
|
|
@@ -1363,11 +1763,15 @@ export class CoreService extends BaseService {
|
|
|
1363
1763
|
}
|
|
1364
1764
|
|
|
1365
1765
|
try {
|
|
1366
|
-
|
|
1766
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}/review`, {
|
|
1367
1767
|
method: 'POST',
|
|
1368
1768
|
body: JSON.stringify(reviewData),
|
|
1369
1769
|
methodName: 'reviewPullRequest'
|
|
1370
1770
|
})
|
|
1771
|
+
if (response.success) {
|
|
1772
|
+
return response.data
|
|
1773
|
+
}
|
|
1774
|
+
throw new Error(response.message)
|
|
1371
1775
|
} catch (error) {
|
|
1372
1776
|
throw new Error(`Failed to review pull request: ${error.message}`)
|
|
1373
1777
|
}
|
|
@@ -1389,11 +1793,15 @@ export class CoreService extends BaseService {
|
|
|
1389
1793
|
}
|
|
1390
1794
|
|
|
1391
1795
|
try {
|
|
1392
|
-
|
|
1796
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}/comment`, {
|
|
1393
1797
|
method: 'POST',
|
|
1394
1798
|
body: JSON.stringify(commentData),
|
|
1395
1799
|
methodName: 'addPullRequestComment'
|
|
1396
1800
|
})
|
|
1801
|
+
if (response.success) {
|
|
1802
|
+
return response.data
|
|
1803
|
+
}
|
|
1804
|
+
throw new Error(response.message)
|
|
1397
1805
|
} catch (error) {
|
|
1398
1806
|
throw new Error(`Failed to add pull request comment: ${error.message}`)
|
|
1399
1807
|
}
|
|
@@ -1417,7 +1825,10 @@ export class CoreService extends BaseService {
|
|
|
1417
1825
|
methodName: 'mergePullRequest'
|
|
1418
1826
|
})
|
|
1419
1827
|
|
|
1420
|
-
|
|
1828
|
+
if (response.success) {
|
|
1829
|
+
return response.data
|
|
1830
|
+
}
|
|
1831
|
+
throw new Error(response.message)
|
|
1421
1832
|
} catch (error) {
|
|
1422
1833
|
// Handle specific merge conflict errors
|
|
1423
1834
|
if (error.message.includes('conflicts') || error.message.includes('409')) {
|
|
@@ -1440,10 +1851,14 @@ export class CoreService extends BaseService {
|
|
|
1440
1851
|
}
|
|
1441
1852
|
|
|
1442
1853
|
try {
|
|
1443
|
-
|
|
1854
|
+
const response = await this._request(`/projects/${projectId}/pull-requests/${prId}/diff`, {
|
|
1444
1855
|
method: 'GET',
|
|
1445
1856
|
methodName: 'getPullRequestDiff'
|
|
1446
1857
|
})
|
|
1858
|
+
if (response.success) {
|
|
1859
|
+
return response.data
|
|
1860
|
+
}
|
|
1861
|
+
throw new Error(response.message)
|
|
1447
1862
|
} catch (error) {
|
|
1448
1863
|
throw new Error(`Failed to get pull request diff: ${error.message}`)
|
|
1449
1864
|
}
|
|
@@ -1577,10 +1992,14 @@ export class CoreService extends BaseService {
|
|
|
1577
1992
|
}
|
|
1578
1993
|
|
|
1579
1994
|
try {
|
|
1580
|
-
|
|
1995
|
+
const response = await this._request(`/projects/${projectId}/branches`, {
|
|
1581
1996
|
method: 'GET',
|
|
1582
1997
|
methodName: 'listBranches'
|
|
1583
1998
|
})
|
|
1999
|
+
if (response.success) {
|
|
2000
|
+
return response.data
|
|
2001
|
+
}
|
|
2002
|
+
throw new Error(response.message)
|
|
1584
2003
|
} catch (error) {
|
|
1585
2004
|
throw new Error(`Failed to list branches: ${error.message}`)
|
|
1586
2005
|
}
|
|
@@ -1601,11 +2020,15 @@ export class CoreService extends BaseService {
|
|
|
1601
2020
|
const { name, source = 'main' } = branchData
|
|
1602
2021
|
|
|
1603
2022
|
try {
|
|
1604
|
-
|
|
2023
|
+
const response = await this._request(`/projects/${projectId}/branches`, {
|
|
1605
2024
|
method: 'POST',
|
|
1606
2025
|
body: JSON.stringify({ name, source }),
|
|
1607
2026
|
methodName: 'createBranch'
|
|
1608
2027
|
})
|
|
2028
|
+
if (response.success) {
|
|
2029
|
+
return response.data
|
|
2030
|
+
}
|
|
2031
|
+
throw new Error(response.message)
|
|
1609
2032
|
} catch (error) {
|
|
1610
2033
|
throw new Error(`Failed to create branch: ${error.message}`)
|
|
1611
2034
|
}
|
|
@@ -1627,10 +2050,14 @@ export class CoreService extends BaseService {
|
|
|
1627
2050
|
}
|
|
1628
2051
|
|
|
1629
2052
|
try {
|
|
1630
|
-
|
|
2053
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}`, {
|
|
1631
2054
|
method: 'DELETE',
|
|
1632
2055
|
methodName: 'deleteBranch'
|
|
1633
2056
|
})
|
|
2057
|
+
if (response.success) {
|
|
2058
|
+
return response.data
|
|
2059
|
+
}
|
|
2060
|
+
throw new Error(response.message)
|
|
1634
2061
|
} catch (error) {
|
|
1635
2062
|
throw new Error(`Failed to delete branch: ${error.message}`)
|
|
1636
2063
|
}
|
|
@@ -1655,11 +2082,15 @@ export class CoreService extends BaseService {
|
|
|
1655
2082
|
}
|
|
1656
2083
|
|
|
1657
2084
|
try {
|
|
1658
|
-
|
|
2085
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}/rename`, {
|
|
1659
2086
|
method: 'POST',
|
|
1660
2087
|
body: JSON.stringify({ newName }),
|
|
1661
2088
|
methodName: 'renameBranch'
|
|
1662
2089
|
})
|
|
2090
|
+
if (response.success) {
|
|
2091
|
+
return response.data
|
|
2092
|
+
}
|
|
2093
|
+
throw new Error(response.message)
|
|
1663
2094
|
} catch (error) {
|
|
1664
2095
|
throw new Error(`Failed to rename branch: ${error.message}`)
|
|
1665
2096
|
}
|
|
@@ -1668,7 +2099,7 @@ export class CoreService extends BaseService {
|
|
|
1668
2099
|
/**
|
|
1669
2100
|
* Get changes/diff for a branch compared to another version
|
|
1670
2101
|
*/
|
|
1671
|
-
async getBranchChanges (projectId, branchName, options = {}) {
|
|
2102
|
+
async getBranchChanges (projectId, branchName = 'main', options = {}) {
|
|
1672
2103
|
this._requireReady('getBranchChanges')
|
|
1673
2104
|
if (!projectId) {
|
|
1674
2105
|
throw new Error('Project ID is required')
|
|
@@ -1688,10 +2119,14 @@ export class CoreService extends BaseService {
|
|
|
1688
2119
|
const url = `/projects/${projectId}/branches/${encodeURIComponent(branchName)}/changes${queryString ? `?${queryString}` : ''}`
|
|
1689
2120
|
|
|
1690
2121
|
try {
|
|
1691
|
-
|
|
2122
|
+
const response = await this._request(url, {
|
|
1692
2123
|
method: 'GET',
|
|
1693
2124
|
methodName: 'getBranchChanges'
|
|
1694
2125
|
})
|
|
2126
|
+
if (response.success) {
|
|
2127
|
+
return response.data
|
|
2128
|
+
}
|
|
2129
|
+
throw new Error(response.message)
|
|
1695
2130
|
} catch (error) {
|
|
1696
2131
|
throw new Error(`Failed to get branch changes: ${error.message}`)
|
|
1697
2132
|
}
|
|
@@ -1726,11 +2161,15 @@ export class CoreService extends BaseService {
|
|
|
1726
2161
|
}
|
|
1727
2162
|
|
|
1728
2163
|
try {
|
|
1729
|
-
|
|
2164
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}/merge`, {
|
|
1730
2165
|
method: 'POST',
|
|
1731
2166
|
body: JSON.stringify(requestBody),
|
|
1732
2167
|
methodName: 'mergeBranch'
|
|
1733
2168
|
})
|
|
2169
|
+
if (response.success) {
|
|
2170
|
+
return response.data
|
|
2171
|
+
}
|
|
2172
|
+
throw new Error(response.message)
|
|
1734
2173
|
} catch (error) {
|
|
1735
2174
|
// Handle merge conflicts specifically
|
|
1736
2175
|
if (error.message.includes('conflicts') || error.message.includes('409')) {
|
|
@@ -1753,10 +2192,14 @@ export class CoreService extends BaseService {
|
|
|
1753
2192
|
}
|
|
1754
2193
|
|
|
1755
2194
|
try {
|
|
1756
|
-
|
|
2195
|
+
const response = await this._request(`/projects/${projectId}/branches/${encodeURIComponent(branchName)}/reset`, {
|
|
1757
2196
|
method: 'POST',
|
|
1758
2197
|
methodName: 'resetBranch'
|
|
1759
2198
|
})
|
|
2199
|
+
if (response.success) {
|
|
2200
|
+
return response.data
|
|
2201
|
+
}
|
|
2202
|
+
throw new Error(response.message)
|
|
1760
2203
|
} catch (error) {
|
|
1761
2204
|
throw new Error(`Failed to reset branch: ${error.message}`)
|
|
1762
2205
|
}
|
|
@@ -1777,11 +2220,15 @@ export class CoreService extends BaseService {
|
|
|
1777
2220
|
const { version, branch = 'main' } = publishData
|
|
1778
2221
|
|
|
1779
2222
|
try {
|
|
1780
|
-
|
|
2223
|
+
const response = await this._request(`/projects/${projectId}/publish`, {
|
|
1781
2224
|
method: 'POST',
|
|
1782
2225
|
body: JSON.stringify({ version, branch }),
|
|
1783
2226
|
methodName: 'publishVersion'
|
|
1784
2227
|
})
|
|
2228
|
+
if (response.success) {
|
|
2229
|
+
return response.data
|
|
2230
|
+
}
|
|
2231
|
+
throw new Error(response.message)
|
|
1785
2232
|
} catch (error) {
|
|
1786
2233
|
throw new Error(`Failed to publish version: ${error.message}`)
|
|
1787
2234
|
}
|
|
@@ -1930,6 +2377,164 @@ export class CoreService extends BaseService {
|
|
|
1930
2377
|
return await this.deleteBranch(projectId, branchName)
|
|
1931
2378
|
}
|
|
1932
2379
|
|
|
2380
|
+
// ==================== ADMIN METHODS ====================
|
|
2381
|
+
|
|
2382
|
+
/**
|
|
2383
|
+
* Get admin users list with comprehensive filtering and search capabilities
|
|
2384
|
+
* Requires admin or super_admin global role
|
|
2385
|
+
*/
|
|
2386
|
+
async getAdminUsers (params = {}) {
|
|
2387
|
+
this._requireReady('getAdminUsers')
|
|
2388
|
+
|
|
2389
|
+
const {
|
|
2390
|
+
emails,
|
|
2391
|
+
ids,
|
|
2392
|
+
query,
|
|
2393
|
+
status,
|
|
2394
|
+
page = 1,
|
|
2395
|
+
limit = 50,
|
|
2396
|
+
sort = { field: 'createdAt', order: 'desc' }
|
|
2397
|
+
} = params
|
|
2398
|
+
|
|
2399
|
+
const queryParams = new URLSearchParams()
|
|
2400
|
+
|
|
2401
|
+
// Add query parameters
|
|
2402
|
+
if (emails) {
|
|
2403
|
+
queryParams.append('emails', emails)
|
|
2404
|
+
}
|
|
2405
|
+
if (ids) {
|
|
2406
|
+
queryParams.append('ids', ids)
|
|
2407
|
+
}
|
|
2408
|
+
if (query) {
|
|
2409
|
+
queryParams.append('query', query)
|
|
2410
|
+
}
|
|
2411
|
+
if (status) {
|
|
2412
|
+
queryParams.append('status', status)
|
|
2413
|
+
}
|
|
2414
|
+
if (page) {
|
|
2415
|
+
queryParams.append('page', page.toString())
|
|
2416
|
+
}
|
|
2417
|
+
if (limit) {
|
|
2418
|
+
queryParams.append('limit', limit.toString())
|
|
2419
|
+
}
|
|
2420
|
+
if (sort && sort.field) {
|
|
2421
|
+
queryParams.append('sort[field]', sort.field)
|
|
2422
|
+
queryParams.append('sort[order]', sort.order || 'desc')
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
const queryString = queryParams.toString()
|
|
2426
|
+
const url = `/users/admin/users${queryString ? `?${queryString}` : ''}`
|
|
2427
|
+
|
|
2428
|
+
try {
|
|
2429
|
+
const response = await this._request(url, {
|
|
2430
|
+
method: 'GET',
|
|
2431
|
+
methodName: 'getAdminUsers'
|
|
2432
|
+
})
|
|
2433
|
+
if (response.success) {
|
|
2434
|
+
return response.data
|
|
2435
|
+
}
|
|
2436
|
+
throw new Error(response.message)
|
|
2437
|
+
} catch (error) {
|
|
2438
|
+
throw new Error(`Failed to get admin users: ${error.message}`)
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
/**
|
|
2443
|
+
* Assign projects to a specific user
|
|
2444
|
+
* Requires admin or super_admin global role
|
|
2445
|
+
*/
|
|
2446
|
+
async assignProjectsToUser (userId, options = {}) {
|
|
2447
|
+
this._requireReady('assignProjectsToUser')
|
|
2448
|
+
|
|
2449
|
+
if (!userId) {
|
|
2450
|
+
throw new Error('User ID is required')
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
const {
|
|
2454
|
+
projectIds,
|
|
2455
|
+
role = 'guest'
|
|
2456
|
+
} = options
|
|
2457
|
+
|
|
2458
|
+
const requestBody = {
|
|
2459
|
+
userId,
|
|
2460
|
+
role
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
// Only include projectIds if provided (otherwise assigns all projects)
|
|
2464
|
+
if (projectIds && Array.isArray(projectIds)) {
|
|
2465
|
+
requestBody.projectIds = projectIds
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
try {
|
|
2469
|
+
const response = await this._request('/assign-projects', {
|
|
2470
|
+
method: 'POST',
|
|
2471
|
+
body: JSON.stringify(requestBody),
|
|
2472
|
+
methodName: 'assignProjectsToUser'
|
|
2473
|
+
})
|
|
2474
|
+
if (response.success) {
|
|
2475
|
+
return response.data
|
|
2476
|
+
}
|
|
2477
|
+
throw new Error(response.message)
|
|
2478
|
+
} catch (error) {
|
|
2479
|
+
throw new Error(`Failed to assign projects to user: ${error.message}`)
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
/**
|
|
2484
|
+
* Helper method for admin users search
|
|
2485
|
+
*/
|
|
2486
|
+
async searchAdminUsers (searchQuery, options = {}) {
|
|
2487
|
+
return await this.getAdminUsers({
|
|
2488
|
+
query: searchQuery,
|
|
2489
|
+
...options
|
|
2490
|
+
})
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
/**
|
|
2494
|
+
* Helper method to get admin users by email list
|
|
2495
|
+
*/
|
|
2496
|
+
async getAdminUsersByEmails (emails, options = {}) {
|
|
2497
|
+
const emailList = Array.isArray(emails) ? emails.join(',') : emails
|
|
2498
|
+
return await this.getAdminUsers({
|
|
2499
|
+
emails: emailList,
|
|
2500
|
+
...options
|
|
2501
|
+
})
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
/**
|
|
2505
|
+
* Helper method to get admin users by ID list
|
|
2506
|
+
*/
|
|
2507
|
+
async getAdminUsersByIds (ids, options = {}) {
|
|
2508
|
+
const idList = Array.isArray(ids) ? ids.join(',') : ids
|
|
2509
|
+
return await this.getAdminUsers({
|
|
2510
|
+
ids: idList,
|
|
2511
|
+
...options
|
|
2512
|
+
})
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
/**
|
|
2516
|
+
* Helper method to assign specific projects to a user with a specific role
|
|
2517
|
+
*/
|
|
2518
|
+
async assignSpecificProjectsToUser (userId, projectIds, role = 'guest') {
|
|
2519
|
+
if (!Array.isArray(projectIds) || projectIds.length === 0) {
|
|
2520
|
+
throw new Error('Project IDs must be a non-empty array')
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
return await this.assignProjectsToUser(userId, {
|
|
2524
|
+
projectIds,
|
|
2525
|
+
role
|
|
2526
|
+
})
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
/**
|
|
2530
|
+
* Helper method to assign all projects to a user with a specific role
|
|
2531
|
+
*/
|
|
2532
|
+
async assignAllProjectsToUser (userId, role = 'guest') {
|
|
2533
|
+
return await this.assignProjectsToUser(userId, {
|
|
2534
|
+
role
|
|
2535
|
+
})
|
|
2536
|
+
}
|
|
2537
|
+
|
|
1933
2538
|
// Cleanup
|
|
1934
2539
|
destroy () {
|
|
1935
2540
|
if (this._tokenManager) {
|