aurabase-js 0.2.0 → 0.2.1
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 +3 -3
- package/.omc/state/hud-stdin-cache.json +1 -1
- package/README.md +70 -2
- package/dist/cli.js +127 -115
- package/dist/index.js +116 -75
- package/dist/index.mjs +111 -81
- package/package.json +6 -5
- package/src/AuraBaseClient.ts +6 -16
- package/src/QueryBuilder.ts +122 -161
- package/src/cli.ts +116 -97
- package/dist/cli.d.mts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +0 -109
- package/lib/aurabase.ts +0 -9
package/dist/index.js
CHANGED
|
@@ -30,6 +30,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
30
30
|
var QueryBuilder = class {
|
|
31
31
|
constructor(url, anonKey, accessToken, tableName, headers = {}) {
|
|
32
32
|
this.isSingle = false;
|
|
33
|
+
this._method = "GET";
|
|
34
|
+
this._body = void 0;
|
|
35
|
+
this._isUpsert = false;
|
|
36
|
+
this._onConflict = void 0;
|
|
37
|
+
this._idValue = void 0;
|
|
33
38
|
this.url = url;
|
|
34
39
|
this.anonKey = anonKey;
|
|
35
40
|
this.accessToken = accessToken;
|
|
@@ -44,94 +49,119 @@ var QueryBuilder = class {
|
|
|
44
49
|
* .select('*')
|
|
45
50
|
*/
|
|
46
51
|
select(columns = "*") {
|
|
47
|
-
this.queryParams.set("select", columns);
|
|
52
|
+
if (columns !== "*") this.queryParams.set("select", columns.replace(/\s/g, ""));
|
|
48
53
|
return this;
|
|
49
54
|
}
|
|
50
|
-
/**
|
|
51
|
-
* Filter by column equality
|
|
52
|
-
* @example
|
|
53
|
-
* .eq('id', 1)
|
|
54
|
-
* .eq('status', 'active')
|
|
55
|
-
*/
|
|
56
55
|
eq(column, value) {
|
|
57
|
-
|
|
56
|
+
if (column === "id") this._idValue = value;
|
|
57
|
+
this.queryParams.append("eq", `${column}:${value}`);
|
|
58
58
|
return this;
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Filter by column inequality
|
|
62
62
|
*/
|
|
63
63
|
neq(column, value) {
|
|
64
|
-
this.queryParams.append(
|
|
64
|
+
this.queryParams.append("neq", `${column}:${value}`);
|
|
65
65
|
return this;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* Filter by greater than
|
|
69
69
|
*/
|
|
70
70
|
gt(column, value) {
|
|
71
|
-
this.queryParams.append(
|
|
71
|
+
this.queryParams.append("gt", `${column}:${value}`);
|
|
72
72
|
return this;
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
75
|
* Filter by greater than or equal
|
|
76
76
|
*/
|
|
77
77
|
gte(column, value) {
|
|
78
|
-
this.queryParams.append(
|
|
78
|
+
this.queryParams.append("gte", `${column}:${value}`);
|
|
79
79
|
return this;
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Filter by less than
|
|
83
83
|
*/
|
|
84
84
|
lt(column, value) {
|
|
85
|
-
this.queryParams.append(
|
|
85
|
+
this.queryParams.append("lt", `${column}:${value}`);
|
|
86
86
|
return this;
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
89
|
* Filter by less than or equal
|
|
90
90
|
*/
|
|
91
91
|
lte(column, value) {
|
|
92
|
-
this.queryParams.append(
|
|
92
|
+
this.queryParams.append("lte", `${column}:${value}`);
|
|
93
93
|
return this;
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
96
96
|
* Filter by like pattern
|
|
97
97
|
*/
|
|
98
98
|
like(column, pattern) {
|
|
99
|
-
this.queryParams.append(
|
|
99
|
+
this.queryParams.append("like", `${column}:${pattern}`);
|
|
100
100
|
return this;
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Filter by case-insensitive like pattern
|
|
104
104
|
*/
|
|
105
105
|
ilike(column, pattern) {
|
|
106
|
-
this.queryParams.append(
|
|
106
|
+
this.queryParams.append("ilike", `${column}:${pattern}`);
|
|
107
107
|
return this;
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
110
|
* Filter by array contains
|
|
111
111
|
*/
|
|
112
112
|
contains(column, value) {
|
|
113
|
-
this.queryParams.append(
|
|
113
|
+
this.queryParams.append("contains", `${column}:${JSON.stringify(value)}`);
|
|
114
114
|
return this;
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
117
117
|
* Filter by value in array
|
|
118
118
|
*/
|
|
119
119
|
in(column, values) {
|
|
120
|
-
this.queryParams.append(
|
|
120
|
+
this.queryParams.append("in", `${column}:${values.join(",")}`);
|
|
121
121
|
return this;
|
|
122
122
|
}
|
|
123
123
|
/**
|
|
124
124
|
* Filter for null values
|
|
125
125
|
*/
|
|
126
126
|
isNull(column) {
|
|
127
|
-
this.queryParams.append(
|
|
127
|
+
this.queryParams.append("is_null", `${column}:true`);
|
|
128
128
|
return this;
|
|
129
129
|
}
|
|
130
130
|
/**
|
|
131
131
|
* Filter for non-null values
|
|
132
132
|
*/
|
|
133
133
|
isNotNull(column) {
|
|
134
|
-
this.queryParams.append(
|
|
134
|
+
this.queryParams.append("is_null", `${column}:false`);
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Full-text search across all columns
|
|
139
|
+
*/
|
|
140
|
+
search(query) {
|
|
141
|
+
this.queryParams.set("search", query);
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Negate a filter
|
|
146
|
+
* @example .not('eq', 'category', 'Electronics')
|
|
147
|
+
*/
|
|
148
|
+
not(operator, column, value) {
|
|
149
|
+
this.queryParams.append("not", `${operator}:${column}:${value}`);
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* OR conditions
|
|
154
|
+
* @example .or('category.eq.Electronics,price.lt.100000')
|
|
155
|
+
*/
|
|
156
|
+
or(conditions) {
|
|
157
|
+
this.queryParams.set("or", conditions);
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Filter by array contained by
|
|
162
|
+
*/
|
|
163
|
+
containedBy(column, value) {
|
|
164
|
+
this.queryParams.append("contained_by", `${column}:${JSON.stringify(value)}`);
|
|
135
165
|
return this;
|
|
136
166
|
}
|
|
137
167
|
/**
|
|
@@ -146,7 +176,8 @@ var QueryBuilder = class {
|
|
|
146
176
|
if (nullsFirst !== void 0) {
|
|
147
177
|
orderStr += nullsFirst ? ".nullsfirst" : ".nullslast";
|
|
148
178
|
}
|
|
149
|
-
this.queryParams.
|
|
179
|
+
const existing = this.queryParams.get("order");
|
|
180
|
+
this.queryParams.set("order", existing ? `${existing},${orderStr}` : orderStr);
|
|
150
181
|
return this;
|
|
151
182
|
}
|
|
152
183
|
/**
|
|
@@ -194,28 +225,36 @@ var QueryBuilder = class {
|
|
|
194
225
|
...this.headers
|
|
195
226
|
};
|
|
196
227
|
}
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
228
|
+
buildUrl() {
|
|
229
|
+
const qs = this.queryParams.toString();
|
|
230
|
+
if (this._isUpsert) {
|
|
231
|
+
const conflict = this._onConflict ? `?on_conflict=${this._onConflict}` : "";
|
|
232
|
+
return `${this.url}/api/${this.tableName}/upsert${conflict}`;
|
|
233
|
+
}
|
|
234
|
+
if ((this._method === "PATCH" || this._method === "DELETE") && this._idValue !== void 0) {
|
|
235
|
+
return `${this.url}/api/${this.tableName}/${this._idValue}/`;
|
|
236
|
+
}
|
|
237
|
+
return `${this.url}/api/${this.tableName}/${qs ? `?${qs}` : ""}`;
|
|
238
|
+
}
|
|
239
|
+
async execute() {
|
|
240
|
+
const fullUrl = this.buildUrl();
|
|
241
|
+
const reqHeaders = this.getHeaders();
|
|
242
|
+
const options = { method: this._method, headers: reqHeaders };
|
|
243
|
+
if (this._body !== void 0 && this._method !== "GET") {
|
|
244
|
+
options.body = JSON.stringify(this._body);
|
|
245
|
+
reqHeaders["Prefer"] = "return=representation";
|
|
207
246
|
}
|
|
208
247
|
try {
|
|
209
248
|
const response = await fetch(fullUrl, options);
|
|
249
|
+
const text = await response.text();
|
|
210
250
|
let data = null;
|
|
211
251
|
let error = null;
|
|
212
|
-
const text = await response.text();
|
|
213
252
|
if (text) {
|
|
214
253
|
try {
|
|
215
254
|
const parsed = JSON.parse(text);
|
|
216
255
|
if (!response.ok) {
|
|
217
256
|
error = {
|
|
218
|
-
message: parsed.message || parsed.error || `HTTP ${response.status}`,
|
|
257
|
+
message: parsed.message || parsed.error || parsed.detail || `HTTP ${response.status}`,
|
|
219
258
|
code: parsed.code,
|
|
220
259
|
details: parsed.details
|
|
221
260
|
};
|
|
@@ -223,69 +262,54 @@ var QueryBuilder = class {
|
|
|
223
262
|
data = this.isSingle && Array.isArray(parsed) ? parsed[0] ?? null : parsed;
|
|
224
263
|
}
|
|
225
264
|
} catch {
|
|
226
|
-
if (!response.ok) {
|
|
227
|
-
error = {
|
|
228
|
-
message: text || `HTTP ${response.status}`
|
|
229
|
-
};
|
|
230
|
-
}
|
|
265
|
+
if (!response.ok) error = { message: text || `HTTP ${response.status}` };
|
|
231
266
|
}
|
|
232
267
|
}
|
|
233
|
-
return {
|
|
234
|
-
data,
|
|
235
|
-
error,
|
|
236
|
-
status: response.status,
|
|
237
|
-
statusText: response.statusText
|
|
238
|
-
};
|
|
268
|
+
return { data, error, status: response.status, statusText: response.statusText };
|
|
239
269
|
} catch (err) {
|
|
240
270
|
return {
|
|
241
271
|
data: null,
|
|
242
|
-
error: {
|
|
243
|
-
message: err instanceof Error ? err.message : "Network error"
|
|
244
|
-
},
|
|
272
|
+
error: { message: err instanceof Error ? err.message : "Network error" },
|
|
245
273
|
status: 0,
|
|
246
274
|
statusText: "Network Error"
|
|
247
275
|
};
|
|
248
276
|
}
|
|
249
277
|
}
|
|
250
|
-
/**
|
|
251
|
-
* Execute SELECT query
|
|
252
|
-
*/
|
|
253
278
|
async then(resolve, reject) {
|
|
254
279
|
try {
|
|
255
|
-
const result = await this.
|
|
280
|
+
const result = await this.execute();
|
|
256
281
|
await resolve(result);
|
|
257
282
|
} catch (err) {
|
|
258
|
-
if (reject)
|
|
259
|
-
await reject(err);
|
|
260
|
-
}
|
|
283
|
+
if (reject) await reject(err);
|
|
261
284
|
}
|
|
262
285
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
286
|
+
// CUD — 모두 this 반환 → Supabase 스타일 체이닝 지원
|
|
287
|
+
// .insert({ title: '할일' })
|
|
288
|
+
insert(row) {
|
|
289
|
+
this._method = "POST";
|
|
267
290
|
const rows = Array.isArray(row) ? row : [row];
|
|
268
|
-
|
|
291
|
+
this._body = rows.length === 1 ? rows[0] : rows;
|
|
292
|
+
return this;
|
|
269
293
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
return this
|
|
294
|
+
// .update({ completed: true }).eq('id', 1)
|
|
295
|
+
update(data) {
|
|
296
|
+
this._method = "PATCH";
|
|
297
|
+
this._body = data;
|
|
298
|
+
return this;
|
|
275
299
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
300
|
+
// .upsert({ id: 1, title: '수정됨' }, { onConflict: 'id' })
|
|
301
|
+
upsert(row, options = {}) {
|
|
302
|
+
this._method = "POST";
|
|
303
|
+
this._isUpsert = true;
|
|
304
|
+
this._onConflict = options.onConflict;
|
|
280
305
|
const rows = Array.isArray(row) ? row : [row];
|
|
281
|
-
this.
|
|
282
|
-
return this
|
|
306
|
+
this._body = rows.length === 1 ? rows[0] : rows;
|
|
307
|
+
return this;
|
|
283
308
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
return this.request("DELETE");
|
|
309
|
+
// .delete().eq('id', 1)
|
|
310
|
+
delete() {
|
|
311
|
+
this._method = "DELETE";
|
|
312
|
+
return this;
|
|
289
313
|
}
|
|
290
314
|
};
|
|
291
315
|
|
|
@@ -585,7 +609,7 @@ var AuraBaseClient = class {
|
|
|
585
609
|
async rpc(functionName, params) {
|
|
586
610
|
const token = this.accessToken || this.anonKey;
|
|
587
611
|
try {
|
|
588
|
-
const response = await fetch(`${this.url}/
|
|
612
|
+
const response = await fetch(`${this.url}/api/${functionName}/`, {
|
|
589
613
|
method: "POST",
|
|
590
614
|
headers: {
|
|
591
615
|
"Content-Type": "application/json",
|
|
@@ -759,6 +783,23 @@ var StorageBucket = class {
|
|
|
759
783
|
|
|
760
784
|
// src/index.ts
|
|
761
785
|
function createClient(options) {
|
|
786
|
+
if (!options.url) {
|
|
787
|
+
console.warn(
|
|
788
|
+
"[aurabase-js] NEXT_PUBLIC_AURABASE_URL이 설정되지 않았습니다.\n" +
|
|
789
|
+
".env.local 파일에 다음 항목을 추가하세요:\n\n" +
|
|
790
|
+
" NEXT_PUBLIC_AURABASE_URL=https://your-project.cloudfront.net\n" +
|
|
791
|
+
" NEXT_PUBLIC_AURABASE_ANON_KEY=your-anon-key\n" +
|
|
792
|
+
" NEXT_PUBLIC_AURABASE_SERVICE_ROLE_KEY=your-service-role-key\n"
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
if (!options.anonKey) {
|
|
796
|
+
console.warn(
|
|
797
|
+
"[aurabase-js] anonKey가 설정되지 않았습니다.\n" +
|
|
798
|
+
".env.local 파일에 다음 항목을 추가하세요:\n\n" +
|
|
799
|
+
" NEXT_PUBLIC_AURABASE_ANON_KEY=your-anon-key (클라이언트용)\n" +
|
|
800
|
+
" NEXT_PUBLIC_AURABASE_SERVICE_ROLE_KEY=your-service-role-key (서버/admin용)\n"
|
|
801
|
+
);
|
|
802
|
+
}
|
|
762
803
|
return new AuraBaseClient(options);
|
|
763
804
|
}
|
|
764
805
|
var index_default = createClient;
|
package/dist/index.mjs
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
var QueryBuilder = class {
|
|
3
3
|
constructor(url, anonKey, accessToken, tableName, headers = {}) {
|
|
4
4
|
this.isSingle = false;
|
|
5
|
+
this._method = "GET";
|
|
6
|
+
this._body = void 0;
|
|
7
|
+
this._isUpsert = false;
|
|
8
|
+
this._onConflict = void 0;
|
|
9
|
+
this._idValue = void 0;
|
|
5
10
|
this.url = url;
|
|
6
11
|
this.anonKey = anonKey;
|
|
7
12
|
this.accessToken = accessToken;
|
|
@@ -9,101 +14,120 @@ var QueryBuilder = class {
|
|
|
9
14
|
this.queryParams = new URLSearchParams();
|
|
10
15
|
this.headers = { ...headers };
|
|
11
16
|
}
|
|
12
|
-
/**
|
|
13
|
-
* Select columns
|
|
14
|
-
* @example
|
|
15
|
-
* .select('id, name, email')
|
|
16
|
-
* .select('*')
|
|
17
|
-
*/
|
|
18
17
|
select(columns = "*") {
|
|
19
|
-
this.queryParams.set("select", columns);
|
|
18
|
+
if (columns !== "*") this.queryParams.set("select", columns.replace(/\s/g, ""));
|
|
20
19
|
return this;
|
|
21
20
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Filter by column equality
|
|
24
|
-
* @example
|
|
25
|
-
* .eq('id', 1)
|
|
26
|
-
* .eq('status', 'active')
|
|
27
|
-
*/
|
|
28
21
|
eq(column, value) {
|
|
29
|
-
|
|
22
|
+
if (column === "id") this._idValue = value;
|
|
23
|
+
this.queryParams.append("eq", `${column}:${value}`);
|
|
30
24
|
return this;
|
|
31
25
|
}
|
|
32
26
|
/**
|
|
33
27
|
* Filter by column inequality
|
|
34
28
|
*/
|
|
35
29
|
neq(column, value) {
|
|
36
|
-
this.queryParams.append(
|
|
30
|
+
this.queryParams.append("neq", `${column}:${value}`);
|
|
37
31
|
return this;
|
|
38
32
|
}
|
|
39
33
|
/**
|
|
40
34
|
* Filter by greater than
|
|
41
35
|
*/
|
|
42
36
|
gt(column, value) {
|
|
43
|
-
this.queryParams.append(
|
|
37
|
+
this.queryParams.append("gt", `${column}:${value}`);
|
|
44
38
|
return this;
|
|
45
39
|
}
|
|
46
40
|
/**
|
|
47
41
|
* Filter by greater than or equal
|
|
48
42
|
*/
|
|
49
43
|
gte(column, value) {
|
|
50
|
-
this.queryParams.append(
|
|
44
|
+
this.queryParams.append("gte", `${column}:${value}`);
|
|
51
45
|
return this;
|
|
52
46
|
}
|
|
53
47
|
/**
|
|
54
48
|
* Filter by less than
|
|
55
49
|
*/
|
|
56
50
|
lt(column, value) {
|
|
57
|
-
this.queryParams.append(
|
|
51
|
+
this.queryParams.append("lt", `${column}:${value}`);
|
|
58
52
|
return this;
|
|
59
53
|
}
|
|
60
54
|
/**
|
|
61
55
|
* Filter by less than or equal
|
|
62
56
|
*/
|
|
63
57
|
lte(column, value) {
|
|
64
|
-
this.queryParams.append(
|
|
58
|
+
this.queryParams.append("lte", `${column}:${value}`);
|
|
65
59
|
return this;
|
|
66
60
|
}
|
|
67
61
|
/**
|
|
68
62
|
* Filter by like pattern
|
|
69
63
|
*/
|
|
70
64
|
like(column, pattern) {
|
|
71
|
-
this.queryParams.append(
|
|
65
|
+
this.queryParams.append("like", `${column}:${pattern}`);
|
|
72
66
|
return this;
|
|
73
67
|
}
|
|
74
68
|
/**
|
|
75
69
|
* Filter by case-insensitive like pattern
|
|
76
70
|
*/
|
|
77
71
|
ilike(column, pattern) {
|
|
78
|
-
this.queryParams.append(
|
|
72
|
+
this.queryParams.append("ilike", `${column}:${pattern}`);
|
|
79
73
|
return this;
|
|
80
74
|
}
|
|
81
75
|
/**
|
|
82
76
|
* Filter by array contains
|
|
83
77
|
*/
|
|
84
78
|
contains(column, value) {
|
|
85
|
-
this.queryParams.append(
|
|
79
|
+
this.queryParams.append("contains", `${column}:${JSON.stringify(value)}`);
|
|
86
80
|
return this;
|
|
87
81
|
}
|
|
88
82
|
/**
|
|
89
83
|
* Filter by value in array
|
|
90
84
|
*/
|
|
91
85
|
in(column, values) {
|
|
92
|
-
this.queryParams.append(
|
|
86
|
+
this.queryParams.append("in", `${column}:${values.join(",")}`);
|
|
93
87
|
return this;
|
|
94
88
|
}
|
|
95
89
|
/**
|
|
96
90
|
* Filter for null values
|
|
97
91
|
*/
|
|
98
92
|
isNull(column) {
|
|
99
|
-
this.queryParams.append(
|
|
93
|
+
this.queryParams.append("is_null", `${column}:true`);
|
|
100
94
|
return this;
|
|
101
95
|
}
|
|
102
96
|
/**
|
|
103
97
|
* Filter for non-null values
|
|
104
98
|
*/
|
|
105
99
|
isNotNull(column) {
|
|
106
|
-
this.queryParams.append(
|
|
100
|
+
this.queryParams.append("is_null", `${column}:false`);
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Full-text search across all columns
|
|
105
|
+
*/
|
|
106
|
+
search(query) {
|
|
107
|
+
this.queryParams.set("search", query);
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Negate a filter
|
|
112
|
+
* @example .not('eq', 'category', 'Electronics')
|
|
113
|
+
*/
|
|
114
|
+
not(operator, column, value) {
|
|
115
|
+
this.queryParams.append("not", `${operator}:${column}:${value}`);
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* OR conditions
|
|
120
|
+
* @example .or('category.eq.Electronics,price.lt.100000')
|
|
121
|
+
*/
|
|
122
|
+
or(conditions) {
|
|
123
|
+
this.queryParams.set("or", conditions);
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Filter by array contained by
|
|
128
|
+
*/
|
|
129
|
+
containedBy(column, value) {
|
|
130
|
+
this.queryParams.append("contained_by", `${column}:${JSON.stringify(value)}`);
|
|
107
131
|
return this;
|
|
108
132
|
}
|
|
109
133
|
/**
|
|
@@ -118,7 +142,8 @@ var QueryBuilder = class {
|
|
|
118
142
|
if (nullsFirst !== void 0) {
|
|
119
143
|
orderStr += nullsFirst ? ".nullsfirst" : ".nullslast";
|
|
120
144
|
}
|
|
121
|
-
this.queryParams.
|
|
145
|
+
const existing = this.queryParams.get("order");
|
|
146
|
+
this.queryParams.set("order", existing ? `${existing},${orderStr}` : orderStr);
|
|
122
147
|
return this;
|
|
123
148
|
}
|
|
124
149
|
/**
|
|
@@ -166,28 +191,36 @@ var QueryBuilder = class {
|
|
|
166
191
|
...this.headers
|
|
167
192
|
};
|
|
168
193
|
}
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
194
|
+
buildUrl() {
|
|
195
|
+
const qs = this.queryParams.toString();
|
|
196
|
+
if (this._isUpsert) {
|
|
197
|
+
const conflict = this._onConflict ? `?on_conflict=${this._onConflict}` : "";
|
|
198
|
+
return `${this.url}/api/${this.tableName}/upsert${conflict}`;
|
|
199
|
+
}
|
|
200
|
+
if ((this._method === "PATCH" || this._method === "DELETE") && this._idValue !== void 0) {
|
|
201
|
+
return `${this.url}/api/${this.tableName}/${this._idValue}/`;
|
|
202
|
+
}
|
|
203
|
+
return `${this.url}/api/${this.tableName}/${qs ? `?${qs}` : ""}`;
|
|
204
|
+
}
|
|
205
|
+
async execute() {
|
|
206
|
+
const fullUrl = this.buildUrl();
|
|
207
|
+
const reqHeaders = this.getHeaders();
|
|
208
|
+
const options = { method: this._method, headers: reqHeaders };
|
|
209
|
+
if (this._body !== void 0 && this._method !== "GET") {
|
|
210
|
+
options.body = JSON.stringify(this._body);
|
|
211
|
+
reqHeaders["Prefer"] = "return=representation";
|
|
179
212
|
}
|
|
180
213
|
try {
|
|
181
214
|
const response = await fetch(fullUrl, options);
|
|
215
|
+
const text = await response.text();
|
|
182
216
|
let data = null;
|
|
183
217
|
let error = null;
|
|
184
|
-
const text = await response.text();
|
|
185
218
|
if (text) {
|
|
186
219
|
try {
|
|
187
220
|
const parsed = JSON.parse(text);
|
|
188
221
|
if (!response.ok) {
|
|
189
222
|
error = {
|
|
190
|
-
message: parsed.message || parsed.error || `HTTP ${response.status}`,
|
|
223
|
+
message: parsed.message || parsed.error || parsed.detail || `HTTP ${response.status}`,
|
|
191
224
|
code: parsed.code,
|
|
192
225
|
details: parsed.details
|
|
193
226
|
};
|
|
@@ -195,69 +228,49 @@ var QueryBuilder = class {
|
|
|
195
228
|
data = this.isSingle && Array.isArray(parsed) ? parsed[0] ?? null : parsed;
|
|
196
229
|
}
|
|
197
230
|
} catch {
|
|
198
|
-
if (!response.ok) {
|
|
199
|
-
error = {
|
|
200
|
-
message: text || `HTTP ${response.status}`
|
|
201
|
-
};
|
|
202
|
-
}
|
|
231
|
+
if (!response.ok) error = { message: text || `HTTP ${response.status}` };
|
|
203
232
|
}
|
|
204
233
|
}
|
|
205
|
-
return {
|
|
206
|
-
data,
|
|
207
|
-
error,
|
|
208
|
-
status: response.status,
|
|
209
|
-
statusText: response.statusText
|
|
210
|
-
};
|
|
234
|
+
return { data, error, status: response.status, statusText: response.statusText };
|
|
211
235
|
} catch (err) {
|
|
212
236
|
return {
|
|
213
237
|
data: null,
|
|
214
|
-
error: {
|
|
215
|
-
message: err instanceof Error ? err.message : "Network error"
|
|
216
|
-
},
|
|
238
|
+
error: { message: err instanceof Error ? err.message : "Network error" },
|
|
217
239
|
status: 0,
|
|
218
240
|
statusText: "Network Error"
|
|
219
241
|
};
|
|
220
242
|
}
|
|
221
243
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Execute SELECT query
|
|
224
|
-
*/
|
|
225
244
|
async then(resolve, reject) {
|
|
226
245
|
try {
|
|
227
|
-
const result = await this.
|
|
246
|
+
const result = await this.execute();
|
|
228
247
|
await resolve(result);
|
|
229
248
|
} catch (err) {
|
|
230
|
-
if (reject)
|
|
231
|
-
await reject(err);
|
|
232
|
-
}
|
|
249
|
+
if (reject) await reject(err);
|
|
233
250
|
}
|
|
234
251
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
*/
|
|
238
|
-
async insert(row) {
|
|
252
|
+
insert(row) {
|
|
253
|
+
this._method = "POST";
|
|
239
254
|
const rows = Array.isArray(row) ? row : [row];
|
|
240
|
-
|
|
255
|
+
this._body = rows.length === 1 ? rows[0] : rows;
|
|
256
|
+
return this;
|
|
241
257
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
return this.request("PATCH", data);
|
|
258
|
+
update(data) {
|
|
259
|
+
this._method = "PATCH";
|
|
260
|
+
this._body = data;
|
|
261
|
+
return this;
|
|
247
262
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
263
|
+
upsert(row, options = {}) {
|
|
264
|
+
this._method = "POST";
|
|
265
|
+
this._isUpsert = true;
|
|
266
|
+
this._onConflict = options.onConflict;
|
|
252
267
|
const rows = Array.isArray(row) ? row : [row];
|
|
253
|
-
this.
|
|
254
|
-
return this
|
|
268
|
+
this._body = rows.length === 1 ? rows[0] : rows;
|
|
269
|
+
return this;
|
|
255
270
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
async delete() {
|
|
260
|
-
return this.request("DELETE");
|
|
271
|
+
delete() {
|
|
272
|
+
this._method = "DELETE";
|
|
273
|
+
return this;
|
|
261
274
|
}
|
|
262
275
|
};
|
|
263
276
|
|
|
@@ -557,7 +570,7 @@ var AuraBaseClient = class {
|
|
|
557
570
|
async rpc(functionName, params) {
|
|
558
571
|
const token = this.accessToken || this.anonKey;
|
|
559
572
|
try {
|
|
560
|
-
const response = await fetch(`${this.url}/
|
|
573
|
+
const response = await fetch(`${this.url}/api/${functionName}/`, {
|
|
561
574
|
method: "POST",
|
|
562
575
|
headers: {
|
|
563
576
|
"Content-Type": "application/json",
|
|
@@ -731,6 +744,23 @@ var StorageBucket = class {
|
|
|
731
744
|
|
|
732
745
|
// src/index.ts
|
|
733
746
|
function createClient(options) {
|
|
747
|
+
if (!options.url) {
|
|
748
|
+
console.warn(
|
|
749
|
+
"[aurabase-js] NEXT_PUBLIC_AURABASE_URL이 설정되지 않았습니다.\n" +
|
|
750
|
+
".env.local 파일에 다음 항목을 추가하세요:\n\n" +
|
|
751
|
+
" NEXT_PUBLIC_AURABASE_URL=https://your-project.cloudfront.net\n" +
|
|
752
|
+
" NEXT_PUBLIC_AURABASE_ANON_KEY=your-anon-key\n" +
|
|
753
|
+
" NEXT_PUBLIC_AURABASE_SERVICE_ROLE_KEY=your-service-role-key\n"
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
if (!options.anonKey) {
|
|
757
|
+
console.warn(
|
|
758
|
+
"[aurabase-js] anonKey가 설정되지 않았습니다.\n" +
|
|
759
|
+
".env.local 파일에 다음 항목을 추가하세요:\n\n" +
|
|
760
|
+
" NEXT_PUBLIC_AURABASE_ANON_KEY=your-anon-key (클라이언트용)\n" +
|
|
761
|
+
" NEXT_PUBLIC_AURABASE_SERVICE_ROLE_KEY=your-service-role-key (서버/admin용)\n"
|
|
762
|
+
);
|
|
763
|
+
}
|
|
734
764
|
return new AuraBaseClient(options);
|
|
735
765
|
}
|
|
736
766
|
var index_default = createClient;
|