@symbo.ls/sdk 3.1.1 → 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 +174 -13
- package/dist/cjs/config/environment.js +32 -42
- package/dist/cjs/index.js +31 -24
- package/dist/cjs/services/AIService.js +3 -3
- package/dist/cjs/services/AuthService.js +44 -3
- package/dist/cjs/services/BasedService.js +530 -24
- package/dist/cjs/services/CollabService.js +420 -0
- package/dist/cjs/services/CoreService.js +2295 -0
- package/dist/cjs/services/SocketService.js +207 -59
- package/dist/cjs/services/SymstoryService.js +135 -49
- package/dist/cjs/services/index.js +8 -16
- 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 +409 -0
- package/dist/cjs/utils/basedQuerys.js +120 -0
- package/dist/cjs/utils/jsonDiff.js +103 -0
- package/dist/cjs/utils/permission.js +4 -4
- package/dist/cjs/utils/services.js +133 -69
- package/dist/cjs/utils/symstoryClient.js +33 -2
- package/dist/esm/config/environment.js +32 -42
- package/dist/esm/index.js +20586 -11525
- package/dist/esm/services/AIService.js +3 -3
- package/dist/esm/services/AuthService.js +48 -7
- package/dist/esm/services/BasedService.js +676 -65
- package/dist/esm/services/CollabService.js +18028 -0
- package/dist/esm/services/CoreService.js +2827 -0
- package/dist/esm/services/SocketService.js +323 -58
- package/dist/esm/services/SymstoryService.js +287 -111
- package/dist/esm/services/index.js +20456 -11470
- 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 +395 -0
- package/dist/esm/utils/basedQuerys.js +120 -0
- package/dist/esm/utils/jsonDiff.js +6096 -0
- package/dist/esm/utils/permission.js +4 -4
- package/dist/esm/utils/services.js +133 -69
- package/dist/esm/utils/symstoryClient.js +63 -43
- package/dist/esm/utils/validation.js +89 -19
- package/dist/node/config/environment.js +32 -42
- package/dist/node/index.js +37 -28
- package/dist/node/services/AIService.js +3 -3
- package/dist/node/services/AuthService.js +44 -3
- package/dist/node/services/BasedService.js +531 -25
- package/dist/node/services/CollabService.js +401 -0
- package/dist/node/services/CoreService.js +2266 -0
- package/dist/node/services/SocketService.js +197 -59
- package/dist/node/services/SymstoryService.js +135 -49
- package/dist/node/services/index.js +8 -16
- 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 +390 -0
- package/dist/node/utils/basedQuerys.js +120 -0
- package/dist/node/utils/jsonDiff.js +74 -0
- package/dist/node/utils/permission.js +4 -4
- package/dist/node/utils/services.js +133 -69
- package/dist/node/utils/symstoryClient.js +33 -2
- package/package.json +23 -14
- package/src/config/environment.js +33 -42
- package/src/index.js +45 -28
- package/src/services/AIService.js +3 -3
- package/src/services/AuthService.js +52 -3
- package/src/services/BasedService.js +603 -23
- package/src/services/CollabService.js +491 -0
- package/src/services/CoreService.js +2548 -0
- package/src/services/SocketService.js +227 -59
- package/src/services/SymstoryService.js +150 -64
- package/src/services/index.js +7 -14
- 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 +462 -0
- package/src/utils/basedQuerys.js +123 -0
- package/src/utils/jsonDiff.js +109 -0
- package/src/utils/permission.js +4 -4
- package/src/utils/services.js +144 -69
- package/src/utils/symstoryClient.js +36 -2
- package/dist/cjs/services/SocketIOService.js +0 -309
- package/dist/esm/services/SocketIOService.js +0 -467
- package/dist/node/services/SocketIOService.js +0 -280
- package/src/services/SocketIOService.js +0 -356
|
@@ -137,7 +137,7 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
137
137
|
role: obj.role,
|
|
138
138
|
joinedAt: Date.now()
|
|
139
139
|
});
|
|
140
|
-
await Promise.all([
|
|
140
|
+
return await Promise.all([
|
|
141
141
|
this._client.call("db:set", {
|
|
142
142
|
$id: userId,
|
|
143
143
|
memberProjects: { $add: membershipId }
|
|
@@ -147,7 +147,6 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
147
147
|
members: { $add: membershipId }
|
|
148
148
|
})
|
|
149
149
|
]);
|
|
150
|
-
return await this._client.call("db:set", obj);
|
|
151
150
|
} catch (error) {
|
|
152
151
|
throw new Error(`Failed to set bucket: ${error.message}`);
|
|
153
152
|
}
|
|
@@ -185,6 +184,7 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
185
184
|
throw new Error(`Query failed: ${error.message}`);
|
|
186
185
|
}
|
|
187
186
|
}
|
|
187
|
+
// DEPRECATED
|
|
188
188
|
async fetchUser(userId) {
|
|
189
189
|
if (!userId) {
|
|
190
190
|
throw new Error("User Id is required");
|
|
@@ -192,15 +192,113 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
192
192
|
return await this.query("db", (0, import_basedQuerys.buildUserQuery)(userId));
|
|
193
193
|
}
|
|
194
194
|
async getUser(userId) {
|
|
195
|
-
this._requireReady();
|
|
196
195
|
if (!userId) {
|
|
197
|
-
throw new Error("
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
196
|
+
throw new Error("UserId is required");
|
|
197
|
+
}
|
|
198
|
+
const userData = await this._client.query("db", (0, import_basedQuerys.buildGetUserDataQuery)(userId)).get();
|
|
199
|
+
const user = {
|
|
200
|
+
id: userData.id,
|
|
201
|
+
name: userData.name,
|
|
202
|
+
email: userData.email,
|
|
203
|
+
username: userData.username,
|
|
204
|
+
globalRole: userData.globalRole,
|
|
205
|
+
createdAt: userData.createdAt,
|
|
206
|
+
updatedAt: userData.updatedAt
|
|
207
|
+
};
|
|
208
|
+
if (!user) {
|
|
209
|
+
throw new Error("User not found");
|
|
210
|
+
}
|
|
211
|
+
let memberProjects = [];
|
|
212
|
+
if (userData.memberProjects && userData.memberProjects.length > 0) {
|
|
213
|
+
const projectKeys = userData.memberProjects.filter((membership) => membership.project && membership.project.key).map((membership) => membership.project.key);
|
|
214
|
+
if (projectKeys.length > 0) {
|
|
215
|
+
const allProjects = await this._fetchProjectsByKeysInChunks(projectKeys);
|
|
216
|
+
memberProjects = userData.memberProjects.filter((membership) => membership.project && membership.project.key).map((membership) => {
|
|
217
|
+
const projectKey = membership.project.key;
|
|
218
|
+
const correctProject = allProjects.find(
|
|
219
|
+
(p) => p.key === projectKey
|
|
220
|
+
);
|
|
221
|
+
return {
|
|
222
|
+
project: correctProject || membership.project,
|
|
223
|
+
role: membership.role,
|
|
224
|
+
updatedAt: membership.updatedAt,
|
|
225
|
+
createdAt: membership.createdAt
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
console.log(`[getUser] No member projects found with ID: ${userId}`);
|
|
231
|
+
}
|
|
232
|
+
const formattedProjects = memberProjects.filter((membership) => membership.project).map((membership) => ({
|
|
233
|
+
id: membership.project.id,
|
|
234
|
+
name: membership.project.name,
|
|
235
|
+
key: membership.project.key,
|
|
236
|
+
thumbnail: membership.project.thumbnail,
|
|
237
|
+
icon: membership.project.icon,
|
|
238
|
+
tier: membership.project.tier,
|
|
239
|
+
visibility: membership.project.visibility,
|
|
240
|
+
access: membership.project.access,
|
|
241
|
+
role: membership.role,
|
|
242
|
+
joinedAt: membership.createdAt,
|
|
243
|
+
updatedAt: membership.updatedAt,
|
|
244
|
+
members: membership.project.members
|
|
245
|
+
})) || [];
|
|
246
|
+
return {
|
|
247
|
+
id: userId,
|
|
248
|
+
name: user.name,
|
|
249
|
+
email: user.email,
|
|
250
|
+
username: user.username,
|
|
251
|
+
globalRole: user.globalRole,
|
|
252
|
+
projects: formattedProjects,
|
|
253
|
+
createdAt: user.createdAt,
|
|
254
|
+
updatedAt: user.updatedAt
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Fetches projects by keys in chunks with adaptive chunk sizing
|
|
259
|
+
* @param {Array<string>} allKeys - All project keys to fetch
|
|
260
|
+
* @returns {Promise<Array>} - All projects found
|
|
261
|
+
*/
|
|
262
|
+
async _fetchProjectsByKeysInChunks(allKeys) {
|
|
263
|
+
if (!allKeys.length) {
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
const INITIAL_CHUNK_SIZE = 50;
|
|
267
|
+
const MAX_CHUNK_SIZE = 1e3;
|
|
268
|
+
const MIN_CHUNK_SIZE = 10;
|
|
269
|
+
const optimalChunkSize = INITIAL_CHUNK_SIZE;
|
|
270
|
+
const processChunks = async (keys, size) => {
|
|
271
|
+
if (!keys.length) {
|
|
272
|
+
return [];
|
|
273
|
+
}
|
|
274
|
+
const chunks = [];
|
|
275
|
+
for (let i = 0; i < keys.length; i += size) {
|
|
276
|
+
chunks.push(keys.slice(i, i + size));
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
const result = await this._client.query("db", (0, import_basedQuerys.buildGetProjectsByKeysQuery)(chunks[0])).get();
|
|
280
|
+
const newSize = Math.min(Math.floor(size * 1.5), MAX_CHUNK_SIZE);
|
|
281
|
+
const firstChunkProjects = result.projects || [];
|
|
282
|
+
const remainingKeys = keys.slice(chunks[0].length);
|
|
283
|
+
const remainingProjects = await processChunks(remainingKeys, newSize);
|
|
284
|
+
return [...firstChunkProjects, ...remainingProjects];
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (error.message && error.message.includes("PayloadTooLarge")) {
|
|
287
|
+
const newSize = Math.max(Math.floor(size / 2), MIN_CHUNK_SIZE);
|
|
288
|
+
console.warn(`Reducing chunk size to ${newSize} due to PayloadTooLarge error`);
|
|
289
|
+
if (newSize === MIN_CHUNK_SIZE && chunks[0].length <= MIN_CHUNK_SIZE) {
|
|
290
|
+
console.error(`Cannot process chunk, skipping ${chunks[0].length} keys`);
|
|
291
|
+
const remainingKeys2 = keys.slice(chunks[0].length);
|
|
292
|
+
return processChunks(remainingKeys2, newSize);
|
|
293
|
+
}
|
|
294
|
+
return processChunks(keys, newSize);
|
|
295
|
+
}
|
|
296
|
+
console.error(`Error fetching projects: ${error.message}`);
|
|
297
|
+
const remainingKeys = keys.slice(chunks[0].length);
|
|
298
|
+
return processChunks(remainingKeys, size);
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
return await processChunks(allKeys, optimalChunkSize);
|
|
204
302
|
}
|
|
205
303
|
async getUserByEmail(email) {
|
|
206
304
|
this._requireReady();
|
|
@@ -362,31 +460,26 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
362
460
|
throw new Error(`Failed to create project: ${error.message}`);
|
|
363
461
|
}
|
|
364
462
|
}
|
|
365
|
-
async getProject(projectId
|
|
463
|
+
async getProject(projectId) {
|
|
366
464
|
this._requireReady();
|
|
367
465
|
if (!projectId) {
|
|
368
466
|
throw new Error("Project ID is required");
|
|
369
467
|
}
|
|
370
468
|
try {
|
|
371
|
-
return await this.
|
|
372
|
-
projectId,
|
|
373
|
-
fields: { ...fields }
|
|
374
|
-
});
|
|
469
|
+
return await this._client.query("db", (0, import_basedQuerys.buildGetProjectDataQuery)(projectId)).get();
|
|
375
470
|
} catch (error) {
|
|
376
471
|
throw new Error(`Failed to get project: ${error.message}`);
|
|
377
472
|
}
|
|
378
473
|
}
|
|
379
|
-
async getProjectByKey(key
|
|
474
|
+
async getProjectByKey(key) {
|
|
380
475
|
this._requireReady();
|
|
381
476
|
try {
|
|
382
|
-
return await this.
|
|
383
|
-
key,
|
|
384
|
-
fields: { ...fields }
|
|
385
|
-
});
|
|
477
|
+
return await this._client.query("db", (0, import_basedQuerys.buildGetProjectByKeyDataQuery)(key)).get();
|
|
386
478
|
} catch (error) {
|
|
387
479
|
throw new Error(`Failed to get project by key: ${error.message}`);
|
|
388
480
|
}
|
|
389
481
|
}
|
|
482
|
+
// DEPRECATED
|
|
390
483
|
async fetchProject(projectId) {
|
|
391
484
|
this._requireReady();
|
|
392
485
|
if (!projectId) {
|
|
@@ -467,7 +560,9 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
467
560
|
pkg = 2,
|
|
468
561
|
seats = 1,
|
|
469
562
|
interval = "monthly",
|
|
470
|
-
plan = "startup"
|
|
563
|
+
plan = "startup",
|
|
564
|
+
successUrl = `${window.location.origin}/success`,
|
|
565
|
+
cancelUrl = `${window.location.origin}/pricing`
|
|
471
566
|
}) {
|
|
472
567
|
this._requireReady();
|
|
473
568
|
const prices = {
|
|
@@ -489,7 +584,9 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
489
584
|
return await this.call("checkout", {
|
|
490
585
|
price,
|
|
491
586
|
seats,
|
|
492
|
-
projectId
|
|
587
|
+
projectId,
|
|
588
|
+
successUrl,
|
|
589
|
+
cancelUrl
|
|
493
590
|
});
|
|
494
591
|
} catch (error) {
|
|
495
592
|
throw new Error(`Failed to checkout: ${error.message}`);
|
|
@@ -664,16 +761,425 @@ class BasedService extends import_BaseService.BaseService {
|
|
|
664
761
|
* @param {string} newKey - The new key of the project (optional)
|
|
665
762
|
* @returns {Promise<Object>} The duplicated project
|
|
666
763
|
*/
|
|
667
|
-
async duplicateProject(projectId, newName, newKey) {
|
|
764
|
+
async duplicateProject(projectId, newName, newKey, targetUserId) {
|
|
668
765
|
this._requireReady();
|
|
669
766
|
try {
|
|
670
767
|
return await this.call("projects:duplicate", {
|
|
671
768
|
projectId,
|
|
672
769
|
newName,
|
|
673
|
-
newKey
|
|
770
|
+
newKey,
|
|
771
|
+
targetUserId
|
|
674
772
|
});
|
|
675
773
|
} catch (error) {
|
|
676
774
|
throw new Error(`Failed to duplicate project: ${error.message}`);
|
|
677
775
|
}
|
|
678
776
|
}
|
|
777
|
+
/**
|
|
778
|
+
* List available subscription plans
|
|
779
|
+
* @param {Object} options - Options for filtering plans
|
|
780
|
+
* @param {number} options.page - Page number (default: 1)
|
|
781
|
+
* @param {number} options.limit - Number of plans per page (default: 20)
|
|
782
|
+
* @param {string} options.status - Filter plans by status (admin only)
|
|
783
|
+
* @param {boolean} options.includeSubscriptionCounts - Include subscription counts (admin only)
|
|
784
|
+
* @param {string} options.sortBy - Field to sort by (default: 'displayOrder')
|
|
785
|
+
* @param {string} options.sortOrder - Sort order ('asc' or 'desc', default: 'asc')
|
|
786
|
+
* @returns {Promise<Object>} List of plans with pagination info
|
|
787
|
+
*/
|
|
788
|
+
async listPlans(options = {}) {
|
|
789
|
+
this._requireReady();
|
|
790
|
+
try {
|
|
791
|
+
return await this.call("plans:list", options);
|
|
792
|
+
} catch (error) {
|
|
793
|
+
throw new Error(`Failed to list plans: ${error.message}`);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Subscribe to a plan
|
|
798
|
+
* @param {string} planId - ID of the plan to subscribe to
|
|
799
|
+
* @param {Object} options - Options for the subscription
|
|
800
|
+
* @param {string} options.paymentMethod - Payment method
|
|
801
|
+
* @param {Object} options.billingAddress - Billing address
|
|
802
|
+
* @param {string} options.stripeCustomerId - Stripe customer ID
|
|
803
|
+
* @param {string} options.stripeSubscriptionId - Stripe subscription ID
|
|
804
|
+
* @returns {Promise<Object>} Subscription details
|
|
805
|
+
*/
|
|
806
|
+
async subscribeToPlan(planId, options = {}) {
|
|
807
|
+
this._requireReady();
|
|
808
|
+
try {
|
|
809
|
+
return await this.call("subscriptions:create", { planId, ...options });
|
|
810
|
+
} catch (error) {
|
|
811
|
+
throw new Error(`Failed to subscribe to plan: ${error.message}`);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Get details of user's current subscription
|
|
816
|
+
* @param {string} subscriptionId - ID of the subscription to get details for
|
|
817
|
+
* @returns {Promise<Object>} Subscription details
|
|
818
|
+
*/
|
|
819
|
+
async getSubscriptionDetails(subscriptionId) {
|
|
820
|
+
this._requireReady();
|
|
821
|
+
try {
|
|
822
|
+
return await this.call("subscriptions:details", {
|
|
823
|
+
subscriptionId
|
|
824
|
+
});
|
|
825
|
+
} catch (error) {
|
|
826
|
+
throw new Error(`Failed to get subscription details: ${error.message}`);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Check if the current subscription is active
|
|
831
|
+
* @param {string} subscriptionId - ID of the subscription to check
|
|
832
|
+
* @returns {Promise<Object>} Subscription status info
|
|
833
|
+
*/
|
|
834
|
+
async checkSubscriptionStatus(subscriptionId) {
|
|
835
|
+
this._requireReady();
|
|
836
|
+
try {
|
|
837
|
+
return await this.call("subscriptions:check-status", {
|
|
838
|
+
subscriptionId
|
|
839
|
+
});
|
|
840
|
+
} catch (error) {
|
|
841
|
+
throw new Error(`Failed to check subscription status: ${error.message}`);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Upgrade the current subscription to a new plan
|
|
846
|
+
* @param {string} planId - ID of the plan to upgrade to
|
|
847
|
+
* @param {string} stripeSubscriptionId - ID of the Stripe subscription to upgrade
|
|
848
|
+
* @returns {Promise<Object>} Updated subscription details
|
|
849
|
+
*/
|
|
850
|
+
async upgradeSubscription(planId, stripeSubscriptionId) {
|
|
851
|
+
this._requireReady();
|
|
852
|
+
try {
|
|
853
|
+
return await this.call("subscriptions:upgrade", {
|
|
854
|
+
planId,
|
|
855
|
+
stripeSubscriptionId
|
|
856
|
+
});
|
|
857
|
+
} catch (error) {
|
|
858
|
+
throw new Error(`Failed to upgrade subscription: ${error.message}`);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Downgrade the current subscription to a new plan
|
|
863
|
+
* @param {string} planId - ID of the plan to downgrade to
|
|
864
|
+
* @param {boolean} applyImmediately - Whether to apply the downgrade immediately
|
|
865
|
+
* @param {string} stripeSubscriptionId - ID of the Stripe subscription to downgrade
|
|
866
|
+
* @returns {Promise<Object>} Updated subscription details
|
|
867
|
+
*/
|
|
868
|
+
async downgradeSubscription(planId, stripeSubscriptionId, applyImmediately = false) {
|
|
869
|
+
this._requireReady();
|
|
870
|
+
try {
|
|
871
|
+
return await this.call("subscriptions:downgrade", {
|
|
872
|
+
planId,
|
|
873
|
+
applyImmediately,
|
|
874
|
+
stripeSubscriptionId
|
|
875
|
+
});
|
|
876
|
+
} catch (error) {
|
|
877
|
+
throw new Error(`Failed to downgrade subscription: ${error.message}`);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Cancel the current subscription
|
|
882
|
+
* @param {boolean} cancelImmediately - Whether to cancel immediately or at period end
|
|
883
|
+
* @param {string} reason - Reason for cancellation
|
|
884
|
+
* @returns {Promise<Object>} Result of cancellation
|
|
885
|
+
*/
|
|
886
|
+
async cancelSubscription(cancelImmediately = false, reason = "") {
|
|
887
|
+
this._requireReady();
|
|
888
|
+
try {
|
|
889
|
+
return await this.call("subscriptions:cancel", {
|
|
890
|
+
cancelImmediately,
|
|
891
|
+
reason
|
|
892
|
+
});
|
|
893
|
+
} catch (error) {
|
|
894
|
+
throw new Error(`Failed to cancel subscription: ${error.message}`);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Reactivate a subscription that was scheduled for cancellation
|
|
899
|
+
* @returns {Promise<Object>} Updated subscription details
|
|
900
|
+
*/
|
|
901
|
+
async reactivateSubscription(stripeSubscriptionId) {
|
|
902
|
+
this._requireReady();
|
|
903
|
+
try {
|
|
904
|
+
return await this.call("subscriptions:reactivate", {
|
|
905
|
+
stripeSubscriptionId
|
|
906
|
+
});
|
|
907
|
+
} catch (error) {
|
|
908
|
+
throw new Error(`Failed to reactivate subscription: ${error.message}`);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Generate an invoice for the current subscription
|
|
913
|
+
* @param {string} subscriptionId - ID of the subscription to generate the invoice for
|
|
914
|
+
* @param {boolean} forceGenerate - Whether to force the generation of the invoice
|
|
915
|
+
* @param {Array} customItems - Custom items to add to the invoice
|
|
916
|
+
* @returns {Promise<Object>} Generated invoice
|
|
917
|
+
*/
|
|
918
|
+
async generateInvoice(subscriptionId, forceGenerate = false, customItems = []) {
|
|
919
|
+
this._requireReady();
|
|
920
|
+
try {
|
|
921
|
+
return await this.call("billing:generate-invoice", {
|
|
922
|
+
subscriptionId,
|
|
923
|
+
forceGenerate,
|
|
924
|
+
customItems
|
|
925
|
+
});
|
|
926
|
+
} catch (error) {
|
|
927
|
+
throw new Error(`Failed to generate invoice: ${error.message}`);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Get usage report for the current subscription
|
|
932
|
+
* @param {string} subscriptionId - ID of the subscription to get the usage report for
|
|
933
|
+
* @param {boolean} forceRefresh - Whether to force the refresh of the usage report
|
|
934
|
+
* @returns {Promise<Object>} Usage report
|
|
935
|
+
*/
|
|
936
|
+
async getUsageReport(subscriptionId, forceRefresh = false) {
|
|
937
|
+
this._requireReady();
|
|
938
|
+
try {
|
|
939
|
+
return await this.call("subscriptions:get-usage-report", {
|
|
940
|
+
subscriptionId,
|
|
941
|
+
forceRefresh
|
|
942
|
+
});
|
|
943
|
+
} catch (error) {
|
|
944
|
+
throw new Error(`Failed to get usage report: ${error.message}`);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Invite a user to be an account owner for the current subscription
|
|
949
|
+
* @param {string} email - Email of the user to invite
|
|
950
|
+
* @param {string} name - Name of the user to invite
|
|
951
|
+
* @param {string} callbackUrl - URL to redirect the user to after accepting the invitation
|
|
952
|
+
* @returns {Promise<Object>} Result of invitation
|
|
953
|
+
*/
|
|
954
|
+
async inviteAccountOwner(email, name, callbackUrl) {
|
|
955
|
+
this._requireReady();
|
|
956
|
+
try {
|
|
957
|
+
return await this.call("subscriptions:invite", {
|
|
958
|
+
email,
|
|
959
|
+
name,
|
|
960
|
+
callbackUrl
|
|
961
|
+
});
|
|
962
|
+
} catch (error) {
|
|
963
|
+
throw new Error(`Failed to invite account owner: ${error.message}`);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Accept an invitation to become an account owner
|
|
968
|
+
* @param {string} token - Invitation token
|
|
969
|
+
* @returns {Promise<Object>} Result of accepting invitation
|
|
970
|
+
*/
|
|
971
|
+
async acceptOwnerInvitation(token) {
|
|
972
|
+
this._requireReady();
|
|
973
|
+
try {
|
|
974
|
+
return await this.call("subscriptions:accept-owner-invitation", {
|
|
975
|
+
token
|
|
976
|
+
});
|
|
977
|
+
} catch (error) {
|
|
978
|
+
throw new Error(`Failed to accept owner invitation: ${error.message}`);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Remove an account owner from the current subscription
|
|
983
|
+
* @param {string} userId - ID of the user to remove
|
|
984
|
+
* @returns {Promise<Object>} Result of removal
|
|
985
|
+
*/
|
|
986
|
+
async removeAccountOwner(userId) {
|
|
987
|
+
this._requireReady();
|
|
988
|
+
try {
|
|
989
|
+
return await this.call("subscriptions:remove-account-owner", {
|
|
990
|
+
targetUserId: userId
|
|
991
|
+
});
|
|
992
|
+
} catch (error) {
|
|
993
|
+
throw new Error(`Failed to remove account owner: ${error.message}`);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Check if a resource limit has been reached
|
|
998
|
+
* @param {string} resourceType - Type of resource to check
|
|
999
|
+
* @param {string} projectId - ID of the project to check the resource limit for
|
|
1000
|
+
* @param {number} quantity - Amount being requested
|
|
1001
|
+
* @param {string} userId - ID of user to check (admin only, defaults to current user)
|
|
1002
|
+
* @returns {Promise<Object>} Result of check
|
|
1003
|
+
*/
|
|
1004
|
+
async checkResourceLimit(resourceType, projectId, quantity = 1, userId = "") {
|
|
1005
|
+
this._requireReady();
|
|
1006
|
+
try {
|
|
1007
|
+
return await this.call("subscriptions:check-resource-limit", {
|
|
1008
|
+
resourceType,
|
|
1009
|
+
projectId,
|
|
1010
|
+
quantity,
|
|
1011
|
+
userId
|
|
1012
|
+
});
|
|
1013
|
+
} catch (error) {
|
|
1014
|
+
throw new Error(`Failed to check resource limit: ${error.message}`);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Check if a user has access to a feature
|
|
1019
|
+
* @param {string} featureKey - Key of the feature to check
|
|
1020
|
+
* @param {string} userId - ID of user to check (admin only, defaults to current user)
|
|
1021
|
+
* @returns {Promise<Object>} Access check result
|
|
1022
|
+
*/
|
|
1023
|
+
async checkFeatureAccess(featureKey, userId) {
|
|
1024
|
+
this._requireReady();
|
|
1025
|
+
try {
|
|
1026
|
+
return await this.call("features:check-access", {
|
|
1027
|
+
featureKey,
|
|
1028
|
+
userId
|
|
1029
|
+
});
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
throw new Error(`Failed to check feature access: ${error.message}`);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Get all features available to the current user
|
|
1036
|
+
* @returns {Promise<Object>} Available features
|
|
1037
|
+
*/
|
|
1038
|
+
async getUserFeatures() {
|
|
1039
|
+
this._requireReady();
|
|
1040
|
+
try {
|
|
1041
|
+
return await this.call("subscriptions:get-user-features", {});
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
throw new Error(`Failed to get user features: ${error.message}`);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Get all available features across all plans
|
|
1048
|
+
* @param {string} subscriptionId - ID of the subscription to get the available features for
|
|
1049
|
+
* @param {string} userId - ID of user to get the available features for (admin only, defaults to current user)
|
|
1050
|
+
* @param {boolean} includeDetails - Whether to include details about the features
|
|
1051
|
+
* @returns {Promise<Object>} Available features
|
|
1052
|
+
*/
|
|
1053
|
+
async getAvailableFeatures(subscriptionId, userId = "", includeDetails = false) {
|
|
1054
|
+
this._requireReady();
|
|
1055
|
+
try {
|
|
1056
|
+
return await this.call("features:get-available", {
|
|
1057
|
+
subscriptionId,
|
|
1058
|
+
userId,
|
|
1059
|
+
includeDetails
|
|
1060
|
+
});
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
throw new Error(`Failed to get available features: ${error.message}`);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* List all feature flags (admin only)
|
|
1067
|
+
* @param {Object} options - Options for listing feature flags
|
|
1068
|
+
* @param {number} options.page - Page number
|
|
1069
|
+
* @param {number} options.limit - Number of items per page
|
|
1070
|
+
* @param {string} options.status - Filter by status
|
|
1071
|
+
* @returns {Promise<Object>} List of feature flags
|
|
1072
|
+
*/
|
|
1073
|
+
async listFeatureFlags(options = {}) {
|
|
1074
|
+
this._requireReady();
|
|
1075
|
+
try {
|
|
1076
|
+
return await this.call("features:list", options);
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
throw new Error(`Failed to list feature flags: ${error.message}`);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Update a feature flag (admin only)
|
|
1083
|
+
* @param {string} flagId - ID of the feature flag to update
|
|
1084
|
+
* @param {Object} options - Update data
|
|
1085
|
+
* @param {string} options.key - Key of the feature flag
|
|
1086
|
+
* @param {string} options.name - Name of the feature flag
|
|
1087
|
+
* @param {string} options.description - Description of the feature flag
|
|
1088
|
+
* @param {string} options.defaultValue - Default value of the feature flag
|
|
1089
|
+
* @param {Object} options.planOverrides - Plan overrides for the feature flag
|
|
1090
|
+
* @param {Object} options.userOverrides - User overrides for the feature flag
|
|
1091
|
+
* @param {string} options.status - Status of the feature flag
|
|
1092
|
+
* @returns {Promise<Object>} Updated feature flag
|
|
1093
|
+
*/
|
|
1094
|
+
async updateFeatureFlag(flagId, options) {
|
|
1095
|
+
this._requireReady();
|
|
1096
|
+
try {
|
|
1097
|
+
return await this.call("features:update", {
|
|
1098
|
+
flagId,
|
|
1099
|
+
...options
|
|
1100
|
+
});
|
|
1101
|
+
} catch (error) {
|
|
1102
|
+
throw new Error(`Failed to update feature flag: ${error.message}`);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Remove a feature flag (admin only)
|
|
1107
|
+
* @param {string} flagId - ID of the feature flag to remove
|
|
1108
|
+
* @returns {Promise<Object>} Result of removal
|
|
1109
|
+
*/
|
|
1110
|
+
async removeFeatureFlag(flagId) {
|
|
1111
|
+
this._requireReady();
|
|
1112
|
+
try {
|
|
1113
|
+
return await this.call("features:remove", {
|
|
1114
|
+
flagId
|
|
1115
|
+
});
|
|
1116
|
+
} catch (error) {
|
|
1117
|
+
throw new Error(`Failed to remove feature flag: ${error.message}`);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
/**
|
|
1121
|
+
* Batch update feature flags (admin only)
|
|
1122
|
+
* @param {Array} operations - Array of feature flag operations
|
|
1123
|
+
* @param {string} operations.flagId - ID of the feature flag to update
|
|
1124
|
+
* @param {string} operations.key - Key of the feature flag
|
|
1125
|
+
* @param {string} operations.name - Name of the feature flag
|
|
1126
|
+
* @param {string} operations.description - Description of the feature flag
|
|
1127
|
+
* @param {boolean} operations.defaultValue - Default value of the feature flag
|
|
1128
|
+
* @param {Object} operations.planOverrides - Plan overrides for the feature flag
|
|
1129
|
+
* @param {Object} operations.userOverrides - User overrides for the feature flag
|
|
1130
|
+
* @param {string} operations.status - Status of the feature flag
|
|
1131
|
+
* @returns {Promise<Object>} Result of batch update
|
|
1132
|
+
*/
|
|
1133
|
+
async batchUpdateFeatureFlags(operations) {
|
|
1134
|
+
this._requireReady();
|
|
1135
|
+
try {
|
|
1136
|
+
return await this.call("features:batch-update", {
|
|
1137
|
+
operations
|
|
1138
|
+
});
|
|
1139
|
+
} catch (error) {
|
|
1140
|
+
throw new Error(`Failed to batch update feature flags: ${error.message}`);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Update plan details (admin only)
|
|
1145
|
+
* @param {string} planId - ID of the plan to update
|
|
1146
|
+
* @param {Object} data - Update data
|
|
1147
|
+
* @param {string} data.name - Display name (e.g., "Pro", "Team")
|
|
1148
|
+
* @param {string} data.description - Marketing description
|
|
1149
|
+
* @param {number} data.price - Monthly price in cents
|
|
1150
|
+
* @param {number} data.annualPrice - Annual price in cents (discounted)
|
|
1151
|
+
* @param {number} data.lifetimePrice - One-time lifetime price in cents
|
|
1152
|
+
* @param {string} data.billingType - Payment type
|
|
1153
|
+
* @param {string} data.status - Status
|
|
1154
|
+
* @param {Object} data.features - Detailed feature configuration
|
|
1155
|
+
* @returns {Promise<Object>} Updated plan
|
|
1156
|
+
*/
|
|
1157
|
+
async updatePlanDetails(planId, data) {
|
|
1158
|
+
this._requireReady();
|
|
1159
|
+
try {
|
|
1160
|
+
return await this.call("plans:update-details", {
|
|
1161
|
+
planId,
|
|
1162
|
+
data
|
|
1163
|
+
});
|
|
1164
|
+
} catch (error) {
|
|
1165
|
+
throw new Error(`Failed to update plan details: ${error.message}`);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Update plan status (admin only)
|
|
1170
|
+
* @param {string} planId - ID of the plan to update
|
|
1171
|
+
* @param {string} status - New status
|
|
1172
|
+
* @returns {Promise<Object>} Updated plan
|
|
1173
|
+
*/
|
|
1174
|
+
async updatePlanStatus(planId, status) {
|
|
1175
|
+
this._requireReady();
|
|
1176
|
+
try {
|
|
1177
|
+
return await this.call("plans:update-status", {
|
|
1178
|
+
planId,
|
|
1179
|
+
status
|
|
1180
|
+
});
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
throw new Error(`Failed to update plan status: ${error.message}`);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
679
1185
|
}
|