@allanfsouza/aether-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Plataforma SDK (Cliente JS/TS)
2
+
3
+ Este é o SDK oficial para interagir com a sua "Plataforma BaaS" (clone do Firebase). Ele gerencia autenticação, banco de dados genérico (com tempo real) e storage.
4
+
5
+ ## Instalação
6
+
7
+ ```bash
8
+ npm install @seu-username/plataforma-sdk
9
+ ```
package/dist/auth.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ import type { AxiosInstance } from "axios";
2
+ import type { PlataformaClient } from "./index.js";
3
+ /**
4
+ * Módulo de Autenticação
5
+ * Lida com login, registro e gerenciamento de token.
6
+ */
7
+ export declare class AuthModule {
8
+ private client;
9
+ private http;
10
+ 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
+ login(email: string, password: string): Promise<any>;
18
+ /**
19
+ * Registra um novo usuário e já o loga.
20
+ * @param credentials Nome, email e senha
21
+ * @returns O objeto do usuário e o token
22
+ */
23
+ register(credentials: {
24
+ name: string;
25
+ email: string;
26
+ password: string;
27
+ }): Promise<any>;
28
+ /**
29
+ * Desconecta o usuário limpando o token do SDK.
30
+ */
31
+ logout(): void;
32
+ }
package/dist/auth.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Módulo de Autenticação
3
+ * Lida com login, registro e gerenciamento de token.
4
+ */
5
+ export class AuthModule {
6
+ constructor(client, http) {
7
+ this.client = client;
8
+ this.http = http;
9
+ }
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
+ async login(email, password) {
17
+ try {
18
+ const { data } = await this.http.post("/auth/login", { email, password });
19
+ // Salva o token DENTRO da instância do SDK
20
+ this.client.setToken(data.token);
21
+ return data; // Retorna { user, token }
22
+ }
23
+ catch (e) {
24
+ this.client.setToken(null); // Limpa o token em caso de falha
25
+ throw e;
26
+ }
27
+ }
28
+ /**
29
+ * Registra um novo usuário e já o loga.
30
+ * @param credentials Nome, email e senha
31
+ * @returns O objeto do usuário e o token
32
+ */
33
+ async register(credentials) {
34
+ try {
35
+ const { data } = await this.http.post("/auth/register", credentials);
36
+ this.client.setToken(data.token);
37
+ return data;
38
+ }
39
+ catch (e) {
40
+ this.client.setToken(null);
41
+ throw e;
42
+ }
43
+ }
44
+ /**
45
+ * Desconecta o usuário limpando o token do SDK.
46
+ */
47
+ logout() {
48
+ this.client.setToken(null);
49
+ }
50
+ }
@@ -0,0 +1,59 @@
1
+ import type { AxiosInstance } from "axios";
2
+ import type { PlataformaClient } from "./index.js";
3
+ /**
4
+ * Módulo de Banco de Dados (Firestore-like)
5
+ * Ponto de entrada para acessar as coleções.
6
+ */
7
+ export declare class DatabaseModule {
8
+ private client;
9
+ private http;
10
+ constructor(client: PlataformaClient, http: AxiosInstance);
11
+ /**
12
+ * Seleciona uma coleção de dados (ex: 'tasks' ou 'posts').
13
+ * @param collectionName O nome da coleção (ex: "tasks")
14
+ * @returns Uma instância de CollectionReference para operar nela
15
+ */
16
+ collection(collectionName: string): CollectionReference;
17
+ }
18
+ /**
19
+ * Representa uma referência a uma coleção específica no banco.
20
+ * Contém os métodos CRUD (create, list, update, delete) e subscribe.
21
+ */
22
+ declare class CollectionReference {
23
+ private client;
24
+ private http;
25
+ private collectionName;
26
+ private wsUrl;
27
+ constructor(client: PlataformaClient, http: AxiosInstance, name: string);
28
+ /**
29
+ * Lista todos os documentos da coleção.
30
+ * (GET /v1/db/tasks)
31
+ */
32
+ list(): Promise<any>;
33
+ /**
34
+ * Cria um novo documento na coleção.
35
+ * (POST /v1/db/tasks)
36
+ * @param newData O objeto de dados a ser criado
37
+ */
38
+ create(newData: Record<string, any>): Promise<any>;
39
+ /**
40
+ * Atualiza um documento existente.
41
+ * (PUT /v1/db/tasks/:id)
42
+ * @param id O ID do documento
43
+ * @param updates Os campos a serem atualizados
44
+ */
45
+ update(id: string, updates: Record<string, any>): Promise<any>;
46
+ /**
47
+ * Deleta um documento.
48
+ * (DELETE /v1/db/tasks/:id)
49
+ * @param id O ID do documento
50
+ */
51
+ delete(id: string): Promise<any>;
52
+ /**
53
+ * Inscreve-se para mudanças em tempo real na coleção.
54
+ * @param callback A função que será chamada com (action, data)
55
+ * @returns Uma função 'unsubscribe' para fechar a conexão
56
+ */
57
+ subscribe(callback: (action: "create" | "update" | "delete", data: any) => void): () => void;
58
+ }
59
+ export {};
@@ -0,0 +1,106 @@
1
+ import WebSocket from "ws";
2
+ /**
3
+ * Módulo de Banco de Dados (Firestore-like)
4
+ * Ponto de entrada para acessar as coleções.
5
+ */
6
+ export class DatabaseModule {
7
+ constructor(client, http) {
8
+ this.client = client;
9
+ this.http = http;
10
+ }
11
+ /**
12
+ * Seleciona uma coleção de dados (ex: 'tasks' ou 'posts').
13
+ * @param collectionName O nome da coleção (ex: "tasks")
14
+ * @returns Uma instância de CollectionReference para operar nela
15
+ */
16
+ collection(collectionName) {
17
+ return new CollectionReference(this.client, this.http, collectionName);
18
+ }
19
+ }
20
+ /**
21
+ * Representa uma referência a uma coleção específica no banco.
22
+ * Contém os métodos CRUD (create, list, update, delete) e subscribe.
23
+ */
24
+ class CollectionReference {
25
+ constructor(client, http, name) {
26
+ this.client = client;
27
+ this.http = http;
28
+ this.collectionName = name;
29
+ // Constrói a URL do WebSocket (substituindo http por ws)
30
+ this.wsUrl = client.apiUrl.replace(/^http/, "ws");
31
+ }
32
+ /**
33
+ * Lista todos os documentos da coleção.
34
+ * (GET /v1/db/tasks)
35
+ */
36
+ async list() {
37
+ const { data } = await this.http.get(`/db/${this.collectionName}`);
38
+ return data.data; // Retorna o array de documentos
39
+ }
40
+ /**
41
+ * Cria um novo documento na coleção.
42
+ * (POST /v1/db/tasks)
43
+ * @param newData O objeto de dados a ser criado
44
+ */
45
+ async create(newData) {
46
+ const { data } = await this.http.post(`/db/${this.collectionName}`, newData);
47
+ return data.data; // Retorna o documento criado
48
+ }
49
+ /**
50
+ * Atualiza um documento existente.
51
+ * (PUT /v1/db/tasks/:id)
52
+ * @param id O ID do documento
53
+ * @param updates Os campos a serem atualizados
54
+ */
55
+ async update(id, updates) {
56
+ const { data } = await this.http.put(`/db/${this.collectionName}/${id}`, updates);
57
+ return data.data; // Retorna o documento atualizado
58
+ }
59
+ /**
60
+ * Deleta um documento.
61
+ * (DELETE /v1/db/tasks/:id)
62
+ * @param id O ID do documento
63
+ */
64
+ async delete(id) {
65
+ const { data } = await this.http.delete(`/db/${this.collectionName}/${id}`);
66
+ return data; // Retorna { ok: true, ... }
67
+ }
68
+ /**
69
+ * Inscreve-se para mudanças em tempo real na coleção.
70
+ * @param callback A função que será chamada com (action, data)
71
+ * @returns Uma função 'unsubscribe' para fechar a conexão
72
+ */
73
+ subscribe(callback) {
74
+ const token = this.client.getToken();
75
+ const projectId = this.client.projectId;
76
+ if (!token || !projectId) {
77
+ throw new Error("Não é possível se inscrever sem um token e projectId.");
78
+ }
79
+ // Constrói a URL: ws://localhost:3000/v1/db/subscribe/tasks?token=...&projectId=...
80
+ const url = `${this.wsUrl}/v1/db/subscribe/${this.collectionName}?token=${token}&projectId=${projectId}`;
81
+ const ws = new WebSocket(url);
82
+ ws.on("open", () => {
83
+ console.log(`[SDK] Inscrito em tempo real na coleção '${this.collectionName}'`);
84
+ });
85
+ ws.on("message", (message) => {
86
+ try {
87
+ const payload = JSON.parse(message);
88
+ // Chama o callback do usuário
89
+ callback(payload.action, payload.data);
90
+ }
91
+ catch (e) {
92
+ console.error("[SDK] Erro ao processar mensagem WS:", e);
93
+ }
94
+ });
95
+ ws.on("close", () => {
96
+ console.log(`[SDK] Desconectado da coleção '${this.collectionName}'`);
97
+ });
98
+ ws.on("error", (err) => {
99
+ console.error("[SDK] Erro no WebSocket:", err.message);
100
+ });
101
+ // Retorna uma função que o usuário pode chamar para parar de "ouvir"
102
+ return () => {
103
+ ws.close();
104
+ };
105
+ }
106
+ }
@@ -0,0 +1,10 @@
1
+ import { type AxiosInstance } from "axios";
2
+ import { PlataformaClient } from "./index.js";
3
+ /**
4
+ * Cria uma instância do Axios pré-configurada.
5
+ * Ela usa um interceptor para adicionar dinamicamente os
6
+ * headers 'Authorization' e 'X-Project-ID' em cada requisição.
7
+ * * @param client A instância principal do PlataformaClient
8
+ * @returns Uma instância configurada do Axios
9
+ */
10
+ export declare function createHttpClient(client: PlataformaClient): AxiosInstance;
@@ -0,0 +1,27 @@
1
+ // src/http-client.ts
2
+ import axios from "axios";
3
+ /**
4
+ * Cria uma instância do Axios pré-configurada.
5
+ * Ela usa um interceptor para adicionar dinamicamente os
6
+ * headers 'Authorization' e 'X-Project-ID' em cada requisição.
7
+ * * @param client A instância principal do PlataformaClient
8
+ * @returns Uma instância configurada do Axios
9
+ */
10
+ export function createHttpClient(client) {
11
+ const http = axios.create({
12
+ baseURL: `${client.apiUrl}/v1`, // Adiciona o /v1 automaticamente
13
+ });
14
+ http.interceptors.request.use((config) => {
15
+ // 1. Pega o token atual do cliente
16
+ const token = client.getToken();
17
+ if (token) {
18
+ config.headers.Authorization = `Bearer ${token}`;
19
+ }
20
+ // 2. Pega o ID do projeto
21
+ if (client.projectId) {
22
+ config.headers["X-Project-ID"] = client.projectId;
23
+ }
24
+ return config;
25
+ });
26
+ return http;
27
+ }
@@ -0,0 +1,32 @@
1
+ import { AuthModule } from "./auth.js";
2
+ import { DatabaseModule } from "./database.js";
3
+ import { StorageModule } from "./storage.js";
4
+ type ClientConfig = {
5
+ apiUrl: string;
6
+ projectId: string;
7
+ };
8
+ /**
9
+ * O cliente principal da Plataforma API.
10
+ * Ponto de entrada para todos os módulos (Auth, DB, Storage).
11
+ */
12
+ export declare class PlataformaClient {
13
+ auth: AuthModule;
14
+ db: DatabaseModule;
15
+ storage: StorageModule;
16
+ apiUrl: string;
17
+ projectId: string;
18
+ private http;
19
+ private _token;
20
+ constructor(config: ClientConfig);
21
+ /**
22
+ * Armazena o token de autenticação em memória.
23
+ * @param token O JWT (ou null para logout)
24
+ */
25
+ setToken(token: string | null): void;
26
+ /**
27
+ * Recupera o token de autenticação atual.
28
+ * @returns O JWT ou null
29
+ */
30
+ getToken(): string | null;
31
+ }
32
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ import { createHttpClient } from "./http-client.js";
2
+ import { AuthModule } from "./auth.js";
3
+ import { DatabaseModule } from "./database.js";
4
+ import { StorageModule } from "./storage.js";
5
+ /**
6
+ * O cliente principal da Plataforma API.
7
+ * Ponto de entrada para todos os módulos (Auth, DB, Storage).
8
+ */
9
+ export class PlataformaClient {
10
+ constructor(config) {
11
+ this._token = null;
12
+ if (!config.apiUrl || !config.projectId) {
13
+ throw new Error("apiUrl e projectId são obrigatórios.");
14
+ }
15
+ this.apiUrl = config.apiUrl.replace(/\/$/, ""); // Remove barra final
16
+ this.projectId = config.projectId;
17
+ // Inicializa o cliente HTTP (passando 'this', a própria instância)
18
+ this.http = createHttpClient(this);
19
+ // Inicializa os módulos
20
+ this.auth = new AuthModule(this, this.http);
21
+ this.db = new DatabaseModule(this, this.http);
22
+ this.storage = new StorageModule(this, this.http);
23
+ }
24
+ // --- Gerenciamento de Token ---
25
+ /**
26
+ * Armazena o token de autenticação em memória.
27
+ * @param token O JWT (ou null para logout)
28
+ */
29
+ setToken(token) {
30
+ this._token = token;
31
+ }
32
+ /**
33
+ * Recupera o token de autenticação atual.
34
+ * @returns O JWT ou null
35
+ */
36
+ getToken() {
37
+ return this._token;
38
+ }
39
+ }
@@ -0,0 +1,20 @@
1
+ import type { AxiosInstance } from "axios";
2
+ import type { PlataformaClient } from "./index.js";
3
+ /**
4
+ * Módulo de Storage
5
+ * Lida com upload e download de arquivos.
6
+ */
7
+ export declare class StorageModule {
8
+ private client;
9
+ private http;
10
+ constructor(client: PlataformaClient, http: AxiosInstance);
11
+ /**
12
+ * Faz o upload de um arquivo para o Storage do projeto.
13
+ * Isso lida com o fluxo de "presign" (URL assinada) automaticamente.
14
+ * @param file O objeto 'File' (do navegador) ou um Buffer (do Node.js)
15
+ * @param fileName O nome do arquivo (ex: "imagem.png")
16
+ * @param contentType O tipo (ex: "image/png")
17
+ * @returns O objeto do arquivo criado no banco
18
+ */
19
+ upload(file: File | Buffer, fileName: string, contentType: string): Promise<any>;
20
+ }
@@ -0,0 +1,40 @@
1
+ import axios from "axios"; // [A CORREÇÃO ESTÁ AQUI]
2
+ /**
3
+ * Módulo de Storage
4
+ * Lida com upload e download de arquivos.
5
+ */
6
+ export class StorageModule {
7
+ constructor(client, http) {
8
+ this.client = client;
9
+ this.http = http;
10
+ }
11
+ /**
12
+ * Faz o upload de um arquivo para o Storage do projeto.
13
+ * Isso lida com o fluxo de "presign" (URL assinada) automaticamente.
14
+ * @param file O objeto 'File' (do navegador) ou um Buffer (do Node.js)
15
+ * @param fileName O nome do arquivo (ex: "imagem.png")
16
+ * @param contentType O tipo (ex: "image/png")
17
+ * @returns O objeto do arquivo criado no banco
18
+ */
19
+ async upload(file, fileName, contentType) {
20
+ const size = file.size || file.length;
21
+ // 1. Pedir a URL de upload para nossa API
22
+ const { data: presignData } = await this.http.post("/storage/presign", {
23
+ fileName: fileName,
24
+ contentType: contentType,
25
+ size: size,
26
+ });
27
+ // O 'presign' vem dentro de 'data'
28
+ const presign = presignData.data;
29
+ if (!presign?.url) {
30
+ throw new Error("API não retornou uma URL de upload assinada.");
31
+ }
32
+ // 2. Enviar o arquivo diretamente para o Minio/S3 (sem auth)
33
+ // Usamos o 'axios' global aqui, não o 'this.http' (que adicionaria auth)
34
+ await axios.put(presign.url, file, {
35
+ headers: { "Content-Type": contentType },
36
+ });
37
+ // 3. Retorna os detalhes do objeto (downloadUrl, objectId, etc.)
38
+ return presign;
39
+ }
40
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@allanfsouza/aether-sdk",
3
+ "version": "1.0.0",
4
+ "description": "SDK do Cliente para a Plataforma API",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "npx tsc",
16
+ "test": "echo \"Error: no test specified\" && exit 1"
17
+ },
18
+ "keywords": [],
19
+ "author": "",
20
+ "license": "ISC",
21
+ "dependencies": {
22
+ "axios": "^1.13.2",
23
+ "ws": "^8.18.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/ws": "^8.5.11",
27
+ "typescript": "^5.9.3"
28
+ }
29
+ }
package/src/auth.ts ADDED
@@ -0,0 +1,62 @@
1
+ // src/auth.ts
2
+ import type { AxiosInstance } from "axios";
3
+ import type { PlataformaClient } from "./index.js";
4
+
5
+ /**
6
+ * Módulo de Autenticação
7
+ * Lida com login, registro e gerenciamento de token.
8
+ */
9
+ export class AuthModule {
10
+ private client: PlataformaClient;
11
+ private http: AxiosInstance;
12
+
13
+ constructor(client: PlataformaClient, http: AxiosInstance) {
14
+ this.client = client;
15
+ this.http = http;
16
+ }
17
+
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
+ async login(email: string, password: string) {
25
+ try {
26
+ const { data } = await this.http.post("/auth/login", { email, password });
27
+ // Salva o token DENTRO da instância do SDK
28
+ this.client.setToken(data.token);
29
+ return data; // Retorna { user, token }
30
+ } catch (e: unknown) {
31
+ this.client.setToken(null); // Limpa o token em caso de falha
32
+ throw e;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Registra um novo usuário e já o loga.
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
+ }) {
46
+ try {
47
+ const { data } = await this.http.post("/auth/register", credentials);
48
+ this.client.setToken(data.token);
49
+ return data;
50
+ } catch (e: unknown) {
51
+ this.client.setToken(null);
52
+ throw e;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Desconecta o usuário limpando o token do SDK.
58
+ */
59
+ logout() {
60
+ this.client.setToken(null);
61
+ }
62
+ }
@@ -0,0 +1,149 @@
1
+ // src/database.ts
2
+ import type { AxiosInstance } from "axios";
3
+ import type { PlataformaClient } from "./index.js";
4
+ import WebSocket from "ws";
5
+
6
+ // Tipo para a mensagem que recebemos do WebSocket
7
+ type WebSocketMessage = {
8
+ action: "create" | "update" | "delete";
9
+ collection: string;
10
+ data: any;
11
+ };
12
+
13
+ /**
14
+ * Módulo de Banco de Dados (Firestore-like)
15
+ * Ponto de entrada para acessar as coleções.
16
+ */
17
+ export class DatabaseModule {
18
+ private client: PlataformaClient;
19
+ private http: AxiosInstance;
20
+
21
+ constructor(client: PlataformaClient, http: AxiosInstance) {
22
+ this.client = client;
23
+ this.http = http;
24
+ }
25
+
26
+ /**
27
+ * Seleciona uma coleção de dados (ex: 'tasks' ou 'posts').
28
+ * @param collectionName O nome da coleção (ex: "tasks")
29
+ * @returns Uma instância de CollectionReference para operar nela
30
+ */
31
+ collection(collectionName: string) {
32
+ return new CollectionReference(this.client, this.http, collectionName);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Representa uma referência a uma coleção específica no banco.
38
+ * Contém os métodos CRUD (create, list, update, delete) e subscribe.
39
+ */
40
+ class CollectionReference {
41
+ private client: PlataformaClient;
42
+ private http: AxiosInstance;
43
+ private collectionName: string;
44
+ private wsUrl: string;
45
+
46
+ constructor(client: PlataformaClient, http: AxiosInstance, name: string) {
47
+ this.client = client;
48
+ this.http = http;
49
+ this.collectionName = name;
50
+ // Constrói a URL do WebSocket (substituindo http por ws)
51
+ this.wsUrl = client.apiUrl.replace(/^http/, "ws");
52
+ }
53
+
54
+ /**
55
+ * Lista todos os documentos da coleção.
56
+ * (GET /v1/db/tasks)
57
+ */
58
+ async list() {
59
+ const { data } = await this.http.get(`/db/${this.collectionName}`);
60
+ return data.data; // Retorna o array de documentos
61
+ }
62
+
63
+ /**
64
+ * Cria um novo documento na coleção.
65
+ * (POST /v1/db/tasks)
66
+ * @param newData O objeto de dados a ser criado
67
+ */
68
+ async create(newData: Record<string, any>) {
69
+ const { data } = await this.http.post(
70
+ `/db/${this.collectionName}`,
71
+ newData
72
+ );
73
+ return data.data; // Retorna o documento criado
74
+ }
75
+
76
+ /**
77
+ * Atualiza um documento existente.
78
+ * (PUT /v1/db/tasks/:id)
79
+ * @param id O ID do documento
80
+ * @param updates Os campos a serem atualizados
81
+ */
82
+ async update(id: string, updates: Record<string, any>) {
83
+ const { data } = await this.http.put(
84
+ `/db/${this.collectionName}/${id}`,
85
+ updates
86
+ );
87
+ return data.data; // Retorna o documento atualizado
88
+ }
89
+
90
+ /**
91
+ * Deleta um documento.
92
+ * (DELETE /v1/db/tasks/:id)
93
+ * @param id O ID do documento
94
+ */
95
+ async delete(id: string) {
96
+ const { data } = await this.http.delete(`/db/${this.collectionName}/${id}`);
97
+ return data; // Retorna { ok: true, ... }
98
+ }
99
+
100
+ /**
101
+ * Inscreve-se para mudanças em tempo real na coleção.
102
+ * @param callback A função que será chamada com (action, data)
103
+ * @returns Uma função 'unsubscribe' para fechar a conexão
104
+ */
105
+ subscribe(
106
+ callback: (action: "create" | "update" | "delete", data: any) => void
107
+ ) {
108
+ const token = this.client.getToken();
109
+ const projectId = this.client.projectId;
110
+
111
+ if (!token || !projectId) {
112
+ throw new Error("Não é possível se inscrever sem um token e projectId.");
113
+ }
114
+
115
+ // Constrói a URL: ws://localhost:3000/v1/db/subscribe/tasks?token=...&projectId=...
116
+ const url = `${this.wsUrl}/v1/db/subscribe/${this.collectionName}?token=${token}&projectId=${projectId}`;
117
+
118
+ const ws = new WebSocket(url);
119
+
120
+ ws.on("open", () => {
121
+ console.log(
122
+ `[SDK] Inscrito em tempo real na coleção '${this.collectionName}'`
123
+ );
124
+ });
125
+
126
+ ws.on("message", (message: string) => {
127
+ try {
128
+ const payload = JSON.parse(message) as WebSocketMessage;
129
+ // Chama o callback do usuário
130
+ callback(payload.action, payload.data);
131
+ } catch (e) {
132
+ console.error("[SDK] Erro ao processar mensagem WS:", e);
133
+ }
134
+ });
135
+
136
+ ws.on("close", () => {
137
+ console.log(`[SDK] Desconectado da coleção '${this.collectionName}'`);
138
+ });
139
+
140
+ ws.on("error", (err) => {
141
+ console.error("[SDK] Erro no WebSocket:", err.message);
142
+ });
143
+
144
+ // Retorna uma função que o usuário pode chamar para parar de "ouvir"
145
+ return () => {
146
+ ws.close();
147
+ };
148
+ }
149
+ }
@@ -0,0 +1,33 @@
1
+ // src/http-client.ts
2
+ import axios, { type AxiosInstance } from "axios";
3
+ import { PlataformaClient } from "./index.js"; // Importa o tipo da classe principal
4
+
5
+ /**
6
+ * Cria uma instância do Axios pré-configurada.
7
+ * Ela usa um interceptor para adicionar dinamicamente os
8
+ * headers 'Authorization' e 'X-Project-ID' em cada requisição.
9
+ * * @param client A instância principal do PlataformaClient
10
+ * @returns Uma instância configurada do Axios
11
+ */
12
+ export function createHttpClient(client: PlataformaClient): AxiosInstance {
13
+ const http = axios.create({
14
+ baseURL: `${client.apiUrl}/v1`, // Adiciona o /v1 automaticamente
15
+ });
16
+
17
+ http.interceptors.request.use((config) => {
18
+ // 1. Pega o token atual do cliente
19
+ const token = client.getToken();
20
+ if (token) {
21
+ config.headers.Authorization = `Bearer ${token}`;
22
+ }
23
+
24
+ // 2. Pega o ID do projeto
25
+ if (client.projectId) {
26
+ config.headers["X-Project-ID"] = client.projectId;
27
+ }
28
+
29
+ return config;
30
+ });
31
+
32
+ return http;
33
+ }
package/src/index.ts ADDED
@@ -0,0 +1,64 @@
1
+ // src/index.ts
2
+ import type { AxiosInstance } from "axios";
3
+ import { createHttpClient } from "./http-client.js";
4
+ import { AuthModule } from "./auth.js";
5
+ import { DatabaseModule } from "./database.js";
6
+ import { StorageModule } from "./storage.js";
7
+
8
+ type ClientConfig = {
9
+ apiUrl: string;
10
+ projectId: string;
11
+ };
12
+
13
+ /**
14
+ * O cliente principal da Plataforma API.
15
+ * Ponto de entrada para todos os módulos (Auth, DB, Storage).
16
+ */
17
+ export class PlataformaClient {
18
+ // Propriedades públicas (os "módulos")
19
+ public auth: AuthModule;
20
+ public db: DatabaseModule;
21
+ public storage: StorageModule;
22
+
23
+ // Propriedades de configuração
24
+ public apiUrl: string;
25
+ public projectId: string;
26
+
27
+ // Propriedades internas
28
+ private http: AxiosInstance;
29
+ private _token: string | null = null;
30
+
31
+ constructor(config: ClientConfig) {
32
+ if (!config.apiUrl || !config.projectId) {
33
+ throw new Error("apiUrl e projectId são obrigatórios.");
34
+ }
35
+ this.apiUrl = config.apiUrl.replace(/\/$/, ""); // Remove barra final
36
+ this.projectId = config.projectId;
37
+
38
+ // Inicializa o cliente HTTP (passando 'this', a própria instância)
39
+ this.http = createHttpClient(this);
40
+
41
+ // Inicializa os módulos
42
+ this.auth = new AuthModule(this, this.http);
43
+ this.db = new DatabaseModule(this, this.http);
44
+ this.storage = new StorageModule(this, this.http);
45
+ }
46
+
47
+ // --- Gerenciamento de Token ---
48
+
49
+ /**
50
+ * Armazena o token de autenticação em memória.
51
+ * @param token O JWT (ou null para logout)
52
+ */
53
+ setToken(token: string | null) {
54
+ this._token = token;
55
+ }
56
+
57
+ /**
58
+ * Recupera o token de autenticação atual.
59
+ * @returns O JWT ou null
60
+ */
61
+ getToken(): string | null {
62
+ return this._token;
63
+ }
64
+ }
package/src/storage.ts ADDED
@@ -0,0 +1,52 @@
1
+ // src/storage.ts
2
+ import type { AxiosInstance } from "axios";
3
+ import type { PlataformaClient } from "./index.js";
4
+ import axios from "axios"; // [A CORREÇÃO ESTÁ AQUI]
5
+
6
+ /**
7
+ * Módulo de Storage
8
+ * Lida com upload e download de arquivos.
9
+ */
10
+ export class StorageModule {
11
+ private client: PlataformaClient;
12
+ private http: AxiosInstance;
13
+
14
+ constructor(client: PlataformaClient, http: AxiosInstance) {
15
+ this.client = client;
16
+ this.http = http;
17
+ }
18
+
19
+ /**
20
+ * Faz o upload de um arquivo para o Storage do projeto.
21
+ * Isso lida com o fluxo de "presign" (URL assinada) automaticamente.
22
+ * @param file O objeto 'File' (do navegador) ou um Buffer (do Node.js)
23
+ * @param fileName O nome do arquivo (ex: "imagem.png")
24
+ * @param contentType O tipo (ex: "image/png")
25
+ * @returns O objeto do arquivo criado no banco
26
+ */
27
+ async upload(file: File | Buffer, fileName: string, contentType: string) {
28
+ const size = (file as File).size || (file as Buffer).length;
29
+
30
+ // 1. Pedir a URL de upload para nossa API
31
+ const { data: presignData } = await this.http.post("/storage/presign", {
32
+ fileName: fileName,
33
+ contentType: contentType,
34
+ size: size,
35
+ });
36
+
37
+ // O 'presign' vem dentro de 'data'
38
+ const presign = presignData.data;
39
+ if (!presign?.url) {
40
+ throw new Error("API não retornou uma URL de upload assinada.");
41
+ }
42
+
43
+ // 2. Enviar o arquivo diretamente para o Minio/S3 (sem auth)
44
+ // Usamos o 'axios' global aqui, não o 'this.http' (que adicionaria auth)
45
+ await axios.put(presign.url, file, {
46
+ headers: { "Content-Type": contentType },
47
+ });
48
+
49
+ // 3. Retorna os detalhes do objeto (downloadUrl, objectId, etc.)
50
+ return presign;
51
+ }
52
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020", // Moderno, mas compatível
4
+ "module": "NodeNext", // Suporta tanto 'require' (CJS) quanto 'import' (ESM)
5
+ "declaration": true, // [IMPORTANTE] Gera arquivos .d.ts (para autocompletar)
6
+ "outDir": "./dist", // Onde o JavaScript compilado irá
7
+ "rootDir": "./src", // Onde nosso código TypeScript está
8
+ "strict": true, // Força boas práticas
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "moduleResolution": "NodeNext"
12
+ },
13
+ "include": ["src"] // Só compila o que está na pasta 'src'
14
+ }