@dotbots-boutique/auth-sdk 1.0.8 → 1.0.9

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 CHANGED
@@ -154,6 +154,42 @@ This is the **only** method that routes via `proxyUrl`. All auth calls and the p
154
154
 
155
155
  ---
156
156
 
157
+ ## Payments
158
+
159
+ Use `auth.charge()` to charge a feature usage to the organisation or app budget. The app never handles token amounts, balances or budgets directly — the platform manages all of that.
160
+
161
+ ```typescript
162
+ const { transactionId } = await auth.charge('ai.generate', 'org');
163
+ ```
164
+
165
+ With a custom quantity:
166
+
167
+ ```typescript
168
+ const { transactionId } = await auth.charge('ai.generate', 'org', 5);
169
+ ```
170
+
171
+ ### Error handling
172
+
173
+ ```typescript
174
+ import { DotBotsAuthError } from '@dotbots-boutique/auth-sdk';
175
+
176
+ try {
177
+ const { transactionId } = await auth.charge('ai.generate', 'org', 1);
178
+ } catch (error) {
179
+ if (error instanceof DotBotsAuthError && error.code === 'PAYMENT_FAILED') {
180
+ if (error.message === 'INSUFFICIENT_BALANCE') {
181
+ // show top-up prompt
182
+ } else if (error.message === 'BUDGET_EXCEEDED') {
183
+ // show budget limit message
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ Possible `PAYMENT_FAILED` messages: `INSUFFICIENT_BALANCE`, `BUDGET_EXCEEDED`, `FEATURE_NOT_FOUND`, `PAYMENT_REJECTED`.
190
+
191
+ ---
192
+
157
193
  ## Checking permissions
158
194
 
159
195
  ```typescript
@@ -223,6 +259,7 @@ try {
223
259
  | `NETWORK_ERROR` | API unreachable | Yes |
224
260
  | `NOT_INITIALIZED` | `initialize()` has not been called yet | Yes |
225
261
  | `PROXY_UNAVAILABLE` | Proxy config could not be fetched | No — falls back to direct API |
262
+ | `PAYMENT_FAILED` | Payment was rejected (402) — see `message` for reason | No |
226
263
 
227
264
  ---
228
265
 
@@ -301,6 +338,10 @@ Check if the user has a specific role.
301
338
 
302
339
  Authenticated fetch wrapper. Routes through the proxy when available, falls back to `apiUrl` when not. Retries once on 401 after refreshing the token.
303
340
 
341
+ #### `charge(featureCode: string, paidBy: 'org' | 'app', quantity?: number): Promise<{ transactionId: string }>`
342
+
343
+ Charges a feature usage. Calls `POST {proxyUrl}/payments/charge`. Throws `PAYMENT_FAILED` on 402 with a message indicating the reason (`INSUFFICIENT_BALANCE`, `BUDGET_EXCEEDED`, `FEATURE_NOT_FOUND`, `PAYMENT_REJECTED`).
344
+
304
345
  #### `logout(): Promise<void>`
305
346
 
306
347
  Logs out the user. Revokes tokens on `apiUrl`, clears state, and redirects (standalone) or notifies the parent (iframe).
@@ -325,6 +366,7 @@ const {
325
366
  canAny, // (permissions: string[]) => boolean
326
367
  hasRole, // (role: string) => boolean
327
368
  fetch, // auth.fetch proxied
369
+ charge, // auth.charge proxied
328
370
  logout, // auth.logout proxied
329
371
  } = useDotBotsAuth();
330
372
  ```
package/dist/cjs/index.js CHANGED
@@ -325,6 +325,23 @@ class DotBotsAuth {
325
325
  }
326
326
  return response;
327
327
  }
328
+ async charge(featureCode, paidBy, quantity) {
329
+ this.assertInitialized();
330
+ const baseUrl = this.proxyConfigManager.getBaseUrl();
331
+ const response = await this.buildRequest(`${baseUrl}/payments/charge`, {
332
+ method: 'POST',
333
+ headers: { 'Content-Type': 'application/json' },
334
+ body: JSON.stringify({ featureCode, paidBy, quantity: quantity ?? 1 }),
335
+ });
336
+ if (response.status === 402) {
337
+ const body = await response.json();
338
+ throw new DotBotsAuthError('PAYMENT_FAILED', body.error, body.reason);
339
+ }
340
+ if (!response.ok) {
341
+ throw new DotBotsAuthError('NETWORK_ERROR', 'Payment request failed');
342
+ }
343
+ return response.json();
344
+ }
328
345
  async logout() {
329
346
  this.assertInitialized();
330
347
  await this.tokenManager.revoke();
@@ -415,7 +432,7 @@ class DotBotsAuth {
415
432
  }
416
433
  }
417
434
  }
418
- DotBotsAuth.SDK_VERSION = '1.0.8';
435
+ DotBotsAuth.SDK_VERSION = '1.0.9';
419
436
 
420
437
  exports.DotBotsAuth = DotBotsAuth;
421
438
  exports.DotBotsAuthError = DotBotsAuthError;
@@ -49,6 +49,7 @@ function DotBotsAuthProvider({ auth, children, loadingComponent, errorComponent,
49
49
  canAny: (permissions) => auth.canAny(permissions),
50
50
  hasRole: (role) => auth.hasRole(role),
51
51
  fetch: (url, options) => auth.fetch(url, options),
52
+ charge: (featureCode, paidBy, quantity) => auth.charge(featureCode, paidBy, quantity),
52
53
  logout: () => auth.logout(),
53
54
  };
54
55
  return (jsxRuntime.jsx(DotBotsAuthContext.Provider, { value: value, children: children }));
package/dist/esm/index.js CHANGED
@@ -323,6 +323,23 @@ class DotBotsAuth {
323
323
  }
324
324
  return response;
325
325
  }
326
+ async charge(featureCode, paidBy, quantity) {
327
+ this.assertInitialized();
328
+ const baseUrl = this.proxyConfigManager.getBaseUrl();
329
+ const response = await this.buildRequest(`${baseUrl}/payments/charge`, {
330
+ method: 'POST',
331
+ headers: { 'Content-Type': 'application/json' },
332
+ body: JSON.stringify({ featureCode, paidBy, quantity: quantity ?? 1 }),
333
+ });
334
+ if (response.status === 402) {
335
+ const body = await response.json();
336
+ throw new DotBotsAuthError('PAYMENT_FAILED', body.error, body.reason);
337
+ }
338
+ if (!response.ok) {
339
+ throw new DotBotsAuthError('NETWORK_ERROR', 'Payment request failed');
340
+ }
341
+ return response.json();
342
+ }
326
343
  async logout() {
327
344
  this.assertInitialized();
328
345
  await this.tokenManager.revoke();
@@ -413,6 +430,6 @@ class DotBotsAuth {
413
430
  }
414
431
  }
415
432
  }
416
- DotBotsAuth.SDK_VERSION = '1.0.8';
433
+ DotBotsAuth.SDK_VERSION = '1.0.9';
417
434
 
418
435
  export { DotBotsAuth, DotBotsAuthError };
@@ -47,6 +47,7 @@ function DotBotsAuthProvider({ auth, children, loadingComponent, errorComponent,
47
47
  canAny: (permissions) => auth.canAny(permissions),
48
48
  hasRole: (role) => auth.hasRole(role),
49
49
  fetch: (url, options) => auth.fetch(url, options),
50
+ charge: (featureCode, paidBy, quantity) => auth.charge(featureCode, paidBy, quantity),
50
51
  logout: () => auth.logout(),
51
52
  };
52
53
  return (jsx(DotBotsAuthContext.Provider, { value: value, children: children }));
@@ -8,7 +8,7 @@ export declare class DotBotsAuth {
8
8
  private readonly listeners;
9
9
  private cachedUser;
10
10
  private initialized;
11
- static readonly SDK_VERSION = "1.0.8";
11
+ static readonly SDK_VERSION = "1.0.9";
12
12
  constructor(config: DotBotsConfig);
13
13
  initialize(): Promise<void>;
14
14
  getUser(): Promise<DotBotsUser>;
@@ -17,6 +17,9 @@ export declare class DotBotsAuth {
17
17
  canAny(permissions: string[]): boolean;
18
18
  hasRole(role: string): boolean;
19
19
  fetch(url: string, options?: RequestInit): Promise<Response>;
20
+ charge(featureCode: string, paidBy: 'org' | 'app', quantity?: number): Promise<{
21
+ transactionId: string;
22
+ }>;
20
23
  logout(): Promise<void>;
21
24
  on(event: DotBotsAuthEvent, handler: Function): void;
22
25
  off(event: DotBotsAuthEvent, handler: Function): void;
@@ -323,6 +323,23 @@ class DotBotsAuth {
323
323
  }
324
324
  return response;
325
325
  }
326
+ async charge(featureCode, paidBy, quantity) {
327
+ this.assertInitialized();
328
+ const baseUrl = this.proxyConfigManager.getBaseUrl();
329
+ const response = await this.buildRequest(`${baseUrl}/payments/charge`, {
330
+ method: 'POST',
331
+ headers: { 'Content-Type': 'application/json' },
332
+ body: JSON.stringify({ featureCode, paidBy, quantity: quantity ?? 1 }),
333
+ });
334
+ if (response.status === 402) {
335
+ const body = await response.json();
336
+ throw new DotBotsAuthError('PAYMENT_FAILED', body.error, body.reason);
337
+ }
338
+ if (!response.ok) {
339
+ throw new DotBotsAuthError('NETWORK_ERROR', 'Payment request failed');
340
+ }
341
+ return response.json();
342
+ }
326
343
  async logout() {
327
344
  this.assertInitialized();
328
345
  await this.tokenManager.revoke();
@@ -413,6 +430,6 @@ class DotBotsAuth {
413
430
  }
414
431
  }
415
432
  }
416
- DotBotsAuth.SDK_VERSION = '1.0.8';
433
+ DotBotsAuth.SDK_VERSION = '1.0.9';
417
434
 
418
435
  export { DotBotsAuth, DotBotsAuthError };
@@ -11,6 +11,9 @@ export interface DotBotsAuthContextValue {
11
11
  canAny: (permissions: string[]) => boolean;
12
12
  hasRole: (role: string) => boolean;
13
13
  fetch: (url: string, options?: RequestInit) => Promise<Response>;
14
+ charge: (featureCode: string, paidBy: 'org' | 'app', quantity?: number) => Promise<{
15
+ transactionId: string;
16
+ }>;
14
17
  logout: () => Promise<void>;
15
18
  }
16
19
  export declare const DotBotsAuthContext: import("react").Context<DotBotsAuthContextValue | null>;
@@ -47,6 +47,7 @@ function DotBotsAuthProvider({ auth, children, loadingComponent, errorComponent,
47
47
  canAny: (permissions) => auth.canAny(permissions),
48
48
  hasRole: (role) => auth.hasRole(role),
49
49
  fetch: (url, options) => auth.fetch(url, options),
50
+ charge: (featureCode, paidBy, quantity) => auth.charge(featureCode, paidBy, quantity),
50
51
  logout: () => auth.logout(),
51
52
  };
52
53
  return (jsx(DotBotsAuthContext.Provider, { value: value, children: children }));
@@ -41,7 +41,7 @@ export interface DotBotsProxyConfig {
41
41
  }
42
42
  export type ProxyFeature = 'cache' | 'localdb' | 'webhooks' | 'ratelimit';
43
43
  export type DotBotsAuthEvent = 'tokenRefreshed' | 'loggedOut' | 'sessionExpired' | 'userLoaded';
44
- export type DotBotsAuthErrorCode = 'IFRAME_TIMEOUT' | 'CODE_EXPIRED' | 'UNAUTHORIZED' | 'REFRESH_FAILED' | 'NETWORK_ERROR' | 'NOT_INITIALIZED' | 'PROXY_UNAVAILABLE';
44
+ export type DotBotsAuthErrorCode = 'IFRAME_TIMEOUT' | 'CODE_EXPIRED' | 'UNAUTHORIZED' | 'REFRESH_FAILED' | 'NETWORK_ERROR' | 'NOT_INITIALIZED' | 'PROXY_UNAVAILABLE' | 'PAYMENT_FAILED';
45
45
  export interface TokenPair {
46
46
  accessToken: string;
47
47
  refreshToken: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotbots-boutique/auth-sdk",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Authentication SDK for DotBots marketplace apps",
5
5
  "license": "MIT",
6
6
  "type": "module",