@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/auth.d.ts +13 -2
- package/dist/auth.js +82 -34
- package/dist/database.d.ts +35 -68
- package/dist/database.js +72 -78
- package/dist/index.d.ts +45 -1
- package/dist/index.js +136 -1
- package/package.json +1 -1
- package/src/auth.ts +96 -35
- package/src/database.ts +80 -81
- package/src/index.ts +162 -6
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";
|
|
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
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
|
-
|
|
35
|
-
// Armazena o user
|
|
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
|
|
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.
|
|
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
|
-
|
|
63
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
104
|
-
this.
|
|
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
|
-
|
|
133
|
+
const refreshToken = this.client.getRefreshToken();
|
|
134
|
+
|
|
135
|
+
if (refreshToken) {
|
|
115
136
|
try {
|
|
116
|
-
await this.http.post("/auth/logout", {
|
|
117
|
-
|
|
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
|
-
|
|
124
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
188
|
+
this.client.setRefreshToken(token);
|
|
164
189
|
}
|
|
165
190
|
|
|
166
|
-
//
|
|
167
|
-
//
|
|
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: {
|
|
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(
|
|
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
|
-
*
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
}
|