-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathclient.ts
More file actions
135 lines (118 loc) · 3.67 KB
/
Copy pathclient.ts
File metadata and controls
135 lines (118 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { UrBackendConfig, RequestOptions } from './types';
import { UrBackendError, parseApiError } from './errors';
import { AuthModule } from './modules/auth';
import { DatabaseModule } from './modules/database';
import { StorageModule } from './modules/storage';
import { SchemaModule } from './modules/schema';
import { MailModule } from './modules/mail';
export class UrBackendClient {
private apiKey: string;
private baseUrl: string;
private _auth?: AuthModule;
private _db?: DatabaseModule;
private _storage?: StorageModule;
private _schema?: SchemaModule;
private _mail?: MailModule;
private headers: Record<string, string>;
constructor(config: UrBackendConfig) {
this.apiKey = config.apiKey;
this.baseUrl = config.baseUrl || 'https://api.ub.bitbros.in';
this.headers = config.headers || {};
if (typeof window !== 'undefined' && this.apiKey.startsWith('sk_live_')) {
console.warn(
'⚠️ urbackend-sdk: Avoid exposing your Secret Key (sk_live_...) in client-side code. This can lead to unauthorized access to your account and data. Use your Publishable Key (pk_live_...) instead.',
);
}
}
get auth(): AuthModule {
if (!this._auth) {
this._auth = new AuthModule(this);
}
return this._auth;
}
get db(): DatabaseModule {
if (!this._db) {
this._db = new DatabaseModule(this);
}
return this._db;
}
get storage(): StorageModule {
if (!this._storage) {
this._storage = new StorageModule(this);
}
return this._storage;
}
get schema(): SchemaModule {
if (!this._schema) {
this._schema = new SchemaModule(this);
}
return this._schema;
}
get mail(): MailModule {
if (!this._mail) {
this._mail = new MailModule(this);
}
return this._mail;
}
/**
* Internal request handler
*/
public async request<T>(
method: string,
path: string,
options: RequestOptions = {},
): Promise<T> {
const url = `${this.baseUrl}${path}`;
const headers: Record<string, string> = {
'x-api-key': this.apiKey,
'User-Agent': `urbackend-sdk-js/0.2.0`,
...this.headers,
};
if (options.token) {
headers['Authorization'] = `Bearer ${options.token}`;
}
// Merge custom headers from options if provided
if ((options as any).headers) {
Object.assign(headers, (options as any).headers);
}
let requestBody: BodyInit | undefined;
if (options.isMultipart) {
// Fetch handles FormData content type and boundary
requestBody = options.body as FormData;
} else if (options.body) {
headers['Content-Type'] = 'application/json';
requestBody = JSON.stringify(options.body);
}
try {
const response = await fetch(url, {
method,
headers,
body: requestBody,
credentials: options.credentials,
});
if (!response.ok) {
throw await parseApiError(response);
}
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
const json = await response.json();
// The API returns { data, success, message }
// If data is present, return it. If success/message are present but no data, return the whole object (for exchange/logout etc)
if (json.data !== undefined) {
return json.data;
}
return json;
}
return (await response.text()) as unknown as T;
} catch (error) {
if (error instanceof UrBackendError) {
throw error;
}
throw new UrBackendError(
error instanceof Error ? error.message : 'Network request failed',
0,
path,
);
}
}
}