@allanfsouza/aether-sdk 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.d.ts +0 -29
- package/dist/auth.js +6 -38
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +42 -0
- package/dist/functions.d.ts +0 -6
- package/dist/functions.js +0 -8
- package/dist/http-client.d.ts +3 -5
- package/dist/http-client.js +11 -7
- package/dist/index.d.ts +8 -6
- package/dist/index.js +10 -9
- package/errors.ts +46 -0
- package/package.json +10 -8
- package/src/auth.ts +10 -46
- package/src/errors.ts +50 -0
- package/src/functions.ts +1 -11
- package/src/http-client.ts +17 -9
- package/src/index.ts +22 -14
- package/tsconfig.json +16 -9
package/dist/auth.d.ts
CHANGED
|
@@ -1,45 +1,16 @@
|
|
|
1
1
|
import type { AxiosInstance } from "axios";
|
|
2
2
|
import type { PlataformaClient } from "./index.js";
|
|
3
|
-
/**
|
|
4
|
-
* Módulo de Autenticação
|
|
5
|
-
* Lida com login, registro, gerenciamento de token e recuperação de senha.
|
|
6
|
-
*/
|
|
7
3
|
export declare class AuthModule {
|
|
8
4
|
private client;
|
|
9
5
|
private http;
|
|
10
6
|
constructor(client: PlataformaClient, http: AxiosInstance);
|
|
11
|
-
/**
|
|
12
|
-
* Autentica um usuário e armazena o token no SDK.
|
|
13
|
-
* @param email O e-mail do usuário
|
|
14
|
-
* @param password A senha do usuário
|
|
15
|
-
* @returns O objeto do usuário e o token
|
|
16
|
-
*/
|
|
17
7
|
login(email: string, password: string): Promise<any>;
|
|
18
|
-
/**
|
|
19
|
-
* Registra um novo usuário e já realiza o login automaticamente.
|
|
20
|
-
* @param credentials Nome, email e senha
|
|
21
|
-
* @returns O objeto do usuário e o token
|
|
22
|
-
*/
|
|
23
8
|
register(credentials: {
|
|
24
9
|
name: string;
|
|
25
10
|
email: string;
|
|
26
11
|
password: string;
|
|
27
12
|
}): Promise<any>;
|
|
28
|
-
/**
|
|
29
|
-
* Solicita um e-mail de recuperação de senha.
|
|
30
|
-
* @param email O e-mail da conta
|
|
31
|
-
* @returns A resposta da API (mensagem de sucesso)
|
|
32
|
-
*/
|
|
33
13
|
forgotPassword(email: string): Promise<any>;
|
|
34
|
-
/**
|
|
35
|
-
* Redefine a senha usando o token recebido por e-mail.
|
|
36
|
-
* @param token O código/token recebido
|
|
37
|
-
* @param newPassword A nova senha desejada
|
|
38
|
-
* @returns A resposta da API (mensagem de sucesso)
|
|
39
|
-
*/
|
|
40
14
|
resetPassword(token: string, newPassword: string): Promise<any>;
|
|
41
|
-
/**
|
|
42
|
-
* Desconecta o usuário limpando o token da memória do SDK.
|
|
43
|
-
*/
|
|
44
15
|
logout(): void;
|
|
45
16
|
}
|
package/dist/auth.js
CHANGED
|
@@ -1,39 +1,24 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Módulo de Autenticação
|
|
3
|
-
* Lida com login, registro, gerenciamento de token e recuperação de senha.
|
|
4
|
-
*/
|
|
5
1
|
export class AuthModule {
|
|
6
2
|
constructor(client, http) {
|
|
7
3
|
this.client = client;
|
|
8
4
|
this.http = http;
|
|
9
5
|
}
|
|
10
|
-
/**
|
|
11
|
-
* Autentica um usuário e armazena o token no SDK.
|
|
12
|
-
* @param email O e-mail do usuário
|
|
13
|
-
* @param password A senha do usuário
|
|
14
|
-
* @returns O objeto do usuário e o token
|
|
15
|
-
*/
|
|
16
6
|
async login(email, password) {
|
|
17
7
|
try {
|
|
18
8
|
const { data } = await this.http.post("/auth/login", { email, password });
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
if (data.token) {
|
|
10
|
+
this.client.setToken(data.token);
|
|
11
|
+
}
|
|
12
|
+
return data;
|
|
22
13
|
}
|
|
23
14
|
catch (e) {
|
|
24
|
-
this.client.setToken(null);
|
|
15
|
+
this.client.setToken(null);
|
|
25
16
|
throw e;
|
|
26
17
|
}
|
|
27
18
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Registra um novo usuário e já realiza o login automaticamente.
|
|
30
|
-
* @param credentials Nome, email e senha
|
|
31
|
-
* @returns O objeto do usuário e o token
|
|
32
|
-
*/
|
|
33
19
|
async register(credentials) {
|
|
34
20
|
try {
|
|
35
21
|
const { data } = await this.http.post("/auth/register", credentials);
|
|
36
|
-
// Se o backend retornar o token no registro, já salvamos
|
|
37
22
|
if (data.token) {
|
|
38
23
|
this.client.setToken(data.token);
|
|
39
24
|
}
|
|
@@ -44,31 +29,14 @@ export class AuthModule {
|
|
|
44
29
|
throw e;
|
|
45
30
|
}
|
|
46
31
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Solicita um e-mail de recuperação de senha.
|
|
49
|
-
* @param email O e-mail da conta
|
|
50
|
-
* @returns A resposta da API (mensagem de sucesso)
|
|
51
|
-
*/
|
|
52
32
|
async forgotPassword(email) {
|
|
53
33
|
const { data } = await this.http.post("/auth/forgot-password", { email });
|
|
54
34
|
return data;
|
|
55
35
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Redefine a senha usando o token recebido por e-mail.
|
|
58
|
-
* @param token O código/token recebido
|
|
59
|
-
* @param newPassword A nova senha desejada
|
|
60
|
-
* @returns A resposta da API (mensagem de sucesso)
|
|
61
|
-
*/
|
|
62
36
|
async resetPassword(token, newPassword) {
|
|
63
|
-
const { data } = await this.http.post("/auth/reset-password", {
|
|
64
|
-
token,
|
|
65
|
-
newPassword,
|
|
66
|
-
});
|
|
37
|
+
const { data } = await this.http.post("/auth/reset-password", { token, newPassword });
|
|
67
38
|
return data;
|
|
68
39
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Desconecta o usuário limpando o token da memória do SDK.
|
|
71
|
-
*/
|
|
72
40
|
logout() {
|
|
73
41
|
this.client.setToken(null);
|
|
74
42
|
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class AetherError extends Error {
|
|
2
|
+
code: string;
|
|
3
|
+
message: string;
|
|
4
|
+
status?: number | undefined;
|
|
5
|
+
details?: any | undefined;
|
|
6
|
+
constructor(code: string, message: string, status?: number | undefined, details?: any | undefined);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Converte qualquer erro vindo do Axios em um AetherError padronizado.
|
|
10
|
+
* Essa função é pensada para ser usada no interceptor de responses.
|
|
11
|
+
*/
|
|
12
|
+
export declare function handleAxiosError(error: any): never;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
export class AetherError extends Error {
|
|
3
|
+
constructor(code, message, status, details) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.message = message;
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.details = details;
|
|
9
|
+
this.name = "AetherError";
|
|
10
|
+
// Garante que instanceof AetherError funcione mesmo em cenários com transpile/bundler
|
|
11
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Converte qualquer erro vindo do Axios em um AetherError padronizado.
|
|
16
|
+
* Essa função é pensada para ser usada no interceptor de responses.
|
|
17
|
+
*/
|
|
18
|
+
export function handleAxiosError(error) {
|
|
19
|
+
// Erro com resposta do servidor (4xx, 5xx)
|
|
20
|
+
if (error && error.response) {
|
|
21
|
+
const data = error.response.data;
|
|
22
|
+
const message = data?.error || data?.message || "Erro desconhecido na API";
|
|
23
|
+
const status = error.response.status;
|
|
24
|
+
let code = "api_error";
|
|
25
|
+
if (status === 401)
|
|
26
|
+
code = "unauthorized";
|
|
27
|
+
if (status === 403)
|
|
28
|
+
code = "permission_denied";
|
|
29
|
+
if (status === 404)
|
|
30
|
+
code = "not_found";
|
|
31
|
+
if (status === 429)
|
|
32
|
+
code = "rate_limit_exceeded";
|
|
33
|
+
throw new AetherError(code, message, status, data);
|
|
34
|
+
}
|
|
35
|
+
// Erro de rede (sem resposta do servidor)
|
|
36
|
+
if (error && error.request && !error.response) {
|
|
37
|
+
throw new AetherError("network_error", "Não foi possível conectar ao servidor Aether.", 0);
|
|
38
|
+
}
|
|
39
|
+
// Erro de configuração / código do cliente
|
|
40
|
+
const fallbackMessage = (error && error.message) || "Erro interno no cliente SDK.";
|
|
41
|
+
throw new AetherError("client_error", fallbackMessage);
|
|
42
|
+
}
|
package/dist/functions.d.ts
CHANGED
|
@@ -4,11 +4,5 @@ export declare class FunctionsModule {
|
|
|
4
4
|
private client;
|
|
5
5
|
private http;
|
|
6
6
|
constructor(client: PlataformaClient, http: AxiosInstance);
|
|
7
|
-
/**
|
|
8
|
-
* Chama uma função HTTP Serverless.
|
|
9
|
-
* @param functionName O nome da função (ou rota, ex: 'pedidos/123')
|
|
10
|
-
* @param body (Opcional) Dados para enviar no corpo (POST)
|
|
11
|
-
* @param method (Opcional) Método HTTP (padrão POST se tiver body, GET se não)
|
|
12
|
-
*/
|
|
13
7
|
invoke<T = any>(functionName: string, body?: any, method?: "GET" | "POST" | "PUT" | "DELETE"): Promise<T>;
|
|
14
8
|
}
|
package/dist/functions.js
CHANGED
|
@@ -3,17 +3,9 @@ export class FunctionsModule {
|
|
|
3
3
|
this.client = client;
|
|
4
4
|
this.http = http;
|
|
5
5
|
}
|
|
6
|
-
/**
|
|
7
|
-
* Chama uma função HTTP Serverless.
|
|
8
|
-
* @param functionName O nome da função (ou rota, ex: 'pedidos/123')
|
|
9
|
-
* @param body (Opcional) Dados para enviar no corpo (POST)
|
|
10
|
-
* @param method (Opcional) Método HTTP (padrão POST se tiver body, GET se não)
|
|
11
|
-
*/
|
|
12
6
|
async invoke(functionName, body, method) {
|
|
13
7
|
const projectId = this.client.projectId;
|
|
14
|
-
// Remove barras iniciais para evitar URL malformada
|
|
15
8
|
const cleanName = functionName.replace(/^\//, "");
|
|
16
|
-
// Define método automaticamente se não informado
|
|
17
9
|
const finalMethod = method || (body ? "POST" : "GET");
|
|
18
10
|
const response = await this.http.request({
|
|
19
11
|
url: `/functions/http/${projectId}/${cleanName}`,
|
package/dist/http-client.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { type AxiosInstance } from "axios";
|
|
2
|
-
import { PlataformaClient } from "./index.js";
|
|
2
|
+
import type { PlataformaClient } from "./index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Cria uma instância do Axios pré-configurada.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* * @param client A instância principal do PlataformaClient
|
|
8
|
-
* @returns Uma instância configurada do Axios
|
|
5
|
+
* - Injeta automaticamente headers de Auth e Projeto.
|
|
6
|
+
* - Converte erros em AetherError.
|
|
9
7
|
*/
|
|
10
8
|
export declare function createHttpClient(client: PlataformaClient): AxiosInstance;
|
package/dist/http-client.js
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
// src/http-client.ts
|
|
2
2
|
import axios from "axios";
|
|
3
|
+
import { handleAxiosError } from "./errors.js";
|
|
3
4
|
/**
|
|
4
5
|
* Cria uma instância do Axios pré-configurada.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* * @param client A instância principal do PlataformaClient
|
|
8
|
-
* @returns Uma instância configurada do Axios
|
|
6
|
+
* - Injeta automaticamente headers de Auth e Projeto.
|
|
7
|
+
* - Converte erros em AetherError.
|
|
9
8
|
*/
|
|
10
9
|
export function createHttpClient(client) {
|
|
11
10
|
const http = axios.create({
|
|
12
|
-
|
|
11
|
+
// Adiciona o /v1 automaticamente em todas as chamadas do SDK
|
|
12
|
+
baseURL: `${client.apiUrl}/v1`,
|
|
13
|
+
headers: {
|
|
14
|
+
"Content-Type": "application/json",
|
|
15
|
+
},
|
|
13
16
|
});
|
|
17
|
+
// Interceptor de REQUEST
|
|
14
18
|
http.interceptors.request.use((config) => {
|
|
15
|
-
// 1. Pega o token atual do cliente
|
|
16
19
|
const token = client.getToken();
|
|
17
20
|
if (token) {
|
|
18
21
|
config.headers.Authorization = `Bearer ${token}`;
|
|
19
22
|
}
|
|
20
|
-
// 2. Pega o ID do projeto
|
|
21
23
|
if (client.projectId) {
|
|
22
24
|
config.headers["X-Project-ID"] = client.projectId;
|
|
23
25
|
}
|
|
24
26
|
return config;
|
|
25
27
|
});
|
|
28
|
+
// Interceptor de RESPONSE
|
|
29
|
+
http.interceptors.response.use((response) => response, (error) => handleAxiosError(error));
|
|
26
30
|
return http;
|
|
27
31
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,12 +2,15 @@ import { AuthModule } from "./auth.js";
|
|
|
2
2
|
import { DatabaseModule } from "./database.js";
|
|
3
3
|
import { StorageModule } from "./storage.js";
|
|
4
4
|
import { FunctionsModule } from "./functions.js";
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Configuração usada para criar o cliente principal da plataforma.
|
|
7
|
+
*/
|
|
8
|
+
export type ClientConfig = {
|
|
6
9
|
apiUrl: string;
|
|
7
10
|
projectId: string;
|
|
8
11
|
};
|
|
9
12
|
/**
|
|
10
|
-
* O cliente principal da Plataforma API.
|
|
13
|
+
* O cliente principal da Plataforma API (Aether).
|
|
11
14
|
* Ponto de entrada para todos os módulos (Auth, DB, Storage, Functions).
|
|
12
15
|
*/
|
|
13
16
|
export declare class PlataformaClient {
|
|
@@ -22,15 +25,14 @@ export declare class PlataformaClient {
|
|
|
22
25
|
constructor(config: ClientConfig);
|
|
23
26
|
/**
|
|
24
27
|
* Armazena o token de autenticação em memória.
|
|
25
|
-
* Chamado automaticamente pelo AuthModule após login.
|
|
26
|
-
* @param token O JWT (ou null para logout)
|
|
28
|
+
* Chamado automaticamente pelo AuthModule após login/registro.
|
|
27
29
|
*/
|
|
28
30
|
setToken(token: string | null): void;
|
|
29
31
|
/**
|
|
30
32
|
* Recupera o token de autenticação atual.
|
|
31
33
|
* Usado pelo http-client para injetar o header Authorization.
|
|
32
|
-
* @returns O JWT ou null
|
|
33
34
|
*/
|
|
34
35
|
getToken(): string | null;
|
|
35
36
|
}
|
|
36
|
-
export {};
|
|
37
|
+
export { AetherError } from "./errors.js";
|
|
38
|
+
export type { ListOptions } from "./database.js";
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@ import { createHttpClient } from "./http-client.js";
|
|
|
2
2
|
import { AuthModule } from "./auth.js";
|
|
3
3
|
import { DatabaseModule } from "./database.js";
|
|
4
4
|
import { StorageModule } from "./storage.js";
|
|
5
|
-
import { FunctionsModule } from "./functions.js";
|
|
5
|
+
import { FunctionsModule } from "./functions.js";
|
|
6
6
|
/**
|
|
7
|
-
* O cliente principal da Plataforma API.
|
|
7
|
+
* O cliente principal da Plataforma API (Aether).
|
|
8
8
|
* Ponto de entrada para todos os módulos (Auth, DB, Storage, Functions).
|
|
9
9
|
*/
|
|
10
10
|
export class PlataformaClient {
|
|
@@ -13,21 +13,21 @@ export class PlataformaClient {
|
|
|
13
13
|
if (!config.apiUrl || !config.projectId) {
|
|
14
14
|
throw new Error("apiUrl e projectId são obrigatórios.");
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
// Normaliza apiUrl removendo barra final, se houver
|
|
17
|
+
this.apiUrl = config.apiUrl.replace(/\/$/, "");
|
|
17
18
|
this.projectId = config.projectId;
|
|
18
|
-
// Inicializa o cliente HTTP (passando
|
|
19
|
+
// Inicializa o cliente HTTP (passando a própria instância)
|
|
19
20
|
this.http = createHttpClient(this);
|
|
20
|
-
// Inicializa os módulos
|
|
21
|
+
// Inicializa os módulos de alto nível
|
|
21
22
|
this.auth = new AuthModule(this, this.http);
|
|
22
23
|
this.db = new DatabaseModule(this, this.http);
|
|
23
24
|
this.storage = new StorageModule(this, this.http);
|
|
24
|
-
this.functions = new FunctionsModule(this, this.http);
|
|
25
|
+
this.functions = new FunctionsModule(this, this.http);
|
|
25
26
|
}
|
|
26
27
|
// --- Gerenciamento de Token ---
|
|
27
28
|
/**
|
|
28
29
|
* Armazena o token de autenticação em memória.
|
|
29
|
-
* Chamado automaticamente pelo AuthModule após login.
|
|
30
|
-
* @param token O JWT (ou null para logout)
|
|
30
|
+
* Chamado automaticamente pelo AuthModule após login/registro.
|
|
31
31
|
*/
|
|
32
32
|
setToken(token) {
|
|
33
33
|
this._token = token;
|
|
@@ -35,9 +35,10 @@ export class PlataformaClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Recupera o token de autenticação atual.
|
|
37
37
|
* Usado pelo http-client para injetar o header Authorization.
|
|
38
|
-
* @returns O JWT ou null
|
|
39
38
|
*/
|
|
40
39
|
getToken() {
|
|
41
40
|
return this._token;
|
|
42
41
|
}
|
|
43
42
|
}
|
|
43
|
+
// Re-exports convenientes para quem consome o SDK
|
|
44
|
+
export { AetherError } from "./errors.js";
|
package/errors.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
export class AetherError extends Error {
|
|
3
|
+
constructor(
|
|
4
|
+
public code: string,
|
|
5
|
+
public message: string,
|
|
6
|
+
public status?: number,
|
|
7
|
+
public details?: any
|
|
8
|
+
) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "AetherError";
|
|
11
|
+
// Garante que instanceof AetherError funcione bem em qualquer bundler (ES5/ES6)
|
|
12
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function handleAxiosError(error: any): never {
|
|
17
|
+
if (error?.response) {
|
|
18
|
+
// Erro vindo da API (4xx, 5xx)
|
|
19
|
+
const data = error.response.data;
|
|
20
|
+
const message =
|
|
21
|
+
data?.error || data?.message || "Erro desconhecido na API";
|
|
22
|
+
const status: number = error.response.status;
|
|
23
|
+
|
|
24
|
+
let code = "api_error";
|
|
25
|
+
if (status === 401) code = "unauthorized";
|
|
26
|
+
if (status === 403) code = "permission_denied";
|
|
27
|
+
if (status === 404) code = "not_found";
|
|
28
|
+
if (status === 409) code = "conflict";
|
|
29
|
+
if (status === 429) code = "rate_limit_exceeded";
|
|
30
|
+
|
|
31
|
+
throw new AetherError(code, message, status, data);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (error?.request && !error.response) {
|
|
35
|
+
// Erro de rede (sem resposta, offline, timeout)
|
|
36
|
+
throw new AetherError(
|
|
37
|
+
"network_error",
|
|
38
|
+
"Não foi possível conectar ao servidor Aether. Verifique sua conexão.",
|
|
39
|
+
0
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Erro na configuração / código cliente
|
|
44
|
+
const fallbackMessage = error?.message || "Erro interno no cliente SDK.";
|
|
45
|
+
throw new AetherError("client_error", fallbackMessage);
|
|
46
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allanfsouza/aether-sdk",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "SDK do Cliente para a Plataforma
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "SDK do Cliente para a Plataforma Aether",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
@@ -15,15 +15,17 @@
|
|
|
15
15
|
"build": "npx tsc",
|
|
16
16
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
17
17
|
},
|
|
18
|
-
"keywords": [
|
|
18
|
+
"keywords": [
|
|
19
|
+
"baas",
|
|
20
|
+
"sdk",
|
|
21
|
+
"aether"
|
|
22
|
+
],
|
|
19
23
|
"author": "",
|
|
20
24
|
"license": "ISC",
|
|
21
25
|
"dependencies": {
|
|
22
|
-
"axios": "^1.
|
|
23
|
-
"ws": "^8.18.0"
|
|
26
|
+
"axios": "^1.6.0"
|
|
24
27
|
},
|
|
25
28
|
"devDependencies": {
|
|
26
|
-
"
|
|
27
|
-
"typescript": "^5.9.3"
|
|
29
|
+
"typescript": "^5.3.0"
|
|
28
30
|
}
|
|
29
|
-
}
|
|
31
|
+
}
|
package/src/auth.ts
CHANGED
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
import type { AxiosInstance } from "axios";
|
|
3
3
|
import type { PlataformaClient } from "./index.js";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Módulo de Autenticação
|
|
7
|
-
* Lida com login, registro, gerenciamento de token e recuperação de senha.
|
|
8
|
-
*/
|
|
9
5
|
export class AuthModule {
|
|
10
6
|
private client: PlataformaClient;
|
|
11
7
|
private http: AxiosInstance;
|
|
@@ -15,75 +11,43 @@ export class AuthModule {
|
|
|
15
11
|
this.http = http;
|
|
16
12
|
}
|
|
17
13
|
|
|
18
|
-
/**
|
|
19
|
-
* Autentica um usuário e armazena o token no SDK.
|
|
20
|
-
* @param email O e-mail do usuário
|
|
21
|
-
* @param password A senha do usuário
|
|
22
|
-
* @returns O objeto do usuário e o token
|
|
23
|
-
*/
|
|
24
14
|
async login(email: string, password: string) {
|
|
25
15
|
try {
|
|
26
16
|
const { data } = await this.http.post("/auth/login", { email, password });
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
if (data.token) {
|
|
18
|
+
this.client.setToken(data.token);
|
|
19
|
+
}
|
|
20
|
+
return data;
|
|
21
|
+
} catch (e) {
|
|
22
|
+
this.client.setToken(null);
|
|
32
23
|
throw e;
|
|
33
24
|
}
|
|
34
25
|
}
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
* Registra um novo usuário e já realiza o login automaticamente.
|
|
38
|
-
* @param credentials Nome, email e senha
|
|
39
|
-
* @returns O objeto do usuário e o token
|
|
40
|
-
*/
|
|
41
|
-
async register(credentials: {
|
|
42
|
-
name: string;
|
|
43
|
-
email: string;
|
|
44
|
-
password: string;
|
|
45
|
-
}) {
|
|
27
|
+
async register(credentials: { name: string; email: string; password: string }) {
|
|
46
28
|
try {
|
|
47
29
|
const { data } = await this.http.post("/auth/register", credentials);
|
|
48
|
-
// Se o backend retornar o token no registro, já salvamos
|
|
49
30
|
if (data.token) {
|
|
50
31
|
this.client.setToken(data.token);
|
|
51
32
|
}
|
|
52
33
|
return data;
|
|
53
|
-
} catch (e
|
|
34
|
+
} catch (e) {
|
|
54
35
|
this.client.setToken(null);
|
|
55
36
|
throw e;
|
|
56
37
|
}
|
|
57
38
|
}
|
|
58
39
|
|
|
59
|
-
/**
|
|
60
|
-
* Solicita um e-mail de recuperação de senha.
|
|
61
|
-
* @param email O e-mail da conta
|
|
62
|
-
* @returns A resposta da API (mensagem de sucesso)
|
|
63
|
-
*/
|
|
64
40
|
async forgotPassword(email: string) {
|
|
65
41
|
const { data } = await this.http.post("/auth/forgot-password", { email });
|
|
66
42
|
return data;
|
|
67
43
|
}
|
|
68
44
|
|
|
69
|
-
/**
|
|
70
|
-
* Redefine a senha usando o token recebido por e-mail.
|
|
71
|
-
* @param token O código/token recebido
|
|
72
|
-
* @param newPassword A nova senha desejada
|
|
73
|
-
* @returns A resposta da API (mensagem de sucesso)
|
|
74
|
-
*/
|
|
75
45
|
async resetPassword(token: string, newPassword: string) {
|
|
76
|
-
const { data } = await this.http.post("/auth/reset-password", {
|
|
77
|
-
token,
|
|
78
|
-
newPassword,
|
|
79
|
-
});
|
|
46
|
+
const { data } = await this.http.post("/auth/reset-password", { token, newPassword });
|
|
80
47
|
return data;
|
|
81
48
|
}
|
|
82
49
|
|
|
83
|
-
/**
|
|
84
|
-
* Desconecta o usuário limpando o token da memória do SDK.
|
|
85
|
-
*/
|
|
86
50
|
logout() {
|
|
87
51
|
this.client.setToken(null);
|
|
88
52
|
}
|
|
89
|
-
}
|
|
53
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
export class AetherError extends Error {
|
|
3
|
+
constructor(
|
|
4
|
+
public code: string,
|
|
5
|
+
public message: string,
|
|
6
|
+
public status?: number,
|
|
7
|
+
public details?: any
|
|
8
|
+
) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "AetherError";
|
|
11
|
+
// Garante que instanceof AetherError funcione mesmo em cenários com transpile/bundler
|
|
12
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Converte qualquer erro vindo do Axios em um AetherError padronizado.
|
|
18
|
+
* Essa função é pensada para ser usada no interceptor de responses.
|
|
19
|
+
*/
|
|
20
|
+
export function handleAxiosError(error: any): never {
|
|
21
|
+
// Erro com resposta do servidor (4xx, 5xx)
|
|
22
|
+
if (error && error.response) {
|
|
23
|
+
const data = error.response.data;
|
|
24
|
+
const message =
|
|
25
|
+
data?.error || data?.message || "Erro desconhecido na API";
|
|
26
|
+
const status: number = error.response.status;
|
|
27
|
+
|
|
28
|
+
let code = "api_error";
|
|
29
|
+
if (status === 401) code = "unauthorized";
|
|
30
|
+
if (status === 403) code = "permission_denied";
|
|
31
|
+
if (status === 404) code = "not_found";
|
|
32
|
+
if (status === 429) code = "rate_limit_exceeded";
|
|
33
|
+
|
|
34
|
+
throw new AetherError(code, message, status, data);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Erro de rede (sem resposta do servidor)
|
|
38
|
+
if (error && error.request && !error.response) {
|
|
39
|
+
throw new AetherError(
|
|
40
|
+
"network_error",
|
|
41
|
+
"Não foi possível conectar ao servidor Aether.",
|
|
42
|
+
0
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Erro de configuração / código do cliente
|
|
47
|
+
const fallbackMessage =
|
|
48
|
+
(error && error.message) || "Erro interno no cliente SDK.";
|
|
49
|
+
throw new AetherError("client_error", fallbackMessage);
|
|
50
|
+
}
|
package/src/functions.ts
CHANGED
|
@@ -11,23 +11,13 @@ export class FunctionsModule {
|
|
|
11
11
|
this.http = http;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* Chama uma função HTTP Serverless.
|
|
16
|
-
* @param functionName O nome da função (ou rota, ex: 'pedidos/123')
|
|
17
|
-
* @param body (Opcional) Dados para enviar no corpo (POST)
|
|
18
|
-
* @param method (Opcional) Método HTTP (padrão POST se tiver body, GET se não)
|
|
19
|
-
*/
|
|
20
14
|
async invoke<T = any>(
|
|
21
15
|
functionName: string,
|
|
22
16
|
body?: any,
|
|
23
17
|
method?: "GET" | "POST" | "PUT" | "DELETE"
|
|
24
18
|
) {
|
|
25
19
|
const projectId = this.client.projectId;
|
|
26
|
-
|
|
27
|
-
// Remove barras iniciais para evitar URL malformada
|
|
28
20
|
const cleanName = functionName.replace(/^\//, "");
|
|
29
|
-
|
|
30
|
-
// Define método automaticamente se não informado
|
|
31
21
|
const finalMethod = method || (body ? "POST" : "GET");
|
|
32
22
|
|
|
33
23
|
const response = await this.http.request<T>({
|
|
@@ -38,4 +28,4 @@ export class FunctionsModule {
|
|
|
38
28
|
|
|
39
29
|
return response.data;
|
|
40
30
|
}
|
|
41
|
-
}
|
|
31
|
+
}
|
package/src/http-client.ts
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
// src/http-client.ts
|
|
2
2
|
import axios, { type AxiosInstance } from "axios";
|
|
3
|
-
import { PlataformaClient } from "./index.js";
|
|
3
|
+
import type { PlataformaClient } from "./index.js";
|
|
4
|
+
import { handleAxiosError } from "./errors.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Cria uma instância do Axios pré-configurada.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* * @param client A instância principal do PlataformaClient
|
|
10
|
-
* @returns Uma instância configurada do Axios
|
|
8
|
+
* - Injeta automaticamente headers de Auth e Projeto.
|
|
9
|
+
* - Converte erros em AetherError.
|
|
11
10
|
*/
|
|
12
11
|
export function createHttpClient(client: PlataformaClient): AxiosInstance {
|
|
13
12
|
const http = axios.create({
|
|
14
|
-
|
|
13
|
+
// Adiciona o /v1 automaticamente em todas as chamadas do SDK
|
|
14
|
+
baseURL: `${client.apiUrl}/v1`,
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/json",
|
|
17
|
+
},
|
|
15
18
|
});
|
|
16
19
|
|
|
20
|
+
// Interceptor de REQUEST
|
|
17
21
|
http.interceptors.request.use((config) => {
|
|
18
|
-
// 1. Pega o token atual do cliente
|
|
19
22
|
const token = client.getToken();
|
|
20
23
|
if (token) {
|
|
21
24
|
config.headers.Authorization = `Bearer ${token}`;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
// 2. Pega o ID do projeto
|
|
25
27
|
if (client.projectId) {
|
|
26
28
|
config.headers["X-Project-ID"] = client.projectId;
|
|
27
29
|
}
|
|
@@ -29,5 +31,11 @@ export function createHttpClient(client: PlataformaClient): AxiosInstance {
|
|
|
29
31
|
return config;
|
|
30
32
|
});
|
|
31
33
|
|
|
34
|
+
// Interceptor de RESPONSE
|
|
35
|
+
http.interceptors.response.use(
|
|
36
|
+
(response) => response,
|
|
37
|
+
(error) => handleAxiosError(error)
|
|
38
|
+
);
|
|
39
|
+
|
|
32
40
|
return http;
|
|
33
|
-
}
|
|
41
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,29 +4,32 @@ import { createHttpClient } from "./http-client.js";
|
|
|
4
4
|
import { AuthModule } from "./auth.js";
|
|
5
5
|
import { DatabaseModule } from "./database.js";
|
|
6
6
|
import { StorageModule } from "./storage.js";
|
|
7
|
-
import { FunctionsModule } from "./functions.js";
|
|
7
|
+
import { FunctionsModule } from "./functions.js";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Configuração usada para criar o cliente principal da plataforma.
|
|
11
|
+
*/
|
|
12
|
+
export type ClientConfig = {
|
|
10
13
|
apiUrl: string;
|
|
11
14
|
projectId: string;
|
|
12
15
|
};
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
|
-
* O cliente principal da Plataforma API.
|
|
18
|
+
* O cliente principal da Plataforma API (Aether).
|
|
16
19
|
* Ponto de entrada para todos os módulos (Auth, DB, Storage, Functions).
|
|
17
20
|
*/
|
|
18
21
|
export class PlataformaClient {
|
|
19
|
-
//
|
|
22
|
+
// Módulos públicos disponíveis para o usuário do SDK
|
|
20
23
|
public auth: AuthModule;
|
|
21
24
|
public db: DatabaseModule;
|
|
22
25
|
public storage: StorageModule;
|
|
23
|
-
public functions: FunctionsModule;
|
|
26
|
+
public functions: FunctionsModule;
|
|
24
27
|
|
|
25
|
-
//
|
|
28
|
+
// Configurações imutáveis da instância
|
|
26
29
|
public apiUrl: string;
|
|
27
30
|
public projectId: string;
|
|
28
31
|
|
|
29
|
-
//
|
|
32
|
+
// Infra interna
|
|
30
33
|
private http: AxiosInstance;
|
|
31
34
|
private _token: string | null = null;
|
|
32
35
|
|
|
@@ -34,25 +37,26 @@ export class PlataformaClient {
|
|
|
34
37
|
if (!config.apiUrl || !config.projectId) {
|
|
35
38
|
throw new Error("apiUrl e projectId são obrigatórios.");
|
|
36
39
|
}
|
|
37
|
-
|
|
40
|
+
|
|
41
|
+
// Normaliza apiUrl removendo barra final, se houver
|
|
42
|
+
this.apiUrl = config.apiUrl.replace(/\/$/, "");
|
|
38
43
|
this.projectId = config.projectId;
|
|
39
44
|
|
|
40
|
-
// Inicializa o cliente HTTP (passando
|
|
45
|
+
// Inicializa o cliente HTTP (passando a própria instância)
|
|
41
46
|
this.http = createHttpClient(this);
|
|
42
47
|
|
|
43
|
-
// Inicializa os módulos
|
|
48
|
+
// Inicializa os módulos de alto nível
|
|
44
49
|
this.auth = new AuthModule(this, this.http);
|
|
45
50
|
this.db = new DatabaseModule(this, this.http);
|
|
46
51
|
this.storage = new StorageModule(this, this.http);
|
|
47
|
-
this.functions = new FunctionsModule(this, this.http);
|
|
52
|
+
this.functions = new FunctionsModule(this, this.http);
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
// --- Gerenciamento de Token ---
|
|
51
56
|
|
|
52
57
|
/**
|
|
53
58
|
* Armazena o token de autenticação em memória.
|
|
54
|
-
* Chamado automaticamente pelo AuthModule após login.
|
|
55
|
-
* @param token O JWT (ou null para logout)
|
|
59
|
+
* Chamado automaticamente pelo AuthModule após login/registro.
|
|
56
60
|
*/
|
|
57
61
|
setToken(token: string | null) {
|
|
58
62
|
this._token = token;
|
|
@@ -61,9 +65,13 @@ export class PlataformaClient {
|
|
|
61
65
|
/**
|
|
62
66
|
* Recupera o token de autenticação atual.
|
|
63
67
|
* Usado pelo http-client para injetar o header Authorization.
|
|
64
|
-
* @returns O JWT ou null
|
|
65
68
|
*/
|
|
66
69
|
getToken(): string | null {
|
|
67
70
|
return this._token;
|
|
68
71
|
}
|
|
69
72
|
}
|
|
73
|
+
|
|
74
|
+
// Re-exports convenientes para quem consome o SDK
|
|
75
|
+
export { AetherError } from "./errors.js";
|
|
76
|
+
export type { ListOptions } from "./database.js";
|
|
77
|
+
|
package/tsconfig.json
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"rootDir": "./src",
|
|
9
|
+
"strict": true,
|
|
9
10
|
"skipLibCheck": true,
|
|
10
11
|
"forceConsistentCasingInFileNames": true,
|
|
11
|
-
|
|
12
|
+
// Adicionado DOM para reconhecer 'File', 'Blob' e 'WebSocket' nativos
|
|
13
|
+
"lib": [
|
|
14
|
+
"ES2020",
|
|
15
|
+
"DOM"
|
|
16
|
+
]
|
|
12
17
|
},
|
|
13
|
-
"include": [
|
|
14
|
-
|
|
18
|
+
"include": [
|
|
19
|
+
"src"
|
|
20
|
+
]
|
|
21
|
+
}
|