@omnibase/core-js 0.7.5 → 0.8.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.
@@ -316,25 +316,56 @@ var PermissionsClient = class {
316
316
  * on an object. This API handles read operations and is optimized for fast
317
317
  * permission checks in your application logic.
318
318
  *
319
+ * All operations are proxied through Omnibase's API at `/api/v1/permissions/read`.
320
+ *
319
321
  * Key methods:
320
- * - `checkPermission()` - Checks if a subject has permission on an object
321
- * - `checkPermissionOrError()` - Same as above but throws error if denied
322
- * - `expandPermissions()` - Expands relationships to show all granted permissions
322
+ * - `checkPermission(params)` - Checks if a subject has permission on an object
323
+ * - `checkPermissionOrError(params)` - Same as above but throws error if denied
324
+ * - `expandPermissions(namespace, object, relation, maxDepth?)` - Expands relationships to show all granted permissions
325
+ * - `postCheckPermission(maxDepth?, body)` - POST variant of permission check
323
326
  *
324
327
  * @example
328
+ * Check a single permission:
325
329
  * ```typescript
326
- * // Check permission
327
- * const result = await client.permissions.checkPermission(
328
- * undefined,
329
- * {
330
+ * const result = await omnibase.permissions.permissions.checkPermission({
331
+ * namespace: 'Tenant',
332
+ * object: 'tenant_123',
333
+ * relation: 'view',
334
+ * subjectId: 'user_456'
335
+ * });
336
+ *
337
+ * if (result.data.allowed) {
338
+ * console.log('User has permission');
339
+ * }
340
+ * ```
341
+ *
342
+ * @example
343
+ * Expand permission tree:
344
+ * ```typescript
345
+ * const tree = await omnibase.permissions.permissions.expandPermissions(
346
+ * 'Tenant',
347
+ * 'tenant_123',
348
+ * 'view'
349
+ * );
350
+ *
351
+ * console.log('Permission tree:', tree.data);
352
+ * ```
353
+ *
354
+ * @example
355
+ * Check permission or throw error:
356
+ * ```typescript
357
+ * try {
358
+ * await omnibase.permissions.permissions.checkPermissionOrError({
330
359
  * namespace: 'Tenant',
331
360
  * object: 'tenant_123',
332
- * relation: 'view',
361
+ * relation: 'edit',
333
362
  * subjectId: 'user_456'
334
- * }
335
- * );
336
- *
337
- * console.log('Has permission:', result.data.allowed);
363
+ * });
364
+ * // Permission granted
365
+ * } catch (error) {
366
+ * // Permission denied
367
+ * console.error('Access denied');
368
+ * }
338
369
  * ```
339
370
  *
340
371
  * @since 1.0.0
@@ -348,20 +379,34 @@ var PermissionsClient = class {
348
379
  * and managing role assignments. Works alongside the Keto-based
349
380
  * permissions system to provide dynamic RBAC capabilities.
350
381
  *
382
+ * Roles are stored in the database and automatically synchronized with
383
+ * Ory Keto relationships, providing a higher-level abstraction over
384
+ * raw relationship tuples.
385
+ *
351
386
  * @example
387
+ * Create a custom role:
352
388
  * ```typescript
353
- * // Create a custom role
354
389
  * const role = await omnibase.permissions.roles.create({
355
390
  * role_name: 'billing_manager',
356
391
  * permissions: ['tenant#manage_billing', 'tenant#view_invoices']
357
392
  * });
393
+ * ```
358
394
  *
359
- * // Assign role to user
395
+ * @example
396
+ * Assign role to a user:
397
+ * ```typescript
360
398
  * await omnibase.permissions.roles.assign('user_123', {
361
399
  * role_id: role.id
362
400
  * });
363
401
  * ```
364
402
  *
403
+ * @example
404
+ * List all roles:
405
+ * ```typescript
406
+ * const roles = await omnibase.permissions.roles.list();
407
+ * console.log('Available roles:', roles);
408
+ * ```
409
+ *
365
410
  * @since 0.7.0
366
411
  * @group Roles
367
412
  */
@@ -370,19 +415,43 @@ var PermissionsClient = class {
370
415
  * Creates a new PermissionsClient instance
371
416
  *
372
417
  * Initializes the client with separate endpoints for read and write operations.
373
- * The client automatically appends the appropriate Keto API paths to the base URL
374
- * for optimal performance and security separation.
418
+ * The client automatically configures the Ory Keto client libraries to use
419
+ * Omnibase's permission proxy endpoints:
420
+ * - Write endpoint: `${apiBaseUrl}/api/v1/permissions/write`
421
+ * - Read endpoint: `${apiBaseUrl}/api/v1/permissions/read`
375
422
  *
376
- * @param apiBaseUrl - The base URL for your Omnibase API instance
377
- * @param client - The main OmnibaseClient instance (for roles handler)
423
+ * This separation follows Ory Keto's recommended architecture for optimal
424
+ * performance and security.
425
+ *
426
+ * @param apiBaseUrl - The base URL for your Omnibase API instance (e.g., 'https://api.example.com')
427
+ * @param client - The main OmnibaseClient instance (required for roles handler)
378
428
  *
379
429
  * @throws {Error} When the base URL is invalid or cannot be reached
380
430
  *
381
431
  * @example
432
+ * Direct instantiation (not recommended - use OmnibaseClient instead):
382
433
  * ```typescript
383
434
  * const client = new PermissionsClient('https://api.example.com', omnibaseClient);
384
435
  * ```
385
436
  *
437
+ * @example
438
+ * Recommended usage via OmnibaseClient:
439
+ * ```typescript
440
+ * import { OmnibaseClient } from '@omnibase/core-js';
441
+ *
442
+ * const omnibase = new OmnibaseClient({
443
+ * apiUrl: 'https://api.example.com'
444
+ * });
445
+ *
446
+ * // Use the permissions client
447
+ * await omnibase.permissions.permissions.checkPermission({
448
+ * namespace: 'Tenant',
449
+ * object: 'tenant_123',
450
+ * relation: 'view',
451
+ * subjectId: 'user_456'
452
+ * });
453
+ * ```
454
+ *
386
455
  * @since 1.0.0
387
456
  * @group Client
388
457
  */
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  PermissionsClient,
3
3
  RolesHandler
4
- } from "../chunk-V4FWENQQ.js";
4
+ } from "../chunk-5B37CXXH.js";
5
5
  export {
6
6
  PermissionsClient,
7
7
  RolesHandler
@@ -437,6 +437,157 @@ var TenantManger = class {
437
437
  }
438
438
  };
439
439
 
440
+ // src/tenants/subscriptions.ts
441
+ var TenantSubscriptionManager = class {
442
+ /**
443
+ * Creates a new TenantSubscriptionManager instance
444
+ *
445
+ * @param omnibaseClient - Configured Omnibase client instance
446
+ *
447
+ * @group Tenant Subscriptions
448
+ */
449
+ constructor(omnibaseClient) {
450
+ this.omnibaseClient = omnibaseClient;
451
+ }
452
+ /**
453
+ * Get all active subscriptions for the current tenant
454
+ *
455
+ * Retrieves all active Stripe subscriptions associated with the user's
456
+ * currently active tenant. Returns subscriptions with config-based price IDs
457
+ * instead of raw Stripe IDs, making it easier to match against your billing
458
+ * configuration.
459
+ *
460
+ * The endpoint automatically:
461
+ * - Fetches subscriptions from Stripe API
462
+ * - Maps Stripe price IDs to your config price IDs
463
+ * - Checks both current and historical price mappings
464
+ * - Flags legacy prices from old billing configurations
465
+ * - Filters to only active/trialing/past_due subscriptions
466
+ *
467
+ * Returns an empty array if:
468
+ * - Tenant has no Stripe customer ID configured
469
+ * - Tenant has no active subscriptions
470
+ * - User is not authenticated
471
+ *
472
+ * @returns Promise resolving to array of active subscriptions
473
+ *
474
+ * @throws {Error} When the user is not authenticated
475
+ * @throws {Error} When the API request fails due to network issues
476
+ * @throws {Error} When the server returns an error response (4xx, 5xx)
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * const response = await subscriptionManager.getActive();
481
+ *
482
+ * if (response.data.length === 0) {
483
+ * console.log('No active subscriptions');
484
+ * } else {
485
+ * response.data.forEach(sub => {
486
+ * console.log(`Plan: ${sub.config_price_id}`);
487
+ * console.log(`Status: ${sub.status}`);
488
+ * if (sub.is_legacy_price) {
489
+ * console.log('⚠️ Using legacy pricing');
490
+ * }
491
+ * });
492
+ * }
493
+ * ```
494
+ *
495
+ * @since 0.6.0
496
+ * @public
497
+ * @group Tenant Subscriptions
498
+ */
499
+ async getActive() {
500
+ try {
501
+ const response = await this.omnibaseClient.fetch(
502
+ `/api/v1/tenants/subscriptions`,
503
+ {
504
+ method: "GET",
505
+ credentials: "include"
506
+ }
507
+ );
508
+ if (!response.ok) {
509
+ const errorData = await response.text();
510
+ throw new Error(
511
+ `Failed to fetch subscriptions: ${response.status} - ${errorData}`
512
+ );
513
+ }
514
+ const data = await response.json();
515
+ return data;
516
+ } catch (error) {
517
+ console.error("Error fetching tenant subscriptions:", error);
518
+ throw error;
519
+ }
520
+ }
521
+ /**
522
+ * Check if the current tenant has billing information configured
523
+ *
524
+ * Verifies whether the tenant has valid payment methods attached to their
525
+ * Stripe customer account. This is useful for:
526
+ * - Showing billing setup prompts
527
+ * - Gating premium features behind payment method requirement
528
+ * - Displaying billing status indicators in UI
529
+ * - Determining if customer portal access should be shown
530
+ *
531
+ * The check verifies:
532
+ * - Default payment source (card, bank account, etc.)
533
+ * - Default payment method in invoice settings
534
+ * - Whether the payment method is valid and active
535
+ *
536
+ * Returns `false` if:
537
+ * - Tenant has no Stripe customer ID
538
+ * - No payment methods are configured
539
+ * - User is not authenticated
540
+ *
541
+ * @returns Promise resolving to billing status information
542
+ *
543
+ * @throws {Error} When the user is not authenticated
544
+ * @throws {Error} When the API request fails due to network issues
545
+ * @throws {Error} When the server returns an error response (4xx, 5xx)
546
+ *
547
+ * @example
548
+ * ```typescript
549
+ * const response = await subscriptionManager.getBillingStatus();
550
+ *
551
+ * if (!response.data.has_billing_info) {
552
+ * // Show billing setup prompt
553
+ * showBillingSetupModal();
554
+ * } else if (!response.data.is_active) {
555
+ * // Payment method exists but may be expired/invalid
556
+ * showPaymentMethodUpdatePrompt();
557
+ * } else {
558
+ * // All good - show customer portal link
559
+ * showManageBillingButton();
560
+ * }
561
+ * ```
562
+ *
563
+ * @since 0.6.0
564
+ * @public
565
+ * @group Tenant Subscriptions
566
+ */
567
+ async getBillingStatus() {
568
+ try {
569
+ const response = await this.omnibaseClient.fetch(
570
+ `/api/v1/tenants/billing-status`,
571
+ {
572
+ method: "GET",
573
+ credentials: "include"
574
+ }
575
+ );
576
+ if (!response.ok) {
577
+ const errorData = await response.text();
578
+ throw new Error(
579
+ `Failed to fetch billing status: ${response.status} - ${errorData}`
580
+ );
581
+ }
582
+ const data = await response.json();
583
+ return data;
584
+ } catch (error) {
585
+ console.error("Error fetching billing status:", error);
586
+ throw error;
587
+ }
588
+ }
589
+ };
590
+
440
591
  // src/tenants/user.ts
441
592
  var TenantUserManager = class {
442
593
  /**
@@ -648,6 +799,7 @@ var TenantHandler = class {
648
799
  constructor(omnibaseClient) {
649
800
  this.invites = new TenantInviteManager(omnibaseClient);
650
801
  this.manage = new TenantManger(omnibaseClient);
802
+ this.subscriptions = new TenantSubscriptionManager(omnibaseClient);
651
803
  this.user = new TenantUserManager(omnibaseClient);
652
804
  }
653
805
  /**
@@ -712,6 +864,30 @@ var TenantHandler = class {
712
864
  * ```
713
865
  */
714
866
  invites;
867
+ /**
868
+ * Tenant subscription and billing management
869
+ *
870
+ * Provides access to subscription data and billing status for the
871
+ * active tenant, including legacy price detection and payment method
872
+ * verification. All operations are automatically scoped to the user's
873
+ * currently active tenant.
874
+ *
875
+ * @example
876
+ * ```typescript
877
+ * // Get active subscriptions
878
+ * const subs = await tenantHandler.subscriptions.getActive();
879
+ *
880
+ * // Check billing status
881
+ * const status = await tenantHandler.subscriptions.getBillingStatus();
882
+ * if (!status.data.has_billing_info) {
883
+ * console.log('No payment method configured');
884
+ * }
885
+ * ```
886
+ *
887
+ * @since 0.6.0
888
+ * @group Tenant Management
889
+ */
890
+ subscriptions;
715
891
  };
716
892
  // Annotate the CommonJS export names for ESM import in node:
717
893
  0 && (module.exports = {
@@ -1,2 +1,2 @@
1
- export { d as AcceptTenantInviteRequest, e as AcceptTenantInviteResponse, n as CreateTenantRequest, l as CreateTenantResponse, h as CreateTenantUserInviteRequest, f as CreateTenantUserInviteResponse, k as DeleteTenantResponse, j as SwitchActiveTenantResponse, m as Tenant, T as TenantHandler, g as TenantInvite, i as TenantInviteManager, o as TenantManger } from '../payments/index.cjs';
1
+ export { d as AcceptTenantInviteRequest, e as AcceptTenantInviteResponse, B as BillingStatus, n as CreateTenantRequest, l as CreateTenantResponse, h as CreateTenantUserInviteRequest, f as CreateTenantUserInviteResponse, k as DeleteTenantResponse, G as GetActiveSubscriptionsResponse, q as GetBillingStatusResponse, j as SwitchActiveTenantResponse, m as Tenant, T as TenantHandler, g as TenantInvite, i as TenantInviteManager, o as TenantManger, p as TenantSubscription, r as TenantSubscriptionManager } from '../payments/index.cjs';
2
2
  import '@ory/client';
@@ -1,2 +1,2 @@
1
- export { d as AcceptTenantInviteRequest, e as AcceptTenantInviteResponse, n as CreateTenantRequest, l as CreateTenantResponse, h as CreateTenantUserInviteRequest, f as CreateTenantUserInviteResponse, k as DeleteTenantResponse, j as SwitchActiveTenantResponse, m as Tenant, T as TenantHandler, g as TenantInvite, i as TenantInviteManager, o as TenantManger } from '../payments/index.js';
1
+ export { d as AcceptTenantInviteRequest, e as AcceptTenantInviteResponse, B as BillingStatus, n as CreateTenantRequest, l as CreateTenantResponse, h as CreateTenantUserInviteRequest, f as CreateTenantUserInviteResponse, k as DeleteTenantResponse, G as GetActiveSubscriptionsResponse, q as GetBillingStatusResponse, j as SwitchActiveTenantResponse, m as Tenant, T as TenantHandler, g as TenantInvite, i as TenantInviteManager, o as TenantManger, p as TenantSubscription, r as TenantSubscriptionManager } from '../payments/index.js';
2
2
  import '@ory/client';
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TenantHandler
3
- } from "../chunk-V6HVRJCU.js";
3
+ } from "../chunk-TFAV5P6I.js";
4
4
  export {
5
5
  TenantHandler
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnibase/core-js",
3
- "version": "0.7.5",
3
+ "version": "0.8.0",
4
4
  "description": "OmniBase core Javascript SDK - framework agnostic",
5
5
  "files": [
6
6
  "dist/**/*"