azirid-react 0.6.0 → 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 +92 -1
- package/dist/index.cjs +52 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -3
- package/dist/index.d.ts +40 -3
- package/dist/index.js +50 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -670,6 +670,89 @@ export default function PayphoneCallbackPage() {
|
|
|
670
670
|
|
|
671
671
|
---
|
|
672
672
|
|
|
673
|
+
## Multi-tenant
|
|
674
|
+
|
|
675
|
+
Every authenticated user always has an active `tenantId` and `tenantRole` in the JWT. On signup, if no `tenantId` is provided, a personal tenant is automatically created and the user becomes `OWNER`.
|
|
676
|
+
|
|
677
|
+
### Tenant switching via `useAzirid()`
|
|
678
|
+
|
|
679
|
+
```tsx
|
|
680
|
+
import { useAzirid } from 'azirid-react'
|
|
681
|
+
|
|
682
|
+
function TenantSwitcher({ tenantId }: { tenantId: string }) {
|
|
683
|
+
const { user, switchTenant } = useAzirid()
|
|
684
|
+
|
|
685
|
+
return (
|
|
686
|
+
<div>
|
|
687
|
+
<p>Active tenant: {user?.tenantId} ({user?.tenantRole})</p>
|
|
688
|
+
<button onClick={() => switchTenant(tenantId)}>Switch</button>
|
|
689
|
+
</div>
|
|
690
|
+
)
|
|
691
|
+
}
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
`switchTenant(tenantId)` calls the refresh endpoint with the new `tenantId`, updates the access token in memory, and invalidates all queries — no re-login required.
|
|
695
|
+
|
|
696
|
+
### `useTenants`
|
|
697
|
+
|
|
698
|
+
List all tenants the authenticated user belongs to.
|
|
699
|
+
|
|
700
|
+
```tsx
|
|
701
|
+
import { useTenants } from 'azirid-react'
|
|
702
|
+
|
|
703
|
+
function TenantList() {
|
|
704
|
+
const { data: tenants, isLoading } = useTenants()
|
|
705
|
+
|
|
706
|
+
if (isLoading) return <Spinner />
|
|
707
|
+
|
|
708
|
+
return (
|
|
709
|
+
<ul>
|
|
710
|
+
{tenants?.map((t) => (
|
|
711
|
+
<li key={t.tenantId}>
|
|
712
|
+
{t.name} — {t.role}
|
|
713
|
+
</li>
|
|
714
|
+
))}
|
|
715
|
+
</ul>
|
|
716
|
+
)
|
|
717
|
+
}
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
### `useTenantMembers`
|
|
721
|
+
|
|
722
|
+
List all members of a specific tenant. The authenticated user must be a member.
|
|
723
|
+
|
|
724
|
+
```tsx
|
|
725
|
+
import { useTenantMembers } from 'azirid-react'
|
|
726
|
+
|
|
727
|
+
function MemberList({ tenantId }: { tenantId: string }) {
|
|
728
|
+
const { data: members } = useTenantMembers(tenantId)
|
|
729
|
+
|
|
730
|
+
return (
|
|
731
|
+
<ul>
|
|
732
|
+
{members?.map((m) => (
|
|
733
|
+
<li key={m.id}>
|
|
734
|
+
{m.user.email} — {m.role}
|
|
735
|
+
</li>
|
|
736
|
+
))}
|
|
737
|
+
</ul>
|
|
738
|
+
)
|
|
739
|
+
}
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
### `useSwitchTenant`
|
|
743
|
+
|
|
744
|
+
Headless hook for tenant switching (same as `switchTenant` from `useAzirid()`, but usable outside the main context hook).
|
|
745
|
+
|
|
746
|
+
```tsx
|
|
747
|
+
import { useSwitchTenant } from 'azirid-react'
|
|
748
|
+
|
|
749
|
+
const { switchTenant } = useSwitchTenant()
|
|
750
|
+
|
|
751
|
+
await switchTenant('tenant-id-here')
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
673
756
|
## Referrals
|
|
674
757
|
|
|
675
758
|
All referral hooks require `<AziridProvider>` in the tree and an authenticated user.
|
|
@@ -1255,7 +1338,7 @@ import type {
|
|
|
1255
1338
|
|
|
1256
1339
|
| Type | Description |
|
|
1257
1340
|
| --- | --- |
|
|
1258
|
-
| `AuthUser` | Authenticated user object (`id`, `email`, `
|
|
1341
|
+
| `AuthUser` | Authenticated user object (`id`, `email`, `tenantId`, `tenantRole`, `appId`, ...) — `tenantId` and `tenantRole` are always present |
|
|
1259
1342
|
| `AuthSuccessResponse` | Login/signup response (`accessToken`, `user`) |
|
|
1260
1343
|
| `AuthState` | Full auth state (`user`, `accessToken`, `isAuthenticated`, `isLoading`, `error`) |
|
|
1261
1344
|
| `SignupData` | Signup payload (`email`, `password`, `acceptedTosVersion?`, `referralCode?`, ...) |
|
|
@@ -1264,6 +1347,14 @@ import type {
|
|
|
1264
1347
|
| `AziridProviderProps` | All provider props (see table above) |
|
|
1265
1348
|
| `AziridContextValue` | Context value returned by `useAzirid()` |
|
|
1266
1349
|
|
|
1350
|
+
### Tenant Types
|
|
1351
|
+
|
|
1352
|
+
| Type | Description |
|
|
1353
|
+
| --- | --- |
|
|
1354
|
+
| `TenantWithRole` | Tenant membership (`tenantId`, `name`, `slug`, `role: 'OWNER' \| 'MEMBER'`, `joinedAt`) |
|
|
1355
|
+
| `TenantMemberInfo` | Tenant member (`id`, `role`, `joinedAt`, `user: { id, email, firstName, lastName }`) |
|
|
1356
|
+
| `CreateTenantData` | Create tenant payload (`name`, `description?`) |
|
|
1357
|
+
|
|
1267
1358
|
### Billing Types
|
|
1268
1359
|
|
|
1269
1360
|
| Type | Description |
|
package/dist/index.cjs
CHANGED
|
@@ -97,7 +97,8 @@ var SUFFIXES = {
|
|
|
97
97
|
transferProofs: "billing/transfer-proofs",
|
|
98
98
|
payphoneConfirm: "billing/payphone/confirm",
|
|
99
99
|
referralMe: "referrals/me",
|
|
100
|
-
referralStats: "referrals/stats"
|
|
100
|
+
referralStats: "referrals/stats",
|
|
101
|
+
userTenants: "tenants"
|
|
101
102
|
};
|
|
102
103
|
var BASE_PATHS = {
|
|
103
104
|
/** Proxy mode (Next.js): requests go to the same origin via route handler */
|
|
@@ -161,7 +162,7 @@ function createAccessClient(config, appContext) {
|
|
|
161
162
|
return match ? decodeURIComponent(match[1]) : null;
|
|
162
163
|
}
|
|
163
164
|
const sessionPaths = [paths.refresh, paths.bootstrap, paths.logout];
|
|
164
|
-
async function refreshTokensInternal() {
|
|
165
|
+
async function refreshTokensInternal(opts) {
|
|
165
166
|
const reqHeaders = {
|
|
166
167
|
"Content-Type": "application/json",
|
|
167
168
|
...config.headers
|
|
@@ -175,6 +176,9 @@ function createAccessClient(config, appContext) {
|
|
|
175
176
|
if (refreshToken) {
|
|
176
177
|
bodyPayload["rt"] = refreshToken;
|
|
177
178
|
}
|
|
179
|
+
if (opts?.tenantId) {
|
|
180
|
+
bodyPayload["tenantId"] = opts.tenantId;
|
|
181
|
+
}
|
|
178
182
|
const res = await fetch(`${baseUrl}${paths.refresh}`, {
|
|
179
183
|
method: "POST",
|
|
180
184
|
headers: reqHeaders,
|
|
@@ -195,7 +199,11 @@ function createAccessClient(config, appContext) {
|
|
|
195
199
|
if (rt) setRefreshToken(rt);
|
|
196
200
|
if (xc) setCsrfToken(xc);
|
|
197
201
|
}
|
|
198
|
-
function refreshTokens() {
|
|
202
|
+
function refreshTokens(opts) {
|
|
203
|
+
if (opts?.tenantId) {
|
|
204
|
+
return refreshTokensInternal(opts).finally(() => {
|
|
205
|
+
});
|
|
206
|
+
}
|
|
199
207
|
if (refreshPromise) return refreshPromise;
|
|
200
208
|
refreshPromise = refreshTokensInternal().finally(() => {
|
|
201
209
|
refreshPromise = null;
|
|
@@ -303,7 +311,7 @@ function createAccessClient(config, appContext) {
|
|
|
303
311
|
getRefreshToken,
|
|
304
312
|
setCsrfToken,
|
|
305
313
|
getCsrfToken,
|
|
306
|
-
refreshSession: refreshTokens
|
|
314
|
+
refreshSession: (opts) => refreshTokens(opts)
|
|
307
315
|
};
|
|
308
316
|
}
|
|
309
317
|
|
|
@@ -726,6 +734,14 @@ function AziridProviderInner({
|
|
|
726
734
|
throw err;
|
|
727
735
|
}
|
|
728
736
|
}, [client, queryClient, props, updateAccessToken, clearSession]);
|
|
737
|
+
const switchTenantFn = react.useCallback(
|
|
738
|
+
async (tenantId) => {
|
|
739
|
+
await client.refreshSession({ tenantId });
|
|
740
|
+
updateAccessToken(client.getAccessToken());
|
|
741
|
+
await queryClient.invalidateQueries({ queryKey: ["azirid-access"] });
|
|
742
|
+
},
|
|
743
|
+
[client, queryClient, updateAccessToken]
|
|
744
|
+
);
|
|
729
745
|
const login = react.useCallback(
|
|
730
746
|
(data) => loginMutation.mutate(data),
|
|
731
747
|
[loginMutation]
|
|
@@ -748,6 +764,7 @@ function AziridProviderInner({
|
|
|
748
764
|
logout,
|
|
749
765
|
clearError,
|
|
750
766
|
refresh: refreshFn,
|
|
767
|
+
switchTenant: switchTenantFn,
|
|
751
768
|
setUser: setUserFn,
|
|
752
769
|
isLoginPending: loginMutation.isPending,
|
|
753
770
|
isSignupPending: signupMutation.isPending,
|
|
@@ -765,6 +782,7 @@ function AziridProviderInner({
|
|
|
765
782
|
logout,
|
|
766
783
|
clearError,
|
|
767
784
|
refreshFn,
|
|
785
|
+
switchTenantFn,
|
|
768
786
|
setUserFn,
|
|
769
787
|
loginMutation,
|
|
770
788
|
signupMutation,
|
|
@@ -2548,7 +2566,7 @@ function TransferModal2({
|
|
|
2548
2566
|
const bankDetails = data.bankDetails;
|
|
2549
2567
|
const plan = data.plan;
|
|
2550
2568
|
const intent = data.intent;
|
|
2551
|
-
const displayAmount = plan ? formatAmount2(plan.amount, plan.currency) : intent ? formatAmount2(intent.amount
|
|
2569
|
+
const displayAmount = plan ? formatAmount2(plan.amount, plan.currency) : intent ? formatAmount2(intent.amount, intent.currency) : "";
|
|
2552
2570
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: modalStyles.overlay, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: modalStyles.card, onClick: (e) => e.stopPropagation(), children: [
|
|
2553
2571
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: modalStyles.title, children: labels?.bankTransfer ?? "Bank Transfer" }),
|
|
2554
2572
|
displayAmount && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3214,6 +3232,31 @@ function useTransferProofs() {
|
|
|
3214
3232
|
queryFn: () => client.get(client.paths.transferProofs)
|
|
3215
3233
|
});
|
|
3216
3234
|
}
|
|
3235
|
+
function useTenants() {
|
|
3236
|
+
const client = useAccessClient();
|
|
3237
|
+
return reactQuery.useQuery({
|
|
3238
|
+
queryKey: ["azirid-access", "tenants"],
|
|
3239
|
+
queryFn: () => client.get(client.paths.userTenants),
|
|
3240
|
+
enabled: !!client.getAccessToken()
|
|
3241
|
+
});
|
|
3242
|
+
}
|
|
3243
|
+
function useTenantMembers(tenantId) {
|
|
3244
|
+
const client = useAccessClient();
|
|
3245
|
+
return reactQuery.useQuery({
|
|
3246
|
+
queryKey: ["azirid-access", "tenants", tenantId, "members"],
|
|
3247
|
+
queryFn: () => client.get(`${client.paths.userTenants}/${tenantId}/members`),
|
|
3248
|
+
enabled: !!client.getAccessToken() && !!tenantId
|
|
3249
|
+
});
|
|
3250
|
+
}
|
|
3251
|
+
function useSwitchTenant() {
|
|
3252
|
+
const client = useAccessClient();
|
|
3253
|
+
const queryClient = reactQuery.useQueryClient();
|
|
3254
|
+
const switchTenant = async (tenantId) => {
|
|
3255
|
+
await client.refreshSession({ tenantId });
|
|
3256
|
+
await queryClient.invalidateQueries({ queryKey: ["azirid-access"] });
|
|
3257
|
+
};
|
|
3258
|
+
return { switchTenant };
|
|
3259
|
+
}
|
|
3217
3260
|
function zodToFieldErrors(zodError) {
|
|
3218
3261
|
return zodError.issues.map((issue) => ({
|
|
3219
3262
|
field: issue.path.join("."),
|
|
@@ -3270,7 +3313,7 @@ function usePasswordToggle() {
|
|
|
3270
3313
|
}
|
|
3271
3314
|
|
|
3272
3315
|
// src/index.ts
|
|
3273
|
-
var SDK_VERSION = "0.
|
|
3316
|
+
var SDK_VERSION = "0.7.0";
|
|
3274
3317
|
|
|
3275
3318
|
exports.AziridProvider = AziridProvider;
|
|
3276
3319
|
exports.BASE_PATHS = BASE_PATHS;
|
|
@@ -3328,6 +3371,9 @@ exports.useSignup = useSignup;
|
|
|
3328
3371
|
exports.useSocialLogin = useSocialLogin;
|
|
3329
3372
|
exports.useSubmitTransferProof = useSubmitTransferProof;
|
|
3330
3373
|
exports.useSubscription = useSubscription;
|
|
3374
|
+
exports.useSwitchTenant = useSwitchTenant;
|
|
3375
|
+
exports.useTenantMembers = useTenantMembers;
|
|
3376
|
+
exports.useTenants = useTenants;
|
|
3331
3377
|
exports.useTransferProofs = useTransferProofs;
|
|
3332
3378
|
//# sourceMappingURL=index.cjs.map
|
|
3333
3379
|
//# sourceMappingURL=index.cjs.map
|