@geekapps/auth-nextjs 0.18.0 → 0.21.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 +76 -0
- package/dist/client.d.ts +102 -4
- package/dist/client.js +79 -2
- package/dist/client.js.map +1 -1
- package/dist/connections.d.ts +3 -2
- package/dist/connections.js +99 -2
- package/dist/connections.js.map +1 -1
- package/dist/typegen.d.ts +46 -0
- package/dist/typegen.js +80 -0
- package/dist/typegen.js.map +1 -0
- package/package.json +12 -5
package/README.md
CHANGED
|
@@ -100,6 +100,62 @@ const { requestToJoin, getMyJoinRequest, listJoinRequests, approveJoinRequest }
|
|
|
100
100
|
await requestToJoin(org.id, { message: "Trabalho na região" });
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
+
## Organizações com CNPJ / Tax ID (`type: "legal"`)
|
|
104
|
+
|
|
105
|
+
Toda organização tem um `type`: `"standard"` (padrão, sem documento) ou `"legal"` (pessoa jurídica, associada a um Tax ID). O Tax ID é único por aplicação e não muda depois da criação.
|
|
106
|
+
|
|
107
|
+
- `taxIdType: "br_cnpj"` (padrão) — valida os dígitos verificadores (inclusive CNPJ alfanumérico) e **busca automaticamente** razão social, nome fantasia, contato e endereço na Receita (via BrasilAPI).
|
|
108
|
+
- `taxIdType: "generic"` — Tax ID de outro país; só é normalizado, e `taxIdCountry` (ISO, ex.: `"US"`) é obrigatório.
|
|
109
|
+
|
|
110
|
+
Obrigatórios de uma organização legal: `legalName` e `legalAddress.street`, `.city`, `.postalCode`, `.country`. O que a consulta não trouxer precisa ser informado pelo usuário.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
// 1. Pré-preenche o formulário e descobre o que ainda falta pedir
|
|
114
|
+
const { lookupTaxId, createOrganization } = useOrg();
|
|
115
|
+
const result = await lookupTaxId("12.345.678/0001-95"); // type padrão: "br_cnpj"
|
|
116
|
+
if (!result.success) throw new Error(result.error);
|
|
117
|
+
const lookup = result.data;
|
|
118
|
+
// lookup.data → { legalName, tradeName, legalEmail, legalPhone, legalAddress }
|
|
119
|
+
// lookup.missingFields → ex.: ["legalAddress.postalCode"]
|
|
120
|
+
// lookup.alreadyRegistered → já existe org com esse CNPJ neste app
|
|
121
|
+
|
|
122
|
+
// 2. Cria — o servidor refaz a consulta e completa o que não foi enviado
|
|
123
|
+
const org = await createOrganization({
|
|
124
|
+
name: lookup.suggestedName ?? "Acme",
|
|
125
|
+
slug: "acme",
|
|
126
|
+
type: "legal",
|
|
127
|
+
taxId: lookup.taxId,
|
|
128
|
+
legalAddress: { postalCode: "01001000" }, // só o que faltou
|
|
129
|
+
});
|
|
130
|
+
// Se ainda faltar obrigatório: { success: false, code: "legal_fields_required", missingFields }.
|
|
131
|
+
|
|
132
|
+
// Tax ID genérico (outro país)
|
|
133
|
+
await createOrganization({
|
|
134
|
+
name: "Acme LLC", slug: "acme-llc", type: "legal",
|
|
135
|
+
taxId: "12-3456789", taxIdType: "generic", taxIdCountry: "US",
|
|
136
|
+
legalName: "Acme LLC",
|
|
137
|
+
legalAddress: { street: "1 Main St", city: "Austin", postalCode: "73301", country: "US" },
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Com `@geekapps/auth-elements-nextjs` (0.3+), o `CreateOrganizationForm` (também usado no `OrgSwitcher` e no `ManageOrganizationModal`) já entrega essa UI pronta: alterna Padrão/Empresa, busca o CNPJ e pede só os obrigatórios que faltarem.
|
|
142
|
+
|
|
143
|
+
## Papel do usuário na organização
|
|
144
|
+
|
|
145
|
+
`useOrg()` traz a participação do usuário logado na organização ativa, carregada sozinha ao trocar de organização:
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
const { currentMembership, getMyMembership, refreshMembership } = useOrg();
|
|
149
|
+
|
|
150
|
+
currentMembership?.role?.key; // ex.: "admin"
|
|
151
|
+
currentMembership?.isOwner; // dono passa em qualquer checagem
|
|
152
|
+
currentMembership?.permissions.includes("org:update");
|
|
153
|
+
|
|
154
|
+
const other = await getMyMembership(orgId); // outra organização
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Qualquer membro ativo pode listar os membros da organização com a role de cada um (`listMembers`). Editar, adicionar ou remover membros continua exigindo as permissões `org:members:*`.
|
|
158
|
+
|
|
103
159
|
## Standalone client auth actions
|
|
104
160
|
|
|
105
161
|
`@geekapps/auth-nextjs/client` exporta funções standalone usadas pela `auth-screens`:
|
|
@@ -118,3 +174,23 @@ Depois de aplicar esse source, rode o build do package para gerar o `dist`:
|
|
|
118
174
|
```bash
|
|
119
175
|
bun --filter @geekapps/auth-nextjs build
|
|
120
176
|
```
|
|
177
|
+
|
|
178
|
+
## Tipos das App Connections
|
|
179
|
+
|
|
180
|
+
Em desenvolvimento (`NODE_ENV=development`), o SDK baixa o OpenAPI de cada app conectável e escreve os tipos em `geekapps-connections/`, ao subir e depois a cada minuto. O gerador vem embutido no próprio SDK; só é preciso ter o `openapi-typescript` como devDependency:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npm i -D openapi-typescript
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Sem ele, a geração simplesmente não roda e o app funciona normalmente. Para desligar, use `GEEKAPPS_CONNECTIONS_TYPES=off`. Para checar no CI se os tipos estão em dia:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { generateConnectionTypes } from "@geekapps/auth-nextjs/typegen";
|
|
190
|
+
|
|
191
|
+
const { stale } = await generateConnectionTypes({
|
|
192
|
+
credentials: { issuer, clientId, clientSecret },
|
|
193
|
+
check: true,
|
|
194
|
+
});
|
|
195
|
+
if (stale.length) process.exit(1);
|
|
196
|
+
```
|
package/dist/client.d.ts
CHANGED
|
@@ -18,6 +18,54 @@ type AuthResult<T = unknown> = {
|
|
|
18
18
|
success: false;
|
|
19
19
|
error: string;
|
|
20
20
|
status?: number;
|
|
21
|
+
/** Código de erro da API (ex.: "legal_fields_required", "invalid_tax_id"). */
|
|
22
|
+
code?: string;
|
|
23
|
+
/** Campos obrigatórios que faltaram (ex.: "legalName", "legalAddress.city"). */
|
|
24
|
+
missingFields?: string[];
|
|
25
|
+
};
|
|
26
|
+
/** Erro de request com o corpo estruturado da API (code/missingFields). */
|
|
27
|
+
declare class GeekappsApiError extends Error {
|
|
28
|
+
readonly status: number;
|
|
29
|
+
readonly code?: string | undefined;
|
|
30
|
+
readonly missingFields?: string[] | undefined;
|
|
31
|
+
constructor(message: string, status: number, code?: string | undefined, missingFields?: string[] | undefined);
|
|
32
|
+
}
|
|
33
|
+
/** standard: organização comum. legal: pessoa jurídica associada a um Tax ID (CNPJ ou genérico). */
|
|
34
|
+
type OrganizationType = "standard" | "legal";
|
|
35
|
+
type TaxIdType = "br_cnpj" | "generic";
|
|
36
|
+
type OrganizationLegalAddress = {
|
|
37
|
+
street?: string | null;
|
|
38
|
+
number?: string | null;
|
|
39
|
+
complement?: string | null;
|
|
40
|
+
district?: string | null;
|
|
41
|
+
city?: string | null;
|
|
42
|
+
state?: string | null;
|
|
43
|
+
postalCode?: string | null;
|
|
44
|
+
/** ISO 3166-1 alpha-2 */
|
|
45
|
+
country?: string | null;
|
|
46
|
+
};
|
|
47
|
+
type OrganizationLegalData = {
|
|
48
|
+
legalName: string | null;
|
|
49
|
+
tradeName: string | null;
|
|
50
|
+
legalEmail: string | null;
|
|
51
|
+
legalPhone: string | null;
|
|
52
|
+
legalAddress: OrganizationLegalAddress | null;
|
|
53
|
+
};
|
|
54
|
+
type TaxIdLookupResult = {
|
|
55
|
+
taxId: string;
|
|
56
|
+
taxIdType: TaxIdType;
|
|
57
|
+
taxIdCountry: string | null;
|
|
58
|
+
valid: boolean;
|
|
59
|
+
/** Já existe uma organização deste app com esse Tax ID. */
|
|
60
|
+
alreadyRegistered: boolean;
|
|
61
|
+
/** false quando a fonte pública estava indisponível — preencha manualmente. */
|
|
62
|
+
lookupAvailable: boolean;
|
|
63
|
+
found: boolean;
|
|
64
|
+
registrationStatus: string | null;
|
|
65
|
+
suggestedName: string | null;
|
|
66
|
+
data: OrganizationLegalData;
|
|
67
|
+
/** Obrigatórios que a consulta não conseguiu preencher — peça ao usuário. */
|
|
68
|
+
missingFields: string[];
|
|
21
69
|
};
|
|
22
70
|
type User = {
|
|
23
71
|
id: string;
|
|
@@ -74,14 +122,38 @@ type RoleAssignment = {
|
|
|
74
122
|
roleDefinition?: Role | null;
|
|
75
123
|
customRole?: Role | null;
|
|
76
124
|
};
|
|
125
|
+
/** Role de um membro, como o auth-server devolve. */
|
|
126
|
+
type MemberRole = {
|
|
127
|
+
id: string;
|
|
128
|
+
key: string;
|
|
129
|
+
name: string;
|
|
130
|
+
isDefault: boolean;
|
|
131
|
+
isActive: boolean;
|
|
132
|
+
};
|
|
77
133
|
type OrganizationMember = {
|
|
78
134
|
id: string;
|
|
79
135
|
organizationId?: string;
|
|
80
136
|
userId?: string;
|
|
137
|
+
status?: OrganizationStatus;
|
|
81
138
|
createdAt?: string | Date;
|
|
82
139
|
user: User;
|
|
140
|
+
/** Role do membro na organização (null = sem role atribuída). */
|
|
141
|
+
role?: MemberRole | null;
|
|
142
|
+
/** @deprecated formato antigo — o auth-server devolve `role`. */
|
|
83
143
|
roleAssignments?: RoleAssignment[];
|
|
84
144
|
};
|
|
145
|
+
/** Participação do usuário logado numa organização (GET /organizations/:id/members/me). */
|
|
146
|
+
type OrganizationMembership = {
|
|
147
|
+
organizationId: string;
|
|
148
|
+
membershipId: string | null;
|
|
149
|
+
status: OrganizationStatus;
|
|
150
|
+
/** Dono da organização: passa em qualquer checagem de permissão. */
|
|
151
|
+
isOwner: boolean;
|
|
152
|
+
role: MemberRole | null;
|
|
153
|
+
/** Permissões efetivas da role (keys). Para o dono, use `isOwner`. */
|
|
154
|
+
permissions: string[];
|
|
155
|
+
joinedAt: string | Date | null;
|
|
156
|
+
};
|
|
85
157
|
type OrganizationInvite = {
|
|
86
158
|
id: string;
|
|
87
159
|
organizationId: string;
|
|
@@ -227,6 +299,16 @@ type Organization = {
|
|
|
227
299
|
status: OrganizationStatus;
|
|
228
300
|
/** "private" (padrão) nunca sai em listPublicOrganizations(); "public" sai, e aceita join requests. */
|
|
229
301
|
visibility?: "public" | "private";
|
|
302
|
+
type?: OrganizationType;
|
|
303
|
+
taxId?: string | null;
|
|
304
|
+
taxIdType?: TaxIdType | null;
|
|
305
|
+
taxIdCountry?: string | null;
|
|
306
|
+
legalName?: string | null;
|
|
307
|
+
tradeName?: string | null;
|
|
308
|
+
legalEmail?: string | null;
|
|
309
|
+
legalPhone?: string | null;
|
|
310
|
+
legalAddress?: OrganizationLegalAddress | null;
|
|
311
|
+
taxIdVerifiedAt?: string | Date | null;
|
|
230
312
|
members?: OrganizationMember[];
|
|
231
313
|
ownedApplications?: OrganizationOwnedApplication[];
|
|
232
314
|
applicationLinks?: Array<{
|
|
@@ -280,8 +362,16 @@ type OrganizationInput = {
|
|
|
280
362
|
domain?: string | null;
|
|
281
363
|
imageUrl?: string | null;
|
|
282
364
|
faviconUrl?: string | null;
|
|
283
|
-
|
|
284
|
-
|
|
365
|
+
visibility?: "public" | "private";
|
|
366
|
+
/** "legal" exige taxId; dados da empresa (CNPJ) são buscados automaticamente no servidor. */
|
|
367
|
+
type?: OrganizationType;
|
|
368
|
+
taxId?: string | null;
|
|
369
|
+
/** Padrão: "br_cnpj". */
|
|
370
|
+
taxIdType?: TaxIdType | null;
|
|
371
|
+
/** Obrigatório para taxIdType "generic". */
|
|
372
|
+
taxIdCountry?: string | null;
|
|
373
|
+
} & Partial<OrganizationLegalData>;
|
|
374
|
+
type OrganizationUpdateInput = Partial<Omit<OrganizationInput, "type" | "taxId" | "taxIdType" | "taxIdCountry">> & {
|
|
285
375
|
status?: OrganizationStatus;
|
|
286
376
|
};
|
|
287
377
|
type RoleInput = {
|
|
@@ -451,9 +541,17 @@ type GeekappsAuthContextValue = {
|
|
|
451
541
|
refreshOrganizations: () => Promise<void>;
|
|
452
542
|
setCurrentOrg: (organizationId: string | null) => Promise<void>;
|
|
453
543
|
createOrganization: (input: OrganizationInput) => Promise<AuthResult<Organization>>;
|
|
544
|
+
/** Valida o Tax ID e busca os dados da empresa (CNPJ) para pré-preencher a criação. */
|
|
545
|
+
lookupTaxId: (value: string, type?: TaxIdType) => Promise<AuthResult<TaxIdLookupResult>>;
|
|
454
546
|
updateOrganization: (id: string, input: OrganizationUpdateInput) => Promise<AuthResult<Organization>>;
|
|
455
547
|
deleteOrganization: (id: string) => Promise<AuthResult<null>>;
|
|
456
548
|
hasPermission: (options: PermissionCheckOptions) => Promise<boolean>;
|
|
549
|
+
/** Participação do usuário na organização ativa (role, permissões, dono). Carregada sozinha ao trocar de organização. */
|
|
550
|
+
currentMembership: OrganizationMembership | null;
|
|
551
|
+
isLoadingMembership: boolean;
|
|
552
|
+
/** Participação do usuário numa organização qualquer (padrão: a ativa). */
|
|
553
|
+
getMyMembership: (organizationId?: string) => Promise<OrganizationMembership | null>;
|
|
554
|
+
refreshMembership: () => Promise<void>;
|
|
457
555
|
/** Organizações públicas e ativas deste app — nunca inclui privadas, não exige membership. Separado de `organizations` (só as do próprio usuário). */
|
|
458
556
|
listPublicOrganizations: () => Promise<PublicOrganization[]>;
|
|
459
557
|
requestToJoin: (organizationId: string, input?: {
|
|
@@ -523,7 +621,7 @@ type GeekappsAuthContextValue = {
|
|
|
523
621
|
listInvites: (organizationId: string) => Promise<OrganizationInvite[]>;
|
|
524
622
|
revokeInvite: (organizationId: string, inviteId: string) => Promise<AuthResult<null>>;
|
|
525
623
|
};
|
|
526
|
-
type UseOrgResult = Pick<GeekappsAuthContextValue, "organizations" | "currentOrg" | "currentOrgId" | "isLoadingOrganizations" | "refreshOrganizations" | "setCurrentOrg" | "createOrganization" | "updateOrganization" | "deleteOrganization" | "hasPermission">;
|
|
624
|
+
type UseOrgResult = Pick<GeekappsAuthContextValue, "organizations" | "currentOrg" | "currentOrgId" | "isLoadingOrganizations" | "refreshOrganizations" | "setCurrentOrg" | "createOrganization" | "lookupTaxId" | "updateOrganization" | "deleteOrganization" | "hasPermission" | "currentMembership" | "isLoadingMembership" | "getMyMembership" | "refreshMembership">;
|
|
527
625
|
type UseAccountsResult = Pick<GeekappsAuthContextValue, "accounts" | "addAccount" | "isLoadingAccounts" | "refreshAccounts" | "switchAccount">;
|
|
528
626
|
type UseUsersResult = Pick<GeekappsAuthContextValue, "listUsers" | "getUser" | "createUser" | "updateUser" | "deleteUser">;
|
|
529
627
|
type UseRolesResult = Pick<GeekappsAuthContextValue, "listRoles" | "getRole" | "createRole" | "updateRole" | "deleteRole">;
|
|
@@ -607,4 +705,4 @@ type UseServiceAccountResult = {
|
|
|
607
705
|
};
|
|
608
706
|
declare function useServiceAccount(): UseServiceAccountResult;
|
|
609
707
|
|
|
610
|
-
export { type AcceptInviteResult, type AddMemberInput, type AuthResult, type CallbackUrlOptions, type ConnectedAccount, type CreateServiceAccountInput, type GeekappsAuthContextValue, GeekappsAuthProvider, type GeekappsAuthProviderProps, GeekappsSessionExpiredError, type JoinRequestStatus, type LoginResponse, type MemberInviteInput, type OAuthClientType, type OidcPrompt, type Organization, type OrganizationInput, type OrganizationInvite, type OrganizationInvitePreview, type OrganizationJoinRequest, type OrganizationMember, type OrganizationOwnedApplication, type OrganizationStatus, type OrganizationUpdateInput, type Permission, type PermissionCheckOptions, type PermissionInput, type PermissionUpdateInput, type PublicOrganization, type RegisterResponse, type Role, type RoleAssignment, type RoleInput, type RolePermission, type RoleUpdateInput, type ServiceAccount, type ServiceAccountWithSecret, type SessionApplication, type SignInInput, type SignInOptions, type UpdateMemberInput, type UpdateMemberRoleInput, type UseAccountsResult, type UseInvitesResult, type UseJoinRequestsResult, type UseMembersResult, type UseOrgResult, type UsePermissionsResult, type UsePublicOrganizationsResult, type UseRolesResult, type UseServiceAccountResult, type UseSessionsResult, type UseUsersResult, type User, type UserInput, type UserSession, type UserStatus, loginWithPassword, registerWithPassword, requestPasswordlessLink, startGoogleLogin, useAccounts, useAuth, useInvites, useJoinRequests, useMembers, useOrg, usePermissions, usePublicOrganizations, useRoles, useServiceAccount, useSessions, useUsers };
|
|
708
|
+
export { type AcceptInviteResult, type AddMemberInput, type AuthResult, type CallbackUrlOptions, type ConnectedAccount, type CreateServiceAccountInput, GeekappsApiError, type GeekappsAuthContextValue, GeekappsAuthProvider, type GeekappsAuthProviderProps, GeekappsSessionExpiredError, type JoinRequestStatus, type LoginResponse, type MemberInviteInput, type MemberRole, type OAuthClientType, type OidcPrompt, type Organization, type OrganizationInput, type OrganizationInvite, type OrganizationInvitePreview, type OrganizationJoinRequest, type OrganizationLegalAddress, type OrganizationLegalData, type OrganizationMember, type OrganizationMembership, type OrganizationOwnedApplication, type OrganizationStatus, type OrganizationType, type OrganizationUpdateInput, type Permission, type PermissionCheckOptions, type PermissionInput, type PermissionUpdateInput, type PublicOrganization, type RegisterResponse, type Role, type RoleAssignment, type RoleInput, type RolePermission, type RoleUpdateInput, type ServiceAccount, type ServiceAccountWithSecret, type SessionApplication, type SignInInput, type SignInOptions, type TaxIdLookupResult, type TaxIdType, type UpdateMemberInput, type UpdateMemberRoleInput, type UseAccountsResult, type UseInvitesResult, type UseJoinRequestsResult, type UseMembersResult, type UseOrgResult, type UsePermissionsResult, type UsePublicOrganizationsResult, type UseRolesResult, type UseServiceAccountResult, type UseSessionsResult, type UseUsersResult, type User, type UserInput, type UserSession, type UserStatus, loginWithPassword, registerWithPassword, requestPasswordlessLink, startGoogleLogin, useAccounts, useAuth, useInvites, useJoinRequests, useMembers, useOrg, usePermissions, usePublicOrganizations, useRoles, useServiceAccount, useSessions, useUsers };
|
package/dist/client.js
CHANGED
|
@@ -18,6 +18,18 @@ var GeekappsSessionExpiredError = class extends Error {
|
|
|
18
18
|
this.name = "GeekappsSessionExpiredError";
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
+
var GeekappsApiError = class extends Error {
|
|
22
|
+
constructor(message, status, code, missingFields) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.status = status;
|
|
25
|
+
this.code = code;
|
|
26
|
+
this.missingFields = missingFields;
|
|
27
|
+
this.name = "GeekappsApiError";
|
|
28
|
+
}
|
|
29
|
+
status;
|
|
30
|
+
code;
|
|
31
|
+
missingFields;
|
|
32
|
+
};
|
|
21
33
|
function normalizeBasePath(basePath) {
|
|
22
34
|
return basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
23
35
|
}
|
|
@@ -164,7 +176,13 @@ function GeekappsAuthProvider({
|
|
|
164
176
|
throw new GeekappsSessionExpiredError();
|
|
165
177
|
}
|
|
166
178
|
if (!response.ok) {
|
|
167
|
-
|
|
179
|
+
const data = await response.clone().json().catch(() => null);
|
|
180
|
+
throw new GeekappsApiError(
|
|
181
|
+
await parseError(response),
|
|
182
|
+
response.status,
|
|
183
|
+
typeof data?.code === "string" ? data.code : void 0,
|
|
184
|
+
Array.isArray(data?.missingFields) ? data.missingFields : void 0
|
|
185
|
+
);
|
|
168
186
|
}
|
|
169
187
|
if (response.status === 204) {
|
|
170
188
|
return null;
|
|
@@ -223,6 +241,37 @@ function GeekappsAuthProvider({
|
|
|
223
241
|
() => organizations.find((organization) => organization.id === currentOrgId) ?? null,
|
|
224
242
|
[currentOrgId, organizations]
|
|
225
243
|
);
|
|
244
|
+
const [currentMembership, setCurrentMembership] = useState(null);
|
|
245
|
+
const [isLoadingMembership, setIsLoadingMembership] = useState(false);
|
|
246
|
+
const getMyMembership = useCallback(
|
|
247
|
+
async (organizationId) => {
|
|
248
|
+
const orgId = organizationId ?? currentOrgId;
|
|
249
|
+
if (!orgId) return null;
|
|
250
|
+
try {
|
|
251
|
+
return await request(
|
|
252
|
+
`/organizations/${encodeURIComponent(orgId)}/members/me`
|
|
253
|
+
);
|
|
254
|
+
} catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
[currentOrgId, request]
|
|
259
|
+
);
|
|
260
|
+
const refreshMembership = useCallback(async () => {
|
|
261
|
+
if (!currentOrgId || !user) {
|
|
262
|
+
setCurrentMembership(null);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
setIsLoadingMembership(true);
|
|
266
|
+
try {
|
|
267
|
+
setCurrentMembership(await getMyMembership(currentOrgId));
|
|
268
|
+
} finally {
|
|
269
|
+
setIsLoadingMembership(false);
|
|
270
|
+
}
|
|
271
|
+
}, [currentOrgId, getMyMembership, user]);
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
void refreshMembership();
|
|
274
|
+
}, [refreshMembership]);
|
|
226
275
|
const setCurrentOrg = useCallback(
|
|
227
276
|
async (organizationId) => {
|
|
228
277
|
await request("/organizations/active", {
|
|
@@ -291,6 +340,15 @@ function GeekappsAuthProvider({
|
|
|
291
340
|
try {
|
|
292
341
|
return { success: true, data: await fn() };
|
|
293
342
|
} catch (error) {
|
|
343
|
+
if (error instanceof GeekappsApiError) {
|
|
344
|
+
return {
|
|
345
|
+
success: false,
|
|
346
|
+
error: error.message,
|
|
347
|
+
status: error.status,
|
|
348
|
+
code: error.code,
|
|
349
|
+
missingFields: error.missingFields
|
|
350
|
+
};
|
|
351
|
+
}
|
|
294
352
|
return { success: false, error: error instanceof Error ? error.message : "Unexpected error" };
|
|
295
353
|
}
|
|
296
354
|
}
|
|
@@ -371,6 +429,10 @@ function GeekappsAuthProvider({
|
|
|
371
429
|
organizations,
|
|
372
430
|
currentOrg,
|
|
373
431
|
currentOrgId,
|
|
432
|
+
currentMembership,
|
|
433
|
+
isLoadingMembership,
|
|
434
|
+
getMyMembership,
|
|
435
|
+
refreshMembership,
|
|
374
436
|
isLoadingOrganizations,
|
|
375
437
|
request,
|
|
376
438
|
signIn,
|
|
@@ -409,6 +471,11 @@ function GeekappsAuthProvider({
|
|
|
409
471
|
setCurrentOrgId(organization.id);
|
|
410
472
|
return organization;
|
|
411
473
|
}),
|
|
474
|
+
lookupTaxId: (value2, type = "br_cnpj") => toAuthResult(
|
|
475
|
+
() => request(
|
|
476
|
+
`/organizations/tax-id/lookup?type=${encodeURIComponent(type)}&value=${encodeURIComponent(value2)}`
|
|
477
|
+
)
|
|
478
|
+
),
|
|
412
479
|
updateOrganization: (id, input) => toAuthResult(async () => {
|
|
413
480
|
const organization = await request(`/organizations/${id}`, { method: "PATCH", body: input });
|
|
414
481
|
await refreshOrganizations();
|
|
@@ -589,6 +656,10 @@ function GeekappsAuthProvider({
|
|
|
589
656
|
basePath,
|
|
590
657
|
currentOrg,
|
|
591
658
|
currentOrgId,
|
|
659
|
+
currentMembership,
|
|
660
|
+
isLoadingMembership,
|
|
661
|
+
getMyMembership,
|
|
662
|
+
refreshMembership,
|
|
592
663
|
getInvitePreview,
|
|
593
664
|
getMyJoinRequest,
|
|
594
665
|
isLoading,
|
|
@@ -626,9 +697,14 @@ function useOrg() {
|
|
|
626
697
|
refreshOrganizations: context.refreshOrganizations,
|
|
627
698
|
setCurrentOrg: context.setCurrentOrg,
|
|
628
699
|
createOrganization: context.createOrganization,
|
|
700
|
+
lookupTaxId: context.lookupTaxId,
|
|
629
701
|
updateOrganization: context.updateOrganization,
|
|
630
702
|
deleteOrganization: context.deleteOrganization,
|
|
631
|
-
hasPermission: context.hasPermission
|
|
703
|
+
hasPermission: context.hasPermission,
|
|
704
|
+
currentMembership: context.currentMembership,
|
|
705
|
+
isLoadingMembership: context.isLoadingMembership,
|
|
706
|
+
getMyMembership: context.getMyMembership,
|
|
707
|
+
refreshMembership: context.refreshMembership
|
|
632
708
|
};
|
|
633
709
|
}
|
|
634
710
|
function useAccounts() {
|
|
@@ -764,6 +840,7 @@ function useServiceAccount() {
|
|
|
764
840
|
};
|
|
765
841
|
}
|
|
766
842
|
export {
|
|
843
|
+
GeekappsApiError,
|
|
767
844
|
GeekappsAuthProvider,
|
|
768
845
|
GeekappsSessionExpiredError,
|
|
769
846
|
loginWithPassword,
|