@allanfsouza/aether-sdk 2.4.3 → 2.4.5

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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { AxiosInstance } from "axios";
2
- import { AuthModule } from "./auth.js";
2
+ import { AuthModule, User } from "./auth.js";
3
3
  import { DatabaseModule } from "./database.js";
4
4
  import { StorageModule } from "./storage.js";
5
5
  import { FunctionsModule } from "./functions.js";
@@ -12,6 +12,11 @@ export type ClientConfig = {
12
12
  baseUrl?: string;
13
13
  projectId?: string;
14
14
  apiKey?: string;
15
+ /**
16
+ * Habilita persistência automática de sessão no localStorage.
17
+ * Padrão: true em browsers, false em Node.js/SSR.
18
+ */
19
+ persistSession?: boolean;
15
20
  };
16
21
  export declare class PlataformaClient {
17
22
  auth: AuthModule;
@@ -24,9 +29,48 @@ export declare class PlataformaClient {
24
29
  projectId: string;
25
30
  http: AxiosInstance;
26
31
  private _token;
32
+ private _persistSession;
27
33
  constructor(config: ClientConfig);
34
+ /**
35
+ * Define o token de acesso (JWT).
36
+ * Se persistSession estiver ativo, salva automaticamente no localStorage.
37
+ */
28
38
  setToken(token: string | null): void;
39
+ /**
40
+ * Retorna o token de acesso atual.
41
+ */
29
42
  getToken(): string | null;
43
+ /**
44
+ * Salva o refresh token.
45
+ * Usado internamente pelo AuthModule após login.
46
+ */
47
+ setRefreshToken(token: string | null): void;
48
+ /**
49
+ * Retorna o refresh token salvo no localStorage.
50
+ */
51
+ getRefreshToken(): string | null;
52
+ /**
53
+ * Salva dados do usuário logado no localStorage.
54
+ */
55
+ setUser(user: User | null): void;
56
+ /**
57
+ * Retorna dados do usuário salvo no localStorage.
58
+ */
59
+ getUser(): User | null;
60
+ /**
61
+ * Limpa toda a sessão (token, refresh, user).
62
+ * Chamado automaticamente no logout.
63
+ */
64
+ clearSession(): void;
65
+ /**
66
+ * Verifica se existe uma sessão salva (token presente).
67
+ */
68
+ hasSession(): boolean;
69
+ /**
70
+ * Restaura sessão do localStorage ao inicializar o client.
71
+ * Executado automaticamente no constructor.
72
+ */
73
+ private _restoreSession;
30
74
  }
31
75
  export { AetherError } from "./errors.js";
32
76
  export type { LoginResponse, Session, User } from "./auth.js";
package/dist/index.js CHANGED
@@ -1,9 +1,26 @@
1
1
  import { createHttpClient } from "./http-client.js";
2
- import { AuthModule } from "./auth.js"; // Importando User
2
+ import { AuthModule } from "./auth.js";
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
+ // CONSTANTES DE STORAGE
9
+ // Chaves padronizadas para localStorage - evita conflito com outros SDKs
10
+ // =============================================================================
11
+ const STORAGE_KEYS = {
12
+ TOKEN: "aether_token",
13
+ REFRESH_TOKEN: "aether_refresh_token",
14
+ USER: "aether_user",
15
+ };
16
+ /**
17
+ * Verifica se estamos em ambiente browser com localStorage disponível.
18
+ * Necessário para evitar erros em SSR (Next.js, Nuxt, etc).
19
+ */
20
+ function isBrowser() {
21
+ return (typeof window !== "undefined" &&
22
+ typeof window.localStorage !== "undefined");
23
+ }
7
24
  export class PlataformaClient {
8
25
  constructor(config) {
9
26
  this._token = null;
@@ -15,6 +32,11 @@ export class PlataformaClient {
15
32
  }
16
33
  this.apiUrl = url.replace(/\/+$/, "");
17
34
  this.projectId = project;
35
+ // Persistência habilitada por padrão apenas em browsers
36
+ this._persistSession = config.persistSession ?? isBrowser();
37
+ // Restaura sessão salva ANTES de criar o httpClient
38
+ // Isso garante que requisições iniciais já tenham o token
39
+ this._restoreSession();
18
40
  this.http = createHttpClient(this);
19
41
  // Inicializa módulos
20
42
  this.auth = new AuthModule(this, this.http);
@@ -25,12 +47,125 @@ export class PlataformaClient {
25
47
  // Cria o alias que o Showcase App espera
26
48
  this.database = this.db;
27
49
  }
50
+ // ===========================================================================
51
+ // TOKEN DE ACESSO
52
+ // ===========================================================================
53
+ /**
54
+ * Define o token de acesso (JWT).
55
+ * Se persistSession estiver ativo, salva automaticamente no localStorage.
56
+ */
28
57
  setToken(token) {
29
58
  this._token = token;
59
+ if (this._persistSession && isBrowser()) {
60
+ if (token) {
61
+ localStorage.setItem(STORAGE_KEYS.TOKEN, token);
62
+ }
63
+ else {
64
+ localStorage.removeItem(STORAGE_KEYS.TOKEN);
65
+ }
66
+ }
30
67
  }
68
+ /**
69
+ * Retorna o token de acesso atual.
70
+ */
31
71
  getToken() {
32
72
  return this._token;
33
73
  }
74
+ // ===========================================================================
75
+ // REFRESH TOKEN
76
+ // ===========================================================================
77
+ /**
78
+ * Salva o refresh token.
79
+ * Usado internamente pelo AuthModule após login.
80
+ */
81
+ setRefreshToken(token) {
82
+ if (this._persistSession && isBrowser()) {
83
+ if (token) {
84
+ localStorage.setItem(STORAGE_KEYS.REFRESH_TOKEN, token);
85
+ }
86
+ else {
87
+ localStorage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);
88
+ }
89
+ }
90
+ }
91
+ /**
92
+ * Retorna o refresh token salvo no localStorage.
93
+ */
94
+ getRefreshToken() {
95
+ if (this._persistSession && isBrowser()) {
96
+ return localStorage.getItem(STORAGE_KEYS.REFRESH_TOKEN);
97
+ }
98
+ return null;
99
+ }
100
+ // ===========================================================================
101
+ // DADOS DO USUÁRIO
102
+ // ===========================================================================
103
+ /**
104
+ * Salva dados do usuário logado no localStorage.
105
+ */
106
+ setUser(user) {
107
+ if (this._persistSession && isBrowser()) {
108
+ if (user) {
109
+ localStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));
110
+ }
111
+ else {
112
+ localStorage.removeItem(STORAGE_KEYS.USER);
113
+ }
114
+ }
115
+ }
116
+ /**
117
+ * Retorna dados do usuário salvo no localStorage.
118
+ */
119
+ getUser() {
120
+ if (this._persistSession && isBrowser()) {
121
+ const saved = localStorage.getItem(STORAGE_KEYS.USER);
122
+ if (saved) {
123
+ try {
124
+ return JSON.parse(saved);
125
+ }
126
+ catch {
127
+ // JSON corrompido - limpa
128
+ localStorage.removeItem(STORAGE_KEYS.USER);
129
+ return null;
130
+ }
131
+ }
132
+ }
133
+ return null;
134
+ }
135
+ // ===========================================================================
136
+ // GERENCIAMENTO DE SESSÃO
137
+ // ===========================================================================
138
+ /**
139
+ * Limpa toda a sessão (token, refresh, user).
140
+ * Chamado automaticamente no logout.
141
+ */
142
+ clearSession() {
143
+ this._token = null;
144
+ if (isBrowser()) {
145
+ localStorage.removeItem(STORAGE_KEYS.TOKEN);
146
+ localStorage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);
147
+ localStorage.removeItem(STORAGE_KEYS.USER);
148
+ }
149
+ }
150
+ /**
151
+ * Verifica se existe uma sessão salva (token presente).
152
+ */
153
+ hasSession() {
154
+ return this._token !== null;
155
+ }
156
+ /**
157
+ * Restaura sessão do localStorage ao inicializar o client.
158
+ * Executado automaticamente no constructor.
159
+ */
160
+ _restoreSession() {
161
+ if (!this._persistSession || !isBrowser()) {
162
+ return;
163
+ }
164
+ const savedToken = localStorage.getItem(STORAGE_KEYS.TOKEN);
165
+ if (savedToken) {
166
+ this._token = savedToken;
167
+ }
168
+ }
34
169
  }
35
170
  // ===== EXPORTS =====
36
171
  export { AetherError } from "./errors.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allanfsouza/aether-sdk",
3
- "version": "2.4.3",
3
+ "version": "2.4.5",
4
4
  "description": "SDK do Cliente para a Plataforma Aether",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/auth.ts CHANGED
@@ -31,18 +31,22 @@ export interface Session {
31
31
  export class AuthModule {
32
32
  private client: PlataformaClient;
33
33
  private http: AxiosInstance;
34
- private refreshToken: string | null = null;
35
- // Armazena o user localmente para acesso rápido via getSession
34
+
35
+ // Armazena o user em memória para acesso rápido
36
+ // Persistência fica no PlataformaClient (localStorage)
36
37
  private currentUser: User | null = null;
37
38
 
38
39
  constructor(client: PlataformaClient, http: AxiosInstance) {
39
40
  this.client = client;
40
41
  this.http = http;
42
+
43
+ // Restaura user do localStorage se existir
44
+ this.currentUser = this.client.getUser();
41
45
  }
42
46
 
43
- // =================================================================
44
- // MÉTODOS ORIGINAIS (MANTIDOS)
45
- // =================================================================
47
+ // ==========================================================================
48
+ // MÉTODOS PRINCIPAIS
49
+ // ==========================================================================
46
50
 
47
51
  async login(email: string, password: string): Promise<LoginResponse> {
48
52
  try {
@@ -52,15 +56,17 @@ export class AuthModule {
52
56
  });
53
57
 
54
58
  if (data.accessToken) {
59
+ // Persiste automaticamente via PlataformaClient
55
60
  this.client.setToken(data.accessToken);
56
- this.refreshToken = data.refreshToken;
61
+ this.client.setRefreshToken(data.refreshToken);
62
+ this.client.setUser(data.user);
57
63
  this.currentUser = data.user;
58
64
  }
59
65
 
60
66
  return data;
61
67
  } catch (e) {
62
- this.client.setToken(null);
63
- this.refreshToken = null;
68
+ // Limpa tudo em caso de erro
69
+ this.client.clearSession();
64
70
  this.currentUser = null;
65
71
  throw e;
66
72
  }
@@ -73,11 +79,15 @@ export class AuthModule {
73
79
  }) {
74
80
  try {
75
81
  const { data } = await this.http.post("/auth/register", credentials);
76
- // Se o register já retornar token, configura:
82
+
83
+ // Se o register retornar token (auto-login), configura sessão
77
84
  if (data.accessToken) {
78
85
  this.client.setToken(data.accessToken);
86
+ this.client.setRefreshToken(data.refreshToken);
87
+ this.client.setUser(data.user);
79
88
  this.currentUser = data.user;
80
89
  }
90
+
81
91
  return data;
82
92
  } catch (e) {
83
93
  throw e;
@@ -85,23 +95,32 @@ export class AuthModule {
85
95
  }
86
96
 
87
97
  async refresh(): Promise<{ accessToken: string }> {
88
- if (!this.refreshToken) {
98
+ // Tenta pegar do localStorage primeiro, depois da memória
99
+ const refreshToken = this.client.getRefreshToken() || this.getRefreshToken();
100
+
101
+ if (!refreshToken) {
89
102
  throw new Error("Nenhum refresh token disponível");
90
103
  }
91
104
 
92
105
  try {
93
106
  const { data } = await this.http.post("/auth/refresh", {
94
- refreshToken: this.refreshToken,
107
+ refreshToken,
95
108
  });
96
109
 
97
110
  if (data.accessToken) {
98
111
  this.client.setToken(data.accessToken);
112
+
113
+ // Se vier novo refresh token, atualiza
114
+ if (data.refreshToken) {
115
+ this.client.setRefreshToken(data.refreshToken);
116
+ }
99
117
  }
100
118
 
101
119
  return data;
102
120
  } catch (e) {
103
- this.client.setToken(null);
104
- this.refreshToken = null;
121
+ // Token expirado - limpa sessão
122
+ this.client.clearSession();
123
+ this.currentUser = null;
105
124
  throw e;
106
125
  }
107
126
  }
@@ -111,17 +130,18 @@ export class AuthModule {
111
130
  }
112
131
 
113
132
  async logout(): Promise<void> {
114
- if (this.refreshToken) {
133
+ const refreshToken = this.client.getRefreshToken();
134
+
135
+ if (refreshToken) {
115
136
  try {
116
- await this.http.post("/auth/logout", {
117
- refreshToken: this.refreshToken,
118
- });
119
- } catch (e) {
120
- // Ignora erro de logout
137
+ await this.http.post("/auth/logout", { refreshToken });
138
+ } catch {
139
+ // Ignora erro de logout no servidor
121
140
  }
122
141
  }
123
- this.client.setToken(null);
124
- this.refreshToken = null;
142
+
143
+ // Limpa tudo (memória + localStorage)
144
+ this.client.clearSession();
125
145
  this.currentUser = null;
126
146
  }
127
147
 
@@ -129,8 +149,7 @@ export class AuthModule {
129
149
  try {
130
150
  await this.http.post("/auth/logout-all");
131
151
  } finally {
132
- this.client.setToken(null);
133
- this.refreshToken = null;
152
+ this.client.clearSession();
134
153
  this.currentUser = null;
135
154
  }
136
155
  }
@@ -155,17 +174,23 @@ export class AuthModule {
155
174
  return data;
156
175
  }
157
176
 
177
+ /**
178
+ * @deprecated Use client.getRefreshToken() - mantido para compatibilidade
179
+ */
158
180
  getRefreshToken(): string | null {
159
- return this.refreshToken;
181
+ return this.client.getRefreshToken();
160
182
  }
161
183
 
184
+ /**
185
+ * @deprecated Use client.setRefreshToken() - mantido para compatibilidade
186
+ */
162
187
  setRefreshToken(token: string | null) {
163
- this.refreshToken = token;
188
+ this.client.setRefreshToken(token);
164
189
  }
165
190
 
166
- // =================================================================
167
- // NOVOS MÉTODOS (COMPATIBILIDADE COM SHOWCASE / SUPABASE STYLE)
168
- // =================================================================
191
+ // ==========================================================================
192
+ // MÉTODOS COMPATÍVEIS COM SUPABASE / SHOWCASE STYLE
193
+ // ==========================================================================
169
194
 
170
195
  /**
171
196
  * Alias para login, retornando { user, error } padrão do Showcase
@@ -182,12 +207,16 @@ export class AuthModule {
182
207
  /**
183
208
  * Alias para register, retornando { user, error }
184
209
  */
185
- async signUp(credentials: { email: string; password: string; data?: { name: string } }) {
210
+ async signUp(credentials: {
211
+ email: string;
212
+ password: string;
213
+ data?: { name: string };
214
+ }) {
186
215
  try {
187
216
  const data = await this.register({
188
217
  email: credentials.email,
189
218
  password: credentials.password,
190
- name: credentials.data?.name || credentials.email.split('@')[0],
219
+ name: credentials.data?.name || credentials.email.split("@")[0],
191
220
  });
192
221
  return { user: data.user, error: null };
193
222
  } catch (err: any) {
@@ -205,21 +234,53 @@ export class AuthModule {
205
234
 
206
235
  /**
207
236
  * Recupera a sessão atual (User + Token).
208
- * Se não tiver logado, retorna null ou tenta validar o token.
237
+ * Primeiro tenta memória, depois localStorage.
238
+ * Se não encontrar, retorna null.
209
239
  */
210
240
  async getSession() {
211
241
  const token = this.client.getToken();
212
242
  if (!token) return null;
213
243
 
214
- // Se já temos o user em memória, retorna.
215
- // O ideal seria validar o token no backend (/auth/me), mas vamos simplificar.
244
+ // Tenta memória primeiro
216
245
  if (this.currentUser) {
217
246
  return {
218
247
  user: this.currentUser,
219
- access_token: token
248
+ access_token: token,
249
+ };
250
+ }
251
+
252
+ // Tenta localStorage
253
+ const savedUser = this.client.getUser();
254
+ if (savedUser) {
255
+ this.currentUser = savedUser;
256
+ return {
257
+ user: savedUser,
258
+ access_token: token,
259
+ };
260
+ }
261
+
262
+ // Última opção: valida token no backend
263
+ try {
264
+ const { data } = await this.http.get<{ user: User }>("/auth/me");
265
+ this.currentUser = data.user;
266
+ this.client.setUser(data.user);
267
+ return {
268
+ user: data.user,
269
+ access_token: token,
220
270
  };
271
+ } catch {
272
+ // Token inválido/expirado - limpa sessão
273
+ this.client.clearSession();
274
+ this.currentUser = null;
275
+ return null;
221
276
  }
277
+ }
222
278
 
223
- return null;
279
+ /**
280
+ * Retorna o usuário atual (sem validar token).
281
+ * Útil para acesso síncrono aos dados do usuário.
282
+ */
283
+ getCurrentUser(): User | null {
284
+ return this.currentUser || this.client.getUser();
224
285
  }
225
286
  }