@palbase/db 0.3.0 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/admin-validation.ts","../src/admin-columns.ts","../src/admin-schemas.ts","../src/admin-tables.ts","../src/admin-client.ts","../src/query-builder.ts","../src/transaction.ts","../src/database-client.ts"],"sourcesContent":["export { DatabaseClient } from './database-client.js';\nexport type { DatabaseClientOptions } from './database-client.js';\nexport { QueryBuilder, SingleQueryBuilder, MaybeSingleQueryBuilder } from './query-builder.js';\nexport type { QueryBuilderOptions } from './query-builder.js';\nexport { TransactionClient, executeTransaction } from './transaction.js';\nexport type { TransactionOptions } from './transaction.js';\nexport type { OrderOptions, GenericSchema, GenericTable } from './types.js';\n","const IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;\n\nexport function validateIdentifier(value: string, label: string): void {\n if (!IDENTIFIER_RE.test(value)) {\n throw new Error(\n `Invalid ${label}: \"${value}\". Identifiers must match ${IDENTIFIER_RE.source}`,\n );\n }\n}\n","import type { HttpClient } from '@palbase/core';\nimport type { Column, CreateColumnDef } from './admin-types.js';\nimport { validateIdentifier } from './admin-validation.js';\n\n/**\n * Postgres-meta column admin client.\n *\n * Wraps the `/v1/meta/columns` endpoints exposed by postgres-meta.\n * Use this to add or drop columns on an existing table — `TablesClient.update()`\n * does not handle column structure changes.\n */\nexport class ColumnsClient {\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Create a new column on the given table. Sends `POST /v1/meta/columns`.\n *\n * The column name is validated against the standard SQL identifier regex.\n * The `type` field is forwarded as-is to postgres-meta — callers SHOULD\n * restrict types to a known allowlist before calling this.\n */\n async create(def: CreateColumnDef): Promise<Column> {\n validateIdentifier(def.name, 'column name');\n\n const response = await this.httpClient.request<Column>('POST', '/v1/meta/columns', {\n body: def,\n });\n if (response.error) {\n throw response.error;\n }\n return response.data as Column;\n }\n\n /**\n * Drop a column. Sends `DELETE /v1/meta/columns/:tableId.:ordinalPosition`.\n *\n * postgres-meta identifies columns by `{tableId}.{ordinalPosition}` (the\n * column's 1-based attnum within its table). Use `TablesClient.get(id)` to\n * find a column id from a column name if needed.\n */\n async drop(columnId: string, options?: { cascade?: boolean }): Promise<Column> {\n if (!/^\\d+\\.\\d+$/.test(columnId)) {\n throw new Error(\n `Invalid column id: \"${columnId}\". Expected format \"{tableId}.{ordinalPosition}\"`,\n );\n }\n\n const params = new URLSearchParams();\n if (options?.cascade) {\n params.set('cascade', 'true');\n }\n\n const queryString = params.toString();\n const path = queryString\n ? `/v1/meta/columns/${columnId}?${queryString}`\n : `/v1/meta/columns/${columnId}`;\n\n const response = await this.httpClient.request<Column>('DELETE', path);\n if (response.error) {\n throw response.error;\n }\n return response.data as Column;\n }\n}\n","import type { HttpClient } from '@palbase/core';\nimport type { Schema } from './admin-types.js';\nimport { validateIdentifier } from './admin-validation.js';\n\nexport class SchemasClient {\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n async list(): Promise<Schema[]> {\n const response = await this.httpClient.request<Schema[]>('GET', '/v1/meta/schemas');\n if (response.error) {\n throw response.error;\n }\n return response.data ?? [];\n }\n\n async create(name: string): Promise<Schema> {\n validateIdentifier(name, 'schema name');\n\n const response = await this.httpClient.request<Schema>('POST', '/v1/meta/schemas', {\n body: { name },\n });\n if (response.error) {\n throw response.error;\n }\n return response.data as Schema;\n }\n\n async drop(name: string, options?: { cascade?: boolean }): Promise<void> {\n validateIdentifier(name, 'schema name');\n\n // Resolve name to id first\n const schemas = await this.list();\n const schema = schemas.find((s) => s.name === name);\n if (!schema) {\n throw new Error(`Schema \"${name}\" not found`);\n }\n\n const params = new URLSearchParams();\n if (options?.cascade) {\n params.set('cascade', 'true');\n }\n\n const queryString = params.toString();\n const path = queryString\n ? `/v1/meta/schemas/${schema.id}?${queryString}`\n : `/v1/meta/schemas/${schema.id}`;\n\n const response = await this.httpClient.request<void>('DELETE', path);\n if (response.error) {\n throw response.error;\n }\n }\n}\n","import type { HttpClient } from '@palbase/core';\nimport type { CreateTableDef, Table, UpdateTableDef } from './admin-types.js';\nimport { validateIdentifier } from './admin-validation.js';\n\nexport class TablesClient {\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n async list(options?: { schema?: string }): Promise<Table[]> {\n const params = new URLSearchParams();\n if (options?.schema) {\n validateIdentifier(options.schema, 'schema name');\n params.set('included_schemas', options.schema);\n }\n\n const queryString = params.toString();\n const path = queryString ? `/v1/meta/tables?${queryString}` : '/v1/meta/tables';\n\n const response = await this.httpClient.request<Table[]>('GET', path);\n if (response.error) {\n throw response.error;\n }\n return response.data ?? [];\n }\n\n async get(id: number): Promise<Table> {\n const response = await this.httpClient.request<Table>('GET', `/v1/meta/tables/${id}`);\n if (response.error) {\n throw response.error;\n }\n return response.data as Table;\n }\n\n async create(def: CreateTableDef): Promise<Table> {\n validateIdentifier(def.name, 'table name');\n if (def.schema) {\n validateIdentifier(def.schema, 'schema name');\n }\n\n const response = await this.httpClient.request<Table>('POST', '/v1/meta/tables', {\n body: def,\n });\n if (response.error) {\n throw response.error;\n }\n return response.data as Table;\n }\n\n /**\n * Apply table-level updates (rename, schema move, RLS toggle, comment, etc).\n * Sends `PATCH /v1/meta/tables/:id`.\n *\n * Note: this does NOT add or drop columns. For column changes, use\n * `ColumnsClient.create()` / `ColumnsClient.drop()`.\n */\n async update(id: number, patch: UpdateTableDef): Promise<Table> {\n if (patch.name !== undefined) {\n validateIdentifier(patch.name, 'table name');\n }\n if (patch.schema !== undefined) {\n validateIdentifier(patch.schema, 'schema name');\n }\n if (patch.primary_keys) {\n for (const pk of patch.primary_keys) {\n validateIdentifier(pk.name, 'primary key column name');\n }\n }\n\n const response = await this.httpClient.request<Table>('PATCH', `/v1/meta/tables/${id}`, {\n body: patch,\n });\n if (response.error) {\n throw response.error;\n }\n return response.data as Table;\n }\n\n async drop(id: number, options?: { cascade?: boolean }): Promise<void> {\n const params = new URLSearchParams();\n if (options?.cascade) {\n params.set('cascade', 'true');\n }\n\n const queryString = params.toString();\n const path = queryString\n ? `/v1/meta/tables/${id}?${queryString}`\n : `/v1/meta/tables/${id}`;\n\n const response = await this.httpClient.request<void>('DELETE', path);\n if (response.error) {\n throw response.error;\n }\n }\n}\n","import type { HttpClient } from '@palbase/core';\nimport { ColumnsClient } from './admin-columns.js';\nimport { SchemasClient } from './admin-schemas.js';\nimport { TablesClient } from './admin-tables.js';\n\nexport class AdminClient {\n readonly schemas: SchemasClient;\n readonly tables: TablesClient;\n readonly columns: ColumnsClient;\n\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n this.schemas = new SchemasClient(httpClient);\n this.tables = new TablesClient(httpClient);\n this.columns = new ColumnsClient(httpClient);\n }\n\n /**\n * Execute a raw SQL query with full privileges (service role).\n *\n * Always use parameterized queries to prevent SQL injection.\n * Never interpolate user input directly into the SQL string.\n *\n * @example\n * ```ts\n * // GOOD — parameterized\n * await admin.query('SELECT * FROM users WHERE id = $1', [userId]);\n *\n * // BAD — string interpolation (SQL injection risk)\n * await admin.query(`SELECT * FROM users WHERE id = '${userId}'`);\n * ```\n */\n async query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]> {\n const response = await this.httpClient.request<T[]>('POST', '/v1/meta/query', {\n body: { query: sql, params },\n });\n if (response.error) {\n throw response.error;\n }\n return response.data ?? [];\n }\n}\n","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":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/query-builder.ts","../src/transaction.ts","../src/database-client.ts"],"sourcesContent":["export { DatabaseClient } from './database-client.js';\nexport type { DatabaseClientOptions } from './database-client.js';\nexport { QueryBuilder, SingleQueryBuilder, MaybeSingleQueryBuilder } from './query-builder.js';\nexport type { QueryBuilderOptions, SelectOptions, CountMode } from './query-builder.js';\nexport { TransactionClient, executeTransaction } from './transaction.js';\nexport type { TransactionOptions } from './transaction.js';\nexport type { OrderOptions, GenericSchema, GenericTable } from './types.js';\n","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\ntype HttpMethodWithHead = HttpMethod | 'HEAD';\n\ninterface QueryState<T> {\n readonly method: HttpMethodWithHead;\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 readonly isHead: boolean;\n}\n\nexport type CountMode = 'exact' | 'planned' | 'estimated';\n\nexport interface SelectOptions {\n /**\n * Request a row count from PostgREST via Prefer: count=<mode>.\n * - 'exact': slow, accurate (full scan)\n * - 'planned': fast, planner estimate\n * - 'estimated': best effort (exact if ≤max, planned otherwise)\n */\n count?: CountMode;\n /**\n * Skip the response body — issue a HEAD request. Only the `count` and\n * `status` fields of the result are populated. Use with `count` to get a\n * row count without paying for the data payload.\n */\n head?: 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 isHead: false,\n };\n }\n\n // --- Operation methods ---\n\n select(columns?: string, options?: SelectOptions): this {\n const nextHeaders = { ...this.state.headers };\n const prefers: string[] = [];\n if (this.state.headers.Prefer) {\n prefers.push(this.state.headers.Prefer);\n }\n if (options?.count) {\n prefers.push(`count=${options.count}`);\n }\n if (prefers.length > 0) {\n nextHeaders.Prefer = prefers.join(',');\n }\n\n const isHead = options?.head === true;\n\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: isHead\n ? 'HEAD'\n : this.state.body !== undefined\n ? this.state.method\n : 'GET',\n params: { ...this.state.params, select: columns ?? '*' },\n headers: nextHeaders,\n isHead,\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 { 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 /** Override the default `/v1/db` path prefix. Set to empty string for direct PostgREST access. */\n pathPrefix?: string;\n}\n\n/**\n * Extract the Tables record from a typed Database schema.\n * Returns an empty-object type when the schema isn't typed so that\n * `keyof TablesOf<unknown>` = `never` (no tables) — which means the\n * typed-table overload in `from()` never matches for untyped clients,\n * and the callsite falls through to the plain `from<T>(string)` overload.\n */\n// deno-lint-ignore ban-types\ntype TablesOf<Schema> = Schema extends { public: { Tables: infer Tables } }\n ? Tables\n : {};\n\n/**\n * Given a typed `Database` schema, resolve the Row type for a table name.\n * Falls back to `Record<string, unknown>` when the schema is untyped or\n * the table name isn't in the schema.\n */\ntype RowOf<Schema, Name extends string> =\n Name extends keyof TablesOf<Schema>\n ? TablesOf<Schema>[Name] extends { Row: infer R }\n ? R\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport class DatabaseClient<Schema = unknown> {\n private readonly httpClient: HttpClient;\n private readonly pathPrefix: string;\n\n constructor(httpClient: HttpClient, options?: DatabaseClientOptions) {\n this.httpClient = httpClient;\n this.pathPrefix = options?.pathPrefix ?? '/v1/db';\n }\n\n /**\n * Get a QueryBuilder for a table.\n *\n * Resolution order for the Row type:\n * 1. Explicit generic: `db.from<Todo>('todos')` → Row = Todo\n * 2. Typed Schema + matching table name: `DatabaseClient<Database>` +\n * `db.from('todos')` → Row = `Schema['public']['Tables']['todos']['Row']`\n * 3. Otherwise: Row = `Record<string, unknown>`\n */\n from<Name extends string & keyof TablesOf<Schema>>(\n table: Name,\n ): QueryBuilder<RowOf<Schema, Name>>;\n from<T = Record<string, unknown>>(table: string): QueryBuilder<T>;\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/dist/index.d.cts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { PalbaseResponse, HttpClient } from '@palbase/core';
2
- import { AdminClient } from './admin.cjs';
3
2
 
4
3
  interface OrderOptions {
5
4
  ascending?: boolean;
@@ -15,6 +14,22 @@ interface GenericSchema {
15
14
  };
16
15
  }
17
16
 
17
+ type CountMode = 'exact' | 'planned' | 'estimated';
18
+ interface SelectOptions {
19
+ /**
20
+ * Request a row count from PostgREST via Prefer: count=<mode>.
21
+ * - 'exact': slow, accurate (full scan)
22
+ * - 'planned': fast, planner estimate
23
+ * - 'estimated': best effort (exact if ≤max, planned otherwise)
24
+ */
25
+ count?: CountMode;
26
+ /**
27
+ * Skip the response body — issue a HEAD request. Only the `count` and
28
+ * `status` fields of the result are populated. Use with `count` to get a
29
+ * row count without paying for the data payload.
30
+ */
31
+ head?: boolean;
32
+ }
18
33
  interface QueryBuilderOptions {
19
34
  basePath?: string;
20
35
  signal?: AbortSignal;
@@ -41,7 +56,7 @@ declare class QueryBuilder<T = Record<string, unknown>> implements PromiseLike<P
41
56
  private readonly signal?;
42
57
  private state;
43
58
  constructor(httpClient: HttpClient, table: string, options?: QueryBuilderOptions);
44
- select(columns?: string): this;
59
+ select(columns?: string, options?: SelectOptions): this;
45
60
  insert(data: Partial<T> | Partial<T>[] | Record<string, unknown> | Record<string, unknown>[]): this;
46
61
  update(data: Partial<T> | Record<string, unknown>): this;
47
62
  delete(): this;
@@ -79,18 +94,46 @@ declare class TransactionClient {
79
94
  declare function executeTransaction<T>(httpClient: HttpClient, fn: (tx: TransactionClient) => Promise<T>, options?: TransactionOptions): Promise<PalbaseResponse<T>>;
80
95
 
81
96
  interface DatabaseClientOptions {
82
- enableAdmin?: boolean;
83
97
  /** Override the default `/v1/db` path prefix. Set to empty string for direct PostgREST access. */
84
98
  pathPrefix?: string;
85
99
  }
86
- declare class DatabaseClient {
100
+ /**
101
+ * Extract the Tables record from a typed Database schema.
102
+ * Returns an empty-object type when the schema isn't typed so that
103
+ * `keyof TablesOf<unknown>` = `never` (no tables) — which means the
104
+ * typed-table overload in `from()` never matches for untyped clients,
105
+ * and the callsite falls through to the plain `from<T>(string)` overload.
106
+ */
107
+ type TablesOf<Schema> = Schema extends {
108
+ public: {
109
+ Tables: infer Tables;
110
+ };
111
+ } ? Tables : {};
112
+ /**
113
+ * Given a typed `Database` schema, resolve the Row type for a table name.
114
+ * Falls back to `Record<string, unknown>` when the schema is untyped or
115
+ * the table name isn't in the schema.
116
+ */
117
+ type RowOf<Schema, Name extends string> = Name extends keyof TablesOf<Schema> ? TablesOf<Schema>[Name] extends {
118
+ Row: infer R;
119
+ } ? R : Record<string, unknown> : Record<string, unknown>;
120
+ declare class DatabaseClient<Schema = unknown> {
87
121
  private readonly httpClient;
88
122
  private readonly pathPrefix;
89
- readonly admin?: AdminClient;
90
123
  constructor(httpClient: HttpClient, options?: DatabaseClientOptions);
124
+ /**
125
+ * Get a QueryBuilder for a table.
126
+ *
127
+ * Resolution order for the Row type:
128
+ * 1. Explicit generic: `db.from<Todo>('todos')` → Row = Todo
129
+ * 2. Typed Schema + matching table name: `DatabaseClient<Database>` +
130
+ * `db.from('todos')` → Row = `Schema['public']['Tables']['todos']['Row']`
131
+ * 3. Otherwise: Row = `Record<string, unknown>`
132
+ */
133
+ from<Name extends string & keyof TablesOf<Schema>>(table: Name): QueryBuilder<RowOf<Schema, Name>>;
91
134
  from<T = Record<string, unknown>>(table: string): QueryBuilder<T>;
92
135
  rpc<T = unknown>(fnName: string, params?: Record<string, unknown>): Promise<PalbaseResponse<T>>;
93
136
  transaction<T>(fn: (tx: TransactionClient) => Promise<T>, options?: TransactionOptions): Promise<PalbaseResponse<T>>;
94
137
  }
95
138
 
96
- export { DatabaseClient, type DatabaseClientOptions, type GenericSchema, type GenericTable, MaybeSingleQueryBuilder, type OrderOptions, QueryBuilder, type QueryBuilderOptions, SingleQueryBuilder, TransactionClient, type TransactionOptions, executeTransaction };
139
+ export { type CountMode, DatabaseClient, type DatabaseClientOptions, type GenericSchema, type GenericTable, MaybeSingleQueryBuilder, type OrderOptions, QueryBuilder, type QueryBuilderOptions, type SelectOptions, SingleQueryBuilder, TransactionClient, type TransactionOptions, executeTransaction };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { PalbaseResponse, HttpClient } from '@palbase/core';
2
- import { AdminClient } from './admin.js';
3
2
 
4
3
  interface OrderOptions {
5
4
  ascending?: boolean;
@@ -15,6 +14,22 @@ interface GenericSchema {
15
14
  };
16
15
  }
17
16
 
17
+ type CountMode = 'exact' | 'planned' | 'estimated';
18
+ interface SelectOptions {
19
+ /**
20
+ * Request a row count from PostgREST via Prefer: count=<mode>.
21
+ * - 'exact': slow, accurate (full scan)
22
+ * - 'planned': fast, planner estimate
23
+ * - 'estimated': best effort (exact if ≤max, planned otherwise)
24
+ */
25
+ count?: CountMode;
26
+ /**
27
+ * Skip the response body — issue a HEAD request. Only the `count` and
28
+ * `status` fields of the result are populated. Use with `count` to get a
29
+ * row count without paying for the data payload.
30
+ */
31
+ head?: boolean;
32
+ }
18
33
  interface QueryBuilderOptions {
19
34
  basePath?: string;
20
35
  signal?: AbortSignal;
@@ -41,7 +56,7 @@ declare class QueryBuilder<T = Record<string, unknown>> implements PromiseLike<P
41
56
  private readonly signal?;
42
57
  private state;
43
58
  constructor(httpClient: HttpClient, table: string, options?: QueryBuilderOptions);
44
- select(columns?: string): this;
59
+ select(columns?: string, options?: SelectOptions): this;
45
60
  insert(data: Partial<T> | Partial<T>[] | Record<string, unknown> | Record<string, unknown>[]): this;
46
61
  update(data: Partial<T> | Record<string, unknown>): this;
47
62
  delete(): this;
@@ -79,18 +94,46 @@ declare class TransactionClient {
79
94
  declare function executeTransaction<T>(httpClient: HttpClient, fn: (tx: TransactionClient) => Promise<T>, options?: TransactionOptions): Promise<PalbaseResponse<T>>;
80
95
 
81
96
  interface DatabaseClientOptions {
82
- enableAdmin?: boolean;
83
97
  /** Override the default `/v1/db` path prefix. Set to empty string for direct PostgREST access. */
84
98
  pathPrefix?: string;
85
99
  }
86
- declare class DatabaseClient {
100
+ /**
101
+ * Extract the Tables record from a typed Database schema.
102
+ * Returns an empty-object type when the schema isn't typed so that
103
+ * `keyof TablesOf<unknown>` = `never` (no tables) — which means the
104
+ * typed-table overload in `from()` never matches for untyped clients,
105
+ * and the callsite falls through to the plain `from<T>(string)` overload.
106
+ */
107
+ type TablesOf<Schema> = Schema extends {
108
+ public: {
109
+ Tables: infer Tables;
110
+ };
111
+ } ? Tables : {};
112
+ /**
113
+ * Given a typed `Database` schema, resolve the Row type for a table name.
114
+ * Falls back to `Record<string, unknown>` when the schema is untyped or
115
+ * the table name isn't in the schema.
116
+ */
117
+ type RowOf<Schema, Name extends string> = Name extends keyof TablesOf<Schema> ? TablesOf<Schema>[Name] extends {
118
+ Row: infer R;
119
+ } ? R : Record<string, unknown> : Record<string, unknown>;
120
+ declare class DatabaseClient<Schema = unknown> {
87
121
  private readonly httpClient;
88
122
  private readonly pathPrefix;
89
- readonly admin?: AdminClient;
90
123
  constructor(httpClient: HttpClient, options?: DatabaseClientOptions);
124
+ /**
125
+ * Get a QueryBuilder for a table.
126
+ *
127
+ * Resolution order for the Row type:
128
+ * 1. Explicit generic: `db.from<Todo>('todos')` → Row = Todo
129
+ * 2. Typed Schema + matching table name: `DatabaseClient<Database>` +
130
+ * `db.from('todos')` → Row = `Schema['public']['Tables']['todos']['Row']`
131
+ * 3. Otherwise: Row = `Record<string, unknown>`
132
+ */
133
+ from<Name extends string & keyof TablesOf<Schema>>(table: Name): QueryBuilder<RowOf<Schema, Name>>;
91
134
  from<T = Record<string, unknown>>(table: string): QueryBuilder<T>;
92
135
  rpc<T = unknown>(fnName: string, params?: Record<string, unknown>): Promise<PalbaseResponse<T>>;
93
136
  transaction<T>(fn: (tx: TransactionClient) => Promise<T>, options?: TransactionOptions): Promise<PalbaseResponse<T>>;
94
137
  }
95
138
 
96
- export { DatabaseClient, type DatabaseClientOptions, type GenericSchema, type GenericTable, MaybeSingleQueryBuilder, type OrderOptions, QueryBuilder, type QueryBuilderOptions, SingleQueryBuilder, TransactionClient, type TransactionOptions, executeTransaction };
139
+ export { type CountMode, DatabaseClient, type DatabaseClientOptions, type GenericSchema, type GenericTable, MaybeSingleQueryBuilder, type OrderOptions, QueryBuilder, type QueryBuilderOptions, type SelectOptions, SingleQueryBuilder, TransactionClient, type TransactionOptions, executeTransaction };
package/dist/index.js CHANGED
@@ -1,7 +1,3 @@
1
- import {
2
- AdminClient
3
- } from "./chunk-AQ6ZQNXC.js";
4
-
5
1
  // src/query-builder.ts
6
2
  var TABLE_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;
7
3
  var COLUMN_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.:\->#]*$/;
@@ -58,17 +54,32 @@ var QueryBuilder = class {
58
54
  filters: [],
59
55
  params: {},
60
56
  isSingle: false,
61
- isMaybeSingle: false
57
+ isMaybeSingle: false,
58
+ isHead: false
62
59
  };
63
60
  }
64
61
  // --- Operation methods ---
65
- select(columns) {
62
+ select(columns, options) {
63
+ const nextHeaders = { ...this.state.headers };
64
+ const prefers = [];
65
+ if (this.state.headers.Prefer) {
66
+ prefers.push(this.state.headers.Prefer);
67
+ }
68
+ if (options?.count) {
69
+ prefers.push(`count=${options.count}`);
70
+ }
71
+ if (prefers.length > 0) {
72
+ nextHeaders.Prefer = prefers.join(",");
73
+ }
74
+ const isHead = options?.head === true;
66
75
  this.state = {
67
76
  ...this.state,
68
77
  // Only set GET if no mutation method (POST/PATCH/DELETE) is already set
69
78
  // 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 ?? "*" }
79
+ method: isHead ? "HEAD" : this.state.body !== void 0 ? this.state.method : "GET",
80
+ params: { ...this.state.params, select: columns ?? "*" },
81
+ headers: nextHeaders,
82
+ isHead
72
83
  };
73
84
  return this;
74
85
  }
@@ -379,13 +390,9 @@ var FN_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;
379
390
  var DatabaseClient = class {
380
391
  httpClient;
381
392
  pathPrefix;
382
- admin;
383
393
  constructor(httpClient, options) {
384
394
  this.httpClient = httpClient;
385
395
  this.pathPrefix = options?.pathPrefix ?? "/v1/db";
386
- if (options?.enableAdmin) {
387
- this.admin = new AdminClient(httpClient);
388
- }
389
396
  }
390
397
  from(table) {
391
398
  return new QueryBuilder(this.httpClient, table, {
package/dist/index.js.map CHANGED
@@ -1 +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":[]}
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\ntype HttpMethodWithHead = HttpMethod | 'HEAD';\n\ninterface QueryState<T> {\n readonly method: HttpMethodWithHead;\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 readonly isHead: boolean;\n}\n\nexport type CountMode = 'exact' | 'planned' | 'estimated';\n\nexport interface SelectOptions {\n /**\n * Request a row count from PostgREST via Prefer: count=<mode>.\n * - 'exact': slow, accurate (full scan)\n * - 'planned': fast, planner estimate\n * - 'estimated': best effort (exact if ≤max, planned otherwise)\n */\n count?: CountMode;\n /**\n * Skip the response body — issue a HEAD request. Only the `count` and\n * `status` fields of the result are populated. Use with `count` to get a\n * row count without paying for the data payload.\n */\n head?: 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 isHead: false,\n };\n }\n\n // --- Operation methods ---\n\n select(columns?: string, options?: SelectOptions): this {\n const nextHeaders = { ...this.state.headers };\n const prefers: string[] = [];\n if (this.state.headers.Prefer) {\n prefers.push(this.state.headers.Prefer);\n }\n if (options?.count) {\n prefers.push(`count=${options.count}`);\n }\n if (prefers.length > 0) {\n nextHeaders.Prefer = prefers.join(',');\n }\n\n const isHead = options?.head === true;\n\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: isHead\n ? 'HEAD'\n : this.state.body !== undefined\n ? this.state.method\n : 'GET',\n params: { ...this.state.params, select: columns ?? '*' },\n headers: nextHeaders,\n isHead,\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 { 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 /** Override the default `/v1/db` path prefix. Set to empty string for direct PostgREST access. */\n pathPrefix?: string;\n}\n\n/**\n * Extract the Tables record from a typed Database schema.\n * Returns an empty-object type when the schema isn't typed so that\n * `keyof TablesOf<unknown>` = `never` (no tables) — which means the\n * typed-table overload in `from()` never matches for untyped clients,\n * and the callsite falls through to the plain `from<T>(string)` overload.\n */\n// deno-lint-ignore ban-types\ntype TablesOf<Schema> = Schema extends { public: { Tables: infer Tables } }\n ? Tables\n : {};\n\n/**\n * Given a typed `Database` schema, resolve the Row type for a table name.\n * Falls back to `Record<string, unknown>` when the schema is untyped or\n * the table name isn't in the schema.\n */\ntype RowOf<Schema, Name extends string> =\n Name extends keyof TablesOf<Schema>\n ? TablesOf<Schema>[Name] extends { Row: infer R }\n ? R\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport class DatabaseClient<Schema = unknown> {\n private readonly httpClient: HttpClient;\n private readonly pathPrefix: string;\n\n constructor(httpClient: HttpClient, options?: DatabaseClientOptions) {\n this.httpClient = httpClient;\n this.pathPrefix = options?.pathPrefix ?? '/v1/db';\n }\n\n /**\n * Get a QueryBuilder for a table.\n *\n * Resolution order for the Row type:\n * 1. Explicit generic: `db.from<Todo>('todos')` → Row = Todo\n * 2. Typed Schema + matching table name: `DatabaseClient<Database>` +\n * `db.from('todos')` → Row = `Schema['public']['Tables']['todos']['Row']`\n * 3. Otherwise: Row = `Record<string, unknown>`\n */\n from<Name extends string & keyof TablesOf<Schema>>(\n table: Name,\n ): QueryBuilder<RowOf<Schema, Name>>;\n from<T = Record<string, unknown>>(table: string): QueryBuilder<T>;\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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palbase/db",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -32,7 +32,7 @@
32
32
  "dist"
33
33
  ],
34
34
  "dependencies": {
35
- "@palbase/core": "0.3.0"
35
+ "@palbase/core": "0.4.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@biomejs/biome": "^2.0.0",