@palbase/modules-db 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/dist/index.js ADDED
@@ -0,0 +1,415 @@
1
+ import {
2
+ AdminClient
3
+ } from "./chunk-AQ6ZQNXC.js";
4
+
5
+ // src/query-builder.ts
6
+ var TABLE_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;
7
+ var COLUMN_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.:\->#]*$/;
8
+ function validateTableName(table) {
9
+ if (!TABLE_NAME_RE.test(table)) {
10
+ throw new Error(`Invalid table name: "${table}". Table names must match ${TABLE_NAME_RE.source}`);
11
+ }
12
+ }
13
+ function validateColumnName(column) {
14
+ if (!COLUMN_NAME_RE.test(column)) {
15
+ throw new Error(`Invalid column name: "${column}". Column names must match ${COLUMN_NAME_RE.source}`);
16
+ }
17
+ }
18
+ function encodeFilterValue(value) {
19
+ return String(value).replace(/[&#]/g, (c) => encodeURIComponent(c));
20
+ }
21
+ var SingleQueryBuilder = class {
22
+ constructor(builder) {
23
+ this.builder = builder;
24
+ }
25
+ builder;
26
+ then(onfulfilled, onrejected) {
27
+ return this.builder["execute"]().then(
28
+ (res) => onfulfilled ? onfulfilled(res) : res,
29
+ onrejected ?? void 0
30
+ );
31
+ }
32
+ };
33
+ var MaybeSingleQueryBuilder = class {
34
+ constructor(builder) {
35
+ this.builder = builder;
36
+ }
37
+ builder;
38
+ then(onfulfilled, onrejected) {
39
+ return this.builder["execute"]().then(
40
+ (res) => onfulfilled ? onfulfilled(res) : res,
41
+ onrejected ?? void 0
42
+ );
43
+ }
44
+ };
45
+ var QueryBuilder = class {
46
+ httpClient;
47
+ basePath;
48
+ signal;
49
+ state;
50
+ constructor(httpClient, table, options) {
51
+ validateTableName(table);
52
+ this.httpClient = httpClient;
53
+ this.basePath = options?.basePath ?? `/v1/db/${table}`;
54
+ this.signal = options?.signal;
55
+ this.state = {
56
+ method: "GET",
57
+ headers: {},
58
+ filters: [],
59
+ params: {},
60
+ isSingle: false,
61
+ isMaybeSingle: false
62
+ };
63
+ }
64
+ // --- Operation methods ---
65
+ select(columns) {
66
+ this.state = {
67
+ ...this.state,
68
+ // Only set GET if no mutation method (POST/PATCH/DELETE) is already set
69
+ // insert().select() should stay POST with Prefer: return=representation
70
+ method: this.state.body !== void 0 ? this.state.method : "GET",
71
+ params: { ...this.state.params, select: columns ?? "*" }
72
+ };
73
+ return this;
74
+ }
75
+ insert(data) {
76
+ this.state = {
77
+ ...this.state,
78
+ method: "POST",
79
+ body: data,
80
+ headers: {
81
+ ...this.state.headers,
82
+ Prefer: "return=representation"
83
+ }
84
+ };
85
+ return this;
86
+ }
87
+ update(data) {
88
+ this.state = {
89
+ ...this.state,
90
+ method: "PATCH",
91
+ body: data,
92
+ headers: {
93
+ ...this.state.headers,
94
+ Prefer: "return=representation"
95
+ }
96
+ };
97
+ return this;
98
+ }
99
+ delete() {
100
+ this.state = {
101
+ ...this.state,
102
+ method: "DELETE"
103
+ };
104
+ return this;
105
+ }
106
+ upsert(data) {
107
+ this.state = {
108
+ ...this.state,
109
+ method: "POST",
110
+ body: data,
111
+ headers: {
112
+ ...this.state.headers,
113
+ Prefer: "resolution=merge-duplicates,return=representation"
114
+ }
115
+ };
116
+ return this;
117
+ }
118
+ // --- Filter methods ---
119
+ eq(column, value) {
120
+ validateColumnName(column);
121
+ this.state = {
122
+ ...this.state,
123
+ filters: [...this.state.filters, `${column}=eq.${encodeFilterValue(value)}`]
124
+ };
125
+ return this;
126
+ }
127
+ neq(column, value) {
128
+ validateColumnName(column);
129
+ this.state = {
130
+ ...this.state,
131
+ filters: [...this.state.filters, `${column}=neq.${encodeFilterValue(value)}`]
132
+ };
133
+ return this;
134
+ }
135
+ gt(column, value) {
136
+ validateColumnName(column);
137
+ this.state = {
138
+ ...this.state,
139
+ filters: [...this.state.filters, `${column}=gt.${encodeFilterValue(value)}`]
140
+ };
141
+ return this;
142
+ }
143
+ gte(column, value) {
144
+ validateColumnName(column);
145
+ this.state = {
146
+ ...this.state,
147
+ filters: [...this.state.filters, `${column}=gte.${encodeFilterValue(value)}`]
148
+ };
149
+ return this;
150
+ }
151
+ lt(column, value) {
152
+ validateColumnName(column);
153
+ this.state = {
154
+ ...this.state,
155
+ filters: [...this.state.filters, `${column}=lt.${encodeFilterValue(value)}`]
156
+ };
157
+ return this;
158
+ }
159
+ lte(column, value) {
160
+ validateColumnName(column);
161
+ this.state = {
162
+ ...this.state,
163
+ filters: [...this.state.filters, `${column}=lte.${encodeFilterValue(value)}`]
164
+ };
165
+ return this;
166
+ }
167
+ like(column, pattern) {
168
+ validateColumnName(column);
169
+ this.state = {
170
+ ...this.state,
171
+ filters: [...this.state.filters, `${column}=like.${encodeFilterValue(pattern)}`]
172
+ };
173
+ return this;
174
+ }
175
+ ilike(column, pattern) {
176
+ validateColumnName(column);
177
+ this.state = {
178
+ ...this.state,
179
+ filters: [...this.state.filters, `${column}=ilike.${encodeFilterValue(pattern)}`]
180
+ };
181
+ return this;
182
+ }
183
+ in(column, values) {
184
+ validateColumnName(column);
185
+ const encoded = values.map((v) => encodeFilterValue(v).replace(/[),]/g, (c) => encodeURIComponent(c)));
186
+ this.state = {
187
+ ...this.state,
188
+ filters: [...this.state.filters, `${column}=in.(${encoded.join(",")})`]
189
+ };
190
+ return this;
191
+ }
192
+ is(column, value) {
193
+ validateColumnName(column);
194
+ this.state = {
195
+ ...this.state,
196
+ filters: [...this.state.filters, `${column}=is.${encodeFilterValue(value)}`]
197
+ };
198
+ return this;
199
+ }
200
+ // --- Modifier methods ---
201
+ order(column, options) {
202
+ validateColumnName(column);
203
+ const direction = options?.ascending === false ? "desc" : "asc";
204
+ this.state = {
205
+ ...this.state,
206
+ params: { ...this.state.params, order: `${column}.${direction}` }
207
+ };
208
+ return this;
209
+ }
210
+ limit(count) {
211
+ this.state = {
212
+ ...this.state,
213
+ params: { ...this.state.params, limit: String(count) }
214
+ };
215
+ return this;
216
+ }
217
+ range(from, to) {
218
+ this.state = {
219
+ ...this.state,
220
+ headers: {
221
+ ...this.state.headers,
222
+ Range: `${from}-${to}`
223
+ }
224
+ };
225
+ return this;
226
+ }
227
+ single() {
228
+ this.state = {
229
+ ...this.state,
230
+ isSingle: true,
231
+ headers: {
232
+ ...this.state.headers,
233
+ Accept: "application/vnd.pgrst.object+json"
234
+ }
235
+ };
236
+ return new SingleQueryBuilder(this);
237
+ }
238
+ maybeSingle() {
239
+ this.state = {
240
+ ...this.state,
241
+ isMaybeSingle: true,
242
+ headers: {
243
+ ...this.state.headers,
244
+ Accept: "application/vnd.pgrst.object+json"
245
+ }
246
+ };
247
+ return new MaybeSingleQueryBuilder(this);
248
+ }
249
+ // --- Execution ---
250
+ then(onfulfilled, onrejected) {
251
+ return this.execute().then(onfulfilled, onrejected);
252
+ }
253
+ buildPath() {
254
+ const parts = [];
255
+ for (const [key, value] of Object.entries(this.state.params)) {
256
+ parts.push(`${key}=${value}`);
257
+ }
258
+ for (const filter of this.state.filters) {
259
+ parts.push(filter);
260
+ }
261
+ return parts.length > 0 ? `${this.basePath}?${parts.join("&")}` : this.basePath;
262
+ }
263
+ async execute() {
264
+ const path = this.buildPath();
265
+ const { method, body, headers } = this.state;
266
+ const response = await this.httpClient.request(method, path, {
267
+ body,
268
+ headers: Object.keys(headers).length > 0 ? headers : void 0,
269
+ signal: this.signal
270
+ });
271
+ if (this.state.isMaybeSingle && response.error && response.status === 406) {
272
+ return { data: null, error: null, status: 200 };
273
+ }
274
+ return response;
275
+ }
276
+ };
277
+
278
+ // src/transaction.ts
279
+ import { PalbaseError } from "@palbase/core";
280
+ var DEFAULT_TIMEOUT_MS = 3e4;
281
+ var TX_ID_RE = /^[a-zA-Z0-9_\-]+$/;
282
+ var TransactionClient = class {
283
+ httpClient;
284
+ txId;
285
+ signal;
286
+ constructor(httpClient, txId, signal) {
287
+ this.httpClient = httpClient;
288
+ this.txId = txId;
289
+ this.signal = signal;
290
+ }
291
+ from(table) {
292
+ return new QueryBuilder(this.httpClient, table, {
293
+ basePath: `/v1/db/transaction/${this.txId}/query/${table}`,
294
+ signal: this.signal
295
+ });
296
+ }
297
+ };
298
+ async function executeTransaction(httpClient, fn, options) {
299
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
300
+ const controller = new AbortController();
301
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
302
+ let txId;
303
+ try {
304
+ const beginResponse = await httpClient.request(
305
+ "POST",
306
+ "/v1/db/transaction/begin",
307
+ { signal: controller.signal }
308
+ );
309
+ if (beginResponse.error || !beginResponse.data) {
310
+ clearTimeout(timer);
311
+ return {
312
+ data: null,
313
+ error: beginResponse.error ?? new PalbaseError(
314
+ "transaction_error",
315
+ "Failed to begin transaction",
316
+ beginResponse.status
317
+ ),
318
+ status: beginResponse.status
319
+ };
320
+ }
321
+ txId = beginResponse.data.txId;
322
+ if (!TX_ID_RE.test(txId)) {
323
+ clearTimeout(timer);
324
+ return {
325
+ data: null,
326
+ error: new PalbaseError(
327
+ "transaction_error",
328
+ `Invalid transaction ID format: "${txId}"`,
329
+ 0
330
+ ),
331
+ status: 0
332
+ };
333
+ }
334
+ const tx = new TransactionClient(httpClient, txId, controller.signal);
335
+ const result = await fn(tx);
336
+ const commitResponse = await httpClient.request(
337
+ "POST",
338
+ `/v1/db/transaction/${txId}/commit`,
339
+ { signal: controller.signal }
340
+ );
341
+ clearTimeout(timer);
342
+ if (commitResponse.error) {
343
+ return {
344
+ data: null,
345
+ error: commitResponse.error,
346
+ status: commitResponse.status
347
+ };
348
+ }
349
+ return { data: result, error: null, status: 200 };
350
+ } catch (error) {
351
+ clearTimeout(timer);
352
+ if (txId) {
353
+ try {
354
+ await httpClient.request(
355
+ "POST",
356
+ `/v1/db/transaction/${txId}/rollback`,
357
+ { signal: void 0 }
358
+ );
359
+ } catch {
360
+ }
361
+ }
362
+ if (error instanceof PalbaseError) {
363
+ return { data: null, error, status: error.status };
364
+ }
365
+ const isAbort = error instanceof DOMException && error.name === "AbortError";
366
+ const code = isAbort ? "transaction_timeout" : "transaction_error";
367
+ const message = isAbort ? `Transaction timed out after ${timeoutMs}ms` : error instanceof Error ? error.message : "Transaction failed";
368
+ const status = isAbort ? 408 : 0;
369
+ return {
370
+ data: null,
371
+ error: new PalbaseError(code, message, status),
372
+ status
373
+ };
374
+ }
375
+ }
376
+
377
+ // src/database-client.ts
378
+ var FN_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;
379
+ var DatabaseClient = class {
380
+ httpClient;
381
+ pathPrefix;
382
+ admin;
383
+ constructor(httpClient, options) {
384
+ this.httpClient = httpClient;
385
+ this.pathPrefix = options?.pathPrefix ?? "/v1/db";
386
+ if (options?.enableAdmin) {
387
+ this.admin = new AdminClient(httpClient);
388
+ }
389
+ }
390
+ from(table) {
391
+ return new QueryBuilder(this.httpClient, table, {
392
+ basePath: `${this.pathPrefix}/${table}`
393
+ });
394
+ }
395
+ async rpc(fnName, params) {
396
+ if (!FN_NAME_RE.test(fnName)) {
397
+ throw new Error(`Invalid function name: "${fnName}". Function names must match ${FN_NAME_RE.source}`);
398
+ }
399
+ return this.httpClient.request("POST", `${this.pathPrefix}/rpc/${fnName}`, {
400
+ body: params
401
+ });
402
+ }
403
+ async transaction(fn, options) {
404
+ return executeTransaction(this.httpClient, fn, options);
405
+ }
406
+ };
407
+ export {
408
+ DatabaseClient,
409
+ MaybeSingleQueryBuilder,
410
+ QueryBuilder,
411
+ SingleQueryBuilder,
412
+ TransactionClient,
413
+ executeTransaction
414
+ };
415
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query-builder.ts","../src/transaction.ts","../src/database-client.ts"],"sourcesContent":["import type { HttpClient, PalbaseResponse } from '@palbase/core';\nimport type { OrderOptions } from './types.js';\n\ntype HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';\n\nconst TABLE_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;\nconst COLUMN_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.:\\->#]*$/;\n\nfunction validateTableName(table: string): void {\n if (!TABLE_NAME_RE.test(table)) {\n throw new Error(`Invalid table name: \"${table}\". Table names must match ${TABLE_NAME_RE.source}`);\n }\n}\n\nfunction validateColumnName(column: string): void {\n if (!COLUMN_NAME_RE.test(column)) {\n throw new Error(`Invalid column name: \"${column}\". Column names must match ${COLUMN_NAME_RE.source}`);\n }\n}\n\nfunction encodeFilterValue(value: unknown): string {\n return String(value).replace(/[&#]/g, (c) => encodeURIComponent(c));\n}\n\ninterface QueryState<T> {\n readonly method: HttpMethod;\n readonly body?: Partial<T> | Partial<T>[] | Record<string, unknown> | Record<string, unknown>[];\n readonly headers: Record<string, string>;\n readonly filters: string[];\n readonly params: Record<string, string>;\n readonly isSingle: boolean;\n readonly isMaybeSingle: boolean;\n}\n\nexport interface QueryBuilderOptions {\n basePath?: string;\n signal?: AbortSignal;\n}\n\n/**\n * Wrapper returned by `.single()` — resolves to `PalbaseResponse<T>` (single row).\n */\nexport class SingleQueryBuilder<T> implements PromiseLike<PalbaseResponse<T>> {\n constructor(private readonly builder: QueryBuilder<T>) {}\n\n then<TResult1 = PalbaseResponse<T>, TResult2 = never>(\n onfulfilled?: ((value: PalbaseResponse<T>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.builder['execute']().then(\n (res) => onfulfilled ? onfulfilled(res as unknown as PalbaseResponse<T>) : res as unknown as TResult1,\n onrejected ?? undefined,\n );\n }\n}\n\n/**\n * Wrapper returned by `.maybeSingle()` — resolves to `PalbaseResponse<T | null>` (single row or null).\n */\nexport class MaybeSingleQueryBuilder<T> implements PromiseLike<PalbaseResponse<T | null>> {\n constructor(private readonly builder: QueryBuilder<T>) {}\n\n then<TResult1 = PalbaseResponse<T | null>, TResult2 = never>(\n onfulfilled?: ((value: PalbaseResponse<T | null>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.builder['execute']().then(\n (res) => onfulfilled ? onfulfilled(res as unknown as PalbaseResponse<T | null>) : res as unknown as TResult1,\n onrejected ?? undefined,\n );\n }\n}\n\nexport class QueryBuilder<T = Record<string, unknown>> implements PromiseLike<PalbaseResponse<T[]>> {\n private readonly httpClient: HttpClient;\n private readonly basePath: string;\n private readonly signal?: AbortSignal;\n private state: QueryState<T>;\n\n constructor(httpClient: HttpClient, table: string, options?: QueryBuilderOptions) {\n validateTableName(table);\n this.httpClient = httpClient;\n this.basePath = options?.basePath ?? `/v1/db/${table}`;\n this.signal = options?.signal;\n this.state = {\n method: 'GET',\n headers: {},\n filters: [],\n params: {},\n isSingle: false,\n isMaybeSingle: false,\n };\n }\n\n // --- Operation methods ---\n\n select(columns?: string): this {\n this.state = {\n ...this.state,\n // Only set GET if no mutation method (POST/PATCH/DELETE) is already set\n // insert().select() should stay POST with Prefer: return=representation\n method: this.state.body !== undefined ? this.state.method : 'GET',\n params: { ...this.state.params, select: columns ?? '*' },\n };\n return this;\n }\n\n insert(data: Partial<T> | Partial<T>[] | Record<string, unknown> | Record<string, unknown>[]): this {\n this.state = {\n ...this.state,\n method: 'POST',\n body: data,\n headers: {\n ...this.state.headers,\n Prefer: 'return=representation',\n },\n };\n return this;\n }\n\n update(data: Partial<T> | Record<string, unknown>): this {\n this.state = {\n ...this.state,\n method: 'PATCH',\n body: data,\n headers: {\n ...this.state.headers,\n Prefer: 'return=representation',\n },\n };\n return this;\n }\n\n delete(): this {\n this.state = {\n ...this.state,\n method: 'DELETE',\n };\n return this;\n }\n\n upsert(data: Partial<T> | Partial<T>[]): this {\n this.state = {\n ...this.state,\n method: 'POST',\n body: data,\n headers: {\n ...this.state.headers,\n Prefer: 'resolution=merge-duplicates,return=representation',\n },\n };\n return this;\n }\n\n // --- Filter methods ---\n\n eq(column: string & keyof T | (string & Record<never, never>), value: unknown): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=eq.${encodeFilterValue(value)}`],\n };\n return this;\n }\n\n neq(column: string & keyof T | (string & Record<never, never>), value: unknown): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=neq.${encodeFilterValue(value)}`],\n };\n return this;\n }\n\n gt(column: string & keyof T | (string & Record<never, never>), value: unknown): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=gt.${encodeFilterValue(value)}`],\n };\n return this;\n }\n\n gte(column: string & keyof T | (string & Record<never, never>), value: unknown): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=gte.${encodeFilterValue(value)}`],\n };\n return this;\n }\n\n lt(column: string & keyof T | (string & Record<never, never>), value: unknown): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=lt.${encodeFilterValue(value)}`],\n };\n return this;\n }\n\n lte(column: string & keyof T | (string & Record<never, never>), value: unknown): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=lte.${encodeFilterValue(value)}`],\n };\n return this;\n }\n\n like(column: string & keyof T | (string & Record<never, never>), pattern: string): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=like.${encodeFilterValue(pattern)}`],\n };\n return this;\n }\n\n ilike(column: string & keyof T | (string & Record<never, never>), pattern: string): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=ilike.${encodeFilterValue(pattern)}`],\n };\n return this;\n }\n\n in(column: string & keyof T | (string & Record<never, never>), values: unknown[]): this {\n validateColumnName(column);\n const encoded = values.map((v) => encodeFilterValue(v).replace(/[),]/g, (c) => encodeURIComponent(c)));\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=in.(${encoded.join(',')})`],\n };\n return this;\n }\n\n is(column: string & keyof T | (string & Record<never, never>), value: unknown): this {\n validateColumnName(column);\n this.state = {\n ...this.state,\n filters: [...this.state.filters, `${column}=is.${encodeFilterValue(value)}`],\n };\n return this;\n }\n\n // --- Modifier methods ---\n\n order(column: string & keyof T | (string & Record<never, never>), options?: OrderOptions): this {\n validateColumnName(column);\n const direction = options?.ascending === false ? 'desc' : 'asc';\n this.state = {\n ...this.state,\n params: { ...this.state.params, order: `${column}.${direction}` },\n };\n return this;\n }\n\n limit(count: number): this {\n this.state = {\n ...this.state,\n params: { ...this.state.params, limit: String(count) },\n };\n return this;\n }\n\n range(from: number, to: number): this {\n this.state = {\n ...this.state,\n headers: {\n ...this.state.headers,\n Range: `${from}-${to}`,\n },\n };\n return this;\n }\n\n single(): SingleQueryBuilder<T> {\n this.state = {\n ...this.state,\n isSingle: true,\n headers: {\n ...this.state.headers,\n Accept: 'application/vnd.pgrst.object+json',\n },\n };\n return new SingleQueryBuilder(this);\n }\n\n maybeSingle(): MaybeSingleQueryBuilder<T> {\n this.state = {\n ...this.state,\n isMaybeSingle: true,\n headers: {\n ...this.state.headers,\n Accept: 'application/vnd.pgrst.object+json',\n },\n };\n return new MaybeSingleQueryBuilder(this);\n }\n\n // --- Execution ---\n\n then<TResult1 = PalbaseResponse<T[]>, TResult2 = never>(\n onfulfilled?: ((value: PalbaseResponse<T[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.execute().then(onfulfilled as unknown as ((value: PalbaseResponse<T>) => TResult1 | PromiseLike<TResult1>) | null, onrejected);\n }\n\n private buildPath(): string {\n // Build query string manually — URLSearchParams percent-encodes\n // parentheses and commas which breaks PostgREST filter syntax\n const parts: string[] = [];\n\n for (const [key, value] of Object.entries(this.state.params)) {\n parts.push(`${key}=${value}`);\n }\n\n for (const filter of this.state.filters) {\n parts.push(filter);\n }\n\n return parts.length > 0 ? `${this.basePath}?${parts.join('&')}` : this.basePath;\n }\n\n private async execute(): Promise<PalbaseResponse<T>> {\n const path = this.buildPath();\n const { method, body, headers } = this.state;\n\n const response = await this.httpClient.request<T>(method, path, {\n body: body,\n headers: Object.keys(headers).length > 0 ? headers : undefined,\n signal: this.signal,\n });\n\n // For maybeSingle, convert 406 (no rows) to { data: null, error: null }\n if (this.state.isMaybeSingle && response.error && response.status === 406) {\n return { data: null, error: null, status: 200 };\n }\n\n return response;\n }\n}\n","import type { HttpClient, PalbaseResponse } from '@palbase/core';\nimport { PalbaseError } from '@palbase/core';\nimport { QueryBuilder } from './query-builder.js';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst TX_ID_RE = /^[a-zA-Z0-9_\\-]+$/;\n\nexport interface TransactionOptions {\n timeoutMs?: number;\n}\n\nexport class TransactionClient {\n private readonly httpClient: HttpClient;\n private readonly txId: string;\n private readonly signal?: AbortSignal;\n\n constructor(httpClient: HttpClient, txId: string, signal?: AbortSignal) {\n this.httpClient = httpClient;\n this.txId = txId;\n this.signal = signal;\n }\n\n from<T = Record<string, unknown>>(table: string): QueryBuilder<T> {\n return new QueryBuilder<T>(this.httpClient, table, {\n basePath: `/v1/db/transaction/${this.txId}/query/${table}`,\n signal: this.signal,\n });\n }\n}\n\nexport async function executeTransaction<T>(\n httpClient: HttpClient,\n fn: (tx: TransactionClient) => Promise<T>,\n options?: TransactionOptions,\n): Promise<PalbaseResponse<T>> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let txId: string | undefined;\n\n try {\n // Begin transaction\n const beginResponse = await httpClient.request<{ txId: string }>(\n 'POST',\n '/v1/db/transaction/begin',\n { signal: controller.signal },\n );\n\n if (beginResponse.error || !beginResponse.data) {\n clearTimeout(timer);\n return {\n data: null,\n error: beginResponse.error ?? new PalbaseError(\n 'transaction_error',\n 'Failed to begin transaction',\n beginResponse.status,\n ),\n status: beginResponse.status,\n };\n }\n\n txId = beginResponse.data.txId;\n\n // Validate txId format to prevent path traversal from a compromised server response\n if (!TX_ID_RE.test(txId)) {\n clearTimeout(timer);\n return {\n data: null,\n error: new PalbaseError(\n 'transaction_error',\n `Invalid transaction ID format: \"${txId}\"`,\n 0,\n ),\n status: 0,\n };\n }\n\n const tx = new TransactionClient(httpClient, txId, controller.signal);\n\n // Execute user function\n const result = await fn(tx);\n\n // Commit\n const commitResponse = await httpClient.request<unknown>(\n 'POST',\n `/v1/db/transaction/${txId}/commit`,\n { signal: controller.signal },\n );\n\n clearTimeout(timer);\n\n if (commitResponse.error) {\n return {\n data: null,\n error: commitResponse.error,\n status: commitResponse.status,\n };\n }\n\n return { data: result, error: null, status: 200 };\n } catch (error) {\n clearTimeout(timer);\n\n // Rollback if we have a transaction ID.\n // Intentionally no signal — rollback must complete even if the timeout controller aborted.\n if (txId) {\n try {\n await httpClient.request<unknown>(\n 'POST',\n `/v1/db/transaction/${txId}/rollback`,\n { signal: undefined },\n );\n } catch {\n // Rollback failed — nothing we can do, return the original error\n }\n }\n\n if (error instanceof PalbaseError) {\n return { data: null, error, status: error.status };\n }\n\n const isAbort = error instanceof DOMException && error.name === 'AbortError';\n const code = isAbort ? 'transaction_timeout' : 'transaction_error';\n const message = isAbort\n ? `Transaction timed out after ${timeoutMs}ms`\n : error instanceof Error ? error.message : 'Transaction failed';\n const status = isAbort ? 408 : 0;\n\n return {\n data: null,\n error: new PalbaseError(code, message, status),\n status,\n };\n }\n}\n","import type { HttpClient, PalbaseResponse } from '@palbase/core';\nimport { AdminClient } from './admin-client.js';\nimport { QueryBuilder } from './query-builder.js';\nimport { type TransactionOptions, executeTransaction } from './transaction.js';\nimport type { TransactionClient } from './transaction.js';\nconst FN_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;\n\nexport interface DatabaseClientOptions {\n enableAdmin?: boolean;\n /** Override the default `/v1/db` path prefix. Set to empty string for direct PostgREST access. */\n pathPrefix?: string;\n}\n\nexport class DatabaseClient {\n private readonly httpClient: HttpClient;\n private readonly pathPrefix: string;\n readonly admin?: AdminClient;\n\n constructor(httpClient: HttpClient, options?: DatabaseClientOptions) {\n this.httpClient = httpClient;\n this.pathPrefix = options?.pathPrefix ?? '/v1/db';\n if (options?.enableAdmin) {\n this.admin = new AdminClient(httpClient);\n }\n }\n\n from<T = Record<string, unknown>>(table: string): QueryBuilder<T> {\n return new QueryBuilder<T>(this.httpClient, table, {\n basePath: `${this.pathPrefix}/${table}`,\n });\n }\n\n async rpc<T = unknown>(fnName: string, params?: Record<string, unknown>): Promise<PalbaseResponse<T>> {\n if (!FN_NAME_RE.test(fnName)) {\n throw new Error(`Invalid function name: \"${fnName}\". Function names must match ${FN_NAME_RE.source}`);\n }\n\n return this.httpClient.request<T>('POST', `${this.pathPrefix}/rpc/${fnName}`, {\n body: params,\n });\n }\n\n async transaction<T>(\n fn: (tx: TransactionClient) => Promise<T>,\n options?: TransactionOptions,\n ): Promise<PalbaseResponse<T>> {\n return executeTransaction(this.httpClient, fn, options);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@palbase/modules-db",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "import": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "require": {
13
+ "types": "./dist/index.d.cts",
14
+ "default": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "./admin": {
18
+ "import": {
19
+ "types": "./dist/admin.d.ts",
20
+ "default": "./dist/admin.js"
21
+ },
22
+ "require": {
23
+ "types": "./dist/admin.d.cts",
24
+ "default": "./dist/admin.cjs"
25
+ }
26
+ }
27
+ },
28
+ "main": "./dist/index.cjs",
29
+ "module": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "dependencies": {
35
+ "@palbase/core": "0.1.0"
36
+ },
37
+ "devDependencies": {
38
+ "@biomejs/biome": "^2.0.0",
39
+ "tsup": "^8.4.0",
40
+ "typescript": "^5.8.0",
41
+ "vitest": "^3.1.0"
42
+ },
43
+ "scripts": {
44
+ "build": "tsup",
45
+ "test": "vitest run",
46
+ "lint": "biome check src/ __tests__/"
47
+ }
48
+ }