@allanfsouza/aether-sdk 2.4.2 → 2.4.3

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 CHANGED
@@ -1,18 +1,19 @@
1
1
  import type { AxiosInstance } from "axios";
2
2
  import type { PlataformaClient } from "./index.js";
3
+ export interface User {
4
+ id: string;
5
+ name: string;
6
+ email: string;
7
+ avatarUrl?: string;
8
+ role?: string;
9
+ aetherRole?: string;
10
+ planCode?: string;
11
+ emailVerified?: boolean;
12
+ }
3
13
  export interface LoginResponse {
4
14
  accessToken: string;
5
15
  refreshToken: string;
6
- user: {
7
- id: string;
8
- name: string;
9
- email: string;
10
- avatarUrl?: string;
11
- role?: string;
12
- aetherRole?: string;
13
- planCode?: string;
14
- emailVerified?: boolean;
15
- };
16
+ user: User;
16
17
  }
17
18
  export interface Session {
18
19
  id: string;
@@ -25,55 +26,66 @@ export declare class AuthModule {
25
26
  private client;
26
27
  private http;
27
28
  private refreshToken;
29
+ private currentUser;
28
30
  constructor(client: PlataformaClient, http: AxiosInstance);
29
- /**
30
- * Login com email e senha
31
- */
32
31
  login(email: string, password: string): Promise<LoginResponse>;
33
- /**
34
- * Registrar novo usuário
35
- */
36
32
  register(credentials: {
37
33
  name: string;
38
34
  email: string;
39
35
  password: string;
40
36
  }): Promise<any>;
41
- /**
42
- * Renovar access token usando refresh token
43
- */
44
37
  refresh(): Promise<{
45
38
  accessToken: string;
46
39
  }>;
47
- /**
48
- * Obter URL de autenticação do Google
49
- */
50
40
  getGoogleAuthUrl(): string;
51
- /**
52
- * Logout da sessão atual
53
- */
54
41
  logout(): Promise<void>;
55
- /**
56
- * Logout de todas as sessões
57
- */
58
42
  logoutAll(): Promise<void>;
59
- /**
60
- * Listar sessões ativas
61
- */
62
43
  getSessions(): Promise<Session[]>;
44
+ forgotPassword(email: string): Promise<any>;
45
+ resetPassword(token: string, newPassword: string): Promise<any>;
46
+ getRefreshToken(): string | null;
47
+ setRefreshToken(token: string | null): void;
63
48
  /**
64
- * Esqueci minha senha
49
+ * Alias para login, retornando { user, error } padrão do Showcase
65
50
  */
66
- forgotPassword(email: string): Promise<any>;
51
+ signInWithPassword(credentials: {
52
+ email: string;
53
+ password: string;
54
+ }): Promise<{
55
+ user: User;
56
+ error: null;
57
+ } | {
58
+ user: null;
59
+ error: any;
60
+ }>;
67
61
  /**
68
- * Redefinir senha
62
+ * Alias para register, retornando { user, error }
69
63
  */
70
- resetPassword(token: string, newPassword: string): Promise<any>;
64
+ signUp(credentials: {
65
+ email: string;
66
+ password: string;
67
+ data?: {
68
+ name: string;
69
+ };
70
+ }): Promise<{
71
+ user: any;
72
+ error: null;
73
+ } | {
74
+ user: null;
75
+ error: any;
76
+ }>;
71
77
  /**
72
- * Obter refresh token atual (para armazenamento)
78
+ * Alias para logout
73
79
  */
74
- getRefreshToken(): string | null;
80
+ signOut(): Promise<{
81
+ error: null;
82
+ }>;
75
83
  /**
76
- * Definir refresh token (para restaurar sessão)
84
+ * Recupera a sessão atual (User + Token).
85
+ * Se não tiver logado, retorna null ou tenta validar o token.
77
86
  */
78
- setRefreshToken(token: string | null): void;
87
+ getSession(): Promise<{
88
+ user: User;
89
+ access_token: string;
90
+ } | null>;
79
91
  }
package/dist/auth.js CHANGED
@@ -1,12 +1,14 @@
1
1
  export class AuthModule {
2
2
  constructor(client, http) {
3
3
  this.refreshToken = null;
4
+ // Armazena o user localmente para acesso rápido via getSession
5
+ this.currentUser = null;
4
6
  this.client = client;
5
7
  this.http = http;
6
8
  }
7
- /**
8
- * Login com email e senha
9
- */
9
+ // =================================================================
10
+ // MÉTODOS ORIGINAIS (MANTIDOS)
11
+ // =================================================================
10
12
  async login(email, password) {
11
13
  try {
12
14
  const { data } = await this.http.post("/auth/login", {
@@ -16,30 +18,31 @@ export class AuthModule {
16
18
  if (data.accessToken) {
17
19
  this.client.setToken(data.accessToken);
18
20
  this.refreshToken = data.refreshToken;
21
+ this.currentUser = data.user;
19
22
  }
20
23
  return data;
21
24
  }
22
25
  catch (e) {
23
26
  this.client.setToken(null);
24
27
  this.refreshToken = null;
28
+ this.currentUser = null;
25
29
  throw e;
26
30
  }
27
31
  }
28
- /**
29
- * Registrar novo usuário
30
- */
31
32
  async register(credentials) {
32
33
  try {
33
34
  const { data } = await this.http.post("/auth/register", credentials);
35
+ // Se o register já retornar token, configura:
36
+ if (data.accessToken) {
37
+ this.client.setToken(data.accessToken);
38
+ this.currentUser = data.user;
39
+ }
34
40
  return data;
35
41
  }
36
42
  catch (e) {
37
43
  throw e;
38
44
  }
39
45
  }
40
- /**
41
- * Renovar access token usando refresh token
42
- */
43
46
  async refresh() {
44
47
  if (!this.refreshToken) {
45
48
  throw new Error("Nenhum refresh token disponível");
@@ -59,15 +62,9 @@ export class AuthModule {
59
62
  throw e;
60
63
  }
61
64
  }
62
- /**
63
- * Obter URL de autenticação do Google
64
- */
65
65
  getGoogleAuthUrl() {
66
66
  return `${this.client.apiUrl}/v1/auth/google`;
67
67
  }
68
- /**
69
- * Logout da sessão atual
70
- */
71
68
  async logout() {
72
69
  if (this.refreshToken) {
73
70
  try {
@@ -81,10 +78,8 @@ export class AuthModule {
81
78
  }
82
79
  this.client.setToken(null);
83
80
  this.refreshToken = null;
81
+ this.currentUser = null;
84
82
  }
85
- /**
86
- * Logout de todas as sessões
87
- */
88
83
  async logoutAll() {
89
84
  try {
90
85
  await this.http.post("/auth/logout-all");
@@ -92,25 +87,17 @@ export class AuthModule {
92
87
  finally {
93
88
  this.client.setToken(null);
94
89
  this.refreshToken = null;
90
+ this.currentUser = null;
95
91
  }
96
92
  }
97
- /**
98
- * Listar sessões ativas
99
- */
100
93
  async getSessions() {
101
94
  const { data } = await this.http.get("/auth/sessions");
102
95
  return data.sessions;
103
96
  }
104
- /**
105
- * Esqueci minha senha
106
- */
107
97
  async forgotPassword(email) {
108
98
  const { data } = await this.http.post("/auth/forgot-password", { email });
109
99
  return data;
110
100
  }
111
- /**
112
- * Redefinir senha
113
- */
114
101
  async resetPassword(token, newPassword) {
115
102
  const { data } = await this.http.post("/auth/reset-password", {
116
103
  token,
@@ -118,16 +105,66 @@ export class AuthModule {
118
105
  });
119
106
  return data;
120
107
  }
121
- /**
122
- * Obter refresh token atual (para armazenamento)
123
- */
124
108
  getRefreshToken() {
125
109
  return this.refreshToken;
126
110
  }
127
- /**
128
- * Definir refresh token (para restaurar sessão)
129
- */
130
111
  setRefreshToken(token) {
131
112
  this.refreshToken = token;
132
113
  }
114
+ // =================================================================
115
+ // NOVOS MÉTODOS (COMPATIBILIDADE COM SHOWCASE / SUPABASE STYLE)
116
+ // =================================================================
117
+ /**
118
+ * Alias para login, retornando { user, error } padrão do Showcase
119
+ */
120
+ async signInWithPassword(credentials) {
121
+ try {
122
+ const data = await this.login(credentials.email, credentials.password);
123
+ return { user: data.user, error: null };
124
+ }
125
+ catch (err) {
126
+ return { user: null, error: err.response?.data?.message || err.message };
127
+ }
128
+ }
129
+ /**
130
+ * Alias para register, retornando { user, error }
131
+ */
132
+ async signUp(credentials) {
133
+ try {
134
+ const data = await this.register({
135
+ email: credentials.email,
136
+ password: credentials.password,
137
+ name: credentials.data?.name || credentials.email.split('@')[0],
138
+ });
139
+ return { user: data.user, error: null };
140
+ }
141
+ catch (err) {
142
+ return { user: null, error: err.response?.data?.message || err.message };
143
+ }
144
+ }
145
+ /**
146
+ * Alias para logout
147
+ */
148
+ async signOut() {
149
+ await this.logout();
150
+ return { error: null };
151
+ }
152
+ /**
153
+ * Recupera a sessão atual (User + Token).
154
+ * Se não tiver logado, retorna null ou tenta validar o token.
155
+ */
156
+ async getSession() {
157
+ const token = this.client.getToken();
158
+ if (!token)
159
+ return null;
160
+ // Se já temos o user em memória, retorna.
161
+ // O ideal seria validar o token no backend (/auth/me), mas vamos simplificar.
162
+ if (this.currentUser) {
163
+ return {
164
+ user: this.currentUser,
165
+ access_token: token
166
+ };
167
+ }
168
+ return null;
169
+ }
133
170
  }
package/dist/index.d.ts CHANGED
@@ -8,36 +8,27 @@ import { PushModule } from "./push.js";
8
8
  * Configuração usada para criar o cliente principal da plataforma.
9
9
  */
10
10
  export type ClientConfig = {
11
- apiUrl: string;
12
- projectId: string;
11
+ apiUrl?: string;
12
+ baseUrl?: string;
13
+ projectId?: string;
14
+ apiKey?: string;
13
15
  };
14
- /**
15
- * O cliente principal da Plataforma API (Aether).
16
- * Ponto de entrada para todos os módulos (Auth, DB, Storage, Functions, Push).
17
- */
18
16
  export declare class PlataformaClient {
19
17
  auth: AuthModule;
20
18
  db: DatabaseModule;
21
19
  storage: StorageModule;
22
20
  functions: FunctionsModule;
23
21
  push: PushModule;
22
+ database: DatabaseModule;
24
23
  apiUrl: string;
25
24
  projectId: string;
26
25
  http: AxiosInstance;
27
26
  private _token;
28
27
  constructor(config: ClientConfig);
29
- /**
30
- * Armazena o token de autenticação em memória.
31
- * Chamado automaticamente pelo AuthModule após login/registro.
32
- */
33
28
  setToken(token: string | null): void;
34
- /**
35
- * Recupera o token de autenticação atual.
36
- * Usado pelo http-client para injetar o header Authorization.
37
- */
38
29
  getToken(): string | null;
39
30
  }
40
31
  export { AetherError } from "./errors.js";
41
- export type { LoginResponse, Session } from "./auth.js";
32
+ export type { LoginResponse, Session, User } from "./auth.js";
42
33
  export type { ListOptions } from "./database.js";
43
34
  export type { PushPlatform, PushEnvironment, PushDevice, RegisterDeviceParams, SendPushResponse, PushStatus, PushLogEntry, ListPushLogsOptions, PushStats, } from "./push.js";
package/dist/index.js CHANGED
@@ -1,47 +1,36 @@
1
1
  import { createHttpClient } from "./http-client.js";
2
- import { AuthModule } from "./auth.js";
2
+ import { AuthModule } from "./auth.js"; // Importando User
3
3
  import { DatabaseModule } from "./database.js";
4
4
  import { StorageModule } from "./storage.js";
5
5
  import { FunctionsModule } from "./functions.js";
6
6
  import { PushModule } from "./push.js";
7
- /**
8
- * O cliente principal da Plataforma API (Aether).
9
- * Ponto de entrada para todos os módulos (Auth, DB, Storage, Functions, Push).
10
- */
11
7
  export class PlataformaClient {
12
8
  constructor(config) {
13
9
  this._token = null;
14
- if (!config.apiUrl || !config.projectId) {
15
- throw new Error("apiUrl e projectId são obrigatórios.");
10
+ // Resolve URL (prioridade para baseUrl se existir, senão apiUrl)
11
+ const url = config.baseUrl || config.apiUrl;
12
+ const project = config.apiKey || config.projectId;
13
+ if (!url || !project) {
14
+ throw new Error("baseUrl (API URL) e apiKey (Project ID) são obrigatórios.");
16
15
  }
17
- // Normaliza apiUrl removendo barras finais, se houver
18
- this.apiUrl = config.apiUrl.replace(/\/+$/, "");
19
- this.projectId = config.projectId;
20
- // Inicializa o cliente HTTP (passando a própria instância)
16
+ this.apiUrl = url.replace(/\/+$/, "");
17
+ this.projectId = project;
21
18
  this.http = createHttpClient(this);
22
- // Inicializa os módulos de alto nível
19
+ // Inicializa módulos
23
20
  this.auth = new AuthModule(this, this.http);
24
21
  this.db = new DatabaseModule(this, this.http);
25
22
  this.storage = new StorageModule(this, this.http);
26
23
  this.functions = new FunctionsModule(this, this.http);
27
24
  this.push = new PushModule(this, this.http);
25
+ // Cria o alias que o Showcase App espera
26
+ this.database = this.db;
28
27
  }
29
- // --- Gerenciamento de Token ---
30
- /**
31
- * Armazena o token de autenticação em memória.
32
- * Chamado automaticamente pelo AuthModule após login/registro.
33
- */
34
28
  setToken(token) {
35
29
  this._token = token;
36
30
  }
37
- /**
38
- * Recupera o token de autenticação atual.
39
- * Usado pelo http-client para injetar o header Authorization.
40
- */
41
31
  getToken() {
42
32
  return this._token;
43
33
  }
44
34
  }
45
- // Re-exports convenientes para quem consome o SDK
46
- // ===== ERRORS =====
35
+ // ===== EXPORTS =====
47
36
  export { AetherError } from "./errors.js";
package/dist/storage.d.ts CHANGED
@@ -4,25 +4,36 @@ export declare class StorageModule {
4
4
  private client;
5
5
  private http;
6
6
  constructor(client: PlataformaClient, http: AxiosInstance);
7
+ /**
8
+ * Seleciona um Bucket para operar.
9
+ * Ex: storage.from('avatars').upload(...)
10
+ */
11
+ from(bucketId: string): {
12
+ upload: (path: string, file: File | Blob | Buffer) => Promise<{
13
+ data: {
14
+ id: any;
15
+ key: any;
16
+ path: any;
17
+ downloadUrl: any;
18
+ url: any;
19
+ };
20
+ error: null;
21
+ }>;
22
+ list: () => Promise<any>;
23
+ };
7
24
  /**
8
25
  * Faz o upload de um arquivo.
9
- * @param file Arquivo (Browser: File, Node: Buffer)
10
- * @param fileName Nome do arquivo (ex: 'foto.jpg')
11
- * @param contentType MIME Type (ex: 'image/jpeg')
12
- * @param folder (Opcional) Pasta de destino (ex: 'usuarios/123/')
13
26
  */
14
27
  upload(file: File | Buffer | Blob, fileName: string, contentType: string, folder?: string): Promise<{
15
- id: any;
16
- key: any;
17
- downloadUrl: any;
18
- url: any;
28
+ data: {
29
+ id: any;
30
+ key: any;
31
+ path: any;
32
+ downloadUrl: any;
33
+ url: any;
34
+ };
35
+ error: null;
19
36
  }>;
20
- /**
21
- * Lista arquivos de uma pasta.
22
- */
23
37
  list(folder?: string): Promise<any>;
24
- /**
25
- * Deleta um arquivo pelo ID.
26
- */
27
38
  delete(fileId: string): Promise<boolean>;
28
39
  }
package/dist/storage.js CHANGED
@@ -4,15 +4,40 @@ export class StorageModule {
4
4
  this.client = client;
5
5
  this.http = http;
6
6
  }
7
+ // =================================================================
8
+ // COMPATIBILIDADE: MÈTODO .from() (Estilo Supabase/Drizzle)
9
+ // =================================================================
10
+ /**
11
+ * Seleciona um Bucket para operar.
12
+ * Ex: storage.from('avatars').upload(...)
13
+ */
14
+ from(bucketId) {
15
+ return {
16
+ upload: async (path, file) => {
17
+ // Tenta inferir o contentType se for File/Blob
18
+ let contentType = "application/octet-stream";
19
+ if (typeof File !== "undefined" && file instanceof File) {
20
+ contentType = file.type;
21
+ }
22
+ else if (typeof Blob !== "undefined" && file instanceof Blob) {
23
+ contentType = file.type;
24
+ }
25
+ // Chama o método upload original passando o bucket como folder/prefix
26
+ // O path vira o nome do arquivo final
27
+ return this.upload(file, path, contentType, bucketId);
28
+ },
29
+ list: async () => {
30
+ return this.list(bucketId);
31
+ }
32
+ };
33
+ }
34
+ // =================================================================
35
+ // MÉTODOS ORIGINAIS
36
+ // =================================================================
7
37
  /**
8
38
  * Faz o upload de um arquivo.
9
- * @param file Arquivo (Browser: File, Node: Buffer)
10
- * @param fileName Nome do arquivo (ex: 'foto.jpg')
11
- * @param contentType MIME Type (ex: 'image/jpeg')
12
- * @param folder (Opcional) Pasta de destino (ex: 'usuarios/123/')
13
39
  */
14
- async upload(file, fileName, contentType, folder // [NOVO]
15
- ) {
40
+ async upload(file, fileName, contentType, folder) {
16
41
  // Calcula tamanho de forma segura para Browser e Node
17
42
  let size = 0;
18
43
  if (typeof File !== "undefined" && file instanceof File) {
@@ -22,7 +47,6 @@ export class StorageModule {
22
47
  size = file.size;
23
48
  }
24
49
  else if (file instanceof Buffer) {
25
- // Node.js
26
50
  size = file.length;
27
51
  }
28
52
  // 1. Pedir URL assinada
@@ -30,34 +54,32 @@ export class StorageModule {
30
54
  fileName,
31
55
  contentType,
32
56
  size,
33
- prefix: folder || "", // [NOVO] Envia o prefixo para o backend
57
+ prefix: folder || "",
34
58
  });
35
59
  const presign = presignData.data;
36
60
  if (!presign?.url)
37
61
  throw new Error("Falha ao obter URL de upload.");
38
- // 2. Upload direto para S3
62
+ // 2. Upload direto para S3 (PUT na URL assinada)
39
63
  await axios.put(presign.url, file, {
40
64
  headers: { "Content-Type": contentType },
41
65
  });
42
66
  return {
43
- id: presign.objectId,
44
- key: presign.key,
45
- downloadUrl: presign.downloadUrl,
46
- url: presign.downloadUrl, // Alias amigável
67
+ data: {
68
+ id: presign.objectId,
69
+ key: presign.key,
70
+ path: presign.key, // Alias para facilitar o frontend
71
+ downloadUrl: presign.downloadUrl,
72
+ url: presign.downloadUrl,
73
+ },
74
+ error: null
47
75
  };
48
76
  }
49
- /**
50
- * Lista arquivos de uma pasta.
51
- */
52
77
  async list(folder = "") {
53
78
  const { data } = await this.http.get("/storage/list", {
54
79
  params: { projectId: this.client.projectId, prefix: folder },
55
80
  });
56
- return data.data; // Retorna { files: [], folders: [] }
81
+ return data.data;
57
82
  }
58
- /**
59
- * Deleta um arquivo pelo ID.
60
- */
61
83
  async delete(fileId) {
62
84
  await this.http.delete("/storage/delete", { data: { objectId: fileId } });
63
85
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allanfsouza/aether-sdk",
3
- "version": "2.4.2",
3
+ "version": "2.4.3",
4
4
  "description": "SDK do Cliente para a Plataforma Aether",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -32,4 +32,4 @@
32
32
  "@types/ws": "^8.5.10",
33
33
  "typescript": "^5.3.0"
34
34
  }
35
- }
35
+ }
package/src/auth.ts CHANGED
@@ -2,19 +2,22 @@
2
2
  import type { AxiosInstance } from "axios";
3
3
  import type { PlataformaClient } from "./index.js";
4
4
 
5
+ // Exportando a interface User para o App usar
6
+ export interface User {
7
+ id: string;
8
+ name: string;
9
+ email: string;
10
+ avatarUrl?: string;
11
+ role?: string;
12
+ aetherRole?: string;
13
+ planCode?: string;
14
+ emailVerified?: boolean;
15
+ }
16
+
5
17
  export interface LoginResponse {
6
18
  accessToken: string;
7
19
  refreshToken: string;
8
- user: {
9
- id: string;
10
- name: string;
11
- email: string;
12
- avatarUrl?: string;
13
- role?: string;
14
- aetherRole?: string;
15
- planCode?: string;
16
- emailVerified?: boolean;
17
- };
20
+ user: User;
18
21
  }
19
22
 
20
23
  export interface Session {
@@ -29,15 +32,18 @@ export class AuthModule {
29
32
  private client: PlataformaClient;
30
33
  private http: AxiosInstance;
31
34
  private refreshToken: string | null = null;
35
+ // Armazena o user localmente para acesso rápido via getSession
36
+ private currentUser: User | null = null;
32
37
 
33
38
  constructor(client: PlataformaClient, http: AxiosInstance) {
34
39
  this.client = client;
35
40
  this.http = http;
36
41
  }
37
42
 
38
- /**
39
- * Login com email e senha
40
- */
43
+ // =================================================================
44
+ // MÉTODOS ORIGINAIS (MANTIDOS)
45
+ // =================================================================
46
+
41
47
  async login(email: string, password: string): Promise<LoginResponse> {
42
48
  try {
43
49
  const { data } = await this.http.post<LoginResponse>("/auth/login", {
@@ -48,19 +54,18 @@ export class AuthModule {
48
54
  if (data.accessToken) {
49
55
  this.client.setToken(data.accessToken);
50
56
  this.refreshToken = data.refreshToken;
57
+ this.currentUser = data.user;
51
58
  }
52
59
 
53
60
  return data;
54
61
  } catch (e) {
55
62
  this.client.setToken(null);
56
63
  this.refreshToken = null;
64
+ this.currentUser = null;
57
65
  throw e;
58
66
  }
59
67
  }
60
68
 
61
- /**
62
- * Registrar novo usuário
63
- */
64
69
  async register(credentials: {
65
70
  name: string;
66
71
  email: string;
@@ -68,15 +73,17 @@ export class AuthModule {
68
73
  }) {
69
74
  try {
70
75
  const { data } = await this.http.post("/auth/register", credentials);
76
+ // Se o register já retornar token, configura:
77
+ if (data.accessToken) {
78
+ this.client.setToken(data.accessToken);
79
+ this.currentUser = data.user;
80
+ }
71
81
  return data;
72
82
  } catch (e) {
73
83
  throw e;
74
84
  }
75
85
  }
76
86
 
77
- /**
78
- * Renovar access token usando refresh token
79
- */
80
87
  async refresh(): Promise<{ accessToken: string }> {
81
88
  if (!this.refreshToken) {
82
89
  throw new Error("Nenhum refresh token disponível");
@@ -99,16 +106,10 @@ export class AuthModule {
99
106
  }
100
107
  }
101
108
 
102
- /**
103
- * Obter URL de autenticação do Google
104
- */
105
109
  getGoogleAuthUrl(): string {
106
110
  return `${this.client.apiUrl}/v1/auth/google`;
107
111
  }
108
112
 
109
- /**
110
- * Logout da sessão atual
111
- */
112
113
  async logout(): Promise<void> {
113
114
  if (this.refreshToken) {
114
115
  try {
@@ -119,26 +120,21 @@ export class AuthModule {
119
120
  // Ignora erro de logout
120
121
  }
121
122
  }
122
-
123
123
  this.client.setToken(null);
124
124
  this.refreshToken = null;
125
+ this.currentUser = null;
125
126
  }
126
127
 
127
- /**
128
- * Logout de todas as sessões
129
- */
130
128
  async logoutAll(): Promise<void> {
131
129
  try {
132
130
  await this.http.post("/auth/logout-all");
133
131
  } finally {
134
132
  this.client.setToken(null);
135
133
  this.refreshToken = null;
134
+ this.currentUser = null;
136
135
  }
137
136
  }
138
137
 
139
- /**
140
- * Listar sessões ativas
141
- */
142
138
  async getSessions(): Promise<Session[]> {
143
139
  const { data } = await this.http.get<{ sessions: Session[] }>(
144
140
  "/auth/sessions"
@@ -146,17 +142,11 @@ export class AuthModule {
146
142
  return data.sessions;
147
143
  }
148
144
 
149
- /**
150
- * Esqueci minha senha
151
- */
152
145
  async forgotPassword(email: string) {
153
146
  const { data } = await this.http.post("/auth/forgot-password", { email });
154
147
  return data;
155
148
  }
156
149
 
157
- /**
158
- * Redefinir senha
159
- */
160
150
  async resetPassword(token: string, newPassword: string) {
161
151
  const { data } = await this.http.post("/auth/reset-password", {
162
152
  token,
@@ -165,17 +155,71 @@ export class AuthModule {
165
155
  return data;
166
156
  }
167
157
 
168
- /**
169
- * Obter refresh token atual (para armazenamento)
170
- */
171
158
  getRefreshToken(): string | null {
172
159
  return this.refreshToken;
173
160
  }
174
161
 
175
- /**
176
- * Definir refresh token (para restaurar sessão)
177
- */
178
162
  setRefreshToken(token: string | null) {
179
163
  this.refreshToken = token;
180
164
  }
165
+
166
+ // =================================================================
167
+ // NOVOS MÉTODOS (COMPATIBILIDADE COM SHOWCASE / SUPABASE STYLE)
168
+ // =================================================================
169
+
170
+ /**
171
+ * Alias para login, retornando { user, error } padrão do Showcase
172
+ */
173
+ async signInWithPassword(credentials: { email: string; password: string }) {
174
+ try {
175
+ const data = await this.login(credentials.email, credentials.password);
176
+ return { user: data.user, error: null };
177
+ } catch (err: any) {
178
+ return { user: null, error: err.response?.data?.message || err.message };
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Alias para register, retornando { user, error }
184
+ */
185
+ async signUp(credentials: { email: string; password: string; data?: { name: string } }) {
186
+ try {
187
+ const data = await this.register({
188
+ email: credentials.email,
189
+ password: credentials.password,
190
+ name: credentials.data?.name || credentials.email.split('@')[0],
191
+ });
192
+ return { user: data.user, error: null };
193
+ } catch (err: any) {
194
+ return { user: null, error: err.response?.data?.message || err.message };
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Alias para logout
200
+ */
201
+ async signOut() {
202
+ await this.logout();
203
+ return { error: null };
204
+ }
205
+
206
+ /**
207
+ * Recupera a sessão atual (User + Token).
208
+ * Se não tiver logado, retorna null ou tenta validar o token.
209
+ */
210
+ async getSession() {
211
+ const token = this.client.getToken();
212
+ if (!token) return null;
213
+
214
+ // Se já temos o user em memória, retorna.
215
+ // O ideal seria validar o token no backend (/auth/me), mas vamos simplificar.
216
+ if (this.currentUser) {
217
+ return {
218
+ user: this.currentUser,
219
+ access_token: token
220
+ };
221
+ }
222
+
223
+ return null;
224
+ }
181
225
  }
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/index.ts
2
2
  import type { AxiosInstance } from "axios";
3
3
  import { createHttpClient } from "./http-client.js";
4
- import { AuthModule } from "./auth.js";
4
+ import { AuthModule, User } from "./auth.js"; // Importando User
5
5
  import { DatabaseModule } from "./database.js";
6
6
  import { StorageModule } from "./storage.js";
7
7
  import { FunctionsModule } from "./functions.js";
@@ -11,89 +11,70 @@ import { PushModule } from "./push.js";
11
11
  * Configuração usada para criar o cliente principal da plataforma.
12
12
  */
13
13
  export type ClientConfig = {
14
- apiUrl: string;
15
- projectId: string;
14
+ // Suporte duplo para compatibilidade:
15
+ // apiUrl (nome original) OU baseUrl (nome novo do App)
16
+ apiUrl?: string;
17
+ baseUrl?: string;
18
+
19
+ // projectId (nome original) OU apiKey (nome novo do App)
20
+ projectId?: string;
21
+ apiKey?: string;
16
22
  };
17
23
 
18
- /**
19
- * O cliente principal da Plataforma API (Aether).
20
- * Ponto de entrada para todos os módulos (Auth, DB, Storage, Functions, Push).
21
- */
22
24
  export class PlataformaClient {
23
- // Módulos públicos disponíveis para o usuário do SDK
24
25
  public auth: AuthModule;
25
26
  public db: DatabaseModule;
26
27
  public storage: StorageModule;
27
28
  public functions: FunctionsModule;
28
29
  public push: PushModule;
29
30
 
30
- // Configurações imutáveis da instância
31
+ // Alias para 'db' que o showcase tenta usar como 'database'
32
+ public database: DatabaseModule;
33
+
31
34
  public apiUrl: string;
32
35
  public projectId: string;
33
36
 
34
- // Infra interna
35
37
  public http: AxiosInstance;
36
38
  private _token: string | null = null;
37
39
 
38
40
  constructor(config: ClientConfig) {
39
- if (!config.apiUrl || !config.projectId) {
40
- throw new Error("apiUrl e projectId são obrigatórios.");
41
+ // Resolve URL (prioridade para baseUrl se existir, senão apiUrl)
42
+ const url = config.baseUrl || config.apiUrl;
43
+ const project = config.apiKey || config.projectId;
44
+
45
+ if (!url || !project) {
46
+ throw new Error("baseUrl (API URL) e apiKey (Project ID) são obrigatórios.");
41
47
  }
42
48
 
43
- // Normaliza apiUrl removendo barras finais, se houver
44
- this.apiUrl = config.apiUrl.replace(/\/+$/, "");
45
- this.projectId = config.projectId;
49
+ this.apiUrl = url.replace(/\/+$/, "");
50
+ this.projectId = project;
46
51
 
47
- // Inicializa o cliente HTTP (passando a própria instância)
48
52
  this.http = createHttpClient(this);
49
53
 
50
- // Inicializa os módulos de alto nível
54
+ // Inicializa módulos
51
55
  this.auth = new AuthModule(this, this.http);
52
56
  this.db = new DatabaseModule(this, this.http);
53
57
  this.storage = new StorageModule(this, this.http);
54
58
  this.functions = new FunctionsModule(this, this.http);
55
59
  this.push = new PushModule(this, this.http);
56
- }
57
60
 
58
- // --- Gerenciamento de Token ---
61
+ // Cria o alias que o Showcase App espera
62
+ this.database = this.db;
63
+ }
59
64
 
60
- /**
61
- * Armazena o token de autenticação em memória.
62
- * Chamado automaticamente pelo AuthModule após login/registro.
63
- */
64
65
  setToken(token: string | null) {
65
66
  this._token = token;
66
67
  }
67
68
 
68
- /**
69
- * Recupera o token de autenticação atual.
70
- * Usado pelo http-client para injetar o header Authorization.
71
- */
72
69
  getToken(): string | null {
73
70
  return this._token;
74
71
  }
75
72
  }
76
73
 
77
- // Re-exports convenientes para quem consome o SDK
78
-
79
- // ===== ERRORS =====
74
+ // ===== EXPORTS =====
80
75
  export { AetherError } from "./errors.js";
81
-
82
- // ===== AUTH =====
83
- export type { LoginResponse, Session } from "./auth.js";
84
-
85
- // ===== DATABASE =====
76
+ export type { LoginResponse, Session, User } from "./auth.js"; // User exportado!
86
77
  export type { ListOptions } from "./database.js";
87
-
88
- // ===== STORAGE =====
89
- // Nota: storage.ts não declara tipos específicos além dos retornos inline
90
- // Se necessário, tipos podem ser adicionados em storage.ts e re-exportados aqui
91
-
92
- // ===== FUNCTIONS =====
93
- // Nota: functions.ts usa genéricos inline
94
- // Se necessário, tipos podem ser adicionados em functions.ts e re-exportados aqui
95
-
96
- // ===== PUSH =====
97
78
  export type {
98
79
  PushPlatform,
99
80
  PushEnvironment,
@@ -104,4 +85,4 @@ export type {
104
85
  PushLogEntry,
105
86
  ListPushLogsOptions,
106
87
  PushStats,
107
- } from "./push.js";
88
+ } from "./push.js";
package/src/storage.ts CHANGED
@@ -12,18 +12,48 @@ export class StorageModule {
12
12
  this.http = http;
13
13
  }
14
14
 
15
+ // =================================================================
16
+ // COMPATIBILIDADE: MÈTODO .from() (Estilo Supabase/Drizzle)
17
+ // =================================================================
18
+
19
+ /**
20
+ * Seleciona um Bucket para operar.
21
+ * Ex: storage.from('avatars').upload(...)
22
+ */
23
+ from(bucketId: string) {
24
+ return {
25
+ upload: async (path: string, file: File | Blob | Buffer) => {
26
+ // Tenta inferir o contentType se for File/Blob
27
+ let contentType = "application/octet-stream";
28
+ if (typeof File !== "undefined" && file instanceof File) {
29
+ contentType = file.type;
30
+ } else if (typeof Blob !== "undefined" && file instanceof Blob) {
31
+ contentType = file.type;
32
+ }
33
+
34
+ // Chama o método upload original passando o bucket como folder/prefix
35
+ // O path vira o nome do arquivo final
36
+ return this.upload(file, path, contentType, bucketId);
37
+ },
38
+
39
+ list: async () => {
40
+ return this.list(bucketId);
41
+ }
42
+ };
43
+ }
44
+
45
+ // =================================================================
46
+ // MÉTODOS ORIGINAIS
47
+ // =================================================================
48
+
15
49
  /**
16
50
  * Faz o upload de um arquivo.
17
- * @param file Arquivo (Browser: File, Node: Buffer)
18
- * @param fileName Nome do arquivo (ex: 'foto.jpg')
19
- * @param contentType MIME Type (ex: 'image/jpeg')
20
- * @param folder (Opcional) Pasta de destino (ex: 'usuarios/123/')
21
51
  */
22
52
  async upload(
23
53
  file: File | Buffer | Blob,
24
54
  fileName: string,
25
55
  contentType: string,
26
- folder?: string // [NOVO]
56
+ folder?: string
27
57
  ) {
28
58
  // Calcula tamanho de forma segura para Browser e Node
29
59
  let size = 0;
@@ -32,7 +62,6 @@ export class StorageModule {
32
62
  } else if (typeof Blob !== "undefined" && file instanceof Blob) {
33
63
  size = file.size;
34
64
  } else if (file instanceof Buffer) {
35
- // Node.js
36
65
  size = file.length;
37
66
  }
38
67
 
@@ -41,40 +70,38 @@ export class StorageModule {
41
70
  fileName,
42
71
  contentType,
43
72
  size,
44
- prefix: folder || "", // [NOVO] Envia o prefixo para o backend
73
+ prefix: folder || "",
45
74
  });
46
75
 
47
76
  const presign = presignData.data;
48
77
  if (!presign?.url) throw new Error("Falha ao obter URL de upload.");
49
78
 
50
- // 2. Upload direto para S3
79
+ // 2. Upload direto para S3 (PUT na URL assinada)
51
80
  await axios.put(presign.url, file, {
52
81
  headers: { "Content-Type": contentType },
53
82
  });
54
83
 
55
84
  return {
56
- id: presign.objectId,
57
- key: presign.key,
58
- downloadUrl: presign.downloadUrl,
59
- url: presign.downloadUrl, // Alias amigável
85
+ data: {
86
+ id: presign.objectId,
87
+ key: presign.key,
88
+ path: presign.key, // Alias para facilitar o frontend
89
+ downloadUrl: presign.downloadUrl,
90
+ url: presign.downloadUrl,
91
+ },
92
+ error: null
60
93
  };
61
94
  }
62
95
 
63
- /**
64
- * Lista arquivos de uma pasta.
65
- */
66
96
  async list(folder = "") {
67
97
  const { data } = await this.http.get("/storage/list", {
68
98
  params: { projectId: this.client.projectId, prefix: folder },
69
99
  });
70
- return data.data; // Retorna { files: [], folders: [] }
100
+ return data.data;
71
101
  }
72
102
 
73
- /**
74
- * Deleta um arquivo pelo ID.
75
- */
76
103
  async delete(fileId: string) {
77
104
  await this.http.delete("/storage/delete", { data: { objectId: fileId } });
78
105
  return true;
79
106
  }
80
- }
107
+ }