@geekapps/auth-nextjs 0.6.0 → 0.7.1

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/dist/client.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  useContext,
8
8
  useEffect,
9
9
  useMemo,
10
+ useRef,
10
11
  useState
11
12
  } from "react";
12
13
  import { jsx } from "react/jsx-runtime";
@@ -138,6 +139,8 @@ function GeekappsAuthProvider({
138
139
  const [organizations, setOrganizations] = useState(initialOrganizations);
139
140
  const [currentOrgId, setCurrentOrgId] = useState(initialCurrentOrgId);
140
141
  const [isLoadingOrganizations, setIsLoadingOrganizations] = useState(true);
142
+ const currentOrgIdRef = useRef(currentOrgId);
143
+ currentOrgIdRef.current = currentOrgId;
141
144
  const request = useCallback(
142
145
  async (path, options = {}) => {
143
146
  const response = await fetch(buildUrl(basePath, path), {
@@ -427,18 +430,60 @@ function GeekappsAuthProvider({
427
430
  await request(`/users/${id}`, { method: "DELETE" });
428
431
  return null;
429
432
  }),
430
- listRoles: (params) => {
431
- const query = new URLSearchParams();
432
- if (params?.organizationId) query.set("organizationId", params.organizationId);
433
- if (params?.applicationId) query.set("applicationId", params.applicationId);
434
- if (params?.type) query.set("type", params.type);
435
- return request(`/roles${query.size ? `?${query.toString()}` : ""}`);
433
+ // Roles são sempre resolvidas no escopo de uma organização — o
434
+ // auth-server não expõe /roles solto. Sem organizationId explícito,
435
+ // usa a organização ativa; sem nenhuma das duas não há o que consultar.
436
+ listRoles: async (params) => {
437
+ const organizationId = params?.organizationId ?? currentOrgIdRef.current;
438
+ if (!organizationId) {
439
+ throw new Error(
440
+ "listRoles: informe organizationId \u2014 n\xE3o h\xE1 organiza\xE7\xE3o ativa para resolver as roles."
441
+ );
442
+ }
443
+ const roles = await request(`/organizations/${organizationId}/roles`);
444
+ return {
445
+ systemRoles: roles.filter((role) => role.isDefault),
446
+ customRoles: roles.filter((role) => !role.isDefault)
447
+ };
448
+ },
449
+ getRole: (id, _type, organizationId) => {
450
+ const orgId = organizationId ?? currentOrgIdRef.current;
451
+ if (!orgId) {
452
+ throw new Error("getRole: informe organizationId \u2014 n\xE3o h\xE1 organiza\xE7\xE3o ativa.");
453
+ }
454
+ return request(`/organizations/${orgId}/roles/${id}`);
436
455
  },
437
- getRole: (id, type) => request(type === "custom" ? `/roles/custom/${id}` : `/roles/definitions/${id}`),
438
- createRole: (input) => toAuthResult(() => request("/roles", { method: "POST", body: input })),
439
- updateRole: (id, input) => toAuthResult(() => request(`/roles/custom/${id}`, { method: "PATCH", body: input })),
440
- deleteRole: (id) => toAuthResult(async () => {
441
- await request(`/roles/custom/${id}`, { method: "DELETE" });
456
+ createRole: ({ organizationId, permissionDefinitionIds, applicationId: _applicationId, ...rest }) => toAuthResult(() => {
457
+ const orgId = organizationId ?? currentOrgIdRef.current;
458
+ if (!orgId) {
459
+ throw new Error("createRole: informe organizationId \u2014 n\xE3o h\xE1 organiza\xE7\xE3o ativa.");
460
+ }
461
+ return request(`/organizations/${orgId}/roles`, {
462
+ method: "POST",
463
+ // O auth-server espera permissionIds; permissionDefinitionIds é o
464
+ // nome herdado no SDK.
465
+ body: { ...rest, permissionIds: permissionDefinitionIds ?? [] }
466
+ });
467
+ }),
468
+ updateRole: (id, { permissionDefinitionIds, ...rest }, organizationId) => toAuthResult(() => {
469
+ const orgId = organizationId ?? currentOrgIdRef.current;
470
+ if (!orgId) {
471
+ throw new Error("updateRole: informe organizationId \u2014 n\xE3o h\xE1 organiza\xE7\xE3o ativa.");
472
+ }
473
+ return request(`/organizations/${orgId}/roles/${id}`, {
474
+ method: "PATCH",
475
+ body: {
476
+ ...rest,
477
+ ...permissionDefinitionIds ? { permissionIds: permissionDefinitionIds } : {}
478
+ }
479
+ });
480
+ }),
481
+ deleteRole: (id, organizationId) => toAuthResult(async () => {
482
+ const orgId = organizationId ?? currentOrgIdRef.current;
483
+ if (!orgId) {
484
+ throw new Error("deleteRole: informe organizationId \u2014 n\xE3o h\xE1 organiza\xE7\xE3o ativa.");
485
+ }
486
+ await request(`/organizations/${orgId}/roles/${id}`, { method: "DELETE" });
442
487
  return null;
443
488
  }),
444
489
  listPermissions: (params) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nexport type UserStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OrganizationStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OAuthClientType = \"public\" | \"confidential\";\n\nexport type AuthResult<T = unknown> =\n | { success: true; data: T }\n | { success: false; error: string; status?: number };\n\nexport type User = {\n id: string;\n email: string;\n name: string | null;\n phone: string | null;\n imageUrl: string | null;\n status?: UserStatus;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type ConnectedAccount = {\n id: string;\n sessionId?: string;\n isActive: boolean;\n user: User;\n};\n\nexport type Permission = {\n id: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description: string | null;\n category: string | null;\n isSystem: boolean;\n isActive: boolean;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RolePermission = {\n permissionDefinition: Permission;\n};\n\nexport type Role = {\n id: string;\n applicationId?: string | null;\n /** Present only on custom roles */\n organizationId?: string | null;\n /** \"system\" | \"custom\" */\n type?: string;\n key: string;\n name: string;\n description: string | null;\n isSystem?: boolean;\n isDefault?: boolean;\n isActive: boolean;\n permissions: RolePermission[];\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RoleAssignment = {\n id: string;\n roleDefinitionId?: string | null;\n customRoleId?: string | null;\n roleDefinition?: Role | null;\n customRole?: Role | null;\n};\n\nexport type OrganizationMember = {\n id: string;\n organizationId?: string;\n userId?: string;\n createdAt?: string | Date;\n user: User;\n roleAssignments?: RoleAssignment[];\n};\n\nexport type OrganizationInvite = {\n id: string;\n organizationId: string;\n email: string;\n roleId?: string | null;\n status: \"pending\" | \"accepted\" | \"expired\" | \"revoked\";\n expiresAt: string | Date;\n createdAt?: string | Date;\n};\n\nexport type MemberInviteInput = {\n email: string;\n roleId?: string;\n /**\n * URI pra onde o link do e-mail manda o usuário — precisa estar cadastrada\n * em Application.redirectUris (mesma validação do /authorize). Este app\n * deve expor uma rota nessa URI que trata o `?invite_token=` anexado (ver\n * useJoinRequests/inviteApi.preview|accept|reject abaixo).\n */\n redirectUri: string;\n emailTitle?: string;\n emailSubtitle?: string;\n emailMessage?: string;\n};\n\nexport type AddMemberInput = {\n userId: string;\n roleId?: string;\n};\n\nexport type UpdateMemberInput = {\n status?: \"active\" | \"inactive\" | \"suspended\";\n roleId?: string | null;\n};\n\n/** @deprecated use UpdateMemberInput */\nexport type UpdateMemberRoleInput = {\n roleId: string;\n};\n\nexport type PublicOrganization = {\n id: string;\n name: string;\n slug: string;\n description: string | null;\n imageUrl: string | null;\n createdAt: string | Date;\n};\n\nexport type OrganizationInvitePreview =\n | {\n alreadyAccepted: true;\n organizationId: string;\n organizationName: string;\n applicationName: string;\n applicationImageUrl: string | null;\n applicationImageFileId: string | null;\n organizationImageUrl: string | null;\n organizationImageFileId: string | null;\n websiteUrl: string | null;\n }\n | {\n alreadyAccepted?: false;\n email: string;\n organizationId: string;\n organizationName: string;\n applicationName: string;\n applicationId: string;\n applicationImageUrl: string | null;\n applicationImageFileId: string | null;\n organizationImageUrl: string | null;\n organizationImageFileId: string | null;\n websiteUrl: string | null;\n redirectUri: string | null;\n appStoreUrl: string | null;\n playStoreUrl: string | null;\n currentAccount: { email: string; name: string | null } | null;\n };\n\nexport type AcceptInviteResult =\n | { success: true; organizationId: string; organizationName: string; websiteUrl: string | null }\n | { success: false; wrongAccount: true; currentEmail: string; invitedEmail: string }\n | { success: false; wrongAccount: false; loginRequired: true }\n | { success: false; wrongAccount: false; loginRequired: false; error: string };\n\nexport type JoinRequestStatus = \"pending\" | \"approved\" | \"rejected\" | \"cancelled\";\n\nexport type OrganizationJoinRequest = {\n id: string;\n organizationId: string;\n userId: string;\n status: JoinRequestStatus;\n message: string | null;\n reviewedByUserId: string | null;\n reviewedAt: string | null;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nexport type OrganizationOwnedApplication = {\n id: string;\n name: string;\n description: string | null;\n imageUrl: string | null;\n type?: OAuthClientType;\n organizationId: string;\n isFirstParty: boolean;\n ssoEnabled: boolean;\n status?: \"active\" | \"inactive\" | \"suspended\";\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type Organization = {\n id: string;\n name: string;\n description: string | null;\n slug: string;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n status: OrganizationStatus;\n /** \"private\" (padrão) nunca sai em listPublicOrganizations(); \"public\" sai, e aceita join requests. */\n visibility?: \"public\" | \"private\";\n members?: OrganizationMember[];\n ownedApplications?: OrganizationOwnedApplication[];\n applicationLinks?: Array<{\n id: string;\n status: OrganizationStatus;\n createdAt?: string | Date;\n application: OrganizationOwnedApplication;\n }>;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nexport type SessionApplication = {\n id: string;\n createdAt: string | Date;\n expiresAt: string | Date;\n application: {\n id: string;\n name: string;\n organizationId: string;\n };\n};\n\nexport type UserSession = {\n id: string;\n userId: string;\n organizationId: string | null;\n deviceAgent: string | null;\n deviceId: string | null;\n deviceName: string | null;\n ip: string | null;\n authState?: unknown;\n authTime?: string | Date;\n expiresAt: string | Date;\n createdAt: string | Date;\n updatedAt: string | Date;\n user?: User;\n applicationSessions?: SessionApplication[];\n};\n\nexport type UserInput = {\n name?: string | null;\n email?: string;\n phone?: string | null;\n imageUrl?: string | null;\n password?: string;\n organizationId?: string | null;\n status?: UserStatus;\n};\n\nexport type OrganizationInput = {\n name: string;\n description?: string | null;\n slug: string;\n domain?: string | null;\n imageUrl?: string | null;\n faviconUrl?: string | null;\n};\n\nexport type OrganizationUpdateInput = Partial<OrganizationInput> & {\n status?: OrganizationStatus;\n};\n\nexport type RoleInput = {\n organizationId: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n permissionDefinitionIds?: string[];\n};\n\nexport type RoleUpdateInput = {\n name?: string;\n description?: string | null;\n isActive?: boolean;\n permissionDefinitionIds?: string[];\n};\n\nexport type PermissionInput = {\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n category?: string | null;\n};\n\nexport type PermissionUpdateInput = {\n name?: string;\n description?: string | null;\n category?: string | null;\n isActive?: boolean;\n};\n\n/**\n * OIDC `prompt` values understood by the Geekapps Auth Server. These control\n * whether — and how — the IDP shows UI during `signIn()`/`signUp()`/`addAccount()`.\n *\n * - `\"login\"` — Forces the login screen, even if the user already has an active\n * session. Use this for a fresh login, unrelated to whatever session already\n * exists (equivalent to the old `silentLogin: false`).\n * - `\"select_account\"` — Shows the account picker so the user can choose among\n * their connected accounts, or add a new one. Use this when you want to let\n * the user switch accounts explicitly.\n * - `\"none\"` — Never shows any UI. The IDP authenticates silently if there is\n * exactly one active session (and no other interaction — like consent or a\n * security check — is pending); otherwise it fails immediately with an OIDC\n * error (`login_required`, `account_selection_required`, `consent_required`,\n * or `interaction_required`) instead of prompting the user. Use this for\n * silent-auth checks (e.g. \"is the user still logged in?\") where you don't\n * want to interrupt them with a screen.\n * - `\"consent\"` — Forces the consent screen even if the user already granted\n * the requested scopes before.\n *\n * Omitting `prompt` entirely runs the IDP's default flow: reuse a single\n * existing session silently, ask the user to pick when there are multiple\n * connected accounts, or show the login screen when there's none.\n */\nexport type OidcPrompt = \"login\" | \"select_account\" | \"none\" | \"consent\";\n\nexport type SignInOptions = {\n redirectTo?: string;\n authorizationFlowId?: string;\n /**\n * Controls whether the IDP shows UI, and which screen, during sign-in. See\n * {@link OidcPrompt} for what each value does. Omit it to run the default flow.\n */\n prompt?: OidcPrompt;\n /**\n * @deprecated Use `prompt: \"login\"` instead. Kept for backwards compatibility —\n * `silentLogin: false` is equivalent to `prompt: \"login\"`.\n */\n silentLogin?: boolean;\n};\n\nexport type SignInInput = SignInOptions | MouseEvent<HTMLElement>;\n\nexport type CallbackUrlOptions = SignInOptions & {\n callbackUrl?: string;\n};\n\nexport type PermissionCheckOptions = {\n permission: string;\n organizationId?: string | null;\n applicationId?: string | null;\n resourceId?: string | null;\n};\n\nexport type LoginResponse = {\n user: User;\n redirectTo?: string | null;\n};\n\nexport type RegisterResponse = User;\n\nexport type GeekappsAuthProviderProps = {\n children: ReactNode;\n basePath?: string;\n initialUser?: User | null;\n initialOrganizations?: Organization[];\n initialCurrentOrgId?: string | null;\n};\n\ntype RequestOptions = {\n body?: unknown;\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n};\n\nfunction normalizeBasePath(basePath: string) {\n return basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n}\n\nfunction buildUrl(basePath: string, path: string) {\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${normalizeBasePath(basePath)}${normalizedPath}`;\n}\n\nasync function parseError(response: Response) {\n const data = await response.json().catch(() => null);\n return (\n data?.error_description ??\n data?.error ??\n data?.message ??\n `Request failed with status ${response.status}`\n );\n}\n\nfunction redirectTo(path: string) {\n window.location.assign(path);\n}\n\nfunction isMouseEvent(value: unknown): value is MouseEvent<HTMLElement> {\n return Boolean(value && typeof value === \"object\" && \"preventDefault\" in value);\n}\n\nfunction normalizeSignInOptions(input?: SignInInput): SignInOptions | undefined {\n if (!input) return undefined;\n if (isMouseEvent(input)) {\n input.preventDefault();\n return undefined;\n }\n return input;\n}\n\n\ntype ClientActionOptions = {\n basePath?: string;\n};\n\nasync function clientRequest<T>(\n path: string,\n options: RequestOptions = {},\n basePath = \"/api/auth\",\n): Promise<T> {\n const response = await fetch(buildUrl(basePath, path), {\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n method: options.method ?? \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n}\n\nasync function toStandaloneAuthResult<T>(\n fn: () => Promise<T>,\n): Promise<AuthResult<T>> {\n try {\n return {\n success: true,\n data: await fn(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Auth request failed\",\n };\n }\n}\n\nexport async function loginWithPassword(\n params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<LoginResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<LoginResponse>(\n \"/login/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo ?? data.redirectTo) {\n redirectTo(params.redirectTo ?? data.redirectTo!);\n }\n\n return data;\n });\n}\n\nexport async function registerWithPassword(\n params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<RegisterResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<RegisterResponse>(\n \"/register/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo) {\n redirectTo(params.redirectTo);\n }\n\n return data;\n });\n}\n\nexport function startGoogleLogin(\n params?: CallbackUrlOptions,\n options?: ClientActionOptions,\n) {\n const basePath = options?.basePath ?? \"/api/auth\";\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n\n if (params?.callbackUrl) {\n url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n }\n\n if (params?.redirectTo) {\n url.searchParams.set(\"redirectTo\", params.redirectTo);\n }\n\n if (params?.authorizationFlowId) {\n url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n }\n\n redirectTo(url.toString());\n}\n\nexport async function requestPasswordlessLink(\n params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult> {\n return toStandaloneAuthResult(() =>\n clientRequest(\n \"/passwordless/link\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n ),\n );\n}\n\nexport type GeekappsAuthContextValue = {\n basePath: string;\n user: User | null;\n isAuthenticated: boolean;\n isLoading: boolean;\n accounts: ConnectedAccount[];\n isLoadingAccounts: boolean;\n organizations: Organization[];\n currentOrg: Organization | null;\n currentOrgId: string | null;\n isLoadingOrganizations: boolean;\n\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n\n signIn: (options?: SignInInput) => Promise<void>;\n signUp: (options?: SignInInput) => Promise<void>;\n addAccount: (options?: SignInInput) => Promise<void>;\n signOut: () => Promise<void>;\n signOutAll: () => Promise<void>;\n refreshUser: () => Promise<void>;\n refreshAccounts: () => Promise<void>;\n switchAccount: (sessionId: string, options?: SignInOptions) => Promise<void>;\n\n loginWithPassword: (params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n }) => Promise<AuthResult<LoginResponse>>;\n registerWithPassword: (params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n }) => Promise<AuthResult<RegisterResponse>>;\n startGoogleLogin: (params?: CallbackUrlOptions) => void;\n requestPasswordlessLink: (params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n }) => Promise<AuthResult>;\n\n refreshOrganizations: () => Promise<void>;\n setCurrentOrg: (organizationId: string | null) => Promise<void>;\n createOrganization: (input: OrganizationInput) => Promise<AuthResult<Organization>>;\n updateOrganization: (id: string, input: OrganizationUpdateInput) => Promise<AuthResult<Organization>>;\n deleteOrganization: (id: string) => Promise<AuthResult<null>>;\n hasPermission: (options: PermissionCheckOptions) => Promise<boolean>;\n\n /** 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). */\n listPublicOrganizations: () => Promise<PublicOrganization[]>;\n\n requestToJoin: (organizationId: string, input?: { message?: string | null }) => Promise<AuthResult<OrganizationJoinRequest>>;\n getMyJoinRequest: (organizationId: string) => Promise<OrganizationJoinRequest | null>;\n cancelJoinRequest: (organizationId: string) => Promise<AuthResult<null>>;\n listJoinRequests: (organizationId: string) => Promise<OrganizationJoinRequest[]>;\n approveJoinRequest: (organizationId: string, requestId: string) => Promise<AuthResult<OrganizationJoinRequest>>;\n rejectJoinRequest: (organizationId: string, requestId: string) => Promise<AuthResult<OrganizationJoinRequest>>;\n\n /** Preview do convite por token — funciona com ou sem sessão (currentAccount vem null se deslogado). */\n getInvitePreview: (token: string) => Promise<OrganizationInvitePreview>;\n /** Aceita o convite. loginRequired:true significa que signIn() precisa rodar antes. */\n acceptInvite: (token: string) => Promise<AcceptInviteResult>;\n /** Recusa o convite — não exige estar logado. */\n rejectInvite: (token: string) => Promise<{ success: true } | { success: false; error: string }>;\n\n listUsers: (params?: { organizationId?: string | null }) => Promise<User[]>;\n getUser: (id: string) => Promise<User>;\n createUser: (input: UserInput) => Promise<AuthResult<User>>;\n updateUser: (id: string, input: UserInput) => Promise<AuthResult<User>>;\n deleteUser: (id: string) => Promise<AuthResult<null>>;\n\n listRoles: (params?: { organizationId?: string; applicationId?: string; type?: \"system\" | \"custom\" | \"all\" }) => Promise<{ systemRoles: Role[]; customRoles: Role[] }>;\n getRole: (id: string, type: \"system\" | \"custom\") => Promise<Role>;\n createRole: (input: RoleInput) => Promise<AuthResult<Role>>;\n updateRole: (id: string, input: RoleUpdateInput) => Promise<AuthResult<Role>>;\n deleteRole: (id: string) => Promise<AuthResult<null>>;\n\n listPermissions: (params?: { applicationId?: string; roleId?: string | null }) => Promise<Permission[]>;\n createPermission: (input: PermissionInput) => Promise<AuthResult<Permission>>;\n updatePermission: (id: string, input: PermissionUpdateInput) => Promise<AuthResult<Permission>>;\n deletePermission: (id: string) => Promise<AuthResult<null>>;\n\n listUserSessions: (params?: { userId?: string; organizationId?: string | null }) => Promise<UserSession[]>;\n revokeUserSession: (sessionId: string) => Promise<AuthResult<null>>;\n\n listMembers: (organizationId: string) => Promise<OrganizationMember[]>;\n getMember: (organizationId: string, memberId: string) => Promise<OrganizationMember>;\n addMember: (organizationId: string, input: AddMemberInput) => Promise<AuthResult<OrganizationMember>>;\n updateMember: (\n organizationId: string,\n memberId: string,\n input: UpdateMemberInput,\n ) => Promise<AuthResult<OrganizationMember>>;\n /** @deprecated use updateMember */\n updateMemberRole: (\n organizationId: string,\n memberId: string,\n input: UpdateMemberRoleInput,\n ) => Promise<AuthResult<OrganizationMember>>;\n removeMember: (organizationId: string, memberId: string) => Promise<AuthResult<null>>;\n inviteMember: (organizationId: string, input: MemberInviteInput) => Promise<AuthResult<OrganizationInvite>>;\n listInvites: (organizationId: string) => Promise<OrganizationInvite[]>;\n revokeInvite: (organizationId: string, inviteId: string) => Promise<AuthResult<null>>;\n};\n\nexport type UseOrgResult = Pick<\n GeekappsAuthContextValue,\n | \"organizations\"\n | \"currentOrg\"\n | \"currentOrgId\"\n | \"isLoadingOrganizations\"\n | \"refreshOrganizations\"\n | \"setCurrentOrg\"\n | \"createOrganization\"\n | \"updateOrganization\"\n | \"deleteOrganization\"\n | \"hasPermission\"\n>;\n\nexport type UseAccountsResult = Pick<\n GeekappsAuthContextValue,\n \"accounts\" | \"addAccount\" | \"isLoadingAccounts\" | \"refreshAccounts\" | \"switchAccount\"\n>;\n\nexport type UseUsersResult = Pick<\n GeekappsAuthContextValue,\n \"listUsers\" | \"getUser\" | \"createUser\" | \"updateUser\" | \"deleteUser\"\n>;\n\nexport type UseRolesResult = Pick<\n GeekappsAuthContextValue,\n \"listRoles\" | \"getRole\" | \"createRole\" | \"updateRole\" | \"deleteRole\"\n>;\n\nexport type UsePermissionsResult = Pick<\n GeekappsAuthContextValue,\n \"listPermissions\" | \"createPermission\" | \"updatePermission\" | \"deletePermission\"\n>;\n\nexport type UseSessionsResult = Pick<\n GeekappsAuthContextValue,\n \"listUserSessions\" | \"revokeUserSession\"\n>;\n\nexport type UseMembersResult = Pick<\n GeekappsAuthContextValue,\n | \"listMembers\"\n | \"getMember\"\n | \"addMember\"\n | \"updateMember\"\n | \"updateMemberRole\"\n | \"removeMember\"\n | \"inviteMember\"\n | \"listInvites\"\n | \"revokeInvite\"\n>;\n\nexport type UsePublicOrganizationsResult = Pick<GeekappsAuthContextValue, \"listPublicOrganizations\">;\n\nexport type UseJoinRequestsResult = Pick<\n GeekappsAuthContextValue,\n | \"requestToJoin\"\n | \"getMyJoinRequest\"\n | \"cancelJoinRequest\"\n | \"listJoinRequests\"\n | \"approveJoinRequest\"\n | \"rejectJoinRequest\"\n>;\n\nexport type UseInvitesResult = Pick<GeekappsAuthContextValue, \"getInvitePreview\" | \"acceptInvite\" | \"rejectInvite\">;\n\nconst GeekappsAuthContext = createContext<GeekappsAuthContextValue | null>(null);\n\nexport function GeekappsAuthProvider({\n children,\n basePath = \"/api/auth\",\n initialUser = null,\n initialOrganizations = [],\n initialCurrentOrgId = null,\n}: GeekappsAuthProviderProps): ReactElement {\n const [user, setUser] = useState<User | null>(initialUser);\n const [isLoading, setIsLoading] = useState(true);\n const [accounts, setAccounts] = useState<ConnectedAccount[]>([]);\n const [isLoadingAccounts, setIsLoadingAccounts] = useState(true);\n const [organizations, setOrganizations] = useState<Organization[]>(initialOrganizations);\n const [currentOrgId, setCurrentOrgId] = useState<string | null>(initialCurrentOrgId);\n const [isLoadingOrganizations, setIsLoadingOrganizations] = useState(true);\n\n const request = useCallback(\n async <T,>(path: string, options: RequestOptions = {}) => {\n const response = await fetch(buildUrl(basePath, path), {\n method: options.method ?? \"GET\",\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n },\n [basePath],\n );\n\n const refreshUser = useCallback(async () => {\n setIsLoading(true);\n try {\n const { user: u } = await request<{ user: User | null }>(\"/me\");\n setUser(u);\n } catch {\n setUser(null);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const refreshAccounts = useCallback(async () => {\n setIsLoadingAccounts(true);\n try {\n const { accounts: a } = await request<{ accounts: ConnectedAccount[] }>(\n \"/accounts\",\n );\n setAccounts(a);\n } catch {\n setAccounts([]);\n } finally {\n setIsLoadingAccounts(false);\n }\n }, []);\n\n const refreshOrganizations = useCallback(async () => {\n setIsLoadingOrganizations(true);\n try {\n const { organizations: orgs, currentOrgId: nextCurrentOrgId } =\n await request<{\n organizations: Organization[];\n currentOrgId?: string | null;\n }>(\"/organizations\");\n setOrganizations(orgs);\n setCurrentOrgId((current) => {\n if (nextCurrentOrgId !== undefined) return nextCurrentOrgId ?? null;\n if (current && orgs.some((org) => org.id === current)) return current;\n return orgs[0]?.id ?? null;\n });\n } catch {\n setOrganizations([]);\n setCurrentOrgId(null);\n } finally {\n setIsLoadingOrganizations(false);\n }\n }, []);\n\n useEffect(() => {\n void refreshUser();\n void refreshAccounts();\n void refreshOrganizations();\n }, [refreshAccounts, refreshOrganizations, refreshUser]);\n\n const currentOrg = useMemo(\n () => organizations.find((organization) => organization.id === currentOrgId) ?? null,\n [currentOrgId, organizations],\n );\n\n const setCurrentOrg = useCallback(\n async (organizationId: string | null) => {\n await request(\"/organizations/active\", {\n method: \"POST\",\n body: { organizationId },\n });\n setCurrentOrgId(organizationId);\n },\n [request],\n );\n\n const signIn = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-in\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n const prompt = options?.prompt ?? (options?.silentLogin === false ? \"login\" : undefined);\n if (prompt) url.searchParams.set(\"prompt\", prompt);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signUp = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-up\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n const prompt = options?.prompt ?? (options?.silentLogin === false ? \"login\" : undefined);\n if (prompt) url.searchParams.set(\"prompt\", prompt);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const addAccount = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/add-account\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signOut = useCallback(async () => {\n await request(\"/sign-out\", { method: \"POST\" });\n setUser(null);\n await refreshAccounts();\n }, [refreshAccounts, request]);\n\n const signOutAll = useCallback(async () => {\n await request(\"/sign-out-all\", { method: \"POST\" });\n setUser(null);\n setAccounts([]);\n }, [request]);\n\n const switchAccount = useCallback(\n async (sessionId: string, options?: SignInOptions) => {\n await request(\"/accounts/switch\", {\n method: \"POST\",\n body: { sessionId },\n });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (options?.redirectTo) redirectTo(options.redirectTo);\n },\n [refreshAccounts, refreshOrganizations, refreshUser, request],\n );\n\n async function toAuthResult<T>(fn: () => Promise<T>): Promise<AuthResult<T>> {\n try {\n return { success: true, data: await fn() };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : \"Unexpected error\" };\n }\n }\n\n // ── Invites: precisam do status HTTP cru (401/404/409), não só uma\n // mensagem — request()/toAuthResult() não bastam aqui.\n const getInvitePreview = useCallback(\n (token: string) => request<OrganizationInvitePreview>(`/organizations/invites/${encodeURIComponent(token)}`),\n [request],\n );\n\n const acceptInvite = useCallback(\n async (token: string): Promise<AcceptInviteResult> => {\n const response = await fetch(buildUrl(basePath, \"/organizations/invites/accept\"), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n const data = await response.json().catch(() => null);\n\n if (response.ok && data) {\n return {\n success: true,\n organizationId: data.organizationId,\n organizationName: data.organizationName,\n websiteUrl: data.websiteUrl ?? null,\n };\n }\n if (response.status === 409 && data?.error === \"wrong_account\") {\n return {\n success: false,\n wrongAccount: true,\n currentEmail: String(data.currentEmail ?? \"\"),\n invitedEmail: String(data.invitedEmail ?? \"\"),\n };\n }\n if (response.status === 401 && data?.error === \"login_required\") {\n return { success: false, wrongAccount: false, loginRequired: true };\n }\n return {\n success: false,\n wrongAccount: false,\n loginRequired: false,\n error: typeof data?.error === \"string\" ? data.error : `HTTP ${response.status}`,\n };\n },\n [basePath],\n );\n\n const rejectInvite = useCallback(\n async (token: string): Promise<{ success: true } | { success: false; error: string }> => {\n const response = await fetch(buildUrl(basePath, \"/organizations/invites/reject\"), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n if (response.ok) return { success: true };\n const data = await response.json().catch(() => null);\n return { success: false, error: typeof data?.error === \"string\" ? data.error : `HTTP ${response.status}` };\n },\n [basePath],\n );\n\n const getMyJoinRequest = useCallback(\n async (organizationId: string): Promise<OrganizationJoinRequest | null> => {\n const response = await fetch(buildUrl(basePath, `/organizations/${organizationId}/join-requests/me`), {\n credentials: \"include\",\n });\n if (response.status === 404) return null;\n if (!response.ok) throw new Error(await parseError(response));\n return response.json();\n },\n [basePath],\n );\n\n const value = useMemo<GeekappsAuthContextValue>(\n () => ({\n basePath,\n user,\n isAuthenticated: !isLoading && user !== null,\n isLoading,\n accounts,\n isLoadingAccounts,\n organizations,\n currentOrg,\n currentOrgId,\n isLoadingOrganizations,\n request,\n signIn,\n signUp,\n addAccount,\n signOut,\n signOutAll,\n refreshUser,\n refreshAccounts,\n switchAccount,\n loginWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<LoginResponse>(\"/login/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo ?? data.redirectTo) redirectTo(params.redirectTo ?? data.redirectTo!);\n return data;\n }),\n registerWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<RegisterResponse>(\"/register/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo) redirectTo(params.redirectTo);\n return data;\n }),\n startGoogleLogin: (params) => {\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n if (params?.callbackUrl) url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n if (params?.redirectTo) url.searchParams.set(\"redirectTo\", params.redirectTo);\n if (params?.authorizationFlowId) url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n redirectTo(url.toString());\n },\n requestPasswordlessLink: (params) =>\n toAuthResult(() => request(\"/passwordless/link\", { method: \"POST\", body: params })),\n refreshOrganizations,\n setCurrentOrg,\n createOrganization: (input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(\"/organizations\", { method: \"POST\", body: input });\n await refreshOrganizations();\n setCurrentOrgId(organization.id);\n return organization;\n }),\n updateOrganization: (id, input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(`/organizations/${id}`, { method: \"PATCH\", body: input });\n await refreshOrganizations();\n return organization;\n }),\n deleteOrganization: (id) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${id}`, { method: \"DELETE\" });\n await refreshOrganizations();\n return null;\n }),\n hasPermission: async (options) => {\n try {\n const data = await request<{ allowed: boolean }>(\"/permissions/check\", {\n method: \"POST\",\n body: options,\n });\n return data.allowed;\n } catch {\n return false;\n }\n },\n listUsers: (params) => {\n const query = new URLSearchParams();\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<User[]>(`/users${query.size ? `?${query.toString()}` : \"\"}`);\n },\n getUser: (id) => request<User>(`/users/${id}`),\n createUser: (input) => toAuthResult(() => request<User>(\"/users\", { method: \"POST\", body: input })),\n updateUser: (id, input) => toAuthResult(() => request<User>(`/users/${id}`, { method: \"PATCH\", body: input })),\n deleteUser: (id) =>\n toAuthResult(async () => {\n await request<null>(`/users/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listRoles: (params) => {\n const query = new URLSearchParams();\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n if (params?.applicationId) query.set(\"applicationId\", params.applicationId);\n if (params?.type) query.set(\"type\", params.type);\n return request<{ systemRoles: Role[]; customRoles: Role[] }>(`/roles${query.size ? `?${query.toString()}` : \"\"}`);\n },\n getRole: (id, type) => request<Role>(type === \"custom\" ? `/roles/custom/${id}` : `/roles/definitions/${id}`),\n createRole: (input) => toAuthResult(() => request<Role>(\"/roles\", { method: \"POST\", body: input })),\n updateRole: (id, input) => toAuthResult(() => request<Role>(`/roles/custom/${id}`, { method: \"PATCH\", body: input })),\n deleteRole: (id) =>\n toAuthResult(async () => {\n await request<null>(`/roles/custom/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listPermissions: (params) => {\n const query = new URLSearchParams();\n if (params?.applicationId) query.set(\"applicationId\", params.applicationId);\n if (params?.roleId) query.set(\"roleId\", params.roleId);\n return request<Permission[]>(`/permissions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n createPermission: (input) =>\n toAuthResult(() => request<Permission>(\"/permissions\", { method: \"POST\", body: input })),\n updatePermission: (id, input) =>\n toAuthResult(() => request<Permission>(`/permissions/${id}`, { method: \"PATCH\", body: input })),\n deletePermission: (id) =>\n toAuthResult(async () => {\n await request<null>(`/permissions/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listUserSessions: (params) => {\n const query = new URLSearchParams();\n if (params?.userId) query.set(\"userId\", params.userId);\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<UserSession[]>(`/sessions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n revokeUserSession: (sessionId) =>\n toAuthResult(async () => {\n await request<null>(`/sessions/${sessionId}`, { method: \"DELETE\" });\n return null;\n }),\n listMembers: (organizationId) =>\n request<OrganizationMember[]>(`/organizations/${organizationId}/members`),\n getMember: (organizationId, memberId) =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`),\n addMember: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members`, {\n method: \"POST\",\n body: input,\n }),\n ),\n updateMember: (organizationId, memberId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`, {\n method: \"PATCH\",\n body: input,\n }),\n ),\n updateMemberRole: (organizationId, memberId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`, {\n method: \"PATCH\",\n body: input,\n }),\n ),\n removeMember: (organizationId, memberId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/members/${memberId}`, { method: \"DELETE\" });\n return null;\n }),\n inviteMember: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationInvite>(`/organizations/${organizationId}/invites`, {\n method: \"POST\",\n body: input,\n }),\n ),\n listInvites: (organizationId) =>\n request<OrganizationInvite[]>(`/organizations/${organizationId}/invites`),\n revokeInvite: (organizationId, inviteId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/invites/${inviteId}`, { method: \"DELETE\" });\n return null;\n }),\n listPublicOrganizations: () => request<PublicOrganization[]>(\"/organizations/public\"),\n requestToJoin: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests`, {\n method: \"POST\",\n body: input ?? {},\n }),\n ),\n getMyJoinRequest,\n cancelJoinRequest: (organizationId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/join-requests/me`, { method: \"DELETE\" });\n return null;\n }),\n listJoinRequests: (organizationId) =>\n request<OrganizationJoinRequest[]>(`/organizations/${organizationId}/join-requests`),\n approveJoinRequest: (organizationId, requestId) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests/${requestId}/approve`, {\n method: \"POST\",\n }),\n ),\n rejectJoinRequest: (organizationId, requestId) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests/${requestId}/reject`, {\n method: \"POST\",\n }),\n ),\n getInvitePreview,\n acceptInvite,\n rejectInvite,\n }),\n [\n accounts,\n acceptInvite,\n addAccount,\n basePath,\n currentOrg,\n currentOrgId,\n getInvitePreview,\n getMyJoinRequest,\n isLoading,\n isLoadingAccounts,\n isLoadingOrganizations,\n organizations,\n refreshAccounts,\n refreshOrganizations,\n refreshUser,\n rejectInvite,\n request,\n setCurrentOrg,\n signIn,\n signOut,\n signOutAll,\n signUp,\n switchAccount,\n user,\n ],\n );\n\n return <GeekappsAuthContext.Provider value={value}>{children}</GeekappsAuthContext.Provider>;\n}\n\nexport function useAuth(): GeekappsAuthContextValue {\n const context = useContext(GeekappsAuthContext);\n if (!context) throw new Error(\"useAuth must be used inside GeekappsAuthProvider\");\n return context;\n}\n\nexport function useOrg(): UseOrgResult {\n const context = useAuth();\n return {\n organizations: context.organizations,\n currentOrg: context.currentOrg,\n currentOrgId: context.currentOrgId,\n isLoadingOrganizations: context.isLoadingOrganizations,\n refreshOrganizations: context.refreshOrganizations,\n setCurrentOrg: context.setCurrentOrg,\n createOrganization: context.createOrganization,\n updateOrganization: context.updateOrganization,\n deleteOrganization: context.deleteOrganization,\n hasPermission: context.hasPermission,\n };\n}\n\nexport function useAccounts(): UseAccountsResult {\n const context = useAuth();\n return {\n accounts: context.accounts,\n addAccount: context.addAccount,\n isLoadingAccounts: context.isLoadingAccounts,\n refreshAccounts: context.refreshAccounts,\n switchAccount: context.switchAccount,\n };\n}\n\nexport function useUsers(): UseUsersResult {\n const context = useAuth();\n return {\n listUsers: context.listUsers,\n getUser: context.getUser,\n createUser: context.createUser,\n updateUser: context.updateUser,\n deleteUser: context.deleteUser,\n };\n}\n\nexport function useRoles(): UseRolesResult {\n const context = useAuth();\n return {\n listRoles: context.listRoles,\n getRole: context.getRole,\n createRole: context.createRole,\n updateRole: context.updateRole,\n deleteRole: context.deleteRole,\n };\n}\n\nexport function usePermissions(): UsePermissionsResult {\n const context = useAuth();\n return {\n listPermissions: context.listPermissions,\n createPermission: context.createPermission,\n updatePermission: context.updatePermission,\n deletePermission: context.deletePermission,\n };\n}\n\nexport function useSessions(): UseSessionsResult {\n const context = useAuth();\n return {\n listUserSessions: context.listUserSessions,\n revokeUserSession: context.revokeUserSession,\n };\n}\n\nexport function useMembers(): UseMembersResult {\n const context = useAuth();\n return {\n listMembers: context.listMembers,\n getMember: context.getMember,\n addMember: context.addMember,\n updateMember: context.updateMember,\n updateMemberRole: context.updateMemberRole,\n removeMember: context.removeMember,\n inviteMember: context.inviteMember,\n listInvites: context.listInvites,\n revokeInvite: context.revokeInvite,\n };\n}\n\n/**\n * Descoberta de organizações PÚBLICAS do app — bem separado de `useOrg()`,\n * que lida com as organizações do próprio usuário (as que ele já é\n * membro/dono). `usePublicOrganizations()` nunca retorna organizações\n * privadas, e não exige que o usuário já pertença a elas.\n */\nexport function usePublicOrganizations(): UsePublicOrganizationsResult {\n const context = useAuth();\n return {\n listPublicOrganizations: context.listPublicOrganizations,\n };\n}\n\n/**\n * Solicitações de entrada em organizações públicas: um usuário pede pra\n * entrar (requestToJoin) e um admin da organização aprova/rejeita\n * (approveJoinRequest/rejectJoinRequest, exigem permissão org:members:add).\n */\nexport function useJoinRequests(): UseJoinRequestsResult {\n const context = useAuth();\n return {\n requestToJoin: context.requestToJoin,\n getMyJoinRequest: context.getMyJoinRequest,\n cancelJoinRequest: context.cancelJoinRequest,\n listJoinRequests: context.listJoinRequests,\n approveJoinRequest: context.approveJoinRequest,\n rejectJoinRequest: context.rejectJoinRequest,\n };\n}\n\n/**\n * Aceite/recusa de convite por email — chamadas a partir do ?invite_token=\n * que este app recebe na sua própria redirectUri (a que foi passada em\n * useMembers().inviteMember). getInvitePreview funciona sem sessão\n * (currentAccount vem null); rejectInvite não exige login; acceptInvite\n * retorna loginRequired:true se não houver sessão.\n */\nexport function useInvites(): UseInvitesResult {\n const context = useAuth();\n return {\n getInvitePreview: context.getInvitePreview,\n acceptInvite: context.acceptInvite,\n rejectInvite: context.rejectInvite,\n };\n}\n\n// ── Service Accounts ─────────────────────────────────────────────────────────\n\nexport type ServiceAccount = {\n id: string;\n membershipId: string;\n organizationId: string;\n applicationId: string | null;\n name: string;\n status: \"active\" | \"inactive\" | \"suspended\";\n serviceId: string | null;\n roleAssignment: { role: { id: string; key: string; name: string } } | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type ServiceAccountWithSecret = ServiceAccount & { serviceSecret: string };\n\nexport type CreateServiceAccountInput = {\n organizationId: string;\n applicationId?: string;\n name: string;\n description?: string;\n roleId?: string;\n};\n\nexport type UseServiceAccountResult = {\n listServiceAccounts: (params: { organizationId: string; applicationId?: string }) => Promise<ServiceAccount[]>;\n createServiceAccount: (input: CreateServiceAccountInput) => Promise<ServiceAccountWithSecret>;\n updateServiceAccountRole: (id: string, roleId: string | null) => Promise<void>;\n revokeServiceAccount: (id: string) => Promise<void>;\n rotateServiceAccountSecret: (id: string) => Promise<{ serviceId: string; serviceSecret: string }>;\n deleteServiceAccount: (id: string) => Promise<void>;\n};\n\nexport function useServiceAccount(): UseServiceAccountResult {\n const { request } = useAuth();\n\n const listServiceAccounts = useCallback(\n (params: { organizationId: string; applicationId?: string }) => {\n const query = new URLSearchParams({ organizationId: params.organizationId });\n if (params.applicationId) query.set(\"applicationId\", params.applicationId);\n return request<ServiceAccount[]>(`/service-accounts?${query.toString()}`);\n },\n [request],\n );\n\n const createServiceAccount = useCallback(\n (input: CreateServiceAccountInput) =>\n request<ServiceAccountWithSecret>(\"/service-accounts\", { method: \"POST\", body: input }),\n [request],\n );\n\n const updateServiceAccountRole = useCallback(\n async (id: string, roleId: string | null) => {\n await request<void>(`/service-accounts/${id}`, { method: \"PATCH\", body: { roleId } });\n },\n [request],\n );\n\n const revokeServiceAccount = useCallback(\n async (id: string) => {\n await request<void>(`/service-accounts/${id}/revoke`, { method: \"POST\" });\n },\n [request],\n );\n\n const rotateServiceAccountSecret = useCallback(\n (id: string) =>\n request<{ serviceId: string; serviceSecret: string }>(`/service-accounts/${id}/rotate-secret`, {\n method: \"POST\",\n }),\n [request],\n );\n\n const deleteServiceAccount = useCallback(\n async (id: string) => {\n await request<null>(`/service-accounts/${id}`, { method: \"DELETE\" });\n },\n [request],\n );\n\n return {\n listServiceAccounts,\n createServiceAccount,\n updateServiceAccountRole,\n revokeServiceAccount,\n rotateServiceAccountSecret,\n deleteServiceAccount,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/client.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type UserStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OrganizationStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OAuthClientType = \"public\" | \"confidential\";\n\nexport type AuthResult<T = unknown> =\n | { success: true; data: T }\n | { success: false; error: string; status?: number };\n\nexport type User = {\n id: string;\n email: string;\n name: string | null;\n phone: string | null;\n imageUrl: string | null;\n status?: UserStatus;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type ConnectedAccount = {\n id: string;\n sessionId?: string;\n isActive: boolean;\n user: User;\n};\n\nexport type Permission = {\n id: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description: string | null;\n category: string | null;\n isSystem: boolean;\n isActive: boolean;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RolePermission = {\n permissionDefinition: Permission;\n};\n\nexport type Role = {\n id: string;\n applicationId?: string | null;\n /** Present only on custom roles */\n organizationId?: string | null;\n /** \"system\" | \"custom\" */\n type?: string;\n key: string;\n name: string;\n description: string | null;\n isSystem?: boolean;\n isDefault?: boolean;\n isActive: boolean;\n permissions: RolePermission[];\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RoleAssignment = {\n id: string;\n roleDefinitionId?: string | null;\n customRoleId?: string | null;\n roleDefinition?: Role | null;\n customRole?: Role | null;\n};\n\nexport type OrganizationMember = {\n id: string;\n organizationId?: string;\n userId?: string;\n createdAt?: string | Date;\n user: User;\n roleAssignments?: RoleAssignment[];\n};\n\nexport type OrganizationInvite = {\n id: string;\n organizationId: string;\n email: string;\n /**\n * Role que o convidado assume ao aceitar. Vem aninhada do auth-server (não\n * como roleId solto) — null quando o convite não fixa nenhuma e o membro\n * cai na role default da organização.\n */\n role: { id: string; key: string; name: string } | null;\n /** @deprecated use `role.id` — o auth-server não devolve este campo. */\n roleId?: string | null;\n status: \"pending\" | \"accepted\" | \"expired\" | \"revoked\";\n expiresAt: string | Date;\n acceptedAt?: string | Date | null;\n createdAt?: string | Date;\n redirectUri?: string | null;\n emailTitle?: string | null;\n emailSubtitle?: string | null;\n emailMessage?: string | null;\n};\n\nexport type MemberInviteInput = {\n email: string;\n roleId?: string;\n /**\n * URI pra onde o link do e-mail manda o usuário — precisa estar cadastrada\n * em Application.redirectUris (mesma validação do /authorize). Este app\n * deve expor uma rota nessa URI que trata o `?invite_token=` anexado (ver\n * useJoinRequests/inviteApi.preview|accept|reject abaixo).\n */\n redirectUri: string;\n emailTitle?: string;\n emailSubtitle?: string;\n emailMessage?: string;\n};\n\nexport type AddMemberInput = {\n userId: string;\n roleId?: string;\n};\n\nexport type UpdateMemberInput = {\n status?: \"active\" | \"inactive\" | \"suspended\";\n roleId?: string | null;\n};\n\n/** @deprecated use UpdateMemberInput */\nexport type UpdateMemberRoleInput = {\n roleId: string;\n};\n\nexport type PublicOrganization = {\n id: string;\n name: string;\n slug: string;\n description: string | null;\n imageUrl: string | null;\n createdAt: string | Date;\n};\n\nexport type OrganizationInvitePreview =\n | {\n alreadyAccepted: true;\n organizationId: string;\n organizationName: string;\n applicationName: string;\n applicationImageUrl: string | null;\n applicationImageFileId: string | null;\n organizationImageUrl: string | null;\n organizationImageFileId: string | null;\n websiteUrl: string | null;\n }\n | {\n alreadyAccepted?: false;\n email: string;\n organizationId: string;\n organizationName: string;\n applicationName: string;\n applicationId: string;\n applicationImageUrl: string | null;\n applicationImageFileId: string | null;\n organizationImageUrl: string | null;\n organizationImageFileId: string | null;\n websiteUrl: string | null;\n redirectUri: string | null;\n appStoreUrl: string | null;\n playStoreUrl: string | null;\n currentAccount: { email: string; name: string | null } | null;\n };\n\nexport type AcceptInviteResult =\n | { success: true; organizationId: string; organizationName: string; websiteUrl: string | null }\n | { success: false; wrongAccount: true; currentEmail: string; invitedEmail: string }\n | { success: false; wrongAccount: false; loginRequired: true }\n | { success: false; wrongAccount: false; loginRequired: false; error: string };\n\nexport type JoinRequestStatus = \"pending\" | \"approved\" | \"rejected\" | \"cancelled\";\n\nexport type OrganizationJoinRequest = {\n id: string;\n organizationId: string;\n userId: string;\n status: JoinRequestStatus;\n message: string | null;\n reviewedByUserId: string | null;\n reviewedAt: string | null;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nexport type OrganizationOwnedApplication = {\n id: string;\n name: string;\n description: string | null;\n imageUrl: string | null;\n type?: OAuthClientType;\n organizationId: string;\n isFirstParty: boolean;\n ssoEnabled: boolean;\n status?: \"active\" | \"inactive\" | \"suspended\";\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type Organization = {\n id: string;\n name: string;\n description: string | null;\n slug: string;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n status: OrganizationStatus;\n /** \"private\" (padrão) nunca sai em listPublicOrganizations(); \"public\" sai, e aceita join requests. */\n visibility?: \"public\" | \"private\";\n members?: OrganizationMember[];\n ownedApplications?: OrganizationOwnedApplication[];\n applicationLinks?: Array<{\n id: string;\n status: OrganizationStatus;\n createdAt?: string | Date;\n application: OrganizationOwnedApplication;\n }>;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nexport type SessionApplication = {\n id: string;\n createdAt: string | Date;\n expiresAt: string | Date;\n application: {\n id: string;\n name: string;\n organizationId: string;\n };\n};\n\nexport type UserSession = {\n id: string;\n userId: string;\n organizationId: string | null;\n deviceAgent: string | null;\n deviceId: string | null;\n deviceName: string | null;\n ip: string | null;\n authState?: unknown;\n authTime?: string | Date;\n expiresAt: string | Date;\n createdAt: string | Date;\n updatedAt: string | Date;\n user?: User;\n applicationSessions?: SessionApplication[];\n};\n\nexport type UserInput = {\n name?: string | null;\n email?: string;\n phone?: string | null;\n imageUrl?: string | null;\n password?: string;\n organizationId?: string | null;\n status?: UserStatus;\n};\n\nexport type OrganizationInput = {\n name: string;\n description?: string | null;\n slug: string;\n domain?: string | null;\n imageUrl?: string | null;\n faviconUrl?: string | null;\n};\n\nexport type OrganizationUpdateInput = Partial<OrganizationInput> & {\n status?: OrganizationStatus;\n};\n\nexport type RoleInput = {\n /** Opcional: sem ele, usa a organização ativa. */\n organizationId?: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n permissionDefinitionIds?: string[];\n};\n\nexport type RoleUpdateInput = {\n name?: string;\n description?: string | null;\n isActive?: boolean;\n permissionDefinitionIds?: string[];\n};\n\nexport type PermissionInput = {\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n category?: string | null;\n};\n\nexport type PermissionUpdateInput = {\n name?: string;\n description?: string | null;\n category?: string | null;\n isActive?: boolean;\n};\n\n/**\n * OIDC `prompt` values understood by the Geekapps Auth Server. These control\n * whether — and how — the IDP shows UI during `signIn()`/`signUp()`/`addAccount()`.\n *\n * - `\"login\"` — Forces the login screen, even if the user already has an active\n * session. Use this for a fresh login, unrelated to whatever session already\n * exists (equivalent to the old `silentLogin: false`).\n * - `\"select_account\"` — Shows the account picker so the user can choose among\n * their connected accounts, or add a new one. Use this when you want to let\n * the user switch accounts explicitly.\n * - `\"none\"` — Never shows any UI. The IDP authenticates silently if there is\n * exactly one active session (and no other interaction — like consent or a\n * security check — is pending); otherwise it fails immediately with an OIDC\n * error (`login_required`, `account_selection_required`, `consent_required`,\n * or `interaction_required`) instead of prompting the user. Use this for\n * silent-auth checks (e.g. \"is the user still logged in?\") where you don't\n * want to interrupt them with a screen.\n * - `\"consent\"` — Forces the consent screen even if the user already granted\n * the requested scopes before.\n *\n * Omitting `prompt` entirely runs the IDP's default flow: reuse a single\n * existing session silently, ask the user to pick when there are multiple\n * connected accounts, or show the login screen when there's none.\n */\nexport type OidcPrompt = \"login\" | \"select_account\" | \"none\" | \"consent\";\n\nexport type SignInOptions = {\n redirectTo?: string;\n authorizationFlowId?: string;\n /**\n * Controls whether the IDP shows UI, and which screen, during sign-in. See\n * {@link OidcPrompt} for what each value does. Omit it to run the default flow.\n */\n prompt?: OidcPrompt;\n /**\n * @deprecated Use `prompt: \"login\"` instead. Kept for backwards compatibility —\n * `silentLogin: false` is equivalent to `prompt: \"login\"`.\n */\n silentLogin?: boolean;\n};\n\nexport type SignInInput = SignInOptions | MouseEvent<HTMLElement>;\n\nexport type CallbackUrlOptions = SignInOptions & {\n callbackUrl?: string;\n};\n\nexport type PermissionCheckOptions = {\n permission: string;\n organizationId?: string | null;\n applicationId?: string | null;\n resourceId?: string | null;\n};\n\nexport type LoginResponse = {\n user: User;\n redirectTo?: string | null;\n};\n\nexport type RegisterResponse = User;\n\nexport type GeekappsAuthProviderProps = {\n children: ReactNode;\n basePath?: string;\n initialUser?: User | null;\n initialOrganizations?: Organization[];\n initialCurrentOrgId?: string | null;\n};\n\ntype RequestOptions = {\n body?: unknown;\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n};\n\nfunction normalizeBasePath(basePath: string) {\n return basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n}\n\nfunction buildUrl(basePath: string, path: string) {\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${normalizeBasePath(basePath)}${normalizedPath}`;\n}\n\nasync function parseError(response: Response) {\n const data = await response.json().catch(() => null);\n return (\n data?.error_description ??\n data?.error ??\n data?.message ??\n `Request failed with status ${response.status}`\n );\n}\n\nfunction redirectTo(path: string) {\n window.location.assign(path);\n}\n\nfunction isMouseEvent(value: unknown): value is MouseEvent<HTMLElement> {\n return Boolean(value && typeof value === \"object\" && \"preventDefault\" in value);\n}\n\nfunction normalizeSignInOptions(input?: SignInInput): SignInOptions | undefined {\n if (!input) return undefined;\n if (isMouseEvent(input)) {\n input.preventDefault();\n return undefined;\n }\n return input;\n}\n\n\ntype ClientActionOptions = {\n basePath?: string;\n};\n\nasync function clientRequest<T>(\n path: string,\n options: RequestOptions = {},\n basePath = \"/api/auth\",\n): Promise<T> {\n const response = await fetch(buildUrl(basePath, path), {\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n method: options.method ?? \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n}\n\nasync function toStandaloneAuthResult<T>(\n fn: () => Promise<T>,\n): Promise<AuthResult<T>> {\n try {\n return {\n success: true,\n data: await fn(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Auth request failed\",\n };\n }\n}\n\nexport async function loginWithPassword(\n params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<LoginResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<LoginResponse>(\n \"/login/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo ?? data.redirectTo) {\n redirectTo(params.redirectTo ?? data.redirectTo!);\n }\n\n return data;\n });\n}\n\nexport async function registerWithPassword(\n params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<RegisterResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<RegisterResponse>(\n \"/register/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo) {\n redirectTo(params.redirectTo);\n }\n\n return data;\n });\n}\n\nexport function startGoogleLogin(\n params?: CallbackUrlOptions,\n options?: ClientActionOptions,\n) {\n const basePath = options?.basePath ?? \"/api/auth\";\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n\n if (params?.callbackUrl) {\n url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n }\n\n if (params?.redirectTo) {\n url.searchParams.set(\"redirectTo\", params.redirectTo);\n }\n\n if (params?.authorizationFlowId) {\n url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n }\n\n redirectTo(url.toString());\n}\n\nexport async function requestPasswordlessLink(\n params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult> {\n return toStandaloneAuthResult(() =>\n clientRequest(\n \"/passwordless/link\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n ),\n );\n}\n\nexport type GeekappsAuthContextValue = {\n basePath: string;\n user: User | null;\n isAuthenticated: boolean;\n isLoading: boolean;\n accounts: ConnectedAccount[];\n isLoadingAccounts: boolean;\n organizations: Organization[];\n currentOrg: Organization | null;\n currentOrgId: string | null;\n isLoadingOrganizations: boolean;\n\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n\n signIn: (options?: SignInInput) => Promise<void>;\n signUp: (options?: SignInInput) => Promise<void>;\n addAccount: (options?: SignInInput) => Promise<void>;\n signOut: () => Promise<void>;\n signOutAll: () => Promise<void>;\n refreshUser: () => Promise<void>;\n refreshAccounts: () => Promise<void>;\n switchAccount: (sessionId: string, options?: SignInOptions) => Promise<void>;\n\n loginWithPassword: (params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n }) => Promise<AuthResult<LoginResponse>>;\n registerWithPassword: (params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n }) => Promise<AuthResult<RegisterResponse>>;\n startGoogleLogin: (params?: CallbackUrlOptions) => void;\n requestPasswordlessLink: (params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n }) => Promise<AuthResult>;\n\n refreshOrganizations: () => Promise<void>;\n setCurrentOrg: (organizationId: string | null) => Promise<void>;\n createOrganization: (input: OrganizationInput) => Promise<AuthResult<Organization>>;\n updateOrganization: (id: string, input: OrganizationUpdateInput) => Promise<AuthResult<Organization>>;\n deleteOrganization: (id: string) => Promise<AuthResult<null>>;\n hasPermission: (options: PermissionCheckOptions) => Promise<boolean>;\n\n /** 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). */\n listPublicOrganizations: () => Promise<PublicOrganization[]>;\n\n requestToJoin: (organizationId: string, input?: { message?: string | null }) => Promise<AuthResult<OrganizationJoinRequest>>;\n getMyJoinRequest: (organizationId: string) => Promise<OrganizationJoinRequest | null>;\n cancelJoinRequest: (organizationId: string) => Promise<AuthResult<null>>;\n listJoinRequests: (organizationId: string) => Promise<OrganizationJoinRequest[]>;\n approveJoinRequest: (organizationId: string, requestId: string) => Promise<AuthResult<OrganizationJoinRequest>>;\n rejectJoinRequest: (organizationId: string, requestId: string) => Promise<AuthResult<OrganizationJoinRequest>>;\n\n /** Preview do convite por token — funciona com ou sem sessão (currentAccount vem null se deslogado). */\n getInvitePreview: (token: string) => Promise<OrganizationInvitePreview>;\n /** Aceita o convite. loginRequired:true significa que signIn() precisa rodar antes. */\n acceptInvite: (token: string) => Promise<AcceptInviteResult>;\n /** Recusa o convite — não exige estar logado. */\n rejectInvite: (token: string) => Promise<{ success: true } | { success: false; error: string }>;\n\n listUsers: (params?: { organizationId?: string | null }) => Promise<User[]>;\n getUser: (id: string) => Promise<User>;\n createUser: (input: UserInput) => Promise<AuthResult<User>>;\n updateUser: (id: string, input: UserInput) => Promise<AuthResult<User>>;\n deleteUser: (id: string) => Promise<AuthResult<null>>;\n\n /**\n * Roles da organização. `organizationId` é opcional: sem ele, usa a\n * organização ativa. `applicationId`/`type` são aceitos por\n * compatibilidade e não filtram nada — a separação system/custom vem no\n * próprio retorno.\n */\n listRoles: (params?: { organizationId?: string; applicationId?: string; type?: \"system\" | \"custom\" | \"all\" }) => Promise<{ systemRoles: Role[]; customRoles: Role[] }>;\n getRole: (id: string, type?: \"system\" | \"custom\", organizationId?: string) => Promise<Role>;\n createRole: (input: RoleInput) => Promise<AuthResult<Role>>;\n updateRole: (id: string, input: RoleUpdateInput, organizationId?: string) => Promise<AuthResult<Role>>;\n deleteRole: (id: string, organizationId?: string) => Promise<AuthResult<null>>;\n\n listPermissions: (params?: { applicationId?: string; roleId?: string | null }) => Promise<Permission[]>;\n createPermission: (input: PermissionInput) => Promise<AuthResult<Permission>>;\n updatePermission: (id: string, input: PermissionUpdateInput) => Promise<AuthResult<Permission>>;\n deletePermission: (id: string) => Promise<AuthResult<null>>;\n\n listUserSessions: (params?: { userId?: string; organizationId?: string | null }) => Promise<UserSession[]>;\n revokeUserSession: (sessionId: string) => Promise<AuthResult<null>>;\n\n listMembers: (organizationId: string) => Promise<OrganizationMember[]>;\n getMember: (organizationId: string, memberId: string) => Promise<OrganizationMember>;\n addMember: (organizationId: string, input: AddMemberInput) => Promise<AuthResult<OrganizationMember>>;\n updateMember: (\n organizationId: string,\n memberId: string,\n input: UpdateMemberInput,\n ) => Promise<AuthResult<OrganizationMember>>;\n /** @deprecated use updateMember */\n updateMemberRole: (\n organizationId: string,\n memberId: string,\n input: UpdateMemberRoleInput,\n ) => Promise<AuthResult<OrganizationMember>>;\n removeMember: (organizationId: string, memberId: string) => Promise<AuthResult<null>>;\n inviteMember: (organizationId: string, input: MemberInviteInput) => Promise<AuthResult<OrganizationInvite>>;\n listInvites: (organizationId: string) => Promise<OrganizationInvite[]>;\n revokeInvite: (organizationId: string, inviteId: string) => Promise<AuthResult<null>>;\n};\n\nexport type UseOrgResult = Pick<\n GeekappsAuthContextValue,\n | \"organizations\"\n | \"currentOrg\"\n | \"currentOrgId\"\n | \"isLoadingOrganizations\"\n | \"refreshOrganizations\"\n | \"setCurrentOrg\"\n | \"createOrganization\"\n | \"updateOrganization\"\n | \"deleteOrganization\"\n | \"hasPermission\"\n>;\n\nexport type UseAccountsResult = Pick<\n GeekappsAuthContextValue,\n \"accounts\" | \"addAccount\" | \"isLoadingAccounts\" | \"refreshAccounts\" | \"switchAccount\"\n>;\n\nexport type UseUsersResult = Pick<\n GeekappsAuthContextValue,\n \"listUsers\" | \"getUser\" | \"createUser\" | \"updateUser\" | \"deleteUser\"\n>;\n\nexport type UseRolesResult = Pick<\n GeekappsAuthContextValue,\n \"listRoles\" | \"getRole\" | \"createRole\" | \"updateRole\" | \"deleteRole\"\n>;\n\nexport type UsePermissionsResult = Pick<\n GeekappsAuthContextValue,\n \"listPermissions\" | \"createPermission\" | \"updatePermission\" | \"deletePermission\"\n>;\n\nexport type UseSessionsResult = Pick<\n GeekappsAuthContextValue,\n \"listUserSessions\" | \"revokeUserSession\"\n>;\n\nexport type UseMembersResult = Pick<\n GeekappsAuthContextValue,\n | \"listMembers\"\n | \"getMember\"\n | \"addMember\"\n | \"updateMember\"\n | \"updateMemberRole\"\n | \"removeMember\"\n | \"inviteMember\"\n | \"listInvites\"\n | \"revokeInvite\"\n>;\n\nexport type UsePublicOrganizationsResult = Pick<GeekappsAuthContextValue, \"listPublicOrganizations\">;\n\nexport type UseJoinRequestsResult = Pick<\n GeekappsAuthContextValue,\n | \"requestToJoin\"\n | \"getMyJoinRequest\"\n | \"cancelJoinRequest\"\n | \"listJoinRequests\"\n | \"approveJoinRequest\"\n | \"rejectJoinRequest\"\n>;\n\nexport type UseInvitesResult = Pick<GeekappsAuthContextValue, \"getInvitePreview\" | \"acceptInvite\" | \"rejectInvite\">;\n\nconst GeekappsAuthContext = createContext<GeekappsAuthContextValue | null>(null);\n\nexport function GeekappsAuthProvider({\n children,\n basePath = \"/api/auth\",\n initialUser = null,\n initialOrganizations = [],\n initialCurrentOrgId = null,\n}: GeekappsAuthProviderProps): ReactElement {\n const [user, setUser] = useState<User | null>(initialUser);\n const [isLoading, setIsLoading] = useState(true);\n const [accounts, setAccounts] = useState<ConnectedAccount[]>([]);\n const [isLoadingAccounts, setIsLoadingAccounts] = useState(true);\n const [organizations, setOrganizations] = useState<Organization[]>(initialOrganizations);\n const [currentOrgId, setCurrentOrgId] = useState<string | null>(initialCurrentOrgId);\n const [isLoadingOrganizations, setIsLoadingOrganizations] = useState(true);\n\n // As chamadas de role resolvem a organização ativa na hora em que rodam, não\n // na hora em que foram criadas — sem o ref, um callback memoizado ficaria com\n // o org id que existia na primeira render.\n const currentOrgIdRef = useRef(currentOrgId);\n currentOrgIdRef.current = currentOrgId;\n\n const request = useCallback(\n async <T,>(path: string, options: RequestOptions = {}) => {\n const response = await fetch(buildUrl(basePath, path), {\n method: options.method ?? \"GET\",\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n },\n [basePath],\n );\n\n const refreshUser = useCallback(async () => {\n setIsLoading(true);\n try {\n const { user: u } = await request<{ user: User | null }>(\"/me\");\n setUser(u);\n } catch {\n setUser(null);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const refreshAccounts = useCallback(async () => {\n setIsLoadingAccounts(true);\n try {\n const { accounts: a } = await request<{ accounts: ConnectedAccount[] }>(\n \"/accounts\",\n );\n setAccounts(a);\n } catch {\n setAccounts([]);\n } finally {\n setIsLoadingAccounts(false);\n }\n }, []);\n\n const refreshOrganizations = useCallback(async () => {\n setIsLoadingOrganizations(true);\n try {\n const { organizations: orgs, currentOrgId: nextCurrentOrgId } =\n await request<{\n organizations: Organization[];\n currentOrgId?: string | null;\n }>(\"/organizations\");\n setOrganizations(orgs);\n setCurrentOrgId((current) => {\n if (nextCurrentOrgId !== undefined) return nextCurrentOrgId ?? null;\n if (current && orgs.some((org) => org.id === current)) return current;\n return orgs[0]?.id ?? null;\n });\n } catch {\n setOrganizations([]);\n setCurrentOrgId(null);\n } finally {\n setIsLoadingOrganizations(false);\n }\n }, []);\n\n useEffect(() => {\n void refreshUser();\n void refreshAccounts();\n void refreshOrganizations();\n }, [refreshAccounts, refreshOrganizations, refreshUser]);\n\n const currentOrg = useMemo(\n () => organizations.find((organization) => organization.id === currentOrgId) ?? null,\n [currentOrgId, organizations],\n );\n\n const setCurrentOrg = useCallback(\n async (organizationId: string | null) => {\n await request(\"/organizations/active\", {\n method: \"POST\",\n body: { organizationId },\n });\n setCurrentOrgId(organizationId);\n },\n [request],\n );\n\n const signIn = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-in\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n const prompt = options?.prompt ?? (options?.silentLogin === false ? \"login\" : undefined);\n if (prompt) url.searchParams.set(\"prompt\", prompt);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signUp = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-up\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n const prompt = options?.prompt ?? (options?.silentLogin === false ? \"login\" : undefined);\n if (prompt) url.searchParams.set(\"prompt\", prompt);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const addAccount = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/add-account\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signOut = useCallback(async () => {\n await request(\"/sign-out\", { method: \"POST\" });\n setUser(null);\n await refreshAccounts();\n }, [refreshAccounts, request]);\n\n const signOutAll = useCallback(async () => {\n await request(\"/sign-out-all\", { method: \"POST\" });\n setUser(null);\n setAccounts([]);\n }, [request]);\n\n const switchAccount = useCallback(\n async (sessionId: string, options?: SignInOptions) => {\n await request(\"/accounts/switch\", {\n method: \"POST\",\n body: { sessionId },\n });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (options?.redirectTo) redirectTo(options.redirectTo);\n },\n [refreshAccounts, refreshOrganizations, refreshUser, request],\n );\n\n async function toAuthResult<T>(fn: () => Promise<T>): Promise<AuthResult<T>> {\n try {\n return { success: true, data: await fn() };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : \"Unexpected error\" };\n }\n }\n\n // ── Invites: precisam do status HTTP cru (401/404/409), não só uma\n // mensagem — request()/toAuthResult() não bastam aqui.\n const getInvitePreview = useCallback(\n (token: string) => request<OrganizationInvitePreview>(`/organizations/invites/${encodeURIComponent(token)}`),\n [request],\n );\n\n const acceptInvite = useCallback(\n async (token: string): Promise<AcceptInviteResult> => {\n const response = await fetch(buildUrl(basePath, \"/organizations/invites/accept\"), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n const data = await response.json().catch(() => null);\n\n if (response.ok && data) {\n return {\n success: true,\n organizationId: data.organizationId,\n organizationName: data.organizationName,\n websiteUrl: data.websiteUrl ?? null,\n };\n }\n if (response.status === 409 && data?.error === \"wrong_account\") {\n return {\n success: false,\n wrongAccount: true,\n currentEmail: String(data.currentEmail ?? \"\"),\n invitedEmail: String(data.invitedEmail ?? \"\"),\n };\n }\n if (response.status === 401 && data?.error === \"login_required\") {\n return { success: false, wrongAccount: false, loginRequired: true };\n }\n return {\n success: false,\n wrongAccount: false,\n loginRequired: false,\n error: typeof data?.error === \"string\" ? data.error : `HTTP ${response.status}`,\n };\n },\n [basePath],\n );\n\n const rejectInvite = useCallback(\n async (token: string): Promise<{ success: true } | { success: false; error: string }> => {\n const response = await fetch(buildUrl(basePath, \"/organizations/invites/reject\"), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n if (response.ok) return { success: true };\n const data = await response.json().catch(() => null);\n return { success: false, error: typeof data?.error === \"string\" ? data.error : `HTTP ${response.status}` };\n },\n [basePath],\n );\n\n const getMyJoinRequest = useCallback(\n async (organizationId: string): Promise<OrganizationJoinRequest | null> => {\n const response = await fetch(buildUrl(basePath, `/organizations/${organizationId}/join-requests/me`), {\n credentials: \"include\",\n });\n if (response.status === 404) return null;\n if (!response.ok) throw new Error(await parseError(response));\n return response.json();\n },\n [basePath],\n );\n\n const value = useMemo<GeekappsAuthContextValue>(\n () => ({\n basePath,\n user,\n isAuthenticated: !isLoading && user !== null,\n isLoading,\n accounts,\n isLoadingAccounts,\n organizations,\n currentOrg,\n currentOrgId,\n isLoadingOrganizations,\n request,\n signIn,\n signUp,\n addAccount,\n signOut,\n signOutAll,\n refreshUser,\n refreshAccounts,\n switchAccount,\n loginWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<LoginResponse>(\"/login/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo ?? data.redirectTo) redirectTo(params.redirectTo ?? data.redirectTo!);\n return data;\n }),\n registerWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<RegisterResponse>(\"/register/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo) redirectTo(params.redirectTo);\n return data;\n }),\n startGoogleLogin: (params) => {\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n if (params?.callbackUrl) url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n if (params?.redirectTo) url.searchParams.set(\"redirectTo\", params.redirectTo);\n if (params?.authorizationFlowId) url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n redirectTo(url.toString());\n },\n requestPasswordlessLink: (params) =>\n toAuthResult(() => request(\"/passwordless/link\", { method: \"POST\", body: params })),\n refreshOrganizations,\n setCurrentOrg,\n createOrganization: (input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(\"/organizations\", { method: \"POST\", body: input });\n await refreshOrganizations();\n setCurrentOrgId(organization.id);\n return organization;\n }),\n updateOrganization: (id, input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(`/organizations/${id}`, { method: \"PATCH\", body: input });\n await refreshOrganizations();\n return organization;\n }),\n deleteOrganization: (id) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${id}`, { method: \"DELETE\" });\n await refreshOrganizations();\n return null;\n }),\n hasPermission: async (options) => {\n try {\n const data = await request<{ allowed: boolean }>(\"/permissions/check\", {\n method: \"POST\",\n body: options,\n });\n return data.allowed;\n } catch {\n return false;\n }\n },\n listUsers: (params) => {\n const query = new URLSearchParams();\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<User[]>(`/users${query.size ? `?${query.toString()}` : \"\"}`);\n },\n getUser: (id) => request<User>(`/users/${id}`),\n createUser: (input) => toAuthResult(() => request<User>(\"/users\", { method: \"POST\", body: input })),\n updateUser: (id, input) => toAuthResult(() => request<User>(`/users/${id}`, { method: \"PATCH\", body: input })),\n deleteUser: (id) =>\n toAuthResult(async () => {\n await request<null>(`/users/${id}`, { method: \"DELETE\" });\n return null;\n }),\n // Roles são sempre resolvidas no escopo de uma organização — o\n // auth-server não expõe /roles solto. Sem organizationId explícito,\n // usa a organização ativa; sem nenhuma das duas não há o que consultar.\n listRoles: async (params) => {\n const organizationId = params?.organizationId ?? currentOrgIdRef.current;\n if (!organizationId) {\n throw new Error(\n \"listRoles: informe organizationId — não há organização ativa para resolver as roles.\",\n );\n }\n const roles = await request<Role[]>(`/organizations/${organizationId}/roles`);\n // O endpoint devolve a lista inteira; a separação system/custom é\n // feita aqui para manter o contrato que os consumidores já usam.\n return {\n systemRoles: roles.filter((role) => role.isDefault),\n customRoles: roles.filter((role) => !role.isDefault),\n };\n },\n getRole: (id, _type, organizationId) => {\n const orgId = organizationId ?? currentOrgIdRef.current;\n if (!orgId) {\n throw new Error(\"getRole: informe organizationId — não há organização ativa.\");\n }\n return request<Role>(`/organizations/${orgId}/roles/${id}`);\n },\n createRole: ({ organizationId, permissionDefinitionIds, applicationId: _applicationId, ...rest }) =>\n toAuthResult(() => {\n const orgId = organizationId ?? currentOrgIdRef.current;\n if (!orgId) {\n throw new Error(\"createRole: informe organizationId — não há organização ativa.\");\n }\n return request<Role>(`/organizations/${orgId}/roles`, {\n method: \"POST\",\n // O auth-server espera permissionIds; permissionDefinitionIds é o\n // nome herdado no SDK.\n body: { ...rest, permissionIds: permissionDefinitionIds ?? [] },\n });\n }),\n updateRole: (id, { permissionDefinitionIds, ...rest }, organizationId) =>\n toAuthResult(() => {\n const orgId = organizationId ?? currentOrgIdRef.current;\n if (!orgId) {\n throw new Error(\"updateRole: informe organizationId — não há organização ativa.\");\n }\n return request<Role>(`/organizations/${orgId}/roles/${id}`, {\n method: \"PATCH\",\n body: {\n ...rest,\n ...(permissionDefinitionIds ? { permissionIds: permissionDefinitionIds } : {}),\n },\n });\n }),\n deleteRole: (id, organizationId) =>\n toAuthResult(async () => {\n const orgId = organizationId ?? currentOrgIdRef.current;\n if (!orgId) {\n throw new Error(\"deleteRole: informe organizationId — não há organização ativa.\");\n }\n await request<null>(`/organizations/${orgId}/roles/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listPermissions: (params) => {\n const query = new URLSearchParams();\n if (params?.applicationId) query.set(\"applicationId\", params.applicationId);\n if (params?.roleId) query.set(\"roleId\", params.roleId);\n return request<Permission[]>(`/permissions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n createPermission: (input) =>\n toAuthResult(() => request<Permission>(\"/permissions\", { method: \"POST\", body: input })),\n updatePermission: (id, input) =>\n toAuthResult(() => request<Permission>(`/permissions/${id}`, { method: \"PATCH\", body: input })),\n deletePermission: (id) =>\n toAuthResult(async () => {\n await request<null>(`/permissions/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listUserSessions: (params) => {\n const query = new URLSearchParams();\n if (params?.userId) query.set(\"userId\", params.userId);\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<UserSession[]>(`/sessions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n revokeUserSession: (sessionId) =>\n toAuthResult(async () => {\n await request<null>(`/sessions/${sessionId}`, { method: \"DELETE\" });\n return null;\n }),\n listMembers: (organizationId) =>\n request<OrganizationMember[]>(`/organizations/${organizationId}/members`),\n getMember: (organizationId, memberId) =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`),\n addMember: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members`, {\n method: \"POST\",\n body: input,\n }),\n ),\n updateMember: (organizationId, memberId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`, {\n method: \"PATCH\",\n body: input,\n }),\n ),\n updateMemberRole: (organizationId, memberId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`, {\n method: \"PATCH\",\n body: input,\n }),\n ),\n removeMember: (organizationId, memberId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/members/${memberId}`, { method: \"DELETE\" });\n return null;\n }),\n inviteMember: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationInvite>(`/organizations/${organizationId}/invites`, {\n method: \"POST\",\n body: input,\n }),\n ),\n listInvites: (organizationId) =>\n request<OrganizationInvite[]>(`/organizations/${organizationId}/invites`),\n revokeInvite: (organizationId, inviteId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/invites/${inviteId}`, { method: \"DELETE\" });\n return null;\n }),\n listPublicOrganizations: () => request<PublicOrganization[]>(\"/organizations/public\"),\n requestToJoin: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests`, {\n method: \"POST\",\n body: input ?? {},\n }),\n ),\n getMyJoinRequest,\n cancelJoinRequest: (organizationId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/join-requests/me`, { method: \"DELETE\" });\n return null;\n }),\n listJoinRequests: (organizationId) =>\n request<OrganizationJoinRequest[]>(`/organizations/${organizationId}/join-requests`),\n approveJoinRequest: (organizationId, requestId) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests/${requestId}/approve`, {\n method: \"POST\",\n }),\n ),\n rejectJoinRequest: (organizationId, requestId) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests/${requestId}/reject`, {\n method: \"POST\",\n }),\n ),\n getInvitePreview,\n acceptInvite,\n rejectInvite,\n }),\n [\n accounts,\n acceptInvite,\n addAccount,\n basePath,\n currentOrg,\n currentOrgId,\n getInvitePreview,\n getMyJoinRequest,\n isLoading,\n isLoadingAccounts,\n isLoadingOrganizations,\n organizations,\n refreshAccounts,\n refreshOrganizations,\n refreshUser,\n rejectInvite,\n request,\n setCurrentOrg,\n signIn,\n signOut,\n signOutAll,\n signUp,\n switchAccount,\n user,\n ],\n );\n\n return <GeekappsAuthContext.Provider value={value}>{children}</GeekappsAuthContext.Provider>;\n}\n\nexport function useAuth(): GeekappsAuthContextValue {\n const context = useContext(GeekappsAuthContext);\n if (!context) throw new Error(\"useAuth must be used inside GeekappsAuthProvider\");\n return context;\n}\n\nexport function useOrg(): UseOrgResult {\n const context = useAuth();\n return {\n organizations: context.organizations,\n currentOrg: context.currentOrg,\n currentOrgId: context.currentOrgId,\n isLoadingOrganizations: context.isLoadingOrganizations,\n refreshOrganizations: context.refreshOrganizations,\n setCurrentOrg: context.setCurrentOrg,\n createOrganization: context.createOrganization,\n updateOrganization: context.updateOrganization,\n deleteOrganization: context.deleteOrganization,\n hasPermission: context.hasPermission,\n };\n}\n\nexport function useAccounts(): UseAccountsResult {\n const context = useAuth();\n return {\n accounts: context.accounts,\n addAccount: context.addAccount,\n isLoadingAccounts: context.isLoadingAccounts,\n refreshAccounts: context.refreshAccounts,\n switchAccount: context.switchAccount,\n };\n}\n\nexport function useUsers(): UseUsersResult {\n const context = useAuth();\n return {\n listUsers: context.listUsers,\n getUser: context.getUser,\n createUser: context.createUser,\n updateUser: context.updateUser,\n deleteUser: context.deleteUser,\n };\n}\n\nexport function useRoles(): UseRolesResult {\n const context = useAuth();\n return {\n listRoles: context.listRoles,\n getRole: context.getRole,\n createRole: context.createRole,\n updateRole: context.updateRole,\n deleteRole: context.deleteRole,\n };\n}\n\nexport function usePermissions(): UsePermissionsResult {\n const context = useAuth();\n return {\n listPermissions: context.listPermissions,\n createPermission: context.createPermission,\n updatePermission: context.updatePermission,\n deletePermission: context.deletePermission,\n };\n}\n\nexport function useSessions(): UseSessionsResult {\n const context = useAuth();\n return {\n listUserSessions: context.listUserSessions,\n revokeUserSession: context.revokeUserSession,\n };\n}\n\nexport function useMembers(): UseMembersResult {\n const context = useAuth();\n return {\n listMembers: context.listMembers,\n getMember: context.getMember,\n addMember: context.addMember,\n updateMember: context.updateMember,\n updateMemberRole: context.updateMemberRole,\n removeMember: context.removeMember,\n inviteMember: context.inviteMember,\n listInvites: context.listInvites,\n revokeInvite: context.revokeInvite,\n };\n}\n\n/**\n * Descoberta de organizações PÚBLICAS do app — bem separado de `useOrg()`,\n * que lida com as organizações do próprio usuário (as que ele já é\n * membro/dono). `usePublicOrganizations()` nunca retorna organizações\n * privadas, e não exige que o usuário já pertença a elas.\n */\nexport function usePublicOrganizations(): UsePublicOrganizationsResult {\n const context = useAuth();\n return {\n listPublicOrganizations: context.listPublicOrganizations,\n };\n}\n\n/**\n * Solicitações de entrada em organizações públicas: um usuário pede pra\n * entrar (requestToJoin) e um admin da organização aprova/rejeita\n * (approveJoinRequest/rejectJoinRequest, exigem permissão org:members:add).\n */\nexport function useJoinRequests(): UseJoinRequestsResult {\n const context = useAuth();\n return {\n requestToJoin: context.requestToJoin,\n getMyJoinRequest: context.getMyJoinRequest,\n cancelJoinRequest: context.cancelJoinRequest,\n listJoinRequests: context.listJoinRequests,\n approveJoinRequest: context.approveJoinRequest,\n rejectJoinRequest: context.rejectJoinRequest,\n };\n}\n\n/**\n * Aceite/recusa de convite por email — chamadas a partir do ?invite_token=\n * que este app recebe na sua própria redirectUri (a que foi passada em\n * useMembers().inviteMember). getInvitePreview funciona sem sessão\n * (currentAccount vem null); rejectInvite não exige login; acceptInvite\n * retorna loginRequired:true se não houver sessão.\n */\nexport function useInvites(): UseInvitesResult {\n const context = useAuth();\n return {\n getInvitePreview: context.getInvitePreview,\n acceptInvite: context.acceptInvite,\n rejectInvite: context.rejectInvite,\n };\n}\n\n// ── Service Accounts ─────────────────────────────────────────────────────────\n\nexport type ServiceAccount = {\n id: string;\n membershipId: string;\n organizationId: string;\n applicationId: string | null;\n name: string;\n status: \"active\" | \"inactive\" | \"suspended\";\n serviceId: string | null;\n roleAssignment: { role: { id: string; key: string; name: string } } | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type ServiceAccountWithSecret = ServiceAccount & { serviceSecret: string };\n\nexport type CreateServiceAccountInput = {\n organizationId: string;\n applicationId?: string;\n name: string;\n description?: string;\n roleId?: string;\n};\n\nexport type UseServiceAccountResult = {\n listServiceAccounts: (params: { organizationId: string; applicationId?: string }) => Promise<ServiceAccount[]>;\n createServiceAccount: (input: CreateServiceAccountInput) => Promise<ServiceAccountWithSecret>;\n updateServiceAccountRole: (id: string, roleId: string | null) => Promise<void>;\n revokeServiceAccount: (id: string) => Promise<void>;\n rotateServiceAccountSecret: (id: string) => Promise<{ serviceId: string; serviceSecret: string }>;\n deleteServiceAccount: (id: string) => Promise<void>;\n};\n\nexport function useServiceAccount(): UseServiceAccountResult {\n const { request } = useAuth();\n\n const listServiceAccounts = useCallback(\n (params: { organizationId: string; applicationId?: string }) => {\n const query = new URLSearchParams({ organizationId: params.organizationId });\n if (params.applicationId) query.set(\"applicationId\", params.applicationId);\n return request<ServiceAccount[]>(`/service-accounts?${query.toString()}`);\n },\n [request],\n );\n\n const createServiceAccount = useCallback(\n (input: CreateServiceAccountInput) =>\n request<ServiceAccountWithSecret>(\"/service-accounts\", { method: \"POST\", body: input }),\n [request],\n );\n\n const updateServiceAccountRole = useCallback(\n async (id: string, roleId: string | null) => {\n await request<void>(`/service-accounts/${id}`, { method: \"PATCH\", body: { roleId } });\n },\n [request],\n );\n\n const revokeServiceAccount = useCallback(\n async (id: string) => {\n await request<void>(`/service-accounts/${id}/revoke`, { method: \"POST\" });\n },\n [request],\n );\n\n const rotateServiceAccountSecret = useCallback(\n (id: string) =>\n request<{ serviceId: string; serviceSecret: string }>(`/service-accounts/${id}/rotate-secret`, {\n method: \"POST\",\n }),\n [request],\n );\n\n const deleteServiceAccount = useCallback(\n async (id: string) => {\n await request<null>(`/service-accounts/${id}`, { method: \"DELETE\" });\n },\n [request],\n );\n\n return {\n listServiceAccounts,\n createServiceAccount,\n updateServiceAccountRole,\n revokeServiceAccount,\n rotateServiceAccountSecret,\n deleteServiceAccount,\n };\n}\n"],"mappings":";;;AAEA;AAAA,EACE;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAixCE;AAh5BT,SAAS,kBAAkB,UAAkB;AAC3C,SAAO,SAAS,SAAS,GAAG,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI;AAC1D;AAEA,SAAS,SAAS,UAAkB,MAAc;AAChD,QAAM,iBAAiB,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAC7D,SAAO,GAAG,kBAAkB,QAAQ,CAAC,GAAG,cAAc;AACxD;AAEA,eAAe,WAAW,UAAoB;AAC5C,QAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACnD,SACE,MAAM,qBACN,MAAM,SACN,MAAM,WACN,8BAA8B,SAAS,MAAM;AAEjD;AAEA,SAAS,WAAW,MAAc;AAChC,SAAO,SAAS,OAAO,IAAI;AAC7B;AAEA,SAAS,aAAa,OAAkD;AACtE,SAAO,QAAQ,SAAS,OAAO,UAAU,YAAY,oBAAoB,KAAK;AAChF;AAEA,SAAS,uBAAuB,OAAgD;AAC9E,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,aAAa,KAAK,GAAG;AACvB,UAAM,eAAe;AACrB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOA,eAAe,cACb,MACA,UAA0B,CAAC,GAC3B,WAAW,aACC;AACZ,QAAM,WAAW,MAAM,MAAM,SAAS,UAAU,IAAI,GAAG;AAAA,IACrD,MAAM,QAAQ,SAAS,SAAY,SAAY,KAAK,UAAU,QAAQ,IAAI;AAAA,IAC1E,aAAa;AAAA,IACb,SACE,QAAQ,SAAS,SACb,SACA;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACN,QAAQ,QAAQ,UAAU;AAAA,EAC5B,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,MAAM,WAAW,QAAQ,CAAC;AAAA,EAC5C;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,WAAO;AAAA,EACT;AAEA,SAAQ,MAAM,SAAS,KAAK;AAC9B;AAEA,eAAe,uBACb,IACwB;AACxB,MAAI;AACF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM,MAAM,GAAG;AAAA,IACjB;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;AAEA,eAAsB,kBACpB,QAQA,SACoC;AACpC,SAAO,uBAAuB,YAAY;AACxC,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,MACA,SAAS;AAAA,IACX;AAEA,QAAI,OAAO,cAAc,KAAK,YAAY;AACxC,iBAAW,OAAO,cAAc,KAAK,UAAW;AAAA,IAClD;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,eAAsB,qBACpB,QASA,SACuC;AACvC,SAAO,uBAAuB,YAAY;AACxC,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,MACA,SAAS;AAAA,IACX;AAEA,QAAI,OAAO,YAAY;AACrB,iBAAW,OAAO,UAAU;AAAA,IAC9B;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AAEO,SAAS,iBACd,QACA,SACA;AACA,QAAM,WAAW,SAAS,YAAY;AACtC,QAAM,MAAM,IAAI,IAAI,SAAS,UAAU,eAAe,GAAG,OAAO,SAAS,MAAM;AAE/E,MAAI,QAAQ,aAAa;AACvB,QAAI,aAAa,IAAI,eAAe,OAAO,WAAW;AAAA,EACxD;AAEA,MAAI,QAAQ,YAAY;AACtB,QAAI,aAAa,IAAI,cAAc,OAAO,UAAU;AAAA,EACtD;AAEA,MAAI,QAAQ,qBAAqB;AAC/B,QAAI,aAAa,IAAI,WAAW,OAAO,mBAAmB;AAAA,EAC5D;AAEA,aAAW,IAAI,SAAS,CAAC;AAC3B;AAEA,eAAsB,wBACpB,QAMA,SACqB;AACrB,SAAO;AAAA,IAAuB,MAC5B;AAAA,MACE;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;AA0LA,IAAM,sBAAsB,cAA+C,IAAI;AAExE,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA,WAAW;AAAA,EACX,cAAc;AAAA,EACd,uBAAuB,CAAC;AAAA,EACxB,sBAAsB;AACxB,GAA4C;AAC1C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,WAAW;AACzD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAC/C,QAAM,CAAC,UAAU,WAAW,IAAI,SAA6B,CAAC,CAAC;AAC/D,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,IAAI;AAC/D,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAyB,oBAAoB;AACvF,QAAM,CAAC,cAAc,eAAe,IAAI,SAAwB,mBAAmB;AACnF,QAAM,CAAC,wBAAwB,yBAAyB,IAAI,SAAS,IAAI;AAKzE,QAAM,kBAAkB,OAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,QAAM,UAAU;AAAA,IACd,OAAW,MAAc,UAA0B,CAAC,MAAM;AACxD,YAAM,WAAW,MAAM,MAAM,SAAS,UAAU,IAAI,GAAG;AAAA,QACrD,QAAQ,QAAQ,UAAU;AAAA,QAC1B,aAAa;AAAA,QACb,SACE,QAAQ,SAAS,SACb,SACA;AAAA,UACE,gBAAgB;AAAA,QAClB;AAAA,QACN,MAAM,QAAQ,SAAS,SAAY,SAAY,KAAK,UAAU,QAAQ,IAAI;AAAA,MAC5E,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,MAAM,WAAW,QAAQ,CAAC;AAAA,MAC5C;AAEA,UAAI,SAAS,WAAW,KAAK;AAC3B,eAAO;AAAA,MACT;AAEA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,cAAc,YAAY,YAAY;AAC1C,iBAAa,IAAI;AACjB,QAAI;AACF,YAAM,EAAE,MAAM,EAAE,IAAI,MAAM,QAA+B,KAAK;AAC9D,cAAQ,CAAC;AAAA,IACX,QAAQ;AACN,cAAQ,IAAI;AAAA,IACd,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkB,YAAY,YAAY;AAC9C,yBAAqB,IAAI;AACzB,QAAI;AACF,YAAM,EAAE,UAAU,EAAE,IAAI,MAAM;AAAA,QAC5B;AAAA,MACF;AACA,kBAAY,CAAC;AAAA,IACf,QAAQ;AACN,kBAAY,CAAC,CAAC;AAAA,IAChB,UAAE;AACA,2BAAqB,KAAK;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,uBAAuB,YAAY,YAAY;AACnD,8BAA0B,IAAI;AAC9B,QAAI;AACF,YAAM,EAAE,eAAe,MAAM,cAAc,iBAAiB,IAC1D,MAAM,QAGH,gBAAgB;AACrB,uBAAiB,IAAI;AACrB,sBAAgB,CAAC,YAAY;AAC3B,YAAI,qBAAqB,OAAW,QAAO,oBAAoB;AAC/D,YAAI,WAAW,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,OAAO,EAAG,QAAO;AAC9D,eAAO,KAAK,CAAC,GAAG,MAAM;AAAA,MACxB,CAAC;AAAA,IACH,QAAQ;AACN,uBAAiB,CAAC,CAAC;AACnB,sBAAgB,IAAI;AAAA,IACtB,UAAE;AACA,gCAA0B,KAAK;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,SAAK,YAAY;AACjB,SAAK,gBAAgB;AACrB,SAAK,qBAAqB;AAAA,EAC5B,GAAG,CAAC,iBAAiB,sBAAsB,WAAW,CAAC;AAEvD,QAAM,aAAa;AAAA,IACjB,MAAM,cAAc,KAAK,CAAC,iBAAiB,aAAa,OAAO,YAAY,KAAK;AAAA,IAChF,CAAC,cAAc,aAAa;AAAA,EAC9B;AAEA,QAAM,gBAAgB;AAAA,IACpB,OAAO,mBAAkC;AACvC,YAAM,QAAQ,yBAAyB;AAAA,QACrC,QAAQ;AAAA,QACR,MAAM,EAAE,eAAe;AAAA,MACzB,CAAC;AACD,sBAAgB,cAAc;AAAA,IAChC;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,SAAS;AAAA,IACb,OAAO,UAAwB;AAC7B,YAAM,UAAU,uBAAuB,KAAK;AAC5C,YAAM,MAAM,IAAI,IAAI,SAAS,UAAU,UAAU,GAAG,OAAO,SAAS,MAAM;AAC1E,UAAI,SAAS,WAAY,KAAI,aAAa,IAAI,cAAc,QAAQ,UAAU;AAC9E,UAAI,SAAS,oBAAqB,KAAI,aAAa,IAAI,WAAW,QAAQ,mBAAmB;AAC7F,YAAM,SAAS,SAAS,WAAW,SAAS,gBAAgB,QAAQ,UAAU;AAC9E,UAAI,OAAQ,KAAI,aAAa,IAAI,UAAU,MAAM;AACjD,iBAAW,IAAI,SAAS,CAAC;AAAA,IAC3B;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,SAAS;AAAA,IACb,OAAO,UAAwB;AAC7B,YAAM,UAAU,uBAAuB,KAAK;AAC5C,YAAM,MAAM,IAAI,IAAI,SAAS,UAAU,UAAU,GAAG,OAAO,SAAS,MAAM;AAC1E,UAAI,SAAS,WAAY,KAAI,aAAa,IAAI,cAAc,QAAQ,UAAU;AAC9E,UAAI,SAAS,oBAAqB,KAAI,aAAa,IAAI,WAAW,QAAQ,mBAAmB;AAC7F,YAAM,SAAS,SAAS,WAAW,SAAS,gBAAgB,QAAQ,UAAU;AAC9E,UAAI,OAAQ,KAAI,aAAa,IAAI,UAAU,MAAM;AACjD,iBAAW,IAAI,SAAS,CAAC;AAAA,IAC3B;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,aAAa;AAAA,IACjB,OAAO,UAAwB;AAC7B,YAAM,UAAU,uBAAuB,KAAK;AAC5C,YAAM,MAAM,IAAI,IAAI,SAAS,UAAU,cAAc,GAAG,OAAO,SAAS,MAAM;AAC9E,UAAI,SAAS,WAAY,KAAI,aAAa,IAAI,cAAc,QAAQ,UAAU;AAC9E,iBAAW,IAAI,SAAS,CAAC;AAAA,IAC3B;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,UAAU,YAAY,YAAY;AACtC,UAAM,QAAQ,aAAa,EAAE,QAAQ,OAAO,CAAC;AAC7C,YAAQ,IAAI;AACZ,UAAM,gBAAgB;AAAA,EACxB,GAAG,CAAC,iBAAiB,OAAO,CAAC;AAE7B,QAAM,aAAa,YAAY,YAAY;AACzC,UAAM,QAAQ,iBAAiB,EAAE,QAAQ,OAAO,CAAC;AACjD,YAAQ,IAAI;AACZ,gBAAY,CAAC,CAAC;AAAA,EAChB,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,gBAAgB;AAAA,IACpB,OAAO,WAAmB,YAA4B;AACpD,YAAM,QAAQ,oBAAoB;AAAA,QAChC,QAAQ;AAAA,QACR,MAAM,EAAE,UAAU;AAAA,MACpB,CAAC;AACD,YAAM,QAAQ,IAAI,CAAC,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,CAAC,CAAC;AAC5E,UAAI,SAAS,WAAY,YAAW,QAAQ,UAAU;AAAA,IACxD;AAAA,IACA,CAAC,iBAAiB,sBAAsB,aAAa,OAAO;AAAA,EAC9D;AAEA,iBAAe,aAAgB,IAA8C;AAC3E,QAAI;AACF,aAAO,EAAE,SAAS,MAAM,MAAM,MAAM,GAAG,EAAE;AAAA,IAC3C,SAAS,OAAO;AACd,aAAO,EAAE,SAAS,OAAO,OAAO,iBAAiB,QAAQ,MAAM,UAAU,mBAAmB;AAAA,IAC9F;AAAA,EACF;AAIA,QAAM,mBAAmB;AAAA,IACvB,CAAC,UAAkB,QAAmC,0BAA0B,mBAAmB,KAAK,CAAC,EAAE;AAAA,IAC3G,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,eAAe;AAAA,IACnB,OAAO,UAA+C;AACpD,YAAM,WAAW,MAAM,MAAM,SAAS,UAAU,+BAA+B,GAAG;AAAA,QAChF,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC;AAAA,MAChC,CAAC;AACD,YAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AAEnD,UAAI,SAAS,MAAM,MAAM;AACvB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,gBAAgB,KAAK;AAAA,UACrB,kBAAkB,KAAK;AAAA,UACvB,YAAY,KAAK,cAAc;AAAA,QACjC;AAAA,MACF;AACA,UAAI,SAAS,WAAW,OAAO,MAAM,UAAU,iBAAiB;AAC9D,eAAO;AAAA,UACL,SAAS;AAAA,UACT,cAAc;AAAA,UACd,cAAc,OAAO,KAAK,gBAAgB,EAAE;AAAA,UAC5C,cAAc,OAAO,KAAK,gBAAgB,EAAE;AAAA,QAC9C;AAAA,MACF;AACA,UAAI,SAAS,WAAW,OAAO,MAAM,UAAU,kBAAkB;AAC/D,eAAO,EAAE,SAAS,OAAO,cAAc,OAAO,eAAe,KAAK;AAAA,MACpE;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,cAAc;AAAA,QACd,eAAe;AAAA,QACf,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ,QAAQ,SAAS,MAAM;AAAA,MAC/E;AAAA,IACF;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,eAAe;AAAA,IACnB,OAAO,UAAkF;AACvF,YAAM,WAAW,MAAM,MAAM,SAAS,UAAU,+BAA+B,GAAG;AAAA,QAChF,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC;AAAA,MAChC,CAAC;AACD,UAAI,SAAS,GAAI,QAAO,EAAE,SAAS,KAAK;AACxC,YAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACnD,aAAO,EAAE,SAAS,OAAO,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ,QAAQ,SAAS,MAAM,GAAG;AAAA,IAC3G;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,mBAAmB;AAAA,IACvB,OAAO,mBAAoE;AACzE,YAAM,WAAW,MAAM,MAAM,SAAS,UAAU,kBAAkB,cAAc,mBAAmB,GAAG;AAAA,QACpG,aAAa;AAAA,MACf,CAAC;AACD,UAAI,SAAS,WAAW,IAAK,QAAO;AACpC,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,MAAM,WAAW,QAAQ,CAAC;AAC5D,aAAO,SAAS,KAAK;AAAA,IACvB;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,iBAAiB,CAAC,aAAa,SAAS;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,CAAC,WAClB,aAAa,YAAY;AACvB,cAAM,OAAO,MAAM,QAAuB,mBAAmB,EAAE,QAAQ,QAAQ,MAAM,OAAO,CAAC;AAC7F,cAAM,QAAQ,IAAI,CAAC,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,CAAC,CAAC;AAC5E,YAAI,OAAO,cAAc,KAAK,WAAY,YAAW,OAAO,cAAc,KAAK,UAAW;AAC1F,eAAO;AAAA,MACT,CAAC;AAAA,MACH,sBAAsB,CAAC,WACrB,aAAa,YAAY;AACvB,cAAM,OAAO,MAAM,QAA0B,sBAAsB,EAAE,QAAQ,QAAQ,MAAM,OAAO,CAAC;AACnG,cAAM,QAAQ,IAAI,CAAC,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,CAAC,CAAC;AAC5E,YAAI,OAAO,WAAY,YAAW,OAAO,UAAU;AACnD,eAAO;AAAA,MACT,CAAC;AAAA,MACH,kBAAkB,CAAC,WAAW;AAC5B,cAAM,MAAM,IAAI,IAAI,SAAS,UAAU,eAAe,GAAG,OAAO,SAAS,MAAM;AAC/E,YAAI,QAAQ,YAAa,KAAI,aAAa,IAAI,eAAe,OAAO,WAAW;AAC/E,YAAI,QAAQ,WAAY,KAAI,aAAa,IAAI,cAAc,OAAO,UAAU;AAC5E,YAAI,QAAQ,oBAAqB,KAAI,aAAa,IAAI,WAAW,OAAO,mBAAmB;AAC3F,mBAAW,IAAI,SAAS,CAAC;AAAA,MAC3B;AAAA,MACA,yBAAyB,CAAC,WACxB,aAAa,MAAM,QAAQ,sBAAsB,EAAE,QAAQ,QAAQ,MAAM,OAAO,CAAC,CAAC;AAAA,MACpF;AAAA,MACA;AAAA,MACA,oBAAoB,CAAC,UACnB,aAAa,YAAY;AACvB,cAAM,eAAe,MAAM,QAAsB,kBAAkB,EAAE,QAAQ,QAAQ,MAAM,MAAM,CAAC;AAClG,cAAM,qBAAqB;AAC3B,wBAAgB,aAAa,EAAE;AAC/B,eAAO;AAAA,MACT,CAAC;AAAA,MACH,oBAAoB,CAAC,IAAI,UACvB,aAAa,YAAY;AACvB,cAAM,eAAe,MAAM,QAAsB,kBAAkB,EAAE,IAAI,EAAE,QAAQ,SAAS,MAAM,MAAM,CAAC;AACzG,cAAM,qBAAqB;AAC3B,eAAO;AAAA,MACT,CAAC;AAAA,MACH,oBAAoB,CAAC,OACnB,aAAa,YAAY;AACvB,cAAM,QAAc,kBAAkB,EAAE,IAAI,EAAE,QAAQ,SAAS,CAAC;AAChE,cAAM,qBAAqB;AAC3B,eAAO;AAAA,MACT,CAAC;AAAA,MACH,eAAe,OAAO,YAAY;AAChC,YAAI;AACF,gBAAM,OAAO,MAAM,QAA8B,sBAAsB;AAAA,YACrE,QAAQ;AAAA,YACR,MAAM;AAAA,UACR,CAAC;AACD,iBAAO,KAAK;AAAA,QACd,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,WAAW,CAAC,WAAW;AACrB,cAAM,QAAQ,IAAI,gBAAgB;AAClC,YAAI,QAAQ,eAAgB,OAAM,IAAI,kBAAkB,OAAO,cAAc;AAC7E,eAAO,QAAgB,SAAS,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC,KAAK,EAAE,EAAE;AAAA,MAC5E;AAAA,MACA,SAAS,CAAC,OAAO,QAAc,UAAU,EAAE,EAAE;AAAA,MAC7C,YAAY,CAAC,UAAU,aAAa,MAAM,QAAc,UAAU,EAAE,QAAQ,QAAQ,MAAM,MAAM,CAAC,CAAC;AAAA,MAClG,YAAY,CAAC,IAAI,UAAU,aAAa,MAAM,QAAc,UAAU,EAAE,IAAI,EAAE,QAAQ,SAAS,MAAM,MAAM,CAAC,CAAC;AAAA,MAC7G,YAAY,CAAC,OACX,aAAa,YAAY;AACvB,cAAM,QAAc,UAAU,EAAE,IAAI,EAAE,QAAQ,SAAS,CAAC;AACxD,eAAO;AAAA,MACT,CAAC;AAAA;AAAA;AAAA;AAAA,MAIH,WAAW,OAAO,WAAW;AAC3B,cAAM,iBAAiB,QAAQ,kBAAkB,gBAAgB;AACjE,YAAI,CAAC,gBAAgB;AACnB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AACA,cAAM,QAAQ,MAAM,QAAgB,kBAAkB,cAAc,QAAQ;AAG5E,eAAO;AAAA,UACL,aAAa,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS;AAAA,UAClD,aAAa,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,SAAS;AAAA,QACrD;AAAA,MACF;AAAA,MACA,SAAS,CAAC,IAAI,OAAO,mBAAmB;AACtC,cAAM,QAAQ,kBAAkB,gBAAgB;AAChD,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,MAAM,8EAA6D;AAAA,QAC/E;AACA,eAAO,QAAc,kBAAkB,KAAK,UAAU,EAAE,EAAE;AAAA,MAC5D;AAAA,MACA,YAAY,CAAC,EAAE,gBAAgB,yBAAyB,eAAe,gBAAgB,GAAG,KAAK,MAC7F,aAAa,MAAM;AACjB,cAAM,QAAQ,kBAAkB,gBAAgB;AAChD,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,MAAM,iFAAgE;AAAA,QAClF;AACA,eAAO,QAAc,kBAAkB,KAAK,UAAU;AAAA,UACpD,QAAQ;AAAA;AAAA;AAAA,UAGR,MAAM,EAAE,GAAG,MAAM,eAAe,2BAA2B,CAAC,EAAE;AAAA,QAChE,CAAC;AAAA,MACH,CAAC;AAAA,MACH,YAAY,CAAC,IAAI,EAAE,yBAAyB,GAAG,KAAK,GAAG,mBACrD,aAAa,MAAM;AACjB,cAAM,QAAQ,kBAAkB,gBAAgB;AAChD,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,MAAM,iFAAgE;AAAA,QAClF;AACA,eAAO,QAAc,kBAAkB,KAAK,UAAU,EAAE,IAAI;AAAA,UAC1D,QAAQ;AAAA,UACR,MAAM;AAAA,YACJ,GAAG;AAAA,YACH,GAAI,0BAA0B,EAAE,eAAe,wBAAwB,IAAI,CAAC;AAAA,UAC9E;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,MACH,YAAY,CAAC,IAAI,mBACf,aAAa,YAAY;AACvB,cAAM,QAAQ,kBAAkB,gBAAgB;AAChD,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,MAAM,iFAAgE;AAAA,QAClF;AACA,cAAM,QAAc,kBAAkB,KAAK,UAAU,EAAE,IAAI,EAAE,QAAQ,SAAS,CAAC;AAC/E,eAAO;AAAA,MACT,CAAC;AAAA,MACH,iBAAiB,CAAC,WAAW;AAC3B,cAAM,QAAQ,IAAI,gBAAgB;AAClC,YAAI,QAAQ,cAAe,OAAM,IAAI,iBAAiB,OAAO,aAAa;AAC1E,YAAI,QAAQ,OAAQ,OAAM,IAAI,UAAU,OAAO,MAAM;AACrD,eAAO,QAAsB,eAAe,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC,KAAK,EAAE,EAAE;AAAA,MACxF;AAAA,MACA,kBAAkB,CAAC,UACjB,aAAa,MAAM,QAAoB,gBAAgB,EAAE,QAAQ,QAAQ,MAAM,MAAM,CAAC,CAAC;AAAA,MACzF,kBAAkB,CAAC,IAAI,UACrB,aAAa,MAAM,QAAoB,gBAAgB,EAAE,IAAI,EAAE,QAAQ,SAAS,MAAM,MAAM,CAAC,CAAC;AAAA,MAChG,kBAAkB,CAAC,OACjB,aAAa,YAAY;AACvB,cAAM,QAAc,gBAAgB,EAAE,IAAI,EAAE,QAAQ,SAAS,CAAC;AAC9D,eAAO;AAAA,MACT,CAAC;AAAA,MACH,kBAAkB,CAAC,WAAW;AAC5B,cAAM,QAAQ,IAAI,gBAAgB;AAClC,YAAI,QAAQ,OAAQ,OAAM,IAAI,UAAU,OAAO,MAAM;AACrD,YAAI,QAAQ,eAAgB,OAAM,IAAI,kBAAkB,OAAO,cAAc;AAC7E,eAAO,QAAuB,YAAY,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC,KAAK,EAAE,EAAE;AAAA,MACtF;AAAA,MACA,mBAAmB,CAAC,cAClB,aAAa,YAAY;AACvB,cAAM,QAAc,aAAa,SAAS,IAAI,EAAE,QAAQ,SAAS,CAAC;AAClE,eAAO;AAAA,MACT,CAAC;AAAA,MACH,aAAa,CAAC,mBACZ,QAA8B,kBAAkB,cAAc,UAAU;AAAA,MAC1E,WAAW,CAAC,gBAAgB,aAC1B,QAA4B,kBAAkB,cAAc,YAAY,QAAQ,EAAE;AAAA,MACpF,WAAW,CAAC,gBAAgB,UAC1B;AAAA,QAAa,MACX,QAA4B,kBAAkB,cAAc,YAAY;AAAA,UACtE,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACF,cAAc,CAAC,gBAAgB,UAAU,UACvC;AAAA,QAAa,MACX,QAA4B,kBAAkB,cAAc,YAAY,QAAQ,IAAI;AAAA,UAClF,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACF,kBAAkB,CAAC,gBAAgB,UAAU,UAC3C;AAAA,QAAa,MACX,QAA4B,kBAAkB,cAAc,YAAY,QAAQ,IAAI;AAAA,UAClF,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACF,cAAc,CAAC,gBAAgB,aAC7B,aAAa,YAAY;AACvB,cAAM,QAAc,kBAAkB,cAAc,YAAY,QAAQ,IAAI,EAAE,QAAQ,SAAS,CAAC;AAChG,eAAO;AAAA,MACT,CAAC;AAAA,MACH,cAAc,CAAC,gBAAgB,UAC7B;AAAA,QAAa,MACX,QAA4B,kBAAkB,cAAc,YAAY;AAAA,UACtE,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACF,aAAa,CAAC,mBACZ,QAA8B,kBAAkB,cAAc,UAAU;AAAA,MAC1E,cAAc,CAAC,gBAAgB,aAC7B,aAAa,YAAY;AACvB,cAAM,QAAc,kBAAkB,cAAc,YAAY,QAAQ,IAAI,EAAE,QAAQ,SAAS,CAAC;AAChG,eAAO;AAAA,MACT,CAAC;AAAA,MACH,yBAAyB,MAAM,QAA8B,uBAAuB;AAAA,MACpF,eAAe,CAAC,gBAAgB,UAC9B;AAAA,QAAa,MACX,QAAiC,kBAAkB,cAAc,kBAAkB;AAAA,UACjF,QAAQ;AAAA,UACR,MAAM,SAAS,CAAC;AAAA,QAClB,CAAC;AAAA,MACH;AAAA,MACF;AAAA,MACA,mBAAmB,CAAC,mBAClB,aAAa,YAAY;AACvB,cAAM,QAAc,kBAAkB,cAAc,qBAAqB,EAAE,QAAQ,SAAS,CAAC;AAC7F,eAAO;AAAA,MACT,CAAC;AAAA,MACH,kBAAkB,CAAC,mBACjB,QAAmC,kBAAkB,cAAc,gBAAgB;AAAA,MACrF,oBAAoB,CAAC,gBAAgB,cACnC;AAAA,QAAa,MACX,QAAiC,kBAAkB,cAAc,kBAAkB,SAAS,YAAY;AAAA,UACtG,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,MACF,mBAAmB,CAAC,gBAAgB,cAClC;AAAA,QAAa,MACX,QAAiC,kBAAkB,cAAc,kBAAkB,SAAS,WAAW;AAAA,UACrG,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,oBAAC,oBAAoB,UAApB,EAA6B,OAAe,UAAS;AAC/D;AAEO,SAAS,UAAoC;AAClD,QAAM,UAAU,WAAW,mBAAmB;AAC9C,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,kDAAkD;AAChF,SAAO;AACT;AAEO,SAAS,SAAuB;AACrC,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,IACpB,cAAc,QAAQ;AAAA,IACtB,wBAAwB,QAAQ;AAAA,IAChC,sBAAsB,QAAQ;AAAA,IAC9B,eAAe,QAAQ;AAAA,IACvB,oBAAoB,QAAQ;AAAA,IAC5B,oBAAoB,QAAQ;AAAA,IAC5B,oBAAoB,QAAQ;AAAA,IAC5B,eAAe,QAAQ;AAAA,EACzB;AACF;AAEO,SAAS,cAAiC;AAC/C,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,UAAU,QAAQ;AAAA,IAClB,YAAY,QAAQ;AAAA,IACpB,mBAAmB,QAAQ;AAAA,IAC3B,iBAAiB,QAAQ;AAAA,IACzB,eAAe,QAAQ;AAAA,EACzB;AACF;AAEO,SAAS,WAA2B;AACzC,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,SAAS,QAAQ;AAAA,IACjB,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,EACtB;AACF;AAEO,SAAS,WAA2B;AACzC,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,SAAS,QAAQ;AAAA,IACjB,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,EACtB;AACF;AAEO,SAAS,iBAAuC;AACrD,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,iBAAiB,QAAQ;AAAA,IACzB,kBAAkB,QAAQ;AAAA,IAC1B,kBAAkB,QAAQ;AAAA,IAC1B,kBAAkB,QAAQ;AAAA,EAC5B;AACF;AAEO,SAAS,cAAiC;AAC/C,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,kBAAkB,QAAQ;AAAA,IAC1B,mBAAmB,QAAQ;AAAA,EAC7B;AACF;AAEO,SAAS,aAA+B;AAC7C,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,cAAc,QAAQ;AAAA,IACtB,kBAAkB,QAAQ;AAAA,IAC1B,cAAc,QAAQ;AAAA,IACtB,cAAc,QAAQ;AAAA,IACtB,aAAa,QAAQ;AAAA,IACrB,cAAc,QAAQ;AAAA,EACxB;AACF;AAQO,SAAS,yBAAuD;AACrE,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,yBAAyB,QAAQ;AAAA,EACnC;AACF;AAOO,SAAS,kBAAyC;AACvD,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,eAAe,QAAQ;AAAA,IACvB,kBAAkB,QAAQ;AAAA,IAC1B,mBAAmB,QAAQ;AAAA,IAC3B,kBAAkB,QAAQ;AAAA,IAC1B,oBAAoB,QAAQ;AAAA,IAC5B,mBAAmB,QAAQ;AAAA,EAC7B;AACF;AASO,SAAS,aAA+B;AAC7C,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,kBAAkB,QAAQ;AAAA,IAC1B,cAAc,QAAQ;AAAA,IACtB,cAAc,QAAQ;AAAA,EACxB;AACF;AAoCO,SAAS,oBAA6C;AAC3D,QAAM,EAAE,QAAQ,IAAI,QAAQ;AAE5B,QAAM,sBAAsB;AAAA,IAC1B,CAAC,WAA+D;AAC9D,YAAM,QAAQ,IAAI,gBAAgB,EAAE,gBAAgB,OAAO,eAAe,CAAC;AAC3E,UAAI,OAAO,cAAe,OAAM,IAAI,iBAAiB,OAAO,aAAa;AACzE,aAAO,QAA0B,qBAAqB,MAAM,SAAS,CAAC,EAAE;AAAA,IAC1E;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,uBAAuB;AAAA,IAC3B,CAAC,UACC,QAAkC,qBAAqB,EAAE,QAAQ,QAAQ,MAAM,MAAM,CAAC;AAAA,IACxF,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,2BAA2B;AAAA,IAC/B,OAAO,IAAY,WAA0B;AAC3C,YAAM,QAAc,qBAAqB,EAAE,IAAI,EAAE,QAAQ,SAAS,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,IACtF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,uBAAuB;AAAA,IAC3B,OAAO,OAAe;AACpB,YAAM,QAAc,qBAAqB,EAAE,WAAW,EAAE,QAAQ,OAAO,CAAC;AAAA,IAC1E;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,6BAA6B;AAAA,IACjC,CAAC,OACC,QAAsD,qBAAqB,EAAE,kBAAkB;AAAA,MAC7F,QAAQ;AAAA,IACV,CAAC;AAAA,IACH,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,uBAAuB;AAAA,IAC3B,OAAO,OAAe;AACpB,YAAM,QAAc,qBAAqB,EAAE,IAAI,EAAE,QAAQ,SAAS,CAAC;AAAA,IACrE;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * App Connections — chamar ações de negócio de OUTRA Application.
3
+ *
4
+ * Uma conexão liga esta app (X) a uma app alvo (Y) e é aprovada UMA VEZ pelo
5
+ * admin, que escolhe no consent as ações liberadas e a identidade dentro do Y
6
+ * sob a qual elas rodam. Por isso a chamada aqui não leva usuário nenhum:
7
+ * venha ela de um request com sessão, de um cron ou de um webhook, chega no Y
8
+ * sempre com a mesma identidade e as mesmas permissões.
9
+ *
10
+ * Nada aqui fala com a API do Y diretamente: tudo passa pelo proxy do
11
+ * auth-server, que valida a conexão e injeta a credencial. Esta app nunca vê
12
+ * essa credencial — é esse o ponto do proxy.
13
+ *
14
+ * O catálogo tipado (`GeekappsConnections`) vem do arquivo gerado por
15
+ * `npx geekapps-connections`.
16
+ */
17
+ type AppConnectionsConfig = {
18
+ issuer?: string;
19
+ /** client_id/secret desta app (a consumidora, X). */
20
+ clientId?: string;
21
+ clientSecret?: string;
22
+ };
23
+ /**
24
+ * Preenchida por declaration merging no arquivo gerado
25
+ * (`geekapps-connections.d.ts`). Vazia aqui de propósito: o SDK não sabe
26
+ * quais apps existem — quem sabe é o auth-server, no momento da geração.
27
+ */
28
+ interface GeekappsConnections {
29
+ }
30
+ /** Erro de uma chamada de proxy — carrega o status HTTP para dar pra tratar. */
31
+ declare class AppConnectionError extends Error {
32
+ readonly status: number;
33
+ readonly code: string | undefined;
34
+ readonly body: unknown;
35
+ constructor(message: string, status: number, code: string | undefined, body: unknown);
36
+ }
37
+ /**
38
+ * A chamada crua do proxy, para quando não há catálogo gerado. `targetAppId` é
39
+ * o client_id da app alvo e `actionKey` é a AppAction.key — o mesmo valor que
40
+ * aparece como scope no consent.
41
+ */
42
+ declare function callAppConnection<T = unknown>(params: {
43
+ targetAppId: string;
44
+ actionKey: string;
45
+ payload?: unknown;
46
+ config?: AppConnectionsConfig;
47
+ }): Promise<T>;
48
+ /**
49
+ * Registry preenchido pelo arquivo gerado via `registerConnections()`. Mapeia
50
+ * o nome amigável da app (`billing`) para o client_id real, e o nome da ação
51
+ * (`createCharge`) para a AppAction.key (`billing.charges.create`).
52
+ */
53
+ type ConnectionRegistryEntry = {
54
+ appId: string;
55
+ actions: Record<string, string>;
56
+ };
57
+ /** Chamado pelo arquivo gerado. Não edite à mão — ele é reescrito a cada geração. */
58
+ declare function registerConnections(entries: Record<string, ConnectionRegistryEntry>): void;
59
+ type AppConnectionsClient = GeekappsConnections;
60
+ /** Cliente com config explícita — para quem não usa as env vars padrão. */
61
+ declare function createAppConnections(config?: AppConnectionsConfig): AppConnectionsClient;
62
+ /** Cliente padrão, lendo GEEKAPPS_AUTH_CLIENT_ID / _SECRET do ambiente. */
63
+ declare const appConnections: AppConnectionsClient;
64
+
65
+ export { AppConnectionError, type AppConnectionsClient, type AppConnectionsConfig, type GeekappsConnections, appConnections, callAppConnection, createAppConnections, registerConnections };
@@ -0,0 +1,115 @@
1
+ // src/server.ts
2
+ import { createHash, randomBytes } from "crypto";
3
+ import { cookies, headers } from "next/headers";
4
+ import { redirect } from "next/navigation";
5
+ import { NextResponse } from "next/server";
6
+ import { createRemoteJWKSet, jwtVerify } from "jose";
7
+ var GEEKAPPS_AUTH_SERVER_URL = "https://accounts-api.geekapps.com.br";
8
+
9
+ // src/connections.ts
10
+ var AppConnectionError = class extends Error {
11
+ status;
12
+ code;
13
+ body;
14
+ constructor(message, status, code, body) {
15
+ super(message);
16
+ this.name = "AppConnectionError";
17
+ this.status = status;
18
+ this.code = code;
19
+ this.body = body;
20
+ }
21
+ };
22
+ function env(name) {
23
+ const value = process.env[name];
24
+ return value && value.trim().length > 0 ? value : void 0;
25
+ }
26
+ function resolveConfig(config) {
27
+ const issuer = (config.issuer ?? env("GEEKAPPS_AUTH_SERVER_ISSUER") ?? env("GEEKAPPS_AUTH_SERVER_URL") ?? GEEKAPPS_AUTH_SERVER_URL).replace(/\/$/, "");
28
+ return {
29
+ issuer,
30
+ clientId: config.clientId ?? env("GEEKAPPS_AUTH_CLIENT_ID") ?? "",
31
+ clientSecret: config.clientSecret ?? env("GEEKAPPS_AUTH_CLIENT_SECRET") ?? ""
32
+ };
33
+ }
34
+ async function callAppConnection(params) {
35
+ const { issuer, clientId, clientSecret } = resolveConfig(params.config ?? {});
36
+ if (!clientId || !clientSecret) {
37
+ throw new Error(
38
+ "App Connections: defina GEEKAPPS_AUTH_CLIENT_ID e GEEKAPPS_AUTH_CLIENT_SECRET \u2014 \xE9 com essas credenciais que o proxy identifica a app que est\xE1 chamando."
39
+ );
40
+ }
41
+ const url = `${issuer}/connections/${encodeURIComponent(params.targetAppId)}/actions/${encodeURIComponent(params.actionKey)}`;
42
+ const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
43
+ const response = await fetch(url, {
44
+ method: "POST",
45
+ headers: {
46
+ authorization: `Basic ${credentials}`,
47
+ "content-type": "application/json"
48
+ },
49
+ body: JSON.stringify(params.payload === void 0 ? {} : { payload: params.payload }),
50
+ cache: "no-store"
51
+ });
52
+ const body = await response.json().catch(() => null);
53
+ if (!response.ok) {
54
+ const code = body && typeof body === "object" && typeof body.error === "string" ? body.error : void 0;
55
+ throw new AppConnectionError(
56
+ `App Connections: ${params.actionKey} falhou (${response.status}${code ? ` ${code}` : ""})`,
57
+ response.status,
58
+ code,
59
+ body
60
+ );
61
+ }
62
+ return body;
63
+ }
64
+ var _registry = /* @__PURE__ */ new Map();
65
+ function registerConnections(entries) {
66
+ for (const [name, entry] of Object.entries(entries)) _registry.set(name, entry);
67
+ }
68
+ function resolveEntry(appName) {
69
+ const entry = _registry.get(appName);
70
+ if (!entry) {
71
+ throw new Error(
72
+ `App Connections: app "${appName}" desconhecida. Rode "npx geekapps-connections" para gerar o cat\xE1logo e importe o arquivo gerado uma vez no boot da app.`
73
+ );
74
+ }
75
+ return entry;
76
+ }
77
+ function resolveActionKey(appName, actionName) {
78
+ const key = resolveEntry(appName).actions[actionName];
79
+ if (!key) {
80
+ throw new Error(
81
+ `App Connections: a\xE7\xE3o "${actionName}" n\xE3o existe em "${appName}", ou n\xE3o foi liberada na aprova\xE7\xE3o da conex\xE3o. Rode "npx geekapps-connections" para atualizar o cat\xE1logo.`
82
+ );
83
+ }
84
+ return key;
85
+ }
86
+ function createCatalog(config) {
87
+ return new Proxy(/* @__PURE__ */ Object.create(null), {
88
+ get(_target, appName) {
89
+ if (typeof appName !== "string") return void 0;
90
+ return new Proxy(/* @__PURE__ */ Object.create(null), {
91
+ get(_t, actionName) {
92
+ if (typeof actionName !== "string") return void 0;
93
+ return (payload) => callAppConnection({
94
+ targetAppId: resolveEntry(appName).appId,
95
+ actionKey: resolveActionKey(appName, actionName),
96
+ payload,
97
+ config
98
+ });
99
+ }
100
+ });
101
+ }
102
+ });
103
+ }
104
+ function createAppConnections(config = {}) {
105
+ return createCatalog(config);
106
+ }
107
+ var appConnections = createAppConnections();
108
+ export {
109
+ AppConnectionError,
110
+ appConnections,
111
+ callAppConnection,
112
+ createAppConnections,
113
+ registerConnections
114
+ };
115
+ //# sourceMappingURL=connections.js.map