bun-query-builder 0.1.12 → 0.1.13
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/browser.js +797 -0
- package/dist/dynamodb/index.js +2274 -0
- package/dist/index.js +14717 -14716
- package/package.json +1 -5
package/dist/browser.js
ADDED
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
set: (newValue) => all[name] = () => newValue
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
13
|
+
var __promiseAll = (args) => Promise.all(args);
|
|
14
|
+
var __require = import.meta.require;
|
|
15
|
+
|
|
16
|
+
// src/browser.ts
|
|
17
|
+
function configureBrowser(config) {
|
|
18
|
+
browserConfig = { ...browserConfig, ...config };
|
|
19
|
+
}
|
|
20
|
+
function getBrowserConfig() {
|
|
21
|
+
return browserConfig;
|
|
22
|
+
}
|
|
23
|
+
function isBrowser() {
|
|
24
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
25
|
+
}
|
|
26
|
+
async function getAuthToken() {
|
|
27
|
+
if (browserConfig.getToken) {
|
|
28
|
+
const token = browserConfig.getToken();
|
|
29
|
+
return token instanceof Promise ? token : token;
|
|
30
|
+
}
|
|
31
|
+
if (typeof localStorage !== "undefined") {
|
|
32
|
+
return localStorage.getItem("auth_token");
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
async function buildHeaders() {
|
|
37
|
+
const headers = {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
Accept: "application/json",
|
|
40
|
+
...browserConfig.headers
|
|
41
|
+
};
|
|
42
|
+
const token = await getAuthToken();
|
|
43
|
+
if (token) {
|
|
44
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
45
|
+
}
|
|
46
|
+
return headers;
|
|
47
|
+
}
|
|
48
|
+
async function handleResponse(response) {
|
|
49
|
+
if (response.status === 401) {
|
|
50
|
+
browserConfig.onUnauthorized?.();
|
|
51
|
+
throw new BrowserQueryError("Unauthorized", 401);
|
|
52
|
+
}
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
const error = await response.json().catch(() => ({ message: "Request failed" }));
|
|
55
|
+
throw new BrowserQueryError(error.message || `HTTP ${response.status}`, response.status);
|
|
56
|
+
}
|
|
57
|
+
const data = await response.json();
|
|
58
|
+
if (browserConfig.transformResponse) {
|
|
59
|
+
return browserConfig.transformResponse(data);
|
|
60
|
+
}
|
|
61
|
+
return data;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class BrowserQueryBuilder {
|
|
65
|
+
state;
|
|
66
|
+
constructor(table) {
|
|
67
|
+
this.state = {
|
|
68
|
+
table,
|
|
69
|
+
wheres: [],
|
|
70
|
+
orderBy: [],
|
|
71
|
+
selectColumns: ["*"],
|
|
72
|
+
withRelations: []
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
select(...columns) {
|
|
76
|
+
this.state.selectColumns = columns;
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
where(column, operatorOrValue, value) {
|
|
80
|
+
if (value === undefined) {
|
|
81
|
+
this.state.wheres.push({
|
|
82
|
+
column,
|
|
83
|
+
operator: "=",
|
|
84
|
+
value: operatorOrValue,
|
|
85
|
+
boolean: "and"
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
this.state.wheres.push({
|
|
89
|
+
column,
|
|
90
|
+
operator: operatorOrValue,
|
|
91
|
+
value,
|
|
92
|
+
boolean: "and"
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
orWhere(column, operatorOrValue, value) {
|
|
98
|
+
if (value === undefined) {
|
|
99
|
+
this.state.wheres.push({
|
|
100
|
+
column,
|
|
101
|
+
operator: "=",
|
|
102
|
+
value: operatorOrValue,
|
|
103
|
+
boolean: "or"
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
this.state.wheres.push({
|
|
107
|
+
column,
|
|
108
|
+
operator: operatorOrValue,
|
|
109
|
+
value,
|
|
110
|
+
boolean: "or"
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
andWhere(column, operatorOrValue, value) {
|
|
116
|
+
return this.where(column, operatorOrValue, value);
|
|
117
|
+
}
|
|
118
|
+
whereNull(column) {
|
|
119
|
+
return this.where(column, "is", null);
|
|
120
|
+
}
|
|
121
|
+
whereNotNull(column) {
|
|
122
|
+
return this.where(column, "is not", null);
|
|
123
|
+
}
|
|
124
|
+
whereIn(column, values) {
|
|
125
|
+
return this.where(column, "in", values);
|
|
126
|
+
}
|
|
127
|
+
whereNotIn(column, values) {
|
|
128
|
+
return this.where(column, "not in", values);
|
|
129
|
+
}
|
|
130
|
+
orderBy(column, direction = "asc") {
|
|
131
|
+
this.state.orderBy.push({ column, direction });
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
orderByDesc(column) {
|
|
135
|
+
return this.orderBy(column, "desc");
|
|
136
|
+
}
|
|
137
|
+
latest(column = "created_at") {
|
|
138
|
+
return this.orderBy(column, "desc");
|
|
139
|
+
}
|
|
140
|
+
oldest(column = "created_at") {
|
|
141
|
+
return this.orderBy(column, "asc");
|
|
142
|
+
}
|
|
143
|
+
limit(count) {
|
|
144
|
+
this.state.limitValue = count;
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
offset(count) {
|
|
148
|
+
this.state.offsetValue = count;
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
skip(count) {
|
|
152
|
+
return this.offset(count);
|
|
153
|
+
}
|
|
154
|
+
take(count) {
|
|
155
|
+
return this.limit(count);
|
|
156
|
+
}
|
|
157
|
+
with(...relations) {
|
|
158
|
+
this.state.withRelations.push(...relations);
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
buildQueryParams() {
|
|
162
|
+
const params = new URLSearchParams;
|
|
163
|
+
for (const where of this.state.wheres) {
|
|
164
|
+
if (where.operator === "=") {
|
|
165
|
+
params.append(where.column, String(where.value));
|
|
166
|
+
} else if (where.operator === "in" && Array.isArray(where.value)) {
|
|
167
|
+
params.append(`${where.column}[]`, where.value.join(","));
|
|
168
|
+
} else if (where.operator === "is" && where.value === null) {
|
|
169
|
+
params.append(`filter[${where.column}][is]`, "null");
|
|
170
|
+
} else if (where.operator === "is not" && where.value === null) {
|
|
171
|
+
params.append(`filter[${where.column}][is_not]`, "null");
|
|
172
|
+
} else {
|
|
173
|
+
params.append(`filter[${where.column}][${where.operator}]`, String(where.value));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (this.state.orderBy.length > 0) {
|
|
177
|
+
const orderStr = this.state.orderBy.map((o) => `${o.direction === "desc" ? "-" : ""}${o.column}`).join(",");
|
|
178
|
+
params.append("sort", orderStr);
|
|
179
|
+
}
|
|
180
|
+
if (this.state.limitValue !== undefined) {
|
|
181
|
+
params.append("limit", String(this.state.limitValue));
|
|
182
|
+
}
|
|
183
|
+
if (this.state.offsetValue !== undefined) {
|
|
184
|
+
params.append("offset", String(this.state.offsetValue));
|
|
185
|
+
}
|
|
186
|
+
if (this.state.selectColumns.length > 0 && !this.state.selectColumns.includes("*")) {
|
|
187
|
+
params.append("fields", this.state.selectColumns.join(","));
|
|
188
|
+
}
|
|
189
|
+
if (this.state.withRelations.length > 0) {
|
|
190
|
+
params.append("include", this.state.withRelations.join(","));
|
|
191
|
+
}
|
|
192
|
+
return params;
|
|
193
|
+
}
|
|
194
|
+
buildUrl(path) {
|
|
195
|
+
const base = `${browserConfig.baseUrl}/${this.state.table}`;
|
|
196
|
+
if (path !== undefined) {
|
|
197
|
+
return `${base}/${path}`;
|
|
198
|
+
}
|
|
199
|
+
const params = this.buildQueryParams();
|
|
200
|
+
const queryString = params.toString();
|
|
201
|
+
return queryString ? `${base}?${queryString}` : base;
|
|
202
|
+
}
|
|
203
|
+
async get() {
|
|
204
|
+
const url = this.buildUrl();
|
|
205
|
+
const response = await fetch(url, {
|
|
206
|
+
method: "GET",
|
|
207
|
+
headers: await buildHeaders()
|
|
208
|
+
});
|
|
209
|
+
const result = await handleResponse(response);
|
|
210
|
+
return Array.isArray(result) ? result : result.data;
|
|
211
|
+
}
|
|
212
|
+
async first() {
|
|
213
|
+
this.limit(1);
|
|
214
|
+
const results = await this.get();
|
|
215
|
+
return results[0] ?? null;
|
|
216
|
+
}
|
|
217
|
+
async firstOrFail() {
|
|
218
|
+
const result = await this.first();
|
|
219
|
+
if (!result) {
|
|
220
|
+
throw new BrowserQueryError(`No ${this.state.table} found`, 404);
|
|
221
|
+
}
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
async find(id) {
|
|
225
|
+
const url = this.buildUrl(id);
|
|
226
|
+
try {
|
|
227
|
+
const response = await fetch(url, {
|
|
228
|
+
method: "GET",
|
|
229
|
+
headers: await buildHeaders()
|
|
230
|
+
});
|
|
231
|
+
if (response.status === 404) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
const result = await handleResponse(response);
|
|
235
|
+
return "data" in result && !Array.isArray(result.data) ? result.data : result;
|
|
236
|
+
} catch {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async findOrFail(id) {
|
|
241
|
+
const result = await this.find(id);
|
|
242
|
+
if (!result) {
|
|
243
|
+
throw new BrowserQueryError(`${this.state.table} with id ${id} not found`, 404);
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
async count() {
|
|
248
|
+
const params = this.buildQueryParams();
|
|
249
|
+
params.append("count", "true");
|
|
250
|
+
const url = `${browserConfig.baseUrl}/${this.state.table}?${params.toString()}`;
|
|
251
|
+
const response = await fetch(url, {
|
|
252
|
+
method: "GET",
|
|
253
|
+
headers: await buildHeaders()
|
|
254
|
+
});
|
|
255
|
+
const result = await handleResponse(response);
|
|
256
|
+
return result.count;
|
|
257
|
+
}
|
|
258
|
+
async exists() {
|
|
259
|
+
const count = await this.count();
|
|
260
|
+
return count > 0;
|
|
261
|
+
}
|
|
262
|
+
async create(data) {
|
|
263
|
+
const url = `${browserConfig.baseUrl}/${this.state.table}`;
|
|
264
|
+
const body = browserConfig.transformRequest ? browserConfig.transformRequest(data) : data;
|
|
265
|
+
const response = await fetch(url, {
|
|
266
|
+
method: "POST",
|
|
267
|
+
headers: await buildHeaders(),
|
|
268
|
+
body: JSON.stringify(body)
|
|
269
|
+
});
|
|
270
|
+
const result = await handleResponse(response);
|
|
271
|
+
return "data" in result && !Array.isArray(result.data) ? result.data : result;
|
|
272
|
+
}
|
|
273
|
+
async insert(data) {
|
|
274
|
+
return this.create(data);
|
|
275
|
+
}
|
|
276
|
+
async update(id, data) {
|
|
277
|
+
const url = `${browserConfig.baseUrl}/${this.state.table}/${id}`;
|
|
278
|
+
const body = browserConfig.transformRequest ? browserConfig.transformRequest(data) : data;
|
|
279
|
+
const response = await fetch(url, {
|
|
280
|
+
method: "PATCH",
|
|
281
|
+
headers: await buildHeaders(),
|
|
282
|
+
body: JSON.stringify(body)
|
|
283
|
+
});
|
|
284
|
+
const result = await handleResponse(response);
|
|
285
|
+
return "data" in result && !Array.isArray(result.data) ? result.data : result;
|
|
286
|
+
}
|
|
287
|
+
async delete(id) {
|
|
288
|
+
const url = `${browserConfig.baseUrl}/${this.state.table}/${id}`;
|
|
289
|
+
const response = await fetch(url, {
|
|
290
|
+
method: "DELETE",
|
|
291
|
+
headers: await buildHeaders()
|
|
292
|
+
});
|
|
293
|
+
return response.ok;
|
|
294
|
+
}
|
|
295
|
+
async destroy(id) {
|
|
296
|
+
return this.delete(id);
|
|
297
|
+
}
|
|
298
|
+
async paginate(page = 1, perPage = 15) {
|
|
299
|
+
this.limit(perPage).offset((page - 1) * perPage);
|
|
300
|
+
const params = this.buildQueryParams();
|
|
301
|
+
params.append("paginate", "true");
|
|
302
|
+
const url = `${browserConfig.baseUrl}/${this.state.table}?${params.toString()}`;
|
|
303
|
+
const response = await fetch(url, {
|
|
304
|
+
method: "GET",
|
|
305
|
+
headers: await buildHeaders()
|
|
306
|
+
});
|
|
307
|
+
return handleResponse(response);
|
|
308
|
+
}
|
|
309
|
+
toState() {
|
|
310
|
+
return { ...this.state };
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function browserQuery(table) {
|
|
314
|
+
return new BrowserQueryBuilder(table);
|
|
315
|
+
}
|
|
316
|
+
function createBrowserDb() {
|
|
317
|
+
return new Proxy({}, {
|
|
318
|
+
get: (_target, prop) => {
|
|
319
|
+
return () => browserQuery(prop);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
class BrowserModelInstance {
|
|
325
|
+
_attributes;
|
|
326
|
+
_definition;
|
|
327
|
+
constructor(definition, attributes = {}) {
|
|
328
|
+
this._definition = definition;
|
|
329
|
+
this._attributes = { ...attributes };
|
|
330
|
+
}
|
|
331
|
+
get(key) {
|
|
332
|
+
return this._attributes[key];
|
|
333
|
+
}
|
|
334
|
+
set(key, value) {
|
|
335
|
+
this._attributes[key] = value;
|
|
336
|
+
}
|
|
337
|
+
get attributes() {
|
|
338
|
+
return { ...this._attributes };
|
|
339
|
+
}
|
|
340
|
+
get id() {
|
|
341
|
+
const pk = this._definition.primaryKey || "id";
|
|
342
|
+
return this._attributes[pk];
|
|
343
|
+
}
|
|
344
|
+
toJSON() {
|
|
345
|
+
const hidden = new Set;
|
|
346
|
+
for (const [key, attr] of Object.entries(this._definition.attributes)) {
|
|
347
|
+
if (attr.hidden)
|
|
348
|
+
hidden.add(key);
|
|
349
|
+
}
|
|
350
|
+
const json = {};
|
|
351
|
+
for (const [key, value] of Object.entries(this._attributes)) {
|
|
352
|
+
if (!hidden.has(key))
|
|
353
|
+
json[key] = value;
|
|
354
|
+
}
|
|
355
|
+
return json;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
class BrowserModelQueryBuilder {
|
|
360
|
+
_definition;
|
|
361
|
+
_wheres = [];
|
|
362
|
+
_orderBy = [];
|
|
363
|
+
_limit;
|
|
364
|
+
_offset;
|
|
365
|
+
_select = ["*"];
|
|
366
|
+
_withRelations = [];
|
|
367
|
+
constructor(definition) {
|
|
368
|
+
this._definition = definition;
|
|
369
|
+
}
|
|
370
|
+
getTablePath() {
|
|
371
|
+
return this._definition.traits?.useApi?.uri || this._definition.table;
|
|
372
|
+
}
|
|
373
|
+
where(column, operatorOrValue, value) {
|
|
374
|
+
if (value === undefined) {
|
|
375
|
+
this._wheres.push({ column, operator: "=", value: operatorOrValue, boolean: "and" });
|
|
376
|
+
} else {
|
|
377
|
+
this._wheres.push({ column, operator: operatorOrValue, value, boolean: "and" });
|
|
378
|
+
}
|
|
379
|
+
return this;
|
|
380
|
+
}
|
|
381
|
+
orWhere(column, operatorOrValue, value) {
|
|
382
|
+
if (value === undefined) {
|
|
383
|
+
this._wheres.push({ column, operator: "=", value: operatorOrValue, boolean: "or" });
|
|
384
|
+
} else {
|
|
385
|
+
this._wheres.push({ column, operator: operatorOrValue, value, boolean: "or" });
|
|
386
|
+
}
|
|
387
|
+
return this;
|
|
388
|
+
}
|
|
389
|
+
whereIn(column, values) {
|
|
390
|
+
this._wheres.push({ column, operator: "in", value: values, boolean: "and" });
|
|
391
|
+
return this;
|
|
392
|
+
}
|
|
393
|
+
whereNotIn(column, values) {
|
|
394
|
+
this._wheres.push({ column, operator: "not in", value: values, boolean: "and" });
|
|
395
|
+
return this;
|
|
396
|
+
}
|
|
397
|
+
whereNull(column) {
|
|
398
|
+
this._wheres.push({ column, operator: "is", value: null, boolean: "and" });
|
|
399
|
+
return this;
|
|
400
|
+
}
|
|
401
|
+
whereNotNull(column) {
|
|
402
|
+
this._wheres.push({ column, operator: "is not", value: null, boolean: "and" });
|
|
403
|
+
return this;
|
|
404
|
+
}
|
|
405
|
+
whereLike(column, pattern) {
|
|
406
|
+
this._wheres.push({ column, operator: "like", value: pattern, boolean: "and" });
|
|
407
|
+
return this;
|
|
408
|
+
}
|
|
409
|
+
orderBy(column, direction = "asc") {
|
|
410
|
+
this._orderBy.push({ column, direction });
|
|
411
|
+
return this;
|
|
412
|
+
}
|
|
413
|
+
orderByDesc(column) {
|
|
414
|
+
return this.orderBy(column, "desc");
|
|
415
|
+
}
|
|
416
|
+
orderByAsc(column) {
|
|
417
|
+
return this.orderBy(column, "asc");
|
|
418
|
+
}
|
|
419
|
+
limit(count) {
|
|
420
|
+
this._limit = count;
|
|
421
|
+
return this;
|
|
422
|
+
}
|
|
423
|
+
take(count) {
|
|
424
|
+
return this.limit(count);
|
|
425
|
+
}
|
|
426
|
+
offset(count) {
|
|
427
|
+
this._offset = count;
|
|
428
|
+
return this;
|
|
429
|
+
}
|
|
430
|
+
skip(count) {
|
|
431
|
+
return this.offset(count);
|
|
432
|
+
}
|
|
433
|
+
select(...columns) {
|
|
434
|
+
this._select = columns;
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
437
|
+
with(...relations) {
|
|
438
|
+
this._withRelations.push(...relations);
|
|
439
|
+
return this;
|
|
440
|
+
}
|
|
441
|
+
latest(column = "created_at") {
|
|
442
|
+
return this.orderByDesc(column);
|
|
443
|
+
}
|
|
444
|
+
oldest(column = "created_at") {
|
|
445
|
+
return this.orderByAsc(column);
|
|
446
|
+
}
|
|
447
|
+
buildQueryParams() {
|
|
448
|
+
const params = new URLSearchParams;
|
|
449
|
+
for (const where of this._wheres) {
|
|
450
|
+
if (where.operator === "=") {
|
|
451
|
+
params.append(where.column, String(where.value));
|
|
452
|
+
} else if ((where.operator === "in" || where.operator === "not in") && Array.isArray(where.value)) {
|
|
453
|
+
params.append(`${where.column}[]`, where.value.join(","));
|
|
454
|
+
} else if (where.operator === "is" && where.value === null) {
|
|
455
|
+
params.append(`filter[${where.column}][is]`, "null");
|
|
456
|
+
} else if (where.operator === "is not" && where.value === null) {
|
|
457
|
+
params.append(`filter[${where.column}][is_not]`, "null");
|
|
458
|
+
} else {
|
|
459
|
+
params.append(`filter[${where.column}][${where.operator}]`, String(where.value));
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (this._orderBy.length > 0) {
|
|
463
|
+
const orderStr = this._orderBy.map((o) => `${o.direction === "desc" ? "-" : ""}${o.column}`).join(",");
|
|
464
|
+
params.append("sort", orderStr);
|
|
465
|
+
}
|
|
466
|
+
if (this._limit !== undefined)
|
|
467
|
+
params.append("limit", String(this._limit));
|
|
468
|
+
if (this._offset !== undefined)
|
|
469
|
+
params.append("offset", String(this._offset));
|
|
470
|
+
if (this._select.length > 0 && !this._select.includes("*")) {
|
|
471
|
+
params.append("fields", this._select.join(","));
|
|
472
|
+
}
|
|
473
|
+
if (this._withRelations.length > 0) {
|
|
474
|
+
params.append("include", this._withRelations.join(","));
|
|
475
|
+
}
|
|
476
|
+
return params;
|
|
477
|
+
}
|
|
478
|
+
buildUrl(path) {
|
|
479
|
+
const base = `${browserConfig.baseUrl}/${this.getTablePath()}`;
|
|
480
|
+
if (path !== undefined)
|
|
481
|
+
return `${base}/${path}`;
|
|
482
|
+
const params = this.buildQueryParams();
|
|
483
|
+
const queryString = params.toString();
|
|
484
|
+
return queryString ? `${base}?${queryString}` : base;
|
|
485
|
+
}
|
|
486
|
+
async get() {
|
|
487
|
+
const url = this.buildUrl();
|
|
488
|
+
const response = await fetch(url, {
|
|
489
|
+
method: "GET",
|
|
490
|
+
headers: await buildHeaders()
|
|
491
|
+
});
|
|
492
|
+
const result = await handleResponse(response);
|
|
493
|
+
const rows = Array.isArray(result) ? result : result.data;
|
|
494
|
+
return rows.map((row) => new BrowserModelInstance(this._definition, row));
|
|
495
|
+
}
|
|
496
|
+
async first() {
|
|
497
|
+
this._limit = 1;
|
|
498
|
+
const results = await this.get();
|
|
499
|
+
return results[0] ?? null;
|
|
500
|
+
}
|
|
501
|
+
async firstOrFail() {
|
|
502
|
+
const result = await this.first();
|
|
503
|
+
if (!result)
|
|
504
|
+
throw new BrowserQueryError(`No ${this._definition.name} found`, 404);
|
|
505
|
+
return result;
|
|
506
|
+
}
|
|
507
|
+
async find(id) {
|
|
508
|
+
const url = this.buildUrl(id);
|
|
509
|
+
try {
|
|
510
|
+
const response = await fetch(url, {
|
|
511
|
+
method: "GET",
|
|
512
|
+
headers: await buildHeaders()
|
|
513
|
+
});
|
|
514
|
+
if (response.status === 404)
|
|
515
|
+
return null;
|
|
516
|
+
const result = await handleResponse(response);
|
|
517
|
+
const row = "data" in result && !Array.isArray(result.data) ? result.data : result;
|
|
518
|
+
return new BrowserModelInstance(this._definition, row);
|
|
519
|
+
} catch {
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
async findOrFail(id) {
|
|
524
|
+
const result = await this.find(id);
|
|
525
|
+
if (!result)
|
|
526
|
+
throw new BrowserQueryError(`${this._definition.name} with id ${id} not found`, 404);
|
|
527
|
+
return result;
|
|
528
|
+
}
|
|
529
|
+
async count() {
|
|
530
|
+
const params = this.buildQueryParams();
|
|
531
|
+
params.append("count", "true");
|
|
532
|
+
const url = `${browserConfig.baseUrl}/${this.getTablePath()}?${params.toString()}`;
|
|
533
|
+
const response = await fetch(url, {
|
|
534
|
+
method: "GET",
|
|
535
|
+
headers: await buildHeaders()
|
|
536
|
+
});
|
|
537
|
+
const result = await handleResponse(response);
|
|
538
|
+
return result.count;
|
|
539
|
+
}
|
|
540
|
+
async exists() {
|
|
541
|
+
const count = await this.count();
|
|
542
|
+
return count > 0;
|
|
543
|
+
}
|
|
544
|
+
async pluck(column) {
|
|
545
|
+
this._select = [column];
|
|
546
|
+
const results = await this.get();
|
|
547
|
+
return results.map((r) => r.get(column));
|
|
548
|
+
}
|
|
549
|
+
async paginate(page = 1, perPage = 15) {
|
|
550
|
+
this._limit = perPage;
|
|
551
|
+
this._offset = (page - 1) * perPage;
|
|
552
|
+
const params = this.buildQueryParams();
|
|
553
|
+
params.append("paginate", "true");
|
|
554
|
+
const url = `${browserConfig.baseUrl}/${this.getTablePath()}?${params.toString()}`;
|
|
555
|
+
const response = await fetch(url, {
|
|
556
|
+
method: "GET",
|
|
557
|
+
headers: await buildHeaders()
|
|
558
|
+
});
|
|
559
|
+
const result = await handleResponse(response);
|
|
560
|
+
return {
|
|
561
|
+
...result,
|
|
562
|
+
data: result.data.map((row) => new BrowserModelInstance(this._definition, row))
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function createBrowserModel(definition) {
|
|
567
|
+
const model = {
|
|
568
|
+
query: () => new BrowserModelQueryBuilder(definition),
|
|
569
|
+
where(column, operatorOrValue, value) {
|
|
570
|
+
return new BrowserModelQueryBuilder(definition).where(column, operatorOrValue, value);
|
|
571
|
+
},
|
|
572
|
+
orWhere(column, operatorOrValue, value) {
|
|
573
|
+
return new BrowserModelQueryBuilder(definition).orWhere(column, operatorOrValue, value);
|
|
574
|
+
},
|
|
575
|
+
whereIn(column, values) {
|
|
576
|
+
return new BrowserModelQueryBuilder(definition).whereIn(column, values);
|
|
577
|
+
},
|
|
578
|
+
whereNotIn(column, values) {
|
|
579
|
+
return new BrowserModelQueryBuilder(definition).whereNotIn(column, values);
|
|
580
|
+
},
|
|
581
|
+
whereNull(column) {
|
|
582
|
+
return new BrowserModelQueryBuilder(definition).whereNull(column);
|
|
583
|
+
},
|
|
584
|
+
whereNotNull(column) {
|
|
585
|
+
return new BrowserModelQueryBuilder(definition).whereNotNull(column);
|
|
586
|
+
},
|
|
587
|
+
whereLike(column, pattern) {
|
|
588
|
+
return new BrowserModelQueryBuilder(definition).whereLike(column, pattern);
|
|
589
|
+
},
|
|
590
|
+
orderBy(column, direction = "asc") {
|
|
591
|
+
return new BrowserModelQueryBuilder(definition).orderBy(column, direction);
|
|
592
|
+
},
|
|
593
|
+
orderByDesc(column) {
|
|
594
|
+
return new BrowserModelQueryBuilder(definition).orderByDesc(column);
|
|
595
|
+
},
|
|
596
|
+
select(...columns) {
|
|
597
|
+
return new BrowserModelQueryBuilder(definition).select(...columns);
|
|
598
|
+
},
|
|
599
|
+
limit: (count) => new BrowserModelQueryBuilder(definition).limit(count),
|
|
600
|
+
take: (count) => new BrowserModelQueryBuilder(definition).take(count),
|
|
601
|
+
skip: (count) => new BrowserModelQueryBuilder(definition).skip(count),
|
|
602
|
+
latest: (column = "created_at") => new BrowserModelQueryBuilder(definition).latest(column),
|
|
603
|
+
oldest: (column = "created_at") => new BrowserModelQueryBuilder(definition).oldest(column),
|
|
604
|
+
async find(id) {
|
|
605
|
+
return new BrowserModelQueryBuilder(definition).find(id);
|
|
606
|
+
},
|
|
607
|
+
async findOrFail(id) {
|
|
608
|
+
return new BrowserModelQueryBuilder(definition).findOrFail(id);
|
|
609
|
+
},
|
|
610
|
+
async all() {
|
|
611
|
+
return new BrowserModelQueryBuilder(definition).get();
|
|
612
|
+
},
|
|
613
|
+
async first() {
|
|
614
|
+
return new BrowserModelQueryBuilder(definition).first();
|
|
615
|
+
},
|
|
616
|
+
async firstOrFail() {
|
|
617
|
+
return new BrowserModelQueryBuilder(definition).firstOrFail();
|
|
618
|
+
},
|
|
619
|
+
async count() {
|
|
620
|
+
return new BrowserModelQueryBuilder(definition).count();
|
|
621
|
+
},
|
|
622
|
+
async exists() {
|
|
623
|
+
return new BrowserModelQueryBuilder(definition).exists();
|
|
624
|
+
},
|
|
625
|
+
async paginate(page, perPage) {
|
|
626
|
+
return new BrowserModelQueryBuilder(definition).paginate(page, perPage);
|
|
627
|
+
},
|
|
628
|
+
async pluck(column) {
|
|
629
|
+
return new BrowserModelQueryBuilder(definition).pluck(column);
|
|
630
|
+
},
|
|
631
|
+
async create(data) {
|
|
632
|
+
const tablePath = definition.traits?.useApi?.uri || definition.table;
|
|
633
|
+
const url = `${browserConfig.baseUrl}/${tablePath}`;
|
|
634
|
+
const body = browserConfig.transformRequest ? browserConfig.transformRequest(data) : data;
|
|
635
|
+
const response = await fetch(url, {
|
|
636
|
+
method: "POST",
|
|
637
|
+
headers: await buildHeaders(),
|
|
638
|
+
body: JSON.stringify(body)
|
|
639
|
+
});
|
|
640
|
+
const result = await handleResponse(response);
|
|
641
|
+
const row = "data" in result && !Array.isArray(result.data) ? result.data : result;
|
|
642
|
+
return new BrowserModelInstance(definition, row);
|
|
643
|
+
},
|
|
644
|
+
async update(id, data) {
|
|
645
|
+
const tablePath = definition.traits?.useApi?.uri || definition.table;
|
|
646
|
+
const url = `${browserConfig.baseUrl}/${tablePath}/${id}`;
|
|
647
|
+
const body = browserConfig.transformRequest ? browserConfig.transformRequest(data) : data;
|
|
648
|
+
const response = await fetch(url, {
|
|
649
|
+
method: "PATCH",
|
|
650
|
+
headers: await buildHeaders(),
|
|
651
|
+
body: JSON.stringify(body)
|
|
652
|
+
});
|
|
653
|
+
const result = await handleResponse(response);
|
|
654
|
+
const row = "data" in result && !Array.isArray(result.data) ? result.data : result;
|
|
655
|
+
return new BrowserModelInstance(definition, row);
|
|
656
|
+
},
|
|
657
|
+
async delete(id) {
|
|
658
|
+
const tablePath = definition.traits?.useApi?.uri || definition.table;
|
|
659
|
+
const url = `${browserConfig.baseUrl}/${tablePath}/${id}`;
|
|
660
|
+
const response = await fetch(url, {
|
|
661
|
+
method: "DELETE",
|
|
662
|
+
headers: await buildHeaders()
|
|
663
|
+
});
|
|
664
|
+
return response.ok;
|
|
665
|
+
},
|
|
666
|
+
async destroy(id) {
|
|
667
|
+
return this.delete(id);
|
|
668
|
+
},
|
|
669
|
+
getDefinition: () => definition,
|
|
670
|
+
getTable: () => definition.table
|
|
671
|
+
};
|
|
672
|
+
return new Proxy(model, {
|
|
673
|
+
get(target, prop) {
|
|
674
|
+
if (typeof prop === "string" && prop.startsWith("where") && prop.length > 5) {
|
|
675
|
+
const columnPascal = prop.slice(5);
|
|
676
|
+
const column = columnPascal.charAt(0).toLowerCase() + columnPascal.slice(1);
|
|
677
|
+
if (column in definition.attributes || column === "id" || column === definition.primaryKey) {
|
|
678
|
+
return (value) => new BrowserModelQueryBuilder(definition).where(column, value);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return Reflect.get(target, prop);
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
var browserConfig, BrowserQueryError, browserAuth, browser_default;
|
|
686
|
+
var init_browser = __esm(() => {
|
|
687
|
+
browserConfig = {
|
|
688
|
+
baseUrl: ""
|
|
689
|
+
};
|
|
690
|
+
BrowserQueryError = class BrowserQueryError extends Error {
|
|
691
|
+
status;
|
|
692
|
+
constructor(message, status) {
|
|
693
|
+
super(message);
|
|
694
|
+
this.name = "BrowserQueryError";
|
|
695
|
+
this.status = status;
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
browserAuth = {
|
|
699
|
+
async login(credentials) {
|
|
700
|
+
const response = await fetch(`${browserConfig.baseUrl}/login`, {
|
|
701
|
+
method: "POST",
|
|
702
|
+
headers: {
|
|
703
|
+
"Content-Type": "application/json",
|
|
704
|
+
Accept: "application/json",
|
|
705
|
+
...browserConfig.headers
|
|
706
|
+
},
|
|
707
|
+
body: JSON.stringify(credentials)
|
|
708
|
+
});
|
|
709
|
+
if (!response.ok) {
|
|
710
|
+
const error = await response.json().catch(() => ({ message: "Login failed" }));
|
|
711
|
+
throw new BrowserQueryError(error.message || "Login failed", response.status);
|
|
712
|
+
}
|
|
713
|
+
const rawData = await response.json();
|
|
714
|
+
const data = rawData.data || rawData;
|
|
715
|
+
if (typeof localStorage !== "undefined" && data.token) {
|
|
716
|
+
localStorage.setItem("auth_token", data.token);
|
|
717
|
+
}
|
|
718
|
+
return data;
|
|
719
|
+
},
|
|
720
|
+
async register(data) {
|
|
721
|
+
const response = await fetch(`${browserConfig.baseUrl}/register`, {
|
|
722
|
+
method: "POST",
|
|
723
|
+
headers: {
|
|
724
|
+
"Content-Type": "application/json",
|
|
725
|
+
Accept: "application/json",
|
|
726
|
+
...browserConfig.headers
|
|
727
|
+
},
|
|
728
|
+
body: JSON.stringify(data)
|
|
729
|
+
});
|
|
730
|
+
if (!response.ok) {
|
|
731
|
+
const error = await response.json().catch(() => ({ message: "Registration failed" }));
|
|
732
|
+
throw new BrowserQueryError(error.message || "Registration failed", response.status);
|
|
733
|
+
}
|
|
734
|
+
const rawResult = await response.json();
|
|
735
|
+
const result = rawResult.data || rawResult;
|
|
736
|
+
if (typeof localStorage !== "undefined" && result.token) {
|
|
737
|
+
localStorage.setItem("auth_token", result.token);
|
|
738
|
+
}
|
|
739
|
+
return result;
|
|
740
|
+
},
|
|
741
|
+
async logout() {
|
|
742
|
+
const token = await getAuthToken();
|
|
743
|
+
if (token) {
|
|
744
|
+
try {
|
|
745
|
+
await fetch(`${browserConfig.baseUrl}/logout`, {
|
|
746
|
+
method: "POST",
|
|
747
|
+
headers: await buildHeaders()
|
|
748
|
+
});
|
|
749
|
+
} catch {}
|
|
750
|
+
}
|
|
751
|
+
if (typeof localStorage !== "undefined") {
|
|
752
|
+
localStorage.removeItem("auth_token");
|
|
753
|
+
}
|
|
754
|
+
},
|
|
755
|
+
async user() {
|
|
756
|
+
const token = await getAuthToken();
|
|
757
|
+
if (!token)
|
|
758
|
+
return null;
|
|
759
|
+
try {
|
|
760
|
+
const response = await fetch(`${browserConfig.baseUrl}/user`, {
|
|
761
|
+
method: "GET",
|
|
762
|
+
headers: await buildHeaders()
|
|
763
|
+
});
|
|
764
|
+
if (response.status === 401) {
|
|
765
|
+
browserConfig.onUnauthorized?.();
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
if (!response.ok)
|
|
769
|
+
return null;
|
|
770
|
+
const data = await response.json();
|
|
771
|
+
return data.user || data;
|
|
772
|
+
} catch {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
},
|
|
776
|
+
async check() {
|
|
777
|
+
const user = await this.user();
|
|
778
|
+
return user !== null;
|
|
779
|
+
},
|
|
780
|
+
getToken: getAuthToken
|
|
781
|
+
};
|
|
782
|
+
browser_default = browserQuery;
|
|
783
|
+
});
|
|
784
|
+
init_browser();
|
|
785
|
+
|
|
786
|
+
export {
|
|
787
|
+
isBrowser,
|
|
788
|
+
getBrowserConfig,
|
|
789
|
+
browser_default as default,
|
|
790
|
+
createBrowserModel,
|
|
791
|
+
createBrowserDb,
|
|
792
|
+
configureBrowser,
|
|
793
|
+
browserQuery,
|
|
794
|
+
browserAuth,
|
|
795
|
+
BrowserQueryError,
|
|
796
|
+
BrowserQueryBuilder
|
|
797
|
+
};
|