@geekapps/auth-nextjs 0.16.1 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,25 @@
1
+ import { ClientOptions, Client } from 'openapi-fetch';
2
+
1
3
  /**
2
- * App Connections — chamar ações de negócio de OUTRA Application.
3
- *
4
- * Uma conexão liga um USUÁRIO desta app (X) a uma app alvo (Y). Ele a aprova
5
- * uma vez no consent, escolhendo as ações liberadas e a organização dentro do
6
- * Y sob a qual elas rodam. A chamada vai com o access token desse usuário (o
7
- * da sessão, por padrão): é ele que diz ao proxy qual conexão usar.
4
+ * App Connections — agir como um usuário numa organização de OUTRA Application.
8
5
  *
9
- * Nada aqui fala com a API do Y diretamente: tudo passa pelo proxy do
10
- * auth-server, que valida a conexão e injeta a credencial. Esta app nunca vê
11
- * essa credencial — é esse o ponto do proxy.
6
+ * Uma conexão liga um USUÁRIO desta app (X) a uma organização da app alvo (Z)
7
+ * de que ele já é membro. Ele a aprova uma vez, no consent; o auth-server
8
+ * devolve a esta app um API token (`gka_…`). Daí em diante esta app guarda o
9
+ * token e o usa quando quiser — com ou sem o usuário logado, num cron, num
10
+ * workflow — trocando-o por um JWT curto que age COMO o usuário naquela
11
+ * organização (`getConnectionAccessToken`). As permissions são as do usuário
12
+ * na organização, hoje: mudou o role dele lá, a conexão muda junto; saiu da
13
+ * organização, ela para.
12
14
  *
13
- * O catálogo tipado (`GeekappsConnections`) vem do arquivo gerado por
14
- * `npx geekapps-connections`.
15
+ * ⚠️ ATENÇÃO — o API token é uma credencial de longa duração.
16
+ * • Guarde-o cifrado, associado ao usuário que aprovou a conexão.
17
+ * • Use-o só para agir em nome DESSE usuário. Usar o token de A para atender
18
+ * um pedido de B dá a B o acesso de A à organização alvo.
19
+ * • Restringir quem pode disparar uma chamada, e o que ela pode pedir, é
20
+ * responsabilidade desta app: o auth-server não tem como saber.
21
+ * • Vazou? Revogue no dashboard do Geekapps Auth ou gire com `rotateConnectionToken`.
15
22
  */
16
- /** Opções por chamada. Sem `userToken`, usa o access token do usuário logado na sessão. */
17
- type ConnectionCallOptions = {
18
- userToken?: string;
19
- };
20
23
  type AppConnectionsConfig = {
21
24
  issuer?: string;
22
25
  /** client_id/secret desta app (a consumidora, X). */
@@ -24,65 +27,23 @@ type AppConnectionsConfig = {
24
27
  clientSecret?: string;
25
28
  };
26
29
  /**
27
- * Preenchida por declaration merging no arquivo gerado
28
- * (`geekapps-connections.d.ts`). Vazia aqui de propósito: o SDK não sabe
29
- * quais apps existem — quem sabe é o auth-server, no momento da geração.
30
+ * Preenchida por declaration merging no `geekapps-connections/index.d.ts` que
31
+ * o SDK gera (em desenvolvimento) ou `npx geekapps-connections` escreve: uma
32
+ * chave por app conectável, com os `paths` do OpenAPI dela. Vazia aqui de
33
+ * propósito — quem sabe quais apps existem é o auth-server.
30
34
  */
31
35
  interface GeekappsConnections {
32
36
  }
33
- /** Erro de uma chamada de proxy — carrega o status HTTP para dar pra tratar. */
37
+ /** Erro de uma chamada ao auth-server — carrega o status HTTP para dar pra tratar. */
34
38
  declare class AppConnectionError extends Error {
35
39
  readonly status: number;
36
40
  readonly code: string | undefined;
37
41
  readonly body: unknown;
38
42
  constructor(message: string, status: number, code: string | undefined, body: unknown);
39
43
  }
40
- /**
41
- * A chamada crua do proxy, para quando não há catálogo gerado. `targetAppId` é
42
- * o client_id da app alvo e `actionKey` é a AppAction.key — o mesmo valor que
43
- * aparece como scope no consent.
44
- */
45
- declare function callAppConnection<T = unknown>(params: {
46
- targetAppId: string;
47
- actionKey: string;
48
- payload?: unknown;
49
- /** Access token do usuário dono da conexão. Padrão: o do usuário logado. */
50
- userToken?: string;
51
- config?: AppConnectionsConfig;
52
- }): Promise<T>;
53
- type ConnectionRegistryEntry = {
54
- appId: string;
55
- actions: Record<string, string>;
56
- };
57
- /** Chamado por arquivos gerados no formato antigo. Não é necessário no fluxo automático. */
58
- declare function registerConnections(entries: Record<string, ConnectionRegistryEntry>): void;
59
- /**
60
- * Sem tipos gerados (primeira execução), qualquer `app.ação` é aceita. Assim
61
- * que o SDK escreve `geekapps-connections.d.ts`, a interface estendida passa a
62
- * valer e o TypeScript confere payload e retorno.
63
- */
64
- type AppConnectionsClient = keyof GeekappsConnections extends never ? Record<string, Record<string, (payload?: unknown, options?: ConnectionCallOptions) => Promise<unknown>>> : GeekappsConnections;
65
- /** Cliente com config explícita — para quem não usa as env vars padrão. */
66
- declare function createAppConnections(config?: AppConnectionsConfig): AppConnectionsClient;
67
- /** Catálogo explícito, como o gerado por `npx geekapps-connections` (`geekappsConnectionsCatalog`). */
68
- type ConnectionsCatalog = Record<string, {
69
- readonly appId: string;
70
- readonly actions: Readonly<Record<string, string>>;
71
- }>;
72
- /**
73
- * Opcional: usa um catálogo fixo em vez de consultar o auth-server. Útil em
74
- * testes ou quando a app não pode falar com o servidor em runtime.
75
- *
76
- * const connections = defineAppConnections<GeekappsConnections>(geekappsConnectionsCatalog);
77
- */
78
- declare function defineAppConnections<T>(catalog: ConnectionsCatalog, config?: AppConnectionsConfig): T;
79
- /** Cliente padrão, lendo GEEKAPPS_AUTH_CLIENT_ID / _SECRET do ambiente. */
80
- declare const appConnections: AppConnectionsClient;
81
44
  type ConnectAppParams = {
82
- /** client_id da app ALVO (a que expõe as ações). */
45
+ /** client_id da app ALVO (a que vai ser acessada). */
83
46
  targetAppId: string;
84
- /** AppAction.key das ações pedidas — as mesmas que aparecem no consent. */
85
- actions: string[];
86
47
  /** URL desta app que recebe o retorno do consent (rota que chama `completeAppConnection`). Precisa estar nos redirect URIs desta app. */
87
48
  redirectUri: string;
88
49
  /** Para onde `completeAppConnection` manda o usuário depois (padrão "/"). */
@@ -93,13 +54,26 @@ type ConnectAppParams = {
93
54
  };
94
55
  /**
95
56
  * Inicia a conexão desta app com `targetAppId`: guarda PKCE/state em cookies
96
- * httpOnly e redireciona para o consent. Chame de um Server Action ou Route
97
- * Handler — não retorna (o `redirect` do Next interrompe a execução).
57
+ * httpOnly e redireciona para o consent, onde o usuário escolhe a organização
58
+ * e a validade. Chame de um Server Action ou Route Handler — não retorna (o
59
+ * `redirect` do Next interrompe a execução).
98
60
  */
99
61
  declare function connectApp(params: ConnectAppParams): Promise<never>;
62
+ /** A conexão recém-criada. O `token` só aparece aqui, uma única vez. */
63
+ type AppConnectionToken = {
64
+ /** API token (`gka_…`). Guarde-o cifrado, associado ao usuário que aprovou. */
65
+ token: string;
66
+ connectionId: string;
67
+ /** null = sem expiração. */
68
+ expiresAt: string | null;
69
+ /** Organização da app alvo em que a conexão age. */
70
+ organizationId: string;
71
+ targetAppId: string;
72
+ };
100
73
  /**
101
74
  * Fecha o fluxo de `connectApp`. Chame no callback com o `code` e o `state`
102
- * da query; devolve o `returnTo` para você redirecionar. Lança
75
+ * da query; devolve o `returnTo` e a conexão, com o API token — a ÚNICA vez em
76
+ * que ele aparece, então persista-o antes de redirecionar. Lança
103
77
  * AppConnectionError se o state não bater ou o auth-server recusar.
104
78
  */
105
79
  declare function completeAppConnection(params: {
@@ -108,6 +82,86 @@ declare function completeAppConnection(params: {
108
82
  config?: AppConnectionsConfig;
109
83
  }): Promise<{
110
84
  returnTo: string;
85
+ connection: AppConnectionToken;
86
+ }>;
87
+ /** Resultado de `getConnectionAccessToken`. */
88
+ type AppConnectionAccessToken = {
89
+ /** JWT curto: use em `Authorization: Bearer` contra a API da app alvo. */
90
+ accessToken: string;
91
+ /** Segundos até o JWT vencer. */
92
+ expiresIn: number;
93
+ organizationId: string;
94
+ targetAppId: string;
95
+ /** apiBaseUrl da app alvo, quando ela declarou uma. */
96
+ targetApiBaseUrl: string | null;
97
+ /** URL do OpenAPI da app alvo, quando ela declarou uma — fonte dos tipos. */
98
+ targetOpenApiUrl: string | null;
99
+ };
100
+ /**
101
+ * Troca o API token por um JWT curto que age como o usuário na organização da
102
+ * conexão. Não exige ninguém logado. O resultado fica em cache até perto de
103
+ * vencer, então pode ser chamado a cada requisição.
104
+ *
105
+ * Erros possíveis (`AppConnectionError.code`): `invalid_token`,
106
+ * `connection_inactive` (revogada), `connection_expired`,
107
+ * `membership_required` (o usuário saiu da organização).
108
+ */
109
+ declare function getConnectionAccessToken(params: {
110
+ /** O API token guardado por esta app. */
111
+ connectionToken: string;
112
+ config?: AppConnectionsConfig;
113
+ }): Promise<AppConnectionAccessToken>;
114
+ /**
115
+ * Atalho: um `fetch` contra a API da app alvo já com o JWT da conexão. `path`
116
+ * é relativo ao `apiBaseUrl` da app alvo (ou uma URL absoluta).
117
+ */
118
+ declare function connectionFetch(params: {
119
+ connectionToken: string;
120
+ path: string;
121
+ init?: RequestInit;
122
+ config?: AppConnectionsConfig;
123
+ }): Promise<Response>;
124
+ /**
125
+ * Cliente tipado para a API da app alvo, a partir do OpenAPI dela: o JWT da
126
+ * conexão é obtido, renovado e injetado a cada chamada.
127
+ *
128
+ * Os tipos de TODAS as apps conectáveis vêm de uma vez: em desenvolvimento o
129
+ * SDK baixa o OpenAPI de cada uma ao subir e escreve `geekapps-connections/`
130
+ * (ou rode `npx geekapps-connections`). Daí basta nomear a app:
131
+ *
132
+ * const billing = await createConnectionClient({ app: "billing", connectionToken });
133
+ * const { data } = await billing.GET("/charges", { params: { query: { limit: 10 } } });
134
+ *
135
+ * `app` só escolhe os tipos; a app alvo de verdade é a do token. Sem tipos
136
+ * gerados, passe os `paths` você mesmo: `createConnectionClient<paths>({ connectionToken })`.
137
+ *
138
+ * Requer o pacote `openapi-fetch` instalado na sua app.
139
+ */
140
+ declare function createConnectionClient<App extends keyof GeekappsConnections>(params: ConnectionClientParams & {
141
+ app: App;
142
+ }): Promise<Client<GeekappsConnections[App] & {}>>;
143
+ declare function createConnectionClient<Paths extends {}>(params: ConnectionClientParams & {
144
+ app?: undefined;
145
+ }): Promise<Client<Paths>>;
146
+ type ConnectionClientParams = {
147
+ /** O API token guardado por esta app. */
148
+ connectionToken: string;
149
+ /** Sobrescreve o apiBaseUrl declarado pela app alvo. */
150
+ baseUrl?: string;
151
+ /** Demais opções do openapi-fetch (headers, querySerializer…). */
152
+ options?: Omit<ClientOptions, "baseUrl" | "fetch">;
153
+ config?: AppConnectionsConfig;
154
+ };
155
+ /**
156
+ * Gira o API token: o antigo deixa de valer na hora e o novo é devolvido (a
157
+ * validade da conexão não muda). Persista o novo no lugar do antigo.
158
+ */
159
+ declare function rotateConnectionToken(params: {
160
+ connectionToken: string;
161
+ config?: AppConnectionsConfig;
162
+ }): Promise<{
163
+ token: string;
164
+ expiresAt: string | null;
111
165
  }>;
112
166
 
113
- export { AppConnectionError, type AppConnectionsClient, type AppConnectionsConfig, type ConnectAppParams, type ConnectionCallOptions, type ConnectionsCatalog, type GeekappsConnections, appConnections, callAppConnection, completeAppConnection, connectApp, createAppConnections, defineAppConnections, registerConnections };
167
+ export { type AppConnectionAccessToken, AppConnectionError, type AppConnectionToken, type AppConnectionsConfig, type ConnectAppParams, type GeekappsConnections, completeAppConnection, connectApp, connectionFetch, createConnectionClient, getConnectionAccessToken, rotateConnectionToken };