@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 +51 -39
- package/dist/auth.js +70 -33
- package/dist/index.d.ts +6 -15
- package/dist/index.js +12 -23
- package/dist/storage.d.ts +25 -14
- package/dist/storage.js +42 -20
- package/package.json +2 -2
- package/src/auth.ts +88 -44
- package/src/index.ts +27 -46
- package/src/storage.ts +47 -20
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
|
-
*
|
|
49
|
+
* Alias para login, retornando { user, error } padrão do Showcase
|
|
65
50
|
*/
|
|
66
|
-
|
|
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
|
-
*
|
|
62
|
+
* Alias para register, retornando { user, error }
|
|
69
63
|
*/
|
|
70
|
-
|
|
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
|
-
*
|
|
78
|
+
* Alias para logout
|
|
73
79
|
*/
|
|
74
|
-
|
|
80
|
+
signOut(): Promise<{
|
|
81
|
+
error: null;
|
|
82
|
+
}>;
|
|
75
83
|
/**
|
|
76
|
-
*
|
|
84
|
+
* Recupera a sessão atual (User + Token).
|
|
85
|
+
* Se não tiver logado, retorna null ou tenta validar o token.
|
|
77
86
|
*/
|
|
78
|
-
|
|
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
|
-
|
|
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
|
|
12
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
|
|
18
|
-
this.
|
|
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
|
|
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
|
-
//
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
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 || "",
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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;
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
44
|
-
this.
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
|
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 || "",
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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;
|
|
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
|
+
}
|