aurabase-js 0.1.0
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/.omc/state/hud-state.json +6 -0
- package/.omc/state/hud-stdin-cache.json +1 -0
- package/README.md +204 -0
- package/dist/index.d.mts +392 -0
- package/dist/index.d.ts +392 -0
- package/dist/index.js +769 -0
- package/dist/index.mjs +741 -0
- package/package.json +34 -0
- package/src/AuraBaseClient.ts +271 -0
- package/src/Auth.ts +329 -0
- package/src/QueryBuilder.ts +319 -0
- package/src/errors.ts +15 -0
- package/src/index.ts +72 -0
- package/src/types.ts +79 -0
- package/tsconfig.json +20 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,741 @@
|
|
|
1
|
+
// src/QueryBuilder.ts
|
|
2
|
+
var QueryBuilder = class {
|
|
3
|
+
constructor(url, anonKey, accessToken, tableName, headers = {}) {
|
|
4
|
+
this.isSingle = false;
|
|
5
|
+
this.url = url;
|
|
6
|
+
this.anonKey = anonKey;
|
|
7
|
+
this.accessToken = accessToken;
|
|
8
|
+
this.tableName = tableName;
|
|
9
|
+
this.queryParams = new URLSearchParams();
|
|
10
|
+
this.headers = { ...headers };
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Select columns
|
|
14
|
+
* @example
|
|
15
|
+
* .select('id, name, email')
|
|
16
|
+
* .select('*')
|
|
17
|
+
*/
|
|
18
|
+
select(columns = "*") {
|
|
19
|
+
this.queryParams.set("select", columns);
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Filter by column equality
|
|
24
|
+
* @example
|
|
25
|
+
* .eq('id', 1)
|
|
26
|
+
* .eq('status', 'active')
|
|
27
|
+
*/
|
|
28
|
+
eq(column, value) {
|
|
29
|
+
this.queryParams.append(column, `eq.${value}`);
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Filter by column inequality
|
|
34
|
+
*/
|
|
35
|
+
neq(column, value) {
|
|
36
|
+
this.queryParams.append(column, `neq.${value}`);
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Filter by greater than
|
|
41
|
+
*/
|
|
42
|
+
gt(column, value) {
|
|
43
|
+
this.queryParams.append(column, `gt.${value}`);
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Filter by greater than or equal
|
|
48
|
+
*/
|
|
49
|
+
gte(column, value) {
|
|
50
|
+
this.queryParams.append(column, `gte.${value}`);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Filter by less than
|
|
55
|
+
*/
|
|
56
|
+
lt(column, value) {
|
|
57
|
+
this.queryParams.append(column, `lt.${value}`);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Filter by less than or equal
|
|
62
|
+
*/
|
|
63
|
+
lte(column, value) {
|
|
64
|
+
this.queryParams.append(column, `lte.${value}`);
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Filter by like pattern
|
|
69
|
+
*/
|
|
70
|
+
like(column, pattern) {
|
|
71
|
+
this.queryParams.append(column, `like.${pattern}`);
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Filter by case-insensitive like pattern
|
|
76
|
+
*/
|
|
77
|
+
ilike(column, pattern) {
|
|
78
|
+
this.queryParams.append(column, `ilike.${pattern}`);
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Filter by array contains
|
|
83
|
+
*/
|
|
84
|
+
contains(column, value) {
|
|
85
|
+
this.queryParams.append(column, `cs.{${value.join(",")}}`);
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Filter by value in array
|
|
90
|
+
*/
|
|
91
|
+
in(column, values) {
|
|
92
|
+
this.queryParams.append(column, `in.(${values.join(",")})`);
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Filter for null values
|
|
97
|
+
*/
|
|
98
|
+
isNull(column) {
|
|
99
|
+
this.queryParams.append(column, "is.null");
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Filter for non-null values
|
|
104
|
+
*/
|
|
105
|
+
isNotNull(column) {
|
|
106
|
+
this.queryParams.append(column, "is.not.null");
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Order results
|
|
111
|
+
* @example
|
|
112
|
+
* .order('created_at', { ascending: false })
|
|
113
|
+
*/
|
|
114
|
+
order(column, options = {}) {
|
|
115
|
+
const { ascending = true, nullsFirst } = options;
|
|
116
|
+
let orderStr = column;
|
|
117
|
+
if (!ascending) orderStr += ".desc";
|
|
118
|
+
if (nullsFirst !== void 0) {
|
|
119
|
+
orderStr += nullsFirst ? ".nullsfirst" : ".nullslast";
|
|
120
|
+
}
|
|
121
|
+
this.queryParams.append("order", orderStr);
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Limit results
|
|
126
|
+
*/
|
|
127
|
+
limit(count) {
|
|
128
|
+
this.queryParams.set("limit", String(count));
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Offset results
|
|
133
|
+
*/
|
|
134
|
+
offset(count) {
|
|
135
|
+
this.queryParams.set("offset", String(count));
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Range of results (offset + limit)
|
|
140
|
+
*/
|
|
141
|
+
range(from, to) {
|
|
142
|
+
this.queryParams.set("offset", String(from));
|
|
143
|
+
this.queryParams.set("limit", String(to - from + 1));
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Return single result
|
|
148
|
+
*/
|
|
149
|
+
single() {
|
|
150
|
+
this.isSingle = true;
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Return single result or null
|
|
155
|
+
*/
|
|
156
|
+
maybeSingle() {
|
|
157
|
+
this.isSingle = true;
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
getHeaders() {
|
|
161
|
+
const token = this.accessToken || this.anonKey;
|
|
162
|
+
return {
|
|
163
|
+
"Content-Type": "application/json",
|
|
164
|
+
"apikey": this.anonKey,
|
|
165
|
+
"Authorization": `Bearer ${token}`,
|
|
166
|
+
...this.headers
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
async request(method, body) {
|
|
170
|
+
const queryString = this.queryParams.toString();
|
|
171
|
+
const fullUrl = `${this.url}/rest/v1/${this.tableName}${queryString ? `?${queryString}` : ""}`;
|
|
172
|
+
const options = {
|
|
173
|
+
method,
|
|
174
|
+
headers: this.getHeaders()
|
|
175
|
+
};
|
|
176
|
+
if (body && method !== "GET") {
|
|
177
|
+
options.body = JSON.stringify(body);
|
|
178
|
+
options.headers["Prefer"] = "return=representation";
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const response = await fetch(fullUrl, options);
|
|
182
|
+
let data = null;
|
|
183
|
+
let error = null;
|
|
184
|
+
const text = await response.text();
|
|
185
|
+
if (text) {
|
|
186
|
+
try {
|
|
187
|
+
const parsed = JSON.parse(text);
|
|
188
|
+
if (!response.ok) {
|
|
189
|
+
error = {
|
|
190
|
+
message: parsed.message || parsed.error || `HTTP ${response.status}`,
|
|
191
|
+
code: parsed.code,
|
|
192
|
+
details: parsed.details
|
|
193
|
+
};
|
|
194
|
+
} else {
|
|
195
|
+
data = this.isSingle && Array.isArray(parsed) ? parsed[0] ?? null : parsed;
|
|
196
|
+
}
|
|
197
|
+
} catch {
|
|
198
|
+
if (!response.ok) {
|
|
199
|
+
error = {
|
|
200
|
+
message: text || `HTTP ${response.status}`
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
data,
|
|
207
|
+
error,
|
|
208
|
+
status: response.status,
|
|
209
|
+
statusText: response.statusText
|
|
210
|
+
};
|
|
211
|
+
} catch (err) {
|
|
212
|
+
return {
|
|
213
|
+
data: null,
|
|
214
|
+
error: {
|
|
215
|
+
message: err instanceof Error ? err.message : "Network error"
|
|
216
|
+
},
|
|
217
|
+
status: 0,
|
|
218
|
+
statusText: "Network Error"
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Execute SELECT query
|
|
224
|
+
*/
|
|
225
|
+
async then(resolve, reject) {
|
|
226
|
+
try {
|
|
227
|
+
const result = await this.request("GET");
|
|
228
|
+
await resolve(result);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
if (reject) {
|
|
231
|
+
await reject(err);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Insert row(s)
|
|
237
|
+
*/
|
|
238
|
+
async insert(row) {
|
|
239
|
+
const rows = Array.isArray(row) ? row : [row];
|
|
240
|
+
return this.request("POST", rows.length === 1 ? rows[0] : rows);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Update row(s)
|
|
244
|
+
*/
|
|
245
|
+
async update(data) {
|
|
246
|
+
return this.request("PATCH", data);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Upsert row(s)
|
|
250
|
+
*/
|
|
251
|
+
async upsert(row) {
|
|
252
|
+
const rows = Array.isArray(row) ? row : [row];
|
|
253
|
+
this.headers["Prefer"] = "resolution=merge-duplicates,return=representation";
|
|
254
|
+
return this.request("POST", rows.length === 1 ? rows[0] : rows);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Delete row(s)
|
|
258
|
+
*/
|
|
259
|
+
async delete() {
|
|
260
|
+
return this.request("DELETE");
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// src/Auth.ts
|
|
265
|
+
var AuthClient = class {
|
|
266
|
+
constructor(url, anonKey) {
|
|
267
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
268
|
+
this.currentSession = null;
|
|
269
|
+
this.storageKey = "aurabase_session";
|
|
270
|
+
this.url = url;
|
|
271
|
+
this.anonKey = anonKey;
|
|
272
|
+
this.loadSession();
|
|
273
|
+
}
|
|
274
|
+
loadSession() {
|
|
275
|
+
if (typeof window === "undefined") return;
|
|
276
|
+
try {
|
|
277
|
+
const stored = localStorage.getItem(this.storageKey);
|
|
278
|
+
if (stored) {
|
|
279
|
+
this.currentSession = JSON.parse(stored);
|
|
280
|
+
}
|
|
281
|
+
} catch {
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
saveSession(session) {
|
|
285
|
+
this.currentSession = session;
|
|
286
|
+
if (typeof window === "undefined") return;
|
|
287
|
+
if (session) {
|
|
288
|
+
localStorage.setItem(this.storageKey, JSON.stringify(session));
|
|
289
|
+
} else {
|
|
290
|
+
localStorage.removeItem(this.storageKey);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
getHeaders() {
|
|
294
|
+
return {
|
|
295
|
+
"Content-Type": "application/json",
|
|
296
|
+
"apikey": this.anonKey
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
emitEvent(event, session) {
|
|
300
|
+
const listeners = this.listeners.get(event) || [];
|
|
301
|
+
listeners.forEach((listener) => listener(event, session));
|
|
302
|
+
const allListeners = this.listeners.get("*") || [];
|
|
303
|
+
allListeners.forEach((listener) => listener(event, session));
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Sign in with email and password
|
|
307
|
+
*/
|
|
308
|
+
async signInWithPassword(credentials) {
|
|
309
|
+
try {
|
|
310
|
+
const response = await fetch(`${this.url}/auth/login`, {
|
|
311
|
+
method: "POST",
|
|
312
|
+
headers: this.getHeaders(),
|
|
313
|
+
body: JSON.stringify(credentials)
|
|
314
|
+
});
|
|
315
|
+
const data = await response.json();
|
|
316
|
+
if (!response.ok) {
|
|
317
|
+
const errorMsg = typeof data.detail === "string" ? data.detail : Array.isArray(data.detail) ? data.detail.map((e) => e.msg).join(", ") : data.error || "Login failed";
|
|
318
|
+
return {
|
|
319
|
+
data: null,
|
|
320
|
+
error: { error: errorMsg }
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const session = {
|
|
324
|
+
access_token: data.access_token,
|
|
325
|
+
token_type: "bearer",
|
|
326
|
+
user: data.user
|
|
327
|
+
};
|
|
328
|
+
this.saveSession(session);
|
|
329
|
+
this.emitEvent("SIGNED_IN", session);
|
|
330
|
+
return {
|
|
331
|
+
data: { user: data.user, session },
|
|
332
|
+
error: null
|
|
333
|
+
};
|
|
334
|
+
} catch (err) {
|
|
335
|
+
return {
|
|
336
|
+
data: null,
|
|
337
|
+
error: { error: err instanceof Error ? err.message : "Network error" }
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Sign up with email and password
|
|
343
|
+
*/
|
|
344
|
+
async signUp(credentials) {
|
|
345
|
+
try {
|
|
346
|
+
const response = await fetch(`${this.url}/auth/register`, {
|
|
347
|
+
method: "POST",
|
|
348
|
+
headers: this.getHeaders(),
|
|
349
|
+
body: JSON.stringify(credentials)
|
|
350
|
+
});
|
|
351
|
+
const data = await response.json();
|
|
352
|
+
if (!response.ok) {
|
|
353
|
+
return {
|
|
354
|
+
data: null,
|
|
355
|
+
error: { error: data.detail || data.error || "Registration failed" }
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
data: { user: data.user || data },
|
|
360
|
+
error: null
|
|
361
|
+
};
|
|
362
|
+
} catch (err) {
|
|
363
|
+
return {
|
|
364
|
+
data: null,
|
|
365
|
+
error: { error: err instanceof Error ? err.message : "Network error" }
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Sign out
|
|
371
|
+
*/
|
|
372
|
+
async signOut() {
|
|
373
|
+
try {
|
|
374
|
+
const token = this.currentSession?.access_token;
|
|
375
|
+
if (token) {
|
|
376
|
+
await fetch(`${this.url}/auth/logout`, {
|
|
377
|
+
method: "POST",
|
|
378
|
+
headers: {
|
|
379
|
+
...this.getHeaders(),
|
|
380
|
+
"Authorization": `Bearer ${token}`
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
this.saveSession(null);
|
|
385
|
+
this.emitEvent("SIGNED_OUT", null);
|
|
386
|
+
return { error: null };
|
|
387
|
+
} catch (err) {
|
|
388
|
+
return { error: { error: err instanceof Error ? err.message : "Network error" } };
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Get current session
|
|
393
|
+
*/
|
|
394
|
+
getSession() {
|
|
395
|
+
return { data: { session: this.currentSession } };
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Get current user
|
|
399
|
+
*/
|
|
400
|
+
async getUser() {
|
|
401
|
+
const token = this.currentSession?.access_token;
|
|
402
|
+
if (!token) {
|
|
403
|
+
return { data: { user: null }, error: null };
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const response = await fetch(`${this.url}/auth/me`, {
|
|
407
|
+
headers: {
|
|
408
|
+
...this.getHeaders(),
|
|
409
|
+
"Authorization": `Bearer ${token}`
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
if (!response.ok) {
|
|
413
|
+
return {
|
|
414
|
+
data: { user: null },
|
|
415
|
+
error: { error: "Failed to get user" }
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const user = await response.json();
|
|
419
|
+
return { data: { user }, error: null };
|
|
420
|
+
} catch (err) {
|
|
421
|
+
return {
|
|
422
|
+
data: { user: null },
|
|
423
|
+
error: { error: err instanceof Error ? err.message : "Network error" }
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Update user
|
|
429
|
+
*/
|
|
430
|
+
async updateUser(attributes) {
|
|
431
|
+
const token = this.currentSession?.access_token;
|
|
432
|
+
if (!token) {
|
|
433
|
+
return {
|
|
434
|
+
data: null,
|
|
435
|
+
error: { error: "Not authenticated" }
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
try {
|
|
439
|
+
const response = await fetch(`${this.url}/auth/me`, {
|
|
440
|
+
method: "PATCH",
|
|
441
|
+
headers: {
|
|
442
|
+
...this.getHeaders(),
|
|
443
|
+
"Authorization": `Bearer ${token}`
|
|
444
|
+
},
|
|
445
|
+
body: JSON.stringify(attributes)
|
|
446
|
+
});
|
|
447
|
+
const data = await response.json();
|
|
448
|
+
if (!response.ok) {
|
|
449
|
+
return {
|
|
450
|
+
data: null,
|
|
451
|
+
error: { error: data.detail || data.error || "Update failed" }
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
if (this.currentSession) {
|
|
455
|
+
this.currentSession.user = data;
|
|
456
|
+
this.saveSession(this.currentSession);
|
|
457
|
+
}
|
|
458
|
+
this.emitEvent("USER_UPDATED", this.currentSession);
|
|
459
|
+
return { data: { user: data }, error: null };
|
|
460
|
+
} catch (err) {
|
|
461
|
+
return {
|
|
462
|
+
data: null,
|
|
463
|
+
error: { error: err instanceof Error ? err.message : "Network error" }
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Request password reset
|
|
469
|
+
*/
|
|
470
|
+
async resetPasswordForEmail(email) {
|
|
471
|
+
try {
|
|
472
|
+
const response = await fetch(`${this.url}/auth/find-password`, {
|
|
473
|
+
method: "POST",
|
|
474
|
+
headers: this.getHeaders(),
|
|
475
|
+
body: JSON.stringify({ email })
|
|
476
|
+
});
|
|
477
|
+
const data = await response.json();
|
|
478
|
+
if (!response.ok) {
|
|
479
|
+
return { error: { error: data.detail || data.error || "Request failed" } };
|
|
480
|
+
}
|
|
481
|
+
return { error: null };
|
|
482
|
+
} catch (err) {
|
|
483
|
+
return { error: { error: err instanceof Error ? err.message : "Network error" } };
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Subscribe to auth state changes
|
|
488
|
+
*/
|
|
489
|
+
onAuthStateChange(callback) {
|
|
490
|
+
const addListener = (event) => {
|
|
491
|
+
if (!this.listeners.has(event)) {
|
|
492
|
+
this.listeners.set(event, []);
|
|
493
|
+
}
|
|
494
|
+
this.listeners.get(event).push(callback);
|
|
495
|
+
};
|
|
496
|
+
addListener("SIGNED_IN");
|
|
497
|
+
addListener("SIGNED_OUT");
|
|
498
|
+
addListener("TOKEN_REFRESHED");
|
|
499
|
+
addListener("USER_UPDATED");
|
|
500
|
+
return {
|
|
501
|
+
data: {
|
|
502
|
+
subscription: {
|
|
503
|
+
unsubscribe: () => {
|
|
504
|
+
this.listeners.forEach((listeners) => {
|
|
505
|
+
const index = listeners.indexOf(callback);
|
|
506
|
+
if (index > -1) {
|
|
507
|
+
listeners.splice(index, 1);
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
// src/AuraBaseClient.ts
|
|
518
|
+
var AuraBaseClient = class {
|
|
519
|
+
constructor(options) {
|
|
520
|
+
this.accessToken = null;
|
|
521
|
+
this.url = options.url;
|
|
522
|
+
this.anonKey = options.anonKey;
|
|
523
|
+
this.customHeaders = options.headers || {};
|
|
524
|
+
this.auth = new AuthClient(this.url, this.anonKey);
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Set access token for authenticated requests
|
|
528
|
+
*/
|
|
529
|
+
setAccessToken(token) {
|
|
530
|
+
this.accessToken = token;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Get the current access token
|
|
534
|
+
*/
|
|
535
|
+
getAccessToken() {
|
|
536
|
+
return this.accessToken;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Query a table
|
|
540
|
+
* @example
|
|
541
|
+
* const { data, error } = await client.from('todos').select('*')
|
|
542
|
+
*/
|
|
543
|
+
from(tableName) {
|
|
544
|
+
return new QueryBuilder(
|
|
545
|
+
this.url,
|
|
546
|
+
this.anonKey,
|
|
547
|
+
this.accessToken,
|
|
548
|
+
tableName,
|
|
549
|
+
this.customHeaders
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Execute raw SQL (RPC function call)
|
|
554
|
+
* @example
|
|
555
|
+
* const { data, error } = await client.rpc('my_function', { arg1: 'value' })
|
|
556
|
+
*/
|
|
557
|
+
async rpc(functionName, params) {
|
|
558
|
+
const token = this.accessToken || this.anonKey;
|
|
559
|
+
try {
|
|
560
|
+
const response = await fetch(`${this.url}/rpc/v1/${functionName}`, {
|
|
561
|
+
method: "POST",
|
|
562
|
+
headers: {
|
|
563
|
+
"Content-Type": "application/json",
|
|
564
|
+
"apikey": this.anonKey,
|
|
565
|
+
"Authorization": `Bearer ${token}`,
|
|
566
|
+
...this.customHeaders
|
|
567
|
+
},
|
|
568
|
+
body: JSON.stringify(params || {})
|
|
569
|
+
});
|
|
570
|
+
const text = await response.text();
|
|
571
|
+
let data = null;
|
|
572
|
+
let error = null;
|
|
573
|
+
if (text) {
|
|
574
|
+
try {
|
|
575
|
+
const parsed = JSON.parse(text);
|
|
576
|
+
if (!response.ok) {
|
|
577
|
+
error = { message: parsed.message || parsed.error || `HTTP ${response.status}` };
|
|
578
|
+
} else {
|
|
579
|
+
data = parsed;
|
|
580
|
+
}
|
|
581
|
+
} catch {
|
|
582
|
+
if (!response.ok) {
|
|
583
|
+
error = { message: text || `HTTP ${response.status}` };
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return { data, error };
|
|
588
|
+
} catch (err) {
|
|
589
|
+
return {
|
|
590
|
+
data: null,
|
|
591
|
+
error: { message: err instanceof Error ? err.message : "Network error" }
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Get storage client (if available)
|
|
597
|
+
*/
|
|
598
|
+
get storage() {
|
|
599
|
+
return {
|
|
600
|
+
from: (bucket) => new StorageBucket(this.url, this.anonKey, bucket, this.accessToken)
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
var StorageBucket = class {
|
|
605
|
+
constructor(url, anonKey, bucket, accessToken) {
|
|
606
|
+
this.url = url;
|
|
607
|
+
this.anonKey = anonKey;
|
|
608
|
+
this.bucket = bucket;
|
|
609
|
+
this.accessToken = accessToken;
|
|
610
|
+
}
|
|
611
|
+
getHeaders() {
|
|
612
|
+
const token = this.accessToken || this.anonKey;
|
|
613
|
+
return {
|
|
614
|
+
"apikey": this.anonKey,
|
|
615
|
+
"Authorization": `Bearer ${token}`
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Upload a file
|
|
620
|
+
*/
|
|
621
|
+
async upload(path, file, options) {
|
|
622
|
+
const formData = new FormData();
|
|
623
|
+
formData.append("file", file);
|
|
624
|
+
const headers = this.getHeaders();
|
|
625
|
+
if (options?.contentType) {
|
|
626
|
+
headers["Content-Type"] = options.contentType;
|
|
627
|
+
}
|
|
628
|
+
try {
|
|
629
|
+
const response = await fetch(
|
|
630
|
+
`${this.url}/storage/v1/object/${this.bucket}/${path}`,
|
|
631
|
+
{
|
|
632
|
+
method: "POST",
|
|
633
|
+
headers,
|
|
634
|
+
body: formData
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
const data = await response.json();
|
|
638
|
+
if (!response.ok) {
|
|
639
|
+
return {
|
|
640
|
+
data: null,
|
|
641
|
+
error: { message: data.message || data.error || "Upload failed" }
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
return { data: { path: data.path || path }, error: null };
|
|
645
|
+
} catch (err) {
|
|
646
|
+
return {
|
|
647
|
+
data: null,
|
|
648
|
+
error: { message: err instanceof Error ? err.message : "Network error" }
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Download a file
|
|
654
|
+
*/
|
|
655
|
+
async download(path) {
|
|
656
|
+
try {
|
|
657
|
+
const response = await fetch(
|
|
658
|
+
`${this.url}/storage/v1/object/${this.bucket}/${path}`,
|
|
659
|
+
{
|
|
660
|
+
headers: this.getHeaders()
|
|
661
|
+
}
|
|
662
|
+
);
|
|
663
|
+
if (!response.ok) {
|
|
664
|
+
const data = await response.json();
|
|
665
|
+
return {
|
|
666
|
+
data: null,
|
|
667
|
+
error: { message: data.message || data.error || "Download failed" }
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
return { data: await response.blob(), error: null };
|
|
671
|
+
} catch (err) {
|
|
672
|
+
return {
|
|
673
|
+
data: null,
|
|
674
|
+
error: { message: err instanceof Error ? err.message : "Network error" }
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Get public URL for a file
|
|
680
|
+
*/
|
|
681
|
+
getPublicUrl(path) {
|
|
682
|
+
return `${this.url}/storage/v1/object/public/${this.bucket}/${path}`;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Delete a file
|
|
686
|
+
*/
|
|
687
|
+
async remove(paths) {
|
|
688
|
+
try {
|
|
689
|
+
const response = await fetch(`${this.url}/storage/v1/object/${this.bucket}`, {
|
|
690
|
+
method: "DELETE",
|
|
691
|
+
headers: {
|
|
692
|
+
...this.getHeaders(),
|
|
693
|
+
"Content-Type": "application/json"
|
|
694
|
+
},
|
|
695
|
+
body: JSON.stringify({ prefixes: paths })
|
|
696
|
+
});
|
|
697
|
+
if (!response.ok) {
|
|
698
|
+
const data = await response.json();
|
|
699
|
+
return { error: { message: data.message || data.error || "Delete failed" } };
|
|
700
|
+
}
|
|
701
|
+
return { error: null };
|
|
702
|
+
} catch (err) {
|
|
703
|
+
return { error: { message: err instanceof Error ? err.message : "Network error" } };
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* List files in a bucket
|
|
708
|
+
*/
|
|
709
|
+
async list(prefix) {
|
|
710
|
+
try {
|
|
711
|
+
const url = prefix ? `${this.url}/storage/v1/object/list/${this.bucket}?prefix=${prefix}` : `${this.url}/storage/v1/object/list/${this.bucket}`;
|
|
712
|
+
const response = await fetch(url, {
|
|
713
|
+
headers: this.getHeaders()
|
|
714
|
+
});
|
|
715
|
+
const data = await response.json();
|
|
716
|
+
if (!response.ok) {
|
|
717
|
+
return {
|
|
718
|
+
data: null,
|
|
719
|
+
error: { message: data.message || data.error || "List failed" }
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
return { data, error: null };
|
|
723
|
+
} catch (err) {
|
|
724
|
+
return {
|
|
725
|
+
data: null,
|
|
726
|
+
error: { message: err instanceof Error ? err.message : "Network error" }
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
// src/index.ts
|
|
733
|
+
function createClient(options) {
|
|
734
|
+
return new AuraBaseClient(options);
|
|
735
|
+
}
|
|
736
|
+
var index_default = createClient;
|
|
737
|
+
export {
|
|
738
|
+
AuraBaseClient,
|
|
739
|
+
createClient,
|
|
740
|
+
index_default as default
|
|
741
|
+
};
|