@dotbots-boutique/auth-sdk 1.0.7 → 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 +42 -0
- package/dist/cjs/index.js +26 -3
- package/dist/cjs/react/index.js +1 -0
- package/dist/esm/index.js +26 -3
- package/dist/esm/react/index.js +1 -0
- package/dist/types/DotBotsAuth.d.ts +4 -1
- package/dist/types/index.js +26 -3
- package/dist/types/react/DotBotsAuthProvider.d.ts +3 -0
- package/dist/types/react/index.js +1 -0
- package/dist/types/types.d.ts +1 -1
- package/package.json +1 -1
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
|
@@ -303,8 +303,14 @@ class DotBotsAuth {
|
|
|
303
303
|
}
|
|
304
304
|
async fetch(url, options) {
|
|
305
305
|
this.assertInitialized();
|
|
306
|
-
|
|
307
|
-
|
|
306
|
+
let fullUrl;
|
|
307
|
+
if (url.startsWith('https://') || url.startsWith('http://')) {
|
|
308
|
+
fullUrl = url;
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
const baseUrl = this.proxyConfigManager.getBaseUrl();
|
|
312
|
+
fullUrl = `${baseUrl}${url.startsWith('/') ? url : `/${url}`}`;
|
|
313
|
+
}
|
|
308
314
|
let response = await this.buildRequest(fullUrl, options);
|
|
309
315
|
// On 401, try one refresh then retry
|
|
310
316
|
if (response.status === 401) {
|
|
@@ -319,6 +325,23 @@ class DotBotsAuth {
|
|
|
319
325
|
}
|
|
320
326
|
return response;
|
|
321
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
|
+
}
|
|
322
345
|
async logout() {
|
|
323
346
|
this.assertInitialized();
|
|
324
347
|
await this.tokenManager.revoke();
|
|
@@ -409,7 +432,7 @@ class DotBotsAuth {
|
|
|
409
432
|
}
|
|
410
433
|
}
|
|
411
434
|
}
|
|
412
|
-
DotBotsAuth.SDK_VERSION = '1.0.
|
|
435
|
+
DotBotsAuth.SDK_VERSION = '1.0.9';
|
|
413
436
|
|
|
414
437
|
exports.DotBotsAuth = DotBotsAuth;
|
|
415
438
|
exports.DotBotsAuthError = DotBotsAuthError;
|
package/dist/cjs/react/index.js
CHANGED
|
@@ -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
|
@@ -301,8 +301,14 @@ class DotBotsAuth {
|
|
|
301
301
|
}
|
|
302
302
|
async fetch(url, options) {
|
|
303
303
|
this.assertInitialized();
|
|
304
|
-
|
|
305
|
-
|
|
304
|
+
let fullUrl;
|
|
305
|
+
if (url.startsWith('https://') || url.startsWith('http://')) {
|
|
306
|
+
fullUrl = url;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
const baseUrl = this.proxyConfigManager.getBaseUrl();
|
|
310
|
+
fullUrl = `${baseUrl}${url.startsWith('/') ? url : `/${url}`}`;
|
|
311
|
+
}
|
|
306
312
|
let response = await this.buildRequest(fullUrl, options);
|
|
307
313
|
// On 401, try one refresh then retry
|
|
308
314
|
if (response.status === 401) {
|
|
@@ -317,6 +323,23 @@ class DotBotsAuth {
|
|
|
317
323
|
}
|
|
318
324
|
return response;
|
|
319
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
|
+
}
|
|
320
343
|
async logout() {
|
|
321
344
|
this.assertInitialized();
|
|
322
345
|
await this.tokenManager.revoke();
|
|
@@ -407,6 +430,6 @@ class DotBotsAuth {
|
|
|
407
430
|
}
|
|
408
431
|
}
|
|
409
432
|
}
|
|
410
|
-
DotBotsAuth.SDK_VERSION = '1.0.
|
|
433
|
+
DotBotsAuth.SDK_VERSION = '1.0.9';
|
|
411
434
|
|
|
412
435
|
export { DotBotsAuth, DotBotsAuthError };
|
package/dist/esm/react/index.js
CHANGED
|
@@ -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.
|
|
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;
|
package/dist/types/index.js
CHANGED
|
@@ -301,8 +301,14 @@ class DotBotsAuth {
|
|
|
301
301
|
}
|
|
302
302
|
async fetch(url, options) {
|
|
303
303
|
this.assertInitialized();
|
|
304
|
-
|
|
305
|
-
|
|
304
|
+
let fullUrl;
|
|
305
|
+
if (url.startsWith('https://') || url.startsWith('http://')) {
|
|
306
|
+
fullUrl = url;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
const baseUrl = this.proxyConfigManager.getBaseUrl();
|
|
310
|
+
fullUrl = `${baseUrl}${url.startsWith('/') ? url : `/${url}`}`;
|
|
311
|
+
}
|
|
306
312
|
let response = await this.buildRequest(fullUrl, options);
|
|
307
313
|
// On 401, try one refresh then retry
|
|
308
314
|
if (response.status === 401) {
|
|
@@ -317,6 +323,23 @@ class DotBotsAuth {
|
|
|
317
323
|
}
|
|
318
324
|
return response;
|
|
319
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
|
+
}
|
|
320
343
|
async logout() {
|
|
321
344
|
this.assertInitialized();
|
|
322
345
|
await this.tokenManager.revoke();
|
|
@@ -407,6 +430,6 @@ class DotBotsAuth {
|
|
|
407
430
|
}
|
|
408
431
|
}
|
|
409
432
|
}
|
|
410
|
-
DotBotsAuth.SDK_VERSION = '1.0.
|
|
433
|
+
DotBotsAuth.SDK_VERSION = '1.0.9';
|
|
411
434
|
|
|
412
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 }));
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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;
|