@omnibase/core-js 0.5.10 → 0.7.0
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 +64 -198
- package/dist/chunk-4VFICD7B.js +563 -0
- package/dist/chunk-4WXOODCF.js +579 -0
- package/dist/chunk-5MDBFHTF.js +555 -0
- package/dist/chunk-6OGESVXW.js +651 -0
- package/dist/chunk-BZSZVT4V.js +152 -0
- package/dist/chunk-CUBJFCZH.js +579 -0
- package/dist/chunk-I6DMWC32.js +129 -0
- package/dist/chunk-IVPULXIA.js +150 -0
- package/dist/chunk-LCEBQTB7.js +563 -0
- package/dist/chunk-LMDKQ6Z2.js +706 -0
- package/dist/chunk-NBPRDG6O.js +643 -0
- package/dist/chunk-QPW6G4PA.js +490 -0
- package/dist/chunk-QXPPBLH4.js +556 -0
- package/dist/chunk-V56G36FZ.js +558 -0
- package/dist/chunk-ZBRAIBZZ.js +658 -0
- package/dist/chunk-ZYLNNK7H.js +555 -0
- package/dist/database/index.cjs +215 -1
- package/dist/database/index.d.cts +194 -1
- package/dist/database/index.d.ts +194 -1
- package/dist/database/index.js +214 -1
- package/dist/index.cjs +449 -185
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +105 -4
- package/dist/payments/index.cjs +22 -74
- package/dist/payments/index.d.cts +554 -245
- package/dist/payments/index.d.ts +554 -245
- package/dist/payments/index.js +1 -1
- package/dist/storage/index.cjs +153 -0
- package/dist/storage/index.d.cts +3 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.js +6 -0
- package/dist/tenants/index.cjs +200 -109
- package/dist/tenants/index.d.cts +1 -1
- package/dist/tenants/index.d.ts +1 -1
- package/dist/tenants/index.js +1 -1
- package/package.json +17 -12
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
OmnibaseClient: () => OmnibaseClient
|
|
23
|
+
OmnibaseClient: () => OmnibaseClient,
|
|
24
|
+
StorageClient: () => StorageClient
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(index_exports);
|
|
26
27
|
|
|
@@ -56,31 +57,20 @@ var CheckoutManager = class {
|
|
|
56
57
|
* @throws {ValidationError} When required parameters are missing or invalid
|
|
57
58
|
*
|
|
58
59
|
* @example
|
|
59
|
-
* Creating a checkout session (mode is auto-detected):
|
|
60
60
|
* ```typescript
|
|
61
61
|
* const session = await checkoutManager.createSession({
|
|
62
|
-
* price_id: '
|
|
62
|
+
* price_id: 'price_monthly_pro',
|
|
63
63
|
* success_url: 'https://app.com/success',
|
|
64
64
|
* cancel_url: 'https://app.com/cancel'
|
|
65
65
|
* });
|
|
66
66
|
*
|
|
67
67
|
* // Redirect to Stripe checkout
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* Checkout with session tracking:
|
|
73
|
-
* ```typescript
|
|
74
|
-
* const session = await checkoutManager.createSession({
|
|
75
|
-
* price_id: 'price_monthly_plan',
|
|
76
|
-
* success_url: 'https://app.com/dashboard?session_id={CHECKOUT_SESSION_ID}',
|
|
77
|
-
* cancel_url: 'https://app.com/pricing',
|
|
78
|
-
* });
|
|
79
|
-
*
|
|
80
|
-
* console.log(`Session created: ${session.data.sessionId}`);
|
|
68
|
+
* if (session.data?.url) {
|
|
69
|
+
* window.location.href = session.data.url;
|
|
70
|
+
* }
|
|
81
71
|
* ```
|
|
82
72
|
*
|
|
83
|
-
* @since
|
|
73
|
+
* @since 0.6.0
|
|
84
74
|
* @group Checkout
|
|
85
75
|
*/
|
|
86
76
|
async createSession(options) {
|
|
@@ -301,7 +291,7 @@ var PortalManager = class {
|
|
|
301
291
|
/**
|
|
302
292
|
* Initialize the portal manager
|
|
303
293
|
*
|
|
304
|
-
* @param
|
|
294
|
+
* @param omnibaseClient - OmnibaseClient instance for API communication
|
|
305
295
|
*
|
|
306
296
|
* @group Portal
|
|
307
297
|
*/
|
|
@@ -328,32 +318,18 @@ var PortalManager = class {
|
|
|
328
318
|
* @throws {ValidationError} When required parameters are missing or invalid
|
|
329
319
|
*
|
|
330
320
|
* @example
|
|
331
|
-
* Basic portal creation:
|
|
332
321
|
* ```typescript
|
|
333
322
|
* const portal = await portalManager.create({
|
|
334
323
|
* return_url: 'https://myapp.com/account/billing'
|
|
335
324
|
* });
|
|
336
325
|
*
|
|
337
326
|
* // Redirect user to portal
|
|
338
|
-
*
|
|
339
|
-
* ```
|
|
340
|
-
*
|
|
341
|
-
* @example
|
|
342
|
-
* With error handling:
|
|
343
|
-
* ```typescript
|
|
344
|
-
* try {
|
|
345
|
-
* const portal = await portalManager.create({
|
|
346
|
-
* return_url: window.location.origin + '/billing'
|
|
347
|
-
* });
|
|
348
|
-
*
|
|
327
|
+
* if (portal.data?.url) {
|
|
349
328
|
* window.location.href = portal.data.url;
|
|
350
|
-
* } catch (error) {
|
|
351
|
-
* console.error('Failed to create portal session:', error);
|
|
352
|
-
* showErrorMessage('Unable to access billing portal. Please try again.');
|
|
353
329
|
* }
|
|
354
330
|
* ```
|
|
355
331
|
*
|
|
356
|
-
* @since
|
|
332
|
+
* @since 0.6.0
|
|
357
333
|
* @group Portal
|
|
358
334
|
*/
|
|
359
335
|
async create(options) {
|
|
@@ -383,7 +359,7 @@ var UsageManager = class {
|
|
|
383
359
|
/**
|
|
384
360
|
* Initialize the usage manager
|
|
385
361
|
*
|
|
386
|
-
* @param
|
|
362
|
+
* @param omnibaseClient - OmnibaseClient instance for API communication
|
|
387
363
|
*
|
|
388
364
|
* @group Usage
|
|
389
365
|
*/
|
|
@@ -412,7 +388,6 @@ var UsageManager = class {
|
|
|
412
388
|
* @throws {ValidationError} When required parameters are missing or invalid
|
|
413
389
|
*
|
|
414
390
|
* @example
|
|
415
|
-
* API call tracking:
|
|
416
391
|
* ```typescript
|
|
417
392
|
* // Record each API call
|
|
418
393
|
* await usageManager.recordUsage({
|
|
@@ -421,37 +396,7 @@ var UsageManager = class {
|
|
|
421
396
|
* });
|
|
422
397
|
* ```
|
|
423
398
|
*
|
|
424
|
-
* @
|
|
425
|
-
* Batch usage recording:
|
|
426
|
-
* ```typescript
|
|
427
|
-
* // Record multiple operations at once
|
|
428
|
-
* const usageEvents = [
|
|
429
|
-
* { meter_event_name: 'compute_hours', value: '0.5' },
|
|
430
|
-
* { meter_event_name: 'storage_gb', value: '10' },
|
|
431
|
-
* { meter_event_name: 'api_calls', value: '50' }
|
|
432
|
-
* ];
|
|
433
|
-
*
|
|
434
|
-
* for (const event of usageEvents) {
|
|
435
|
-
* await usageManager.recordUsage(event);
|
|
436
|
-
* }
|
|
437
|
-
* ```
|
|
438
|
-
*
|
|
439
|
-
* @example
|
|
440
|
-
* With error handling:
|
|
441
|
-
* ```typescript
|
|
442
|
-
* try {
|
|
443
|
-
* await usageManager.recordUsage({
|
|
444
|
-
* meter_event_name: 'file_uploads',
|
|
445
|
-
* value: String(uploadedFiles.length)
|
|
446
|
-
* });
|
|
447
|
-
* } catch (error) {
|
|
448
|
-
* console.error('Failed to record usage:', error);
|
|
449
|
-
* // Usage recording failure shouldn't block user operations
|
|
450
|
-
* // but should be logged for billing accuracy
|
|
451
|
-
* }
|
|
452
|
-
* ```
|
|
453
|
-
*
|
|
454
|
-
* @since 1.0.0
|
|
399
|
+
* @since 0.6.0
|
|
455
400
|
* @group Usage
|
|
456
401
|
*/
|
|
457
402
|
async recordUsage(options) {
|
|
@@ -476,20 +421,20 @@ var UsageManager = class {
|
|
|
476
421
|
// src/payments/handler.ts
|
|
477
422
|
var PaymentHandler = class {
|
|
478
423
|
/**
|
|
479
|
-
* Initialize the payment handler with
|
|
424
|
+
* Initialize the payment handler with OmnibaseClient
|
|
480
425
|
*
|
|
481
|
-
* Creates a new payment handler instance
|
|
482
|
-
*
|
|
483
|
-
*
|
|
426
|
+
* Creates a new payment handler instance with access to all payment
|
|
427
|
+
* operations including checkout, configuration, portal, and usage tracking.
|
|
428
|
+
* The handler uses the provided OmnibaseClient for API communication.
|
|
484
429
|
*
|
|
485
|
-
* @param
|
|
430
|
+
* @param omnibaseClient - OmnibaseClient instance for API communication
|
|
486
431
|
*
|
|
487
432
|
* @example
|
|
488
433
|
* ```typescript
|
|
489
|
-
* const paymentHandler = new PaymentHandler(
|
|
434
|
+
* const paymentHandler = new PaymentHandler(omnibaseClient);
|
|
490
435
|
* ```
|
|
491
436
|
*
|
|
492
|
-
* @since
|
|
437
|
+
* @since 0.6.0
|
|
493
438
|
* @group Client
|
|
494
439
|
*/
|
|
495
440
|
constructor(omnibaseClient) {
|
|
@@ -508,10 +453,14 @@ var PaymentHandler = class {
|
|
|
508
453
|
* @example
|
|
509
454
|
* ```typescript
|
|
510
455
|
* const session = await paymentHandler.checkout.createSession({
|
|
511
|
-
* price_id: '
|
|
456
|
+
* price_id: 'price_monthly_pro',
|
|
512
457
|
* success_url: window.location.origin + '/success',
|
|
513
458
|
* cancel_url: window.location.origin + '/pricing'
|
|
514
459
|
* });
|
|
460
|
+
*
|
|
461
|
+
* if (session.data?.url) {
|
|
462
|
+
* window.location.href = session.data.url;
|
|
463
|
+
* }
|
|
515
464
|
* ```
|
|
516
465
|
*/
|
|
517
466
|
checkout;
|
|
@@ -662,6 +611,132 @@ var PermissionsClient = class {
|
|
|
662
611
|
}
|
|
663
612
|
};
|
|
664
613
|
|
|
614
|
+
// src/storage/index.ts
|
|
615
|
+
var StorageClient = class {
|
|
616
|
+
constructor(client) {
|
|
617
|
+
this.client = client;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Upload a file to storage
|
|
621
|
+
*
|
|
622
|
+
* @param path - Full path for the file (e.g., "public/images/avatar.png", "users/123/private/doc.pdf")
|
|
623
|
+
* @param file - File or Blob to upload
|
|
624
|
+
* @param options - Upload options including custom metadata
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* ```typescript
|
|
628
|
+
* const result = await storage.upload(
|
|
629
|
+
* 'public/avatars/user-123.png',
|
|
630
|
+
* file,
|
|
631
|
+
* {
|
|
632
|
+
* metadata: {
|
|
633
|
+
* userId: '123',
|
|
634
|
+
* uploadedBy: 'john@example.com',
|
|
635
|
+
* tags: ['profile', 'avatar']
|
|
636
|
+
* }
|
|
637
|
+
* }
|
|
638
|
+
* );
|
|
639
|
+
*
|
|
640
|
+
* // File is automatically uploaded to S3 via the presigned URL
|
|
641
|
+
* console.log('File uploaded to:', result.path);
|
|
642
|
+
* ```
|
|
643
|
+
*/
|
|
644
|
+
async upload(path, file, options) {
|
|
645
|
+
const metadata = {
|
|
646
|
+
// File metadata
|
|
647
|
+
filename: file instanceof File ? file.name : "blob",
|
|
648
|
+
size: file.size,
|
|
649
|
+
mime_type: file.type,
|
|
650
|
+
uploaded_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
651
|
+
// Merge custom metadata
|
|
652
|
+
...options?.metadata || {}
|
|
653
|
+
};
|
|
654
|
+
const response = await this.client.fetch("/api/v1/storage/upload", {
|
|
655
|
+
method: "POST",
|
|
656
|
+
headers: {
|
|
657
|
+
"Content-Type": "application/json"
|
|
658
|
+
},
|
|
659
|
+
body: JSON.stringify({
|
|
660
|
+
path,
|
|
661
|
+
metadata
|
|
662
|
+
})
|
|
663
|
+
});
|
|
664
|
+
if (!response.ok) {
|
|
665
|
+
const error = await response.json().catch(() => ({ error: "Upload failed" }));
|
|
666
|
+
throw new Error(error.error || "Failed to get upload URL");
|
|
667
|
+
}
|
|
668
|
+
const responseData = await response.json();
|
|
669
|
+
const result = responseData.data;
|
|
670
|
+
const uploadResponse = await fetch(result.upload_url, {
|
|
671
|
+
method: "PUT",
|
|
672
|
+
body: file,
|
|
673
|
+
headers: {
|
|
674
|
+
"Content-Type": file.type
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
if (!uploadResponse.ok) {
|
|
678
|
+
throw new Error("Failed to upload file to storage");
|
|
679
|
+
}
|
|
680
|
+
return result;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Download a file from storage
|
|
684
|
+
*
|
|
685
|
+
* @param path - Full path to the file
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* ```typescript
|
|
689
|
+
* const { download_url } = await storage.download('public/images/logo.png');
|
|
690
|
+
*
|
|
691
|
+
* // Download the file
|
|
692
|
+
* const response = await fetch(download_url);
|
|
693
|
+
* const blob = await response.blob();
|
|
694
|
+
* ```
|
|
695
|
+
*/
|
|
696
|
+
async download(path) {
|
|
697
|
+
const response = await this.client.fetch("/api/v1/storage/download", {
|
|
698
|
+
method: "POST",
|
|
699
|
+
headers: {
|
|
700
|
+
"Content-Type": "application/json"
|
|
701
|
+
},
|
|
702
|
+
body: JSON.stringify({
|
|
703
|
+
path
|
|
704
|
+
})
|
|
705
|
+
});
|
|
706
|
+
if (!response.ok) {
|
|
707
|
+
const error = await response.json().catch(() => ({ error: "Download failed" }));
|
|
708
|
+
throw new Error(error.error || "Failed to get download URL");
|
|
709
|
+
}
|
|
710
|
+
const responseData = await response.json();
|
|
711
|
+
return responseData.data;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Delete a file from storage
|
|
715
|
+
*
|
|
716
|
+
* @param path - Full path to the file
|
|
717
|
+
*
|
|
718
|
+
* @example
|
|
719
|
+
* ```typescript
|
|
720
|
+
* await storage.delete('users/123/documents/old-report.pdf');
|
|
721
|
+
* ```
|
|
722
|
+
*/
|
|
723
|
+
async delete(path) {
|
|
724
|
+
const response = await this.client.fetch("/api/v1/storage/object", {
|
|
725
|
+
method: "DELETE",
|
|
726
|
+
headers: {
|
|
727
|
+
"Content-Type": "application/json"
|
|
728
|
+
},
|
|
729
|
+
body: JSON.stringify({
|
|
730
|
+
path
|
|
731
|
+
})
|
|
732
|
+
});
|
|
733
|
+
if (!response.ok) {
|
|
734
|
+
const error = await response.json().catch(() => ({ error: "Delete failed" }));
|
|
735
|
+
throw new Error(error.error || "Failed to delete file");
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
|
|
665
740
|
// src/tenants/invites.ts
|
|
666
741
|
var TenantInviteManager = class {
|
|
667
742
|
/**
|
|
@@ -706,17 +781,6 @@ var TenantInviteManager = class {
|
|
|
706
781
|
* @throws {Error} When the server returns an error response (4xx, 5xx status codes)
|
|
707
782
|
*
|
|
708
783
|
* @example
|
|
709
|
-
* Basic invitation acceptance:
|
|
710
|
-
* ```typescript
|
|
711
|
-
* const result = await acceptTenantInvite('inv_secure_token_abc123');
|
|
712
|
-
*
|
|
713
|
-
* console.log(`Successfully joined tenant: ${result.data.tenant_id}`);
|
|
714
|
-
* // User can now access tenant resources
|
|
715
|
-
* await switchActiveTenant(result.data.tenant_id);
|
|
716
|
-
* ```
|
|
717
|
-
*
|
|
718
|
-
* @example
|
|
719
|
-
* Handling the invitation flow:
|
|
720
784
|
* ```typescript
|
|
721
785
|
* // Typically called from an invitation link like:
|
|
722
786
|
* // https://app.com/accept-invite?token=inv_secure_token_abc123
|
|
@@ -726,21 +790,20 @@ var TenantInviteManager = class {
|
|
|
726
790
|
*
|
|
727
791
|
* if (inviteToken) {
|
|
728
792
|
* try {
|
|
729
|
-
* const result = await
|
|
793
|
+
* const result = await inviteManager.accept(inviteToken);
|
|
730
794
|
*
|
|
731
795
|
* // Success - redirect to tenant dashboard
|
|
796
|
+
* console.log(`Successfully joined tenant: ${result.data.tenant_id}`);
|
|
732
797
|
* window.location.href = `/dashboard?tenant=${result.data.tenant_id}`;
|
|
733
798
|
* } catch (error) {
|
|
734
799
|
* console.error('Failed to accept invitation:', error.message);
|
|
735
|
-
* // Show error to user
|
|
736
800
|
* }
|
|
737
801
|
* }
|
|
738
802
|
* ```
|
|
739
803
|
*
|
|
740
|
-
*
|
|
741
|
-
* @since 1.0.0
|
|
804
|
+
* @since 0.6.0
|
|
742
805
|
* @public
|
|
743
|
-
* @group
|
|
806
|
+
* @group Tenant Invitations
|
|
744
807
|
*/
|
|
745
808
|
async accept(token) {
|
|
746
809
|
if (!token) {
|
|
@@ -775,73 +838,58 @@ var TenantInviteManager = class {
|
|
|
775
838
|
}
|
|
776
839
|
}
|
|
777
840
|
/**
|
|
778
|
-
* Creates a new user invitation for
|
|
841
|
+
* Creates a new user invitation for the active tenant
|
|
779
842
|
*
|
|
780
|
-
* Generates a secure invitation that allows a user to join the
|
|
781
|
-
* tenant with the defined role. The invitation is sent to the provided
|
|
782
|
-
*
|
|
843
|
+
* Generates a secure invitation that allows a user to join the currently active
|
|
844
|
+
* tenant with the defined role. The invitation is sent to the provided email address
|
|
845
|
+
* and includes a time-limited token for security. The invite URL will be automatically
|
|
846
|
+
* appended with ?token=XYZ when sent to the user.
|
|
783
847
|
*
|
|
784
|
-
* The function creates the invitation record in the database and
|
|
785
|
-
*
|
|
786
|
-
* The invitation expires after a predefined time period and can only
|
|
848
|
+
* The function creates the invitation record in the database and triggers an email
|
|
849
|
+
* notification to the invited user. The invitation expires after 7 days and can only
|
|
787
850
|
* be used once.
|
|
788
851
|
*
|
|
789
|
-
* Only existing tenant members with appropriate permissions
|
|
790
|
-
* invitations. The inviter's authentication
|
|
791
|
-
* cookies sent with the request.
|
|
852
|
+
* Only existing tenant members with appropriate permissions (invite_user permission)
|
|
853
|
+
* can create invitations. The inviter's authentication and tenant context are validated
|
|
854
|
+
* via HTTP-only cookies sent with the request.
|
|
792
855
|
*
|
|
793
|
-
* @param tenantId - Unique identifier of the tenant to invite the user to
|
|
794
856
|
* @param inviteData - Configuration object for the invitation
|
|
795
857
|
* @param inviteData.email - Email address of the user to invite
|
|
796
858
|
* @param inviteData.role - Role the user will have after joining (e.g., 'member', 'admin')
|
|
859
|
+
* @param inviteData.invite_url - Base URL for the invitation link (will be appended with ?token=XYZ)
|
|
797
860
|
*
|
|
798
861
|
* @returns Promise resolving to the created invitation with secure token
|
|
799
862
|
*
|
|
800
|
-
* @throws {Error} When
|
|
801
|
-
* @throws {Error} When
|
|
863
|
+
* @throws {Error} When required fields (email, role, invite_url) are missing or empty
|
|
864
|
+
* @throws {Error} When the user doesn't have permission to invite users to the tenant
|
|
802
865
|
* @throws {Error} When the API request fails due to network issues
|
|
803
866
|
* @throws {Error} When the server returns an error response (4xx, 5xx status codes)
|
|
804
867
|
*
|
|
805
868
|
* @example
|
|
806
|
-
* Basic invitation creation:
|
|
807
869
|
* ```typescript
|
|
808
|
-
* const invite = await
|
|
870
|
+
* const invite = await inviteManager.create({
|
|
809
871
|
* email: 'colleague@company.com',
|
|
810
|
-
* role: 'member'
|
|
872
|
+
* role: 'member',
|
|
873
|
+
* invite_url: 'https://yourapp.com/accept-invite'
|
|
811
874
|
* });
|
|
812
875
|
*
|
|
813
876
|
* console.log(`Invite sent to: ${invite.data.invite.email}`);
|
|
814
|
-
*
|
|
815
|
-
* const inviteLink = `https://app.com/accept-invite?token=${invite.data.invite.token}`;
|
|
816
|
-
* ```
|
|
817
|
-
*
|
|
818
|
-
* @example
|
|
819
|
-
* Creating admin invitation:
|
|
820
|
-
* ```typescript
|
|
821
|
-
* const adminInvite = await createTenantUserInvite('tenant_456', {
|
|
822
|
-
* email: 'admin@company.com',
|
|
823
|
-
* role: 'admin'
|
|
824
|
-
* });
|
|
825
|
-
*
|
|
826
|
-
* // Admin users get elevated permissions
|
|
827
|
-
* console.log(`Admin invite created with ID: ${adminInvite.data.invite.id}`);
|
|
877
|
+
* console.log(`Invite token: ${invite.data.invite.token}`);
|
|
828
878
|
* ```
|
|
829
879
|
*
|
|
830
|
-
*
|
|
831
|
-
* @since 1.0.0
|
|
880
|
+
* @since 0.6.0
|
|
832
881
|
* @public
|
|
833
|
-
* @group
|
|
882
|
+
* @group Tenant Invitations
|
|
834
883
|
*/
|
|
835
|
-
async create(
|
|
836
|
-
if (!
|
|
837
|
-
throw new Error(
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
throw new Error("Email and role are required");
|
|
884
|
+
async create(inviteData) {
|
|
885
|
+
if (!inviteData.email || !inviteData.role || !inviteData.invite_url) {
|
|
886
|
+
throw new Error(
|
|
887
|
+
"Missing data in `create` - email, role, and invite_url are required"
|
|
888
|
+
);
|
|
841
889
|
}
|
|
842
890
|
try {
|
|
843
891
|
const response = await this.omnibaseClient.fetch(
|
|
844
|
-
`/api/v1/tenants
|
|
892
|
+
`/api/v1/tenants/invites`,
|
|
845
893
|
{
|
|
846
894
|
method: "POST",
|
|
847
895
|
headers: {
|
|
@@ -905,21 +953,17 @@ var TenantManger = class {
|
|
|
905
953
|
* @throws {Error} When the server returns an error response (4xx, 5xx status codes)
|
|
906
954
|
*
|
|
907
955
|
* @example
|
|
908
|
-
* Basic tenant creation:
|
|
909
956
|
* ```typescript
|
|
910
|
-
* const newTenant = await createTenant({
|
|
957
|
+
* const newTenant = await tenantManager.createTenant({
|
|
911
958
|
* name: 'Acme Corporation',
|
|
912
959
|
* billing_email: 'billing@acme.com',
|
|
913
960
|
* user_id: 'user_123'
|
|
914
961
|
* });
|
|
915
962
|
*
|
|
916
|
-
* console.log(`
|
|
917
|
-
* // Store the token for authenticated requests
|
|
918
|
-
* localStorage.setItem('tenant_token', newTenant.data.token);
|
|
963
|
+
* console.log(`Tenant created: ${newTenant.data.tenant.id}`);
|
|
919
964
|
* ```
|
|
920
965
|
*
|
|
921
|
-
*
|
|
922
|
-
* @since 1.0.0
|
|
966
|
+
* @since 0.6.0
|
|
923
967
|
* @public
|
|
924
968
|
* @group Tenant Management
|
|
925
969
|
*/
|
|
@@ -984,7 +1028,6 @@ var TenantManger = class {
|
|
|
984
1028
|
* @throws {Error} When the server returns an error response (4xx, 5xx status codes)
|
|
985
1029
|
*
|
|
986
1030
|
* @example
|
|
987
|
-
* Basic tenant deletion with confirmation:
|
|
988
1031
|
* ```typescript
|
|
989
1032
|
* const tenantToDelete = 'tenant_abc123';
|
|
990
1033
|
*
|
|
@@ -995,8 +1038,8 @@ var TenantManger = class {
|
|
|
995
1038
|
*
|
|
996
1039
|
* if (userConfirmed) {
|
|
997
1040
|
* try {
|
|
998
|
-
* const result = await deleteTenant(tenantToDelete);
|
|
999
|
-
* console.log(result.data.message);
|
|
1041
|
+
* const result = await tenantManager.deleteTenant(tenantToDelete);
|
|
1042
|
+
* console.log(result.data.message);
|
|
1000
1043
|
*
|
|
1001
1044
|
* // Redirect user away from deleted tenant
|
|
1002
1045
|
* window.location.href = '/dashboard';
|
|
@@ -1006,7 +1049,7 @@ var TenantManger = class {
|
|
|
1006
1049
|
* }
|
|
1007
1050
|
* ```
|
|
1008
1051
|
*
|
|
1009
|
-
* @since
|
|
1052
|
+
* @since 0.6.0
|
|
1010
1053
|
* @public
|
|
1011
1054
|
* @group Tenant Management
|
|
1012
1055
|
*/
|
|
@@ -1069,46 +1112,17 @@ var TenantManger = class {
|
|
|
1069
1112
|
* @throws {Error} When the server returns an error response (4xx, 5xx status codes)
|
|
1070
1113
|
*
|
|
1071
1114
|
* @example
|
|
1072
|
-
* Basic tenant switching:
|
|
1073
1115
|
* ```typescript
|
|
1074
|
-
* const result = await switchActiveTenant('tenant_xyz789');
|
|
1116
|
+
* const result = await tenantManager.switchActiveTenant('tenant_xyz789');
|
|
1117
|
+
*
|
|
1118
|
+
* // Store the new token for future requests
|
|
1119
|
+
* console.log(`Switched to tenant. New token: ${result.data.token}`);
|
|
1075
1120
|
*
|
|
1076
1121
|
* // Now all API calls will be in the context of tenant_xyz789
|
|
1077
1122
|
* const tenantData = await getCurrentTenantData();
|
|
1078
1123
|
* ```
|
|
1079
1124
|
*
|
|
1080
|
-
* @
|
|
1081
|
-
* Using with tenant-aware data fetching:
|
|
1082
|
-
* ```typescript
|
|
1083
|
-
* // Switch tenant and immediately fetch tenant-specific data
|
|
1084
|
-
* const switchAndLoadTenant = async (tenantId: string) => {
|
|
1085
|
-
* try {
|
|
1086
|
-
* // Switch to new tenant context
|
|
1087
|
-
* const switchResult = await switchActiveTenant(tenantId);
|
|
1088
|
-
*
|
|
1089
|
-
* // Update authentication token
|
|
1090
|
-
* setAuthToken(switchResult.data.token);
|
|
1091
|
-
*
|
|
1092
|
-
* // Fetch data in new tenant context
|
|
1093
|
-
* const [tenantInfo, userPermissions, tenantSettings] = await Promise.all([
|
|
1094
|
-
* getTenantInfo(),
|
|
1095
|
-
* getUserPermissions(),
|
|
1096
|
-
* getTenantSettings()
|
|
1097
|
-
* ]);
|
|
1098
|
-
*
|
|
1099
|
-
* return {
|
|
1100
|
-
* tenant: tenantInfo,
|
|
1101
|
-
* permissions: userPermissions,
|
|
1102
|
-
* settings: tenantSettings
|
|
1103
|
-
* };
|
|
1104
|
-
* } catch (error) {
|
|
1105
|
-
* console.error('Failed to switch tenant and load data:', error);
|
|
1106
|
-
* throw error;
|
|
1107
|
-
* }
|
|
1108
|
-
* };
|
|
1109
|
-
* ```
|
|
1110
|
-
*
|
|
1111
|
-
* @since 1.0.0
|
|
1125
|
+
* @since 0.6.0
|
|
1112
1126
|
* @public
|
|
1113
1127
|
* @group Tenant Management
|
|
1114
1128
|
*/
|
|
@@ -1146,6 +1160,140 @@ var TenantManger = class {
|
|
|
1146
1160
|
}
|
|
1147
1161
|
};
|
|
1148
1162
|
|
|
1163
|
+
// src/tenants/user.ts
|
|
1164
|
+
var TenantUserManager = class {
|
|
1165
|
+
/**
|
|
1166
|
+
* Creates a new tenant user manager
|
|
1167
|
+
*
|
|
1168
|
+
* @param omnibaseClient - Configured OmnibaseClient instance for API communication
|
|
1169
|
+
*
|
|
1170
|
+
* @group Tenant User Management
|
|
1171
|
+
*/
|
|
1172
|
+
constructor(omnibaseClient) {
|
|
1173
|
+
this.omnibaseClient = omnibaseClient;
|
|
1174
|
+
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Removes a user from the active tenant
|
|
1177
|
+
*
|
|
1178
|
+
* This method removes a specified user from the current active tenant. The operation
|
|
1179
|
+
* requires the requesting user to have appropriate permissions (admin or owner role).
|
|
1180
|
+
* The user being removed will lose access to the tenant and all its resources.
|
|
1181
|
+
*
|
|
1182
|
+
* Note: You cannot remove yourself from a tenant using this method. To leave a tenant,
|
|
1183
|
+
* use the appropriate leave or delete tenant operations instead.
|
|
1184
|
+
*
|
|
1185
|
+
* @param data - Request data containing the user ID to remove
|
|
1186
|
+
* @param data.user_id - ID of the user to remove from the tenant
|
|
1187
|
+
*
|
|
1188
|
+
* @returns Promise resolving to an API response confirming the removal
|
|
1189
|
+
*
|
|
1190
|
+
* @throws {Error} When user_id is not provided
|
|
1191
|
+
* @throws {Error} When the API request fails (includes status code and error details)
|
|
1192
|
+
* @throws {Error} When the user doesn't have permission to remove users
|
|
1193
|
+
* @throws {Error} When the specified user is not a member of the tenant
|
|
1194
|
+
*
|
|
1195
|
+
* @example
|
|
1196
|
+
* ```typescript
|
|
1197
|
+
* // Remove a user from the active tenant
|
|
1198
|
+
* try {
|
|
1199
|
+
* await userManager.remove({ user_id: 'user_abc123' });
|
|
1200
|
+
* console.log('User removed successfully');
|
|
1201
|
+
* } catch (error) {
|
|
1202
|
+
* if (error.message.includes('403')) {
|
|
1203
|
+
* console.error('Insufficient permissions to remove user');
|
|
1204
|
+
* } else if (error.message.includes('404')) {
|
|
1205
|
+
* console.error('User not found in tenant');
|
|
1206
|
+
* } else {
|
|
1207
|
+
* console.error('Failed to remove user:', error);
|
|
1208
|
+
* }
|
|
1209
|
+
* }
|
|
1210
|
+
* ```
|
|
1211
|
+
*
|
|
1212
|
+
* @since 0.6.0
|
|
1213
|
+
* @public
|
|
1214
|
+
* @group Tenant User Management
|
|
1215
|
+
*/
|
|
1216
|
+
async remove(data) {
|
|
1217
|
+
if (!data.user_id) {
|
|
1218
|
+
throw new Error("user_id is required");
|
|
1219
|
+
}
|
|
1220
|
+
const response = await this.omnibaseClient.fetch("/api/v1/tenants/users", {
|
|
1221
|
+
method: "DELETE",
|
|
1222
|
+
body: JSON.stringify(data)
|
|
1223
|
+
});
|
|
1224
|
+
if (!response.ok) {
|
|
1225
|
+
const errorData = await response.text();
|
|
1226
|
+
throw new Error(
|
|
1227
|
+
`Failed to delete user from tenant: ${response.status} - ${errorData}`
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
return await response.json();
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Updates a user's role within the active tenant
|
|
1234
|
+
*
|
|
1235
|
+
* This method changes the role of a specified user in the current active tenant. The operation
|
|
1236
|
+
* requires the requesting user to have appropriate permissions (typically admin or owner role).
|
|
1237
|
+
* Role updates take effect immediately and affect the user's permissions and access rights
|
|
1238
|
+
* within the tenant.
|
|
1239
|
+
*
|
|
1240
|
+
* Common roles include 'admin', 'member', and 'viewer', but the exact roles available depend
|
|
1241
|
+
* on your tenant's configuration. Changing a user's role will modify their ability to perform
|
|
1242
|
+
* various operations within the tenant.
|
|
1243
|
+
*
|
|
1244
|
+
* @param data - Request data containing the user ID and new role
|
|
1245
|
+
* @param data.user_id - ID of the user whose role is being updated
|
|
1246
|
+
* @param data.role - New role to assign to the user
|
|
1247
|
+
*
|
|
1248
|
+
* @returns Promise resolving to an API response confirming the role update
|
|
1249
|
+
*
|
|
1250
|
+
* @throws {Error} When user_id or role is not provided
|
|
1251
|
+
* @throws {Error} When the API request fails (includes status code and error details)
|
|
1252
|
+
* @throws {Error} When the user doesn't have permission to update roles
|
|
1253
|
+
* @throws {Error} When the specified user is not a member of the tenant
|
|
1254
|
+
* @throws {Error} When the specified role is invalid or not allowed
|
|
1255
|
+
*
|
|
1256
|
+
* @example
|
|
1257
|
+
* ```typescript
|
|
1258
|
+
* // Update a user's role to admin
|
|
1259
|
+
* try {
|
|
1260
|
+
* const result = await userManager.updateRole({
|
|
1261
|
+
* user_id: 'user_abc123',
|
|
1262
|
+
* role: 'admin'
|
|
1263
|
+
* });
|
|
1264
|
+
* console.log('Role updated successfully:', result.data.message);
|
|
1265
|
+
* } catch (error) {
|
|
1266
|
+
* if (error.message.includes('403')) {
|
|
1267
|
+
* console.error('Insufficient permissions to update roles');
|
|
1268
|
+
* } else if (error.message.includes('404')) {
|
|
1269
|
+
* console.error('User not found in tenant');
|
|
1270
|
+
* } else {
|
|
1271
|
+
* console.error('Failed to update role:', error);
|
|
1272
|
+
* }
|
|
1273
|
+
* }
|
|
1274
|
+
* ```
|
|
1275
|
+
*
|
|
1276
|
+
* @since 0.6.0
|
|
1277
|
+
* @public
|
|
1278
|
+
* @group Tenant User Management
|
|
1279
|
+
*/
|
|
1280
|
+
async updateRole(data) {
|
|
1281
|
+
if (!data.role || !data.user_id)
|
|
1282
|
+
throw new Error("user_id and role is required");
|
|
1283
|
+
const response = await this.omnibaseClient.fetch("/api/v1/tenants/users", {
|
|
1284
|
+
method: "PUT",
|
|
1285
|
+
body: JSON.stringify(data)
|
|
1286
|
+
});
|
|
1287
|
+
if (!response.ok) {
|
|
1288
|
+
const errorData = await response.text();
|
|
1289
|
+
throw new Error(
|
|
1290
|
+
`Failed to update users role: ${response.status} - ${errorData}`
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
return await response.json();
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
|
|
1149
1297
|
// src/tenants/handler.ts
|
|
1150
1298
|
var TenantHandler = class {
|
|
1151
1299
|
/**
|
|
@@ -1169,10 +1317,27 @@ var TenantHandler = class {
|
|
|
1169
1317
|
* @group Tenant Management
|
|
1170
1318
|
*/
|
|
1171
1319
|
constructor(omnibaseClient) {
|
|
1172
|
-
this.
|
|
1173
|
-
this.
|
|
1174
|
-
this.
|
|
1320
|
+
this.invites = new TenantInviteManager(omnibaseClient);
|
|
1321
|
+
this.manage = new TenantManger(omnibaseClient);
|
|
1322
|
+
this.user = new TenantUserManager(omnibaseClient);
|
|
1175
1323
|
}
|
|
1324
|
+
/**
|
|
1325
|
+
* Tenant user management operations
|
|
1326
|
+
*
|
|
1327
|
+
* Provides access to operations for managing users within tenants, including
|
|
1328
|
+
* removing users from the active tenant. All operations respect user permissions
|
|
1329
|
+
* and tenant ownership rules.
|
|
1330
|
+
*
|
|
1331
|
+
* @example
|
|
1332
|
+
* ```typescript
|
|
1333
|
+
* // Remove a user from the active tenant
|
|
1334
|
+
* await tenantHandler.user.remove({ user_id: 'user_123' });
|
|
1335
|
+
* ```
|
|
1336
|
+
*
|
|
1337
|
+
* @since 0.6.0
|
|
1338
|
+
* @group Tenant Management
|
|
1339
|
+
*/
|
|
1340
|
+
user;
|
|
1176
1341
|
/**
|
|
1177
1342
|
* Core tenant management operations
|
|
1178
1343
|
*
|
|
@@ -1183,17 +1348,17 @@ var TenantHandler = class {
|
|
|
1183
1348
|
* @example
|
|
1184
1349
|
* ```typescript
|
|
1185
1350
|
* // Create a new tenant
|
|
1186
|
-
* const tenant = await tenantHandler.
|
|
1351
|
+
* const tenant = await tenantHandler.manage.createTenant({
|
|
1187
1352
|
* name: 'New Company',
|
|
1188
1353
|
* billing_email: 'billing@newcompany.com',
|
|
1189
1354
|
* user_id: 'user_456'
|
|
1190
1355
|
* });
|
|
1191
1356
|
*
|
|
1192
1357
|
* // Switch to the tenant
|
|
1193
|
-
* await tenantHandler.
|
|
1358
|
+
* await tenantHandler.manage.switchActiveTenant(tenant.data.tenant.id);
|
|
1194
1359
|
*
|
|
1195
1360
|
* // Delete the tenant (owner only)
|
|
1196
|
-
* await tenantHandler.
|
|
1361
|
+
* await tenantHandler.manage.deleteTenant(tenant.data.tenant.id);
|
|
1197
1362
|
* ```
|
|
1198
1363
|
*/
|
|
1199
1364
|
manage;
|
|
@@ -1207,9 +1372,10 @@ var TenantHandler = class {
|
|
|
1207
1372
|
* @example
|
|
1208
1373
|
* ```typescript
|
|
1209
1374
|
* // Create an invitation
|
|
1210
|
-
* const invite = await tenantHandler.invites.create(
|
|
1375
|
+
* const invite = await tenantHandler.invites.create({
|
|
1211
1376
|
* email: 'newuser@company.com',
|
|
1212
|
-
* role: 'admin'
|
|
1377
|
+
* role: 'admin',
|
|
1378
|
+
* invite_url: 'https://yourapp.com/accept-invite'
|
|
1213
1379
|
* });
|
|
1214
1380
|
*
|
|
1215
1381
|
* // Accept an invitation (from the invited user's session)
|
|
@@ -1250,8 +1416,105 @@ var OmnibaseClient = class {
|
|
|
1250
1416
|
* ```
|
|
1251
1417
|
*/
|
|
1252
1418
|
payments = new PaymentHandler(this);
|
|
1419
|
+
/**
|
|
1420
|
+
* Main tenant management handler
|
|
1421
|
+
*
|
|
1422
|
+
* This is the primary entry point for all tenant-related operations in the
|
|
1423
|
+
* Omnibase SDK. It provides a unified interface to tenant management,
|
|
1424
|
+
* user management, and invitation functionality through dedicated manager instances.
|
|
1425
|
+
*
|
|
1426
|
+
* The handler follows the composition pattern, combining specialized managers
|
|
1427
|
+
* for different aspects of tenant functionality:
|
|
1428
|
+
* - `manage`: Core tenant operations (create, delete, switch)
|
|
1429
|
+
* - `invites`: User invitation management (create, accept)
|
|
1430
|
+
* - `user`: Tenant user operations (remove, update role)
|
|
1431
|
+
*
|
|
1432
|
+
* All operations are performed within the context of the authenticated user
|
|
1433
|
+
* and respect tenant-level permissions and row-level security policies.
|
|
1434
|
+
*
|
|
1435
|
+
* @example
|
|
1436
|
+
* ```typescript
|
|
1437
|
+
* // Create a new tenant
|
|
1438
|
+
* const tenant = await omnibase.tenants.manage.createTenant({
|
|
1439
|
+
* name: 'My Company',
|
|
1440
|
+
* billing_email: 'billing@company.com',
|
|
1441
|
+
* user_id: 'user_123'
|
|
1442
|
+
* });
|
|
1443
|
+
*
|
|
1444
|
+
* // Invite users to the tenant
|
|
1445
|
+
* const invite = await omnibase.tenants.invites.create({
|
|
1446
|
+
* email: 'colleague@company.com',
|
|
1447
|
+
* role: 'member',
|
|
1448
|
+
* invite_url: 'https://yourapp.com/accept-invite'
|
|
1449
|
+
* });
|
|
1450
|
+
*
|
|
1451
|
+
* // Switch to the new tenant
|
|
1452
|
+
* await omnibase.tenants.manage.switchActiveTenant(tenant.data.tenant.id);
|
|
1453
|
+
* ```
|
|
1454
|
+
*
|
|
1455
|
+
* @since 0.6.0
|
|
1456
|
+
* @public
|
|
1457
|
+
* @group Tenant Management
|
|
1458
|
+
*/
|
|
1253
1459
|
tenants = new TenantHandler(this);
|
|
1460
|
+
/**
|
|
1461
|
+
* Client for managing permissions and relationships using Ory Keto
|
|
1462
|
+
*
|
|
1463
|
+
* This client provides access to Ory Keto's permission system, allowing you to
|
|
1464
|
+
* create, manage, and check relationships between subjects and objects. It handles
|
|
1465
|
+
* both read operations (permission checks) and write operations (relationship management).
|
|
1466
|
+
*
|
|
1467
|
+
* The client automatically configures separate endpoints for read and write operations
|
|
1468
|
+
* to optimize performance and security by following Ory Keto's recommended architecture.
|
|
1469
|
+
*
|
|
1470
|
+
* @example
|
|
1471
|
+
* ```typescript
|
|
1472
|
+
* // Check if a user can view a tenant
|
|
1473
|
+
* const canView = await omnibase.permissions.permissions.checkPermission(
|
|
1474
|
+
* undefined,
|
|
1475
|
+
* {
|
|
1476
|
+
* namespace: 'Tenant',
|
|
1477
|
+
* object: 'tenant_123',
|
|
1478
|
+
* relation: 'view',
|
|
1479
|
+
* subjectId: 'user_456'
|
|
1480
|
+
* }
|
|
1481
|
+
* );
|
|
1482
|
+
*
|
|
1483
|
+
* if (canView.data.allowed) {
|
|
1484
|
+
* console.log('User can view the tenant');
|
|
1485
|
+
* }
|
|
1486
|
+
*
|
|
1487
|
+
* // Create a relationship making a user an owner of a tenant
|
|
1488
|
+
* await omnibase.permissions.relationships.createRelationship(
|
|
1489
|
+
* undefined,
|
|
1490
|
+
* {
|
|
1491
|
+
* namespace: 'Tenant',
|
|
1492
|
+
* object: 'tenant_123',
|
|
1493
|
+
* relation: 'owners',
|
|
1494
|
+
* subjectId: 'user_456'
|
|
1495
|
+
* }
|
|
1496
|
+
* );
|
|
1497
|
+
* ```
|
|
1498
|
+
*
|
|
1499
|
+
* @since 0.6.0
|
|
1500
|
+
* @public
|
|
1501
|
+
* @group Permissions
|
|
1502
|
+
*/
|
|
1254
1503
|
permissions;
|
|
1504
|
+
/**
|
|
1505
|
+
* Storage client for file upload/download operations
|
|
1506
|
+
*
|
|
1507
|
+
* @example
|
|
1508
|
+
* ```typescript
|
|
1509
|
+
* // Upload with metadata
|
|
1510
|
+
* await omnibase.storage.bucket('documents').upload(
|
|
1511
|
+
* 'report.pdf',
|
|
1512
|
+
* file,
|
|
1513
|
+
* { metadata: { department: 'engineering' } }
|
|
1514
|
+
* );
|
|
1515
|
+
* ```
|
|
1516
|
+
*/
|
|
1517
|
+
storage = new StorageClient(this);
|
|
1255
1518
|
async fetch(endpoint, options = {}) {
|
|
1256
1519
|
if (this.config.fetch)
|
|
1257
1520
|
return this.config.fetch(this.config.api_url + endpoint, options);
|
|
@@ -1263,5 +1526,6 @@ var OmnibaseClient = class {
|
|
|
1263
1526
|
};
|
|
1264
1527
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1265
1528
|
0 && (module.exports = {
|
|
1266
|
-
OmnibaseClient
|
|
1529
|
+
OmnibaseClient,
|
|
1530
|
+
StorageClient
|
|
1267
1531
|
});
|