@reactor-cloud/data 0.2.0 → 0.3.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.cjs +32 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +32 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -263,6 +263,32 @@ var PostgrestFilterBuilder = class {
|
|
|
263
263
|
}
|
|
264
264
|
};
|
|
265
265
|
var PostgrestQueryBuilder = class extends PostgrestFilterBuilder {
|
|
266
|
+
realtime;
|
|
267
|
+
constructor(ctx, table, realtime) {
|
|
268
|
+
super(ctx, table);
|
|
269
|
+
this.realtime = realtime;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Subscribe to row changes on this table over realtime (a convenience
|
|
273
|
+
* wrapper over `reactor.realtime.channel(...).on('postgres_changes', ...)`).
|
|
274
|
+
*
|
|
275
|
+
* Filters applied with `.eq()` etc. are NOT applied to the subscription;
|
|
276
|
+
* the server enforces RLS and per-record grants on the realtime stream.
|
|
277
|
+
* Returns the underlying {@link RealtimeChannel} so callers can unsubscribe.
|
|
278
|
+
*/
|
|
279
|
+
subscribe(callback, options) {
|
|
280
|
+
if (!this.realtime) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
"Realtime is not configured. Use `createClient(...)` (which wires realtime into the data client) to call `.subscribe()`."
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
const schema = options?.schema ?? "public";
|
|
286
|
+
const event = options?.event ?? "*";
|
|
287
|
+
const channel = this.realtime.channel(`db:${schema}.${this.table}`);
|
|
288
|
+
channel.on("postgres_changes", { event, schema, table: this.table }, callback);
|
|
289
|
+
void channel.subscribe();
|
|
290
|
+
return channel;
|
|
291
|
+
}
|
|
266
292
|
/** Select specific columns */
|
|
267
293
|
select(columns, options) {
|
|
268
294
|
this.selectColumns = columns ?? "*";
|
|
@@ -374,10 +400,12 @@ var RpcBuilder = class {
|
|
|
374
400
|
|
|
375
401
|
// src/client.ts
|
|
376
402
|
var DataClient = class {
|
|
377
|
-
constructor(ctx) {
|
|
403
|
+
constructor(ctx, realtime) {
|
|
378
404
|
this.ctx = ctx;
|
|
405
|
+
this.realtime = realtime;
|
|
379
406
|
}
|
|
380
407
|
ctx;
|
|
408
|
+
realtime;
|
|
381
409
|
/**
|
|
382
410
|
* Start a query on a table.
|
|
383
411
|
*
|
|
@@ -385,7 +413,7 @@ var DataClient = class {
|
|
|
385
413
|
* @returns A query builder
|
|
386
414
|
*/
|
|
387
415
|
from(table) {
|
|
388
|
-
return new PostgrestQueryBuilder(this.ctx, table);
|
|
416
|
+
return new PostgrestQueryBuilder(this.ctx, table, this.realtime);
|
|
389
417
|
}
|
|
390
418
|
/**
|
|
391
419
|
* Call a database function via RPC.
|
|
@@ -409,8 +437,8 @@ var DataClient = class {
|
|
|
409
437
|
return this;
|
|
410
438
|
}
|
|
411
439
|
};
|
|
412
|
-
function createDataClient(ctx) {
|
|
413
|
-
return new DataClient(ctx);
|
|
440
|
+
function createDataClient(ctx, realtime) {
|
|
441
|
+
return new DataClient(ctx, realtime);
|
|
414
442
|
}
|
|
415
443
|
|
|
416
444
|
exports.DataClient = DataClient;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/builder.ts","../src/rpc.ts","../src/client.ts"],"names":["encodeFilterValue","ok","request","post"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n type RequestContext,\n type Result,\n request,\n ok,\n encodeFilterValue,\n} from '@reactor-cloud/shared';\n\nimport type {\n CountMode,\n FilterOperator,\n FilterValue,\n OrderOptions,\n PendingFilter,\n TextSearchOptions,\n UpsertOptions,\n} from './types.js';\n\n/**\n * PostgrestFilterBuilder provides methods for building filter queries.\n */\nexport class PostgrestFilterBuilder<T, ResultType = T[]> {\n protected table: string;\n protected ctx: RequestContext;\n protected selectColumns: string = '*';\n protected filters: PendingFilter[] = [];\n protected orderClauses: string[] = [];\n protected limitValue?: number;\n protected offsetValue?: number;\n protected countMode?: CountMode;\n protected signalValue?: AbortSignal;\n protected customHeaders: Record<string, string> = {};\n protected responseFormat: 'json' | 'csv' = 'json';\n protected explainMode?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean };\n protected resultModifier?: 'single' | 'maybeSingle';\n protected method: 'GET' | 'POST' | 'PATCH' | 'DELETE' = 'GET';\n protected body?: unknown;\n\n constructor(ctx: RequestContext, table: string) {\n this.ctx = ctx;\n this.table = table;\n }\n\n /** Equal to */\n eq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Not equal to */\n neq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'neq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than */\n gt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than or equal */\n gte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than */\n lt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than or equal */\n lte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Pattern match (LIKE) */\n like<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'like', value: pattern, negated: false });\n return this;\n }\n\n /** Case-insensitive pattern match (ILIKE) */\n ilike<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'ilike', value: pattern, negated: false });\n return this;\n }\n\n /** Is NULL or boolean */\n is<K extends keyof T & string>(column: K, value: null | boolean): this {\n this.filters.push({ column, operator: 'is', value, negated: false });\n return this;\n }\n\n /** In list */\n in<K extends keyof T & string>(column: K, values: T[K][]): this {\n this.filters.push({ column, operator: 'in', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contains */\n contains<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cs', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contained by */\n containedBy<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cd', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array overlaps */\n overlaps<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'ov', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Full-text search */\n textSearch<K extends keyof T & string>(column: K, query: string, options?: TextSearchOptions): this {\n const { type = 'plain', config } = options ?? {};\n const value = config ? `${config}:${type}:${query}` : `${type}:${query}`;\n this.filters.push({ column, operator: 'fts', value, negated: false });\n return this;\n }\n\n /** Match multiple conditions (shorthand for multiple eq) */\n match(query: Partial<T>): this {\n for (const [column, value] of Object.entries(query)) {\n if (value !== undefined) {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n }\n }\n return this;\n }\n\n /** Negate a filter */\n not<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: true });\n return this;\n }\n\n /** OR condition (raw string format) */\n or(conditions: string, options?: { foreignTable?: string }): this {\n const column = options?.foreignTable ? `${options.foreignTable}.or` : 'or';\n this.filters.push({ column, operator: 'eq', value: `(${conditions})`, negated: false });\n return this;\n }\n\n /** Generic filter (escape hatch) */\n filter<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: false });\n return this;\n }\n\n /** Order results */\n order<K extends keyof T & string>(column: K, options?: OrderOptions): this {\n const parts = [column as string];\n if (options?.ascending === false) {\n parts.push('desc');\n }\n if (options?.nullsFirst !== undefined) {\n parts.push(options.nullsFirst ? 'nullsfirst' : 'nullslast');\n }\n if (options?.foreignTable) {\n this.orderClauses.push(`${options.foreignTable}(${parts.join('.')})`);\n } else {\n this.orderClauses.push(parts.join('.'));\n }\n return this;\n }\n\n /** Limit results */\n limit(count: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-limit`] = String(count);\n } else {\n this.limitValue = count;\n }\n return this;\n }\n\n /** Offset results (for pagination) */\n range(from: number, to: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-offset`] = String(from);\n this.customHeaders[`${options.foreignTable}-limit`] = String(to - from + 1);\n } else {\n this.offsetValue = from;\n this.limitValue = to - from + 1;\n }\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signalValue = signal;\n return this;\n }\n\n /** Return CSV instead of JSON */\n csv(): PostgrestFilterBuilder<T, string> {\n this.responseFormat = 'csv';\n return this as unknown as PostgrestFilterBuilder<T, string>;\n }\n\n /** Return query execution plan */\n explain(options?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean }): this {\n this.explainMode = options ?? {};\n return this;\n }\n\n /** Override return type */\n returns<R>(): PostgrestFilterBuilder<R, R[]> {\n return this as unknown as PostgrestFilterBuilder<R, R[]>;\n }\n\n /** Execute and return exactly one row (throws if not exactly one) */\n single(): PostgrestFilterBuilder<T, T> {\n this.resultModifier = 'single';\n return this as unknown as PostgrestFilterBuilder<T, T>;\n }\n\n /** Execute and return zero or one row */\n maybeSingle(): PostgrestFilterBuilder<T, T | null> {\n this.resultModifier = 'maybeSingle';\n return this as unknown as PostgrestFilterBuilder<T, T | null>;\n }\n\n protected buildUrl(): string {\n const url = new URL(`/data/v1/${encodeURIComponent(this.table)}`, this.ctx.baseUrl);\n\n // Select\n url.searchParams.set('select', this.selectColumns);\n\n // Filters\n for (const filter of this.filters) {\n const prefix = filter.negated ? 'not.' : '';\n const value = filter.operator === 'in' || filter.operator === 'cs' || filter.operator === 'cd' || filter.operator === 'ov'\n ? encodeFilterValue(filter.value)\n : String(filter.value);\n url.searchParams.append(filter.column, `${prefix}${filter.operator}.${value}`);\n }\n\n // Order\n if (this.orderClauses.length > 0) {\n url.searchParams.set('order', this.orderClauses.join(','));\n }\n\n // Pagination\n if (this.limitValue !== undefined) {\n url.searchParams.set('limit', String(this.limitValue));\n }\n if (this.offsetValue !== undefined) {\n url.searchParams.set('offset', String(this.offsetValue));\n }\n\n return url.toString();\n }\n\n protected buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { ...this.customHeaders };\n\n if (this.countMode) {\n headers['Prefer'] = `count=${this.countMode}`;\n }\n\n if (this.responseFormat === 'csv') {\n headers['Accept'] = 'text/csv';\n }\n\n if (this.explainMode) {\n const parts = ['explain'];\n if (this.explainMode.analyze) parts.push('analyze');\n if (this.explainMode.verbose) parts.push('verbose');\n if (this.explainMode.costs !== false) parts.push('costs');\n if (this.explainMode.buffers) parts.push('buffers');\n headers['Accept'] = `application/vnd.pgrst.plan+${this.responseFormat === 'csv' ? 'text' : 'json'}`;\n }\n\n if (this.resultModifier === 'single' || this.resultModifier === 'maybeSingle') {\n headers['Accept'] = 'application/vnd.pgrst.object+json';\n }\n\n return headers;\n }\n\n /** Execute the query */\n async then<TResult1 = Result<ResultType>, TResult2 = never>(\n onfulfilled?: ((value: Result<ResultType>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not error\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n if (onfulfilled) {\n return onfulfilled(ok(null) as Result<ResultType>);\n }\n return ok(null) as unknown as TResult1;\n }\n\n if (onfulfilled) {\n return onfulfilled(result as Result<ResultType>);\n }\n return result as unknown as TResult1;\n }\n\n protected async execute(): Promise<Result<unknown>> {\n const url = this.buildUrl();\n const headers = this.buildHeaders();\n\n const result = await request<unknown>(this.ctx, url, {\n method: this.method,\n body: this.body,\n headers,\n signal: this.signalValue,\n responseType: this.responseFormat === 'csv' ? 'text' : 'json',\n });\n\n return result;\n }\n\n /** Throw on error instead of returning { data, error } */\n async throwOnError(): Promise<ResultType> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not throw\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n return null as ResultType;\n }\n\n if (result.error) {\n throw result.error;\n }\n return result.data as ResultType;\n }\n}\n\n/**\n * Builder for SELECT queries with column selection.\n */\nexport class PostgrestQueryBuilder<T> extends PostgrestFilterBuilder<T> {\n /** Select specific columns */\n select<Columns extends string = '*'>(\n columns?: Columns,\n options?: { count?: CountMode }\n ): PostgrestFilterBuilder<T> {\n this.selectColumns = columns ?? '*';\n this.countMode = options?.count;\n this.method = 'GET';\n return this;\n }\n\n /** Insert row(s) */\n insert(values: Partial<T> | Partial<T>[], options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Upsert row(s) */\n upsert(values: Partial<T> | Partial<T>[], options?: UpsertOptions): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n this.customHeaders['Prefer'] = `resolution=${options?.ignoreDuplicates ? 'ignore' : 'merge'}-duplicates`;\n if (options?.onConflict) {\n this.customHeaders['Prefer'] += `,on_conflict=${options.onConflict}`;\n }\n return this;\n }\n\n /** Update row(s) */\n update(values: Partial<T>, options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'PATCH';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Delete row(s) */\n delete(options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'DELETE';\n this.countMode = options?.count;\n return this;\n }\n}\n","import {\n type RequestContext,\n type Result,\n post,\n} from '@reactor-cloud/shared';\n\n/**\n * Call a database function via RPC.\n */\nexport async function rpc<Args extends Record<string, unknown>, Returns>(\n ctx: RequestContext,\n functionName: string,\n args: Args,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n): Promise<Result<Returns>> {\n return post<Returns>(\n ctx,\n `/data/v1/rpc/${encodeURIComponent(functionName)}`,\n args,\n {\n signal: options?.signal,\n headers: options?.headers,\n }\n );\n}\n\n/**\n * RPC builder for type-safe function calls.\n */\nexport class RpcBuilder<Args extends Record<string, unknown>, Returns> {\n private args?: Args;\n private signal?: AbortSignal;\n private customHeaders: Record<string, string> = {};\n\n constructor(\n private ctx: RequestContext,\n private functionName: string\n ) {}\n\n /** Set function arguments */\n call(args: Args): this {\n this.args = args;\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signal = signal;\n return this;\n }\n\n /** Set custom headers */\n headers(headers: Record<string, string>): this {\n this.customHeaders = { ...this.customHeaders, ...headers };\n return this;\n }\n\n /** Execute the RPC call */\n async then<TResult1 = Result<Returns>, TResult2 = never>(\n onfulfilled?: ((value: Result<Returns>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (onfulfilled) {\n return onfulfilled(result);\n }\n return result as unknown as TResult1;\n }\n\n /** Throw on error */\n async throwOnError(): Promise<Returns> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (result.error) {\n throw result.error;\n }\n return result.data;\n }\n}\n","import { type RequestContext } from '@reactor-cloud/shared';\nimport { PostgrestQueryBuilder } from './builder.js';\nimport { RpcBuilder } from './rpc.js';\nimport type { GenericSchema } from './types.js';\n\n/**\n * Data client for Reactor - PostgREST-style query builder.\n *\n * @example\n * ```ts\n * const client = new DataClient(ctx);\n *\n * // Select with filters\n * const { data, error } = await client\n * .from('posts')\n * .select('id, title, author:users(name)')\n * .eq('published', true)\n * .order('created_at', { ascending: false })\n * .limit(10);\n *\n * // Insert\n * const { data } = await client\n * .from('posts')\n * .insert({ title: 'Hello', body: 'World' })\n * .select()\n * .single();\n *\n * // RPC\n * const { data } = await client.rpc('search', { query: 'rust' });\n * ```\n */\nexport class DataClient<Schema extends GenericSchema = GenericSchema> {\n constructor(private ctx: RequestContext) {}\n\n /**\n * Start a query on a table.\n *\n * @param table - The table name\n * @returns A query builder\n */\n from<TableName extends keyof Schema['Tables'] & string>(\n table: TableName\n ): PostgrestQueryBuilder<Schema['Tables'][TableName]['Row']> {\n return new PostgrestQueryBuilder(this.ctx, table);\n }\n\n /**\n * Call a database function via RPC.\n *\n * @param functionName - The function name\n * @param args - Function arguments\n * @returns RPC builder\n */\n rpc<\n FunctionName extends keyof Schema['Functions'] & string,\n Args extends Schema['Functions'][FunctionName]['Args'],\n Returns = Schema['Functions'][FunctionName]['Returns']\n >(\n functionName: FunctionName,\n args?: Args\n ): RpcBuilder<Args, Returns> {\n const builder = new RpcBuilder<Args, Returns>(this.ctx, functionName);\n if (args) {\n builder.call(args);\n }\n return builder;\n }\n\n /**\n * Access a schema (for multi-schema support).\n * Currently returns self as we only support public schema.\n */\n schema(_name: string): DataClient<Schema> {\n // TODO: Implement multi-schema support when needed\n return this;\n }\n}\n\n/**\n * Create a data client with typed schema.\n */\nexport function createDataClient<Schema extends GenericSchema = GenericSchema>(\n ctx: RequestContext\n): DataClient<Schema> {\n return new DataClient<Schema>(ctx);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/builder.ts","../src/rpc.ts","../src/client.ts"],"names":["encodeFilterValue","ok","request","post"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n type RequestContext,\n type Result,\n request,\n ok,\n encodeFilterValue,\n} from '@reactor-cloud/shared';\n\nimport type {\n RealtimeClient,\n RealtimeChannel,\n RealtimeChangeEvent,\n RealtimePayload,\n} from '@reactor-cloud/realtime';\n\nimport type {\n CountMode,\n FilterOperator,\n FilterValue,\n OrderOptions,\n PendingFilter,\n TextSearchOptions,\n UpsertOptions,\n} from './types.js';\n\n/**\n * PostgrestFilterBuilder provides methods for building filter queries.\n */\nexport class PostgrestFilterBuilder<T, ResultType = T[]> {\n protected table: string;\n protected ctx: RequestContext;\n protected selectColumns: string = '*';\n protected filters: PendingFilter[] = [];\n protected orderClauses: string[] = [];\n protected limitValue?: number;\n protected offsetValue?: number;\n protected countMode?: CountMode;\n protected signalValue?: AbortSignal;\n protected customHeaders: Record<string, string> = {};\n protected responseFormat: 'json' | 'csv' = 'json';\n protected explainMode?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean };\n protected resultModifier?: 'single' | 'maybeSingle';\n protected method: 'GET' | 'POST' | 'PATCH' | 'DELETE' = 'GET';\n protected body?: unknown;\n\n constructor(ctx: RequestContext, table: string) {\n this.ctx = ctx;\n this.table = table;\n }\n\n /** Equal to */\n eq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Not equal to */\n neq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'neq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than */\n gt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than or equal */\n gte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than */\n lt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than or equal */\n lte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Pattern match (LIKE) */\n like<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'like', value: pattern, negated: false });\n return this;\n }\n\n /** Case-insensitive pattern match (ILIKE) */\n ilike<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'ilike', value: pattern, negated: false });\n return this;\n }\n\n /** Is NULL or boolean */\n is<K extends keyof T & string>(column: K, value: null | boolean): this {\n this.filters.push({ column, operator: 'is', value, negated: false });\n return this;\n }\n\n /** In list */\n in<K extends keyof T & string>(column: K, values: T[K][]): this {\n this.filters.push({ column, operator: 'in', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contains */\n contains<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cs', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contained by */\n containedBy<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cd', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array overlaps */\n overlaps<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'ov', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Full-text search */\n textSearch<K extends keyof T & string>(column: K, query: string, options?: TextSearchOptions): this {\n const { type = 'plain', config } = options ?? {};\n const value = config ? `${config}:${type}:${query}` : `${type}:${query}`;\n this.filters.push({ column, operator: 'fts', value, negated: false });\n return this;\n }\n\n /** Match multiple conditions (shorthand for multiple eq) */\n match(query: Partial<T>): this {\n for (const [column, value] of Object.entries(query)) {\n if (value !== undefined) {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n }\n }\n return this;\n }\n\n /** Negate a filter */\n not<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: true });\n return this;\n }\n\n /** OR condition (raw string format) */\n or(conditions: string, options?: { foreignTable?: string }): this {\n const column = options?.foreignTable ? `${options.foreignTable}.or` : 'or';\n this.filters.push({ column, operator: 'eq', value: `(${conditions})`, negated: false });\n return this;\n }\n\n /** Generic filter (escape hatch) */\n filter<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: false });\n return this;\n }\n\n /** Order results */\n order<K extends keyof T & string>(column: K, options?: OrderOptions): this {\n const parts = [column as string];\n if (options?.ascending === false) {\n parts.push('desc');\n }\n if (options?.nullsFirst !== undefined) {\n parts.push(options.nullsFirst ? 'nullsfirst' : 'nullslast');\n }\n if (options?.foreignTable) {\n this.orderClauses.push(`${options.foreignTable}(${parts.join('.')})`);\n } else {\n this.orderClauses.push(parts.join('.'));\n }\n return this;\n }\n\n /** Limit results */\n limit(count: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-limit`] = String(count);\n } else {\n this.limitValue = count;\n }\n return this;\n }\n\n /** Offset results (for pagination) */\n range(from: number, to: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-offset`] = String(from);\n this.customHeaders[`${options.foreignTable}-limit`] = String(to - from + 1);\n } else {\n this.offsetValue = from;\n this.limitValue = to - from + 1;\n }\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signalValue = signal;\n return this;\n }\n\n /** Return CSV instead of JSON */\n csv(): PostgrestFilterBuilder<T, string> {\n this.responseFormat = 'csv';\n return this as unknown as PostgrestFilterBuilder<T, string>;\n }\n\n /** Return query execution plan */\n explain(options?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean }): this {\n this.explainMode = options ?? {};\n return this;\n }\n\n /** Override return type */\n returns<R>(): PostgrestFilterBuilder<R, R[]> {\n return this as unknown as PostgrestFilterBuilder<R, R[]>;\n }\n\n /** Execute and return exactly one row (throws if not exactly one) */\n single(): PostgrestFilterBuilder<T, T> {\n this.resultModifier = 'single';\n return this as unknown as PostgrestFilterBuilder<T, T>;\n }\n\n /** Execute and return zero or one row */\n maybeSingle(): PostgrestFilterBuilder<T, T | null> {\n this.resultModifier = 'maybeSingle';\n return this as unknown as PostgrestFilterBuilder<T, T | null>;\n }\n\n protected buildUrl(): string {\n const url = new URL(`/data/v1/${encodeURIComponent(this.table)}`, this.ctx.baseUrl);\n\n // Select\n url.searchParams.set('select', this.selectColumns);\n\n // Filters\n for (const filter of this.filters) {\n const prefix = filter.negated ? 'not.' : '';\n const value = filter.operator === 'in' || filter.operator === 'cs' || filter.operator === 'cd' || filter.operator === 'ov'\n ? encodeFilterValue(filter.value)\n : String(filter.value);\n url.searchParams.append(filter.column, `${prefix}${filter.operator}.${value}`);\n }\n\n // Order\n if (this.orderClauses.length > 0) {\n url.searchParams.set('order', this.orderClauses.join(','));\n }\n\n // Pagination\n if (this.limitValue !== undefined) {\n url.searchParams.set('limit', String(this.limitValue));\n }\n if (this.offsetValue !== undefined) {\n url.searchParams.set('offset', String(this.offsetValue));\n }\n\n return url.toString();\n }\n\n protected buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { ...this.customHeaders };\n\n if (this.countMode) {\n headers['Prefer'] = `count=${this.countMode}`;\n }\n\n if (this.responseFormat === 'csv') {\n headers['Accept'] = 'text/csv';\n }\n\n if (this.explainMode) {\n const parts = ['explain'];\n if (this.explainMode.analyze) parts.push('analyze');\n if (this.explainMode.verbose) parts.push('verbose');\n if (this.explainMode.costs !== false) parts.push('costs');\n if (this.explainMode.buffers) parts.push('buffers');\n headers['Accept'] = `application/vnd.pgrst.plan+${this.responseFormat === 'csv' ? 'text' : 'json'}`;\n }\n\n if (this.resultModifier === 'single' || this.resultModifier === 'maybeSingle') {\n headers['Accept'] = 'application/vnd.pgrst.object+json';\n }\n\n return headers;\n }\n\n /** Execute the query */\n async then<TResult1 = Result<ResultType>, TResult2 = never>(\n onfulfilled?: ((value: Result<ResultType>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not error\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n if (onfulfilled) {\n return onfulfilled(ok(null) as Result<ResultType>);\n }\n return ok(null) as unknown as TResult1;\n }\n\n if (onfulfilled) {\n return onfulfilled(result as Result<ResultType>);\n }\n return result as unknown as TResult1;\n }\n\n protected async execute(): Promise<Result<unknown>> {\n const url = this.buildUrl();\n const headers = this.buildHeaders();\n\n const result = await request<unknown>(this.ctx, url, {\n method: this.method,\n body: this.body,\n headers,\n signal: this.signalValue,\n responseType: this.responseFormat === 'csv' ? 'text' : 'json',\n });\n\n return result;\n }\n\n /** Throw on error instead of returning { data, error } */\n async throwOnError(): Promise<ResultType> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not throw\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n return null as ResultType;\n }\n\n if (result.error) {\n throw result.error;\n }\n return result.data as ResultType;\n }\n}\n\n/**\n * Builder for SELECT queries with column selection.\n */\nexport class PostgrestQueryBuilder<T> extends PostgrestFilterBuilder<T> {\n private realtime?: RealtimeClient;\n\n constructor(ctx: RequestContext, table: string, realtime?: RealtimeClient) {\n super(ctx, table);\n this.realtime = realtime;\n }\n\n /**\n * Subscribe to row changes on this table over realtime (a convenience\n * wrapper over `reactor.realtime.channel(...).on('postgres_changes', ...)`).\n *\n * Filters applied with `.eq()` etc. are NOT applied to the subscription;\n * the server enforces RLS and per-record grants on the realtime stream.\n * Returns the underlying {@link RealtimeChannel} so callers can unsubscribe.\n */\n subscribe(\n callback: (payload: RealtimePayload) => void,\n options?: { event?: RealtimeChangeEvent; schema?: string }\n ): RealtimeChannel {\n if (!this.realtime) {\n throw new Error(\n 'Realtime is not configured. Use `createClient(...)` (which wires realtime into the data client) to call `.subscribe()`.'\n );\n }\n const schema = options?.schema ?? 'public';\n const event = options?.event ?? '*';\n const channel = this.realtime.channel(`db:${schema}.${this.table}`);\n channel.on('postgres_changes', { event, schema, table: this.table }, callback);\n void channel.subscribe();\n return channel;\n }\n\n /** Select specific columns */\n select<Columns extends string = '*'>(\n columns?: Columns,\n options?: { count?: CountMode }\n ): PostgrestFilterBuilder<T> {\n this.selectColumns = columns ?? '*';\n this.countMode = options?.count;\n this.method = 'GET';\n return this;\n }\n\n /** Insert row(s) */\n insert(values: Partial<T> | Partial<T>[], options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Upsert row(s) */\n upsert(values: Partial<T> | Partial<T>[], options?: UpsertOptions): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n this.customHeaders['Prefer'] = `resolution=${options?.ignoreDuplicates ? 'ignore' : 'merge'}-duplicates`;\n if (options?.onConflict) {\n this.customHeaders['Prefer'] += `,on_conflict=${options.onConflict}`;\n }\n return this;\n }\n\n /** Update row(s) */\n update(values: Partial<T>, options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'PATCH';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Delete row(s) */\n delete(options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'DELETE';\n this.countMode = options?.count;\n return this;\n }\n}\n","import {\n type RequestContext,\n type Result,\n post,\n} from '@reactor-cloud/shared';\n\n/**\n * Call a database function via RPC.\n */\nexport async function rpc<Args extends Record<string, unknown>, Returns>(\n ctx: RequestContext,\n functionName: string,\n args: Args,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n): Promise<Result<Returns>> {\n return post<Returns>(\n ctx,\n `/data/v1/rpc/${encodeURIComponent(functionName)}`,\n args,\n {\n signal: options?.signal,\n headers: options?.headers,\n }\n );\n}\n\n/**\n * RPC builder for type-safe function calls.\n */\nexport class RpcBuilder<Args extends Record<string, unknown>, Returns> {\n private args?: Args;\n private signal?: AbortSignal;\n private customHeaders: Record<string, string> = {};\n\n constructor(\n private ctx: RequestContext,\n private functionName: string\n ) {}\n\n /** Set function arguments */\n call(args: Args): this {\n this.args = args;\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signal = signal;\n return this;\n }\n\n /** Set custom headers */\n headers(headers: Record<string, string>): this {\n this.customHeaders = { ...this.customHeaders, ...headers };\n return this;\n }\n\n /** Execute the RPC call */\n async then<TResult1 = Result<Returns>, TResult2 = never>(\n onfulfilled?: ((value: Result<Returns>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (onfulfilled) {\n return onfulfilled(result);\n }\n return result as unknown as TResult1;\n }\n\n /** Throw on error */\n async throwOnError(): Promise<Returns> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (result.error) {\n throw result.error;\n }\n return result.data;\n }\n}\n","import { type RequestContext } from '@reactor-cloud/shared';\nimport type { RealtimeClient } from '@reactor-cloud/realtime';\nimport { PostgrestQueryBuilder } from './builder.js';\nimport { RpcBuilder } from './rpc.js';\nimport type { GenericSchema } from './types.js';\n\n/**\n * Data client for Reactor - PostgREST-style query builder.\n *\n * @example\n * ```ts\n * const client = new DataClient(ctx);\n *\n * // Select with filters\n * const { data, error } = await client\n * .from('posts')\n * .select('id, title, author:users(name)')\n * .eq('published', true)\n * .order('created_at', { ascending: false })\n * .limit(10);\n *\n * // Insert\n * const { data } = await client\n * .from('posts')\n * .insert({ title: 'Hello', body: 'World' })\n * .select()\n * .single();\n *\n * // RPC\n * const { data } = await client.rpc('search', { query: 'rust' });\n * ```\n */\nexport class DataClient<Schema extends GenericSchema = GenericSchema> {\n constructor(\n private ctx: RequestContext,\n private realtime?: RealtimeClient\n ) {}\n\n /**\n * Start a query on a table.\n *\n * @param table - The table name\n * @returns A query builder\n */\n from<TableName extends keyof Schema['Tables'] & string>(\n table: TableName\n ): PostgrestQueryBuilder<Schema['Tables'][TableName]['Row']> {\n return new PostgrestQueryBuilder(this.ctx, table, this.realtime);\n }\n\n /**\n * Call a database function via RPC.\n *\n * @param functionName - The function name\n * @param args - Function arguments\n * @returns RPC builder\n */\n rpc<\n FunctionName extends keyof Schema['Functions'] & string,\n Args extends Schema['Functions'][FunctionName]['Args'],\n Returns = Schema['Functions'][FunctionName]['Returns']\n >(\n functionName: FunctionName,\n args?: Args\n ): RpcBuilder<Args, Returns> {\n const builder = new RpcBuilder<Args, Returns>(this.ctx, functionName);\n if (args) {\n builder.call(args);\n }\n return builder;\n }\n\n /**\n * Access a schema (for multi-schema support).\n * Currently returns self as we only support public schema.\n */\n schema(_name: string): DataClient<Schema> {\n // TODO: Implement multi-schema support when needed\n return this;\n }\n}\n\n/**\n * Create a data client with typed schema.\n */\nexport function createDataClient<Schema extends GenericSchema = GenericSchema>(\n ctx: RequestContext,\n realtime?: RealtimeClient\n): DataClient<Schema> {\n return new DataClient<Schema>(ctx, realtime);\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RequestContext, Result } from '@reactor-cloud/shared';
|
|
2
|
+
import { RealtimeClient, RealtimePayload, RealtimeChangeEvent, RealtimeChannel } from '@reactor-cloud/realtime';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Generic schema for untyped queries.
|
|
@@ -203,6 +204,20 @@ declare class PostgrestFilterBuilder<T, ResultType = T[]> {
|
|
|
203
204
|
* Builder for SELECT queries with column selection.
|
|
204
205
|
*/
|
|
205
206
|
declare class PostgrestQueryBuilder<T> extends PostgrestFilterBuilder<T> {
|
|
207
|
+
private realtime?;
|
|
208
|
+
constructor(ctx: RequestContext, table: string, realtime?: RealtimeClient);
|
|
209
|
+
/**
|
|
210
|
+
* Subscribe to row changes on this table over realtime (a convenience
|
|
211
|
+
* wrapper over `reactor.realtime.channel(...).on('postgres_changes', ...)`).
|
|
212
|
+
*
|
|
213
|
+
* Filters applied with `.eq()` etc. are NOT applied to the subscription;
|
|
214
|
+
* the server enforces RLS and per-record grants on the realtime stream.
|
|
215
|
+
* Returns the underlying {@link RealtimeChannel} so callers can unsubscribe.
|
|
216
|
+
*/
|
|
217
|
+
subscribe(callback: (payload: RealtimePayload) => void, options?: {
|
|
218
|
+
event?: RealtimeChangeEvent;
|
|
219
|
+
schema?: string;
|
|
220
|
+
}): RealtimeChannel;
|
|
206
221
|
/** Select specific columns */
|
|
207
222
|
select<Columns extends string = '*'>(columns?: Columns, options?: {
|
|
208
223
|
count?: CountMode;
|
|
@@ -280,7 +295,8 @@ declare class RpcBuilder<Args extends Record<string, unknown>, Returns> {
|
|
|
280
295
|
*/
|
|
281
296
|
declare class DataClient<Schema extends GenericSchema = GenericSchema> {
|
|
282
297
|
private ctx;
|
|
283
|
-
|
|
298
|
+
private realtime?;
|
|
299
|
+
constructor(ctx: RequestContext, realtime?: RealtimeClient | undefined);
|
|
284
300
|
/**
|
|
285
301
|
* Start a query on a table.
|
|
286
302
|
*
|
|
@@ -305,6 +321,6 @@ declare class DataClient<Schema extends GenericSchema = GenericSchema> {
|
|
|
305
321
|
/**
|
|
306
322
|
* Create a data client with typed schema.
|
|
307
323
|
*/
|
|
308
|
-
declare function createDataClient<Schema extends GenericSchema = GenericSchema>(ctx: RequestContext): DataClient<Schema>;
|
|
324
|
+
declare function createDataClient<Schema extends GenericSchema = GenericSchema>(ctx: RequestContext, realtime?: RealtimeClient): DataClient<Schema>;
|
|
309
325
|
|
|
310
326
|
export { type CountMode, DataClient, type FilterOperator, type FilterValue, type GenericSchema, type OrderOptions, type PendingFilter, PostgrestFilterBuilder, PostgrestQueryBuilder, type QueryOptions, type QueryResult, type ResponseFormat, type ResultModifier, RpcBuilder, type SelectResult, type TextSearchOptions, type UpsertOptions, createDataClient, rpc };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RequestContext, Result } from '@reactor-cloud/shared';
|
|
2
|
+
import { RealtimeClient, RealtimePayload, RealtimeChangeEvent, RealtimeChannel } from '@reactor-cloud/realtime';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Generic schema for untyped queries.
|
|
@@ -203,6 +204,20 @@ declare class PostgrestFilterBuilder<T, ResultType = T[]> {
|
|
|
203
204
|
* Builder for SELECT queries with column selection.
|
|
204
205
|
*/
|
|
205
206
|
declare class PostgrestQueryBuilder<T> extends PostgrestFilterBuilder<T> {
|
|
207
|
+
private realtime?;
|
|
208
|
+
constructor(ctx: RequestContext, table: string, realtime?: RealtimeClient);
|
|
209
|
+
/**
|
|
210
|
+
* Subscribe to row changes on this table over realtime (a convenience
|
|
211
|
+
* wrapper over `reactor.realtime.channel(...).on('postgres_changes', ...)`).
|
|
212
|
+
*
|
|
213
|
+
* Filters applied with `.eq()` etc. are NOT applied to the subscription;
|
|
214
|
+
* the server enforces RLS and per-record grants on the realtime stream.
|
|
215
|
+
* Returns the underlying {@link RealtimeChannel} so callers can unsubscribe.
|
|
216
|
+
*/
|
|
217
|
+
subscribe(callback: (payload: RealtimePayload) => void, options?: {
|
|
218
|
+
event?: RealtimeChangeEvent;
|
|
219
|
+
schema?: string;
|
|
220
|
+
}): RealtimeChannel;
|
|
206
221
|
/** Select specific columns */
|
|
207
222
|
select<Columns extends string = '*'>(columns?: Columns, options?: {
|
|
208
223
|
count?: CountMode;
|
|
@@ -280,7 +295,8 @@ declare class RpcBuilder<Args extends Record<string, unknown>, Returns> {
|
|
|
280
295
|
*/
|
|
281
296
|
declare class DataClient<Schema extends GenericSchema = GenericSchema> {
|
|
282
297
|
private ctx;
|
|
283
|
-
|
|
298
|
+
private realtime?;
|
|
299
|
+
constructor(ctx: RequestContext, realtime?: RealtimeClient | undefined);
|
|
284
300
|
/**
|
|
285
301
|
* Start a query on a table.
|
|
286
302
|
*
|
|
@@ -305,6 +321,6 @@ declare class DataClient<Schema extends GenericSchema = GenericSchema> {
|
|
|
305
321
|
/**
|
|
306
322
|
* Create a data client with typed schema.
|
|
307
323
|
*/
|
|
308
|
-
declare function createDataClient<Schema extends GenericSchema = GenericSchema>(ctx: RequestContext): DataClient<Schema>;
|
|
324
|
+
declare function createDataClient<Schema extends GenericSchema = GenericSchema>(ctx: RequestContext, realtime?: RealtimeClient): DataClient<Schema>;
|
|
309
325
|
|
|
310
326
|
export { type CountMode, DataClient, type FilterOperator, type FilterValue, type GenericSchema, type OrderOptions, type PendingFilter, PostgrestFilterBuilder, PostgrestQueryBuilder, type QueryOptions, type QueryResult, type ResponseFormat, type ResultModifier, RpcBuilder, type SelectResult, type TextSearchOptions, type UpsertOptions, createDataClient, rpc };
|
package/dist/index.js
CHANGED
|
@@ -261,6 +261,32 @@ var PostgrestFilterBuilder = class {
|
|
|
261
261
|
}
|
|
262
262
|
};
|
|
263
263
|
var PostgrestQueryBuilder = class extends PostgrestFilterBuilder {
|
|
264
|
+
realtime;
|
|
265
|
+
constructor(ctx, table, realtime) {
|
|
266
|
+
super(ctx, table);
|
|
267
|
+
this.realtime = realtime;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Subscribe to row changes on this table over realtime (a convenience
|
|
271
|
+
* wrapper over `reactor.realtime.channel(...).on('postgres_changes', ...)`).
|
|
272
|
+
*
|
|
273
|
+
* Filters applied with `.eq()` etc. are NOT applied to the subscription;
|
|
274
|
+
* the server enforces RLS and per-record grants on the realtime stream.
|
|
275
|
+
* Returns the underlying {@link RealtimeChannel} so callers can unsubscribe.
|
|
276
|
+
*/
|
|
277
|
+
subscribe(callback, options) {
|
|
278
|
+
if (!this.realtime) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
"Realtime is not configured. Use `createClient(...)` (which wires realtime into the data client) to call `.subscribe()`."
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
const schema = options?.schema ?? "public";
|
|
284
|
+
const event = options?.event ?? "*";
|
|
285
|
+
const channel = this.realtime.channel(`db:${schema}.${this.table}`);
|
|
286
|
+
channel.on("postgres_changes", { event, schema, table: this.table }, callback);
|
|
287
|
+
void channel.subscribe();
|
|
288
|
+
return channel;
|
|
289
|
+
}
|
|
264
290
|
/** Select specific columns */
|
|
265
291
|
select(columns, options) {
|
|
266
292
|
this.selectColumns = columns ?? "*";
|
|
@@ -372,10 +398,12 @@ var RpcBuilder = class {
|
|
|
372
398
|
|
|
373
399
|
// src/client.ts
|
|
374
400
|
var DataClient = class {
|
|
375
|
-
constructor(ctx) {
|
|
401
|
+
constructor(ctx, realtime) {
|
|
376
402
|
this.ctx = ctx;
|
|
403
|
+
this.realtime = realtime;
|
|
377
404
|
}
|
|
378
405
|
ctx;
|
|
406
|
+
realtime;
|
|
379
407
|
/**
|
|
380
408
|
* Start a query on a table.
|
|
381
409
|
*
|
|
@@ -383,7 +411,7 @@ var DataClient = class {
|
|
|
383
411
|
* @returns A query builder
|
|
384
412
|
*/
|
|
385
413
|
from(table) {
|
|
386
|
-
return new PostgrestQueryBuilder(this.ctx, table);
|
|
414
|
+
return new PostgrestQueryBuilder(this.ctx, table, this.realtime);
|
|
387
415
|
}
|
|
388
416
|
/**
|
|
389
417
|
* Call a database function via RPC.
|
|
@@ -407,8 +435,8 @@ var DataClient = class {
|
|
|
407
435
|
return this;
|
|
408
436
|
}
|
|
409
437
|
};
|
|
410
|
-
function createDataClient(ctx) {
|
|
411
|
-
return new DataClient(ctx);
|
|
438
|
+
function createDataClient(ctx, realtime) {
|
|
439
|
+
return new DataClient(ctx, realtime);
|
|
412
440
|
}
|
|
413
441
|
|
|
414
442
|
export { DataClient, PostgrestFilterBuilder, PostgrestQueryBuilder, RpcBuilder, createDataClient, rpc };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/builder.ts","../src/rpc.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n type RequestContext,\n type Result,\n request,\n ok,\n encodeFilterValue,\n} from '@reactor-cloud/shared';\n\nimport type {\n CountMode,\n FilterOperator,\n FilterValue,\n OrderOptions,\n PendingFilter,\n TextSearchOptions,\n UpsertOptions,\n} from './types.js';\n\n/**\n * PostgrestFilterBuilder provides methods for building filter queries.\n */\nexport class PostgrestFilterBuilder<T, ResultType = T[]> {\n protected table: string;\n protected ctx: RequestContext;\n protected selectColumns: string = '*';\n protected filters: PendingFilter[] = [];\n protected orderClauses: string[] = [];\n protected limitValue?: number;\n protected offsetValue?: number;\n protected countMode?: CountMode;\n protected signalValue?: AbortSignal;\n protected customHeaders: Record<string, string> = {};\n protected responseFormat: 'json' | 'csv' = 'json';\n protected explainMode?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean };\n protected resultModifier?: 'single' | 'maybeSingle';\n protected method: 'GET' | 'POST' | 'PATCH' | 'DELETE' = 'GET';\n protected body?: unknown;\n\n constructor(ctx: RequestContext, table: string) {\n this.ctx = ctx;\n this.table = table;\n }\n\n /** Equal to */\n eq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Not equal to */\n neq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'neq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than */\n gt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than or equal */\n gte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than */\n lt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than or equal */\n lte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Pattern match (LIKE) */\n like<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'like', value: pattern, negated: false });\n return this;\n }\n\n /** Case-insensitive pattern match (ILIKE) */\n ilike<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'ilike', value: pattern, negated: false });\n return this;\n }\n\n /** Is NULL or boolean */\n is<K extends keyof T & string>(column: K, value: null | boolean): this {\n this.filters.push({ column, operator: 'is', value, negated: false });\n return this;\n }\n\n /** In list */\n in<K extends keyof T & string>(column: K, values: T[K][]): this {\n this.filters.push({ column, operator: 'in', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contains */\n contains<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cs', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contained by */\n containedBy<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cd', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array overlaps */\n overlaps<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'ov', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Full-text search */\n textSearch<K extends keyof T & string>(column: K, query: string, options?: TextSearchOptions): this {\n const { type = 'plain', config } = options ?? {};\n const value = config ? `${config}:${type}:${query}` : `${type}:${query}`;\n this.filters.push({ column, operator: 'fts', value, negated: false });\n return this;\n }\n\n /** Match multiple conditions (shorthand for multiple eq) */\n match(query: Partial<T>): this {\n for (const [column, value] of Object.entries(query)) {\n if (value !== undefined) {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n }\n }\n return this;\n }\n\n /** Negate a filter */\n not<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: true });\n return this;\n }\n\n /** OR condition (raw string format) */\n or(conditions: string, options?: { foreignTable?: string }): this {\n const column = options?.foreignTable ? `${options.foreignTable}.or` : 'or';\n this.filters.push({ column, operator: 'eq', value: `(${conditions})`, negated: false });\n return this;\n }\n\n /** Generic filter (escape hatch) */\n filter<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: false });\n return this;\n }\n\n /** Order results */\n order<K extends keyof T & string>(column: K, options?: OrderOptions): this {\n const parts = [column as string];\n if (options?.ascending === false) {\n parts.push('desc');\n }\n if (options?.nullsFirst !== undefined) {\n parts.push(options.nullsFirst ? 'nullsfirst' : 'nullslast');\n }\n if (options?.foreignTable) {\n this.orderClauses.push(`${options.foreignTable}(${parts.join('.')})`);\n } else {\n this.orderClauses.push(parts.join('.'));\n }\n return this;\n }\n\n /** Limit results */\n limit(count: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-limit`] = String(count);\n } else {\n this.limitValue = count;\n }\n return this;\n }\n\n /** Offset results (for pagination) */\n range(from: number, to: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-offset`] = String(from);\n this.customHeaders[`${options.foreignTable}-limit`] = String(to - from + 1);\n } else {\n this.offsetValue = from;\n this.limitValue = to - from + 1;\n }\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signalValue = signal;\n return this;\n }\n\n /** Return CSV instead of JSON */\n csv(): PostgrestFilterBuilder<T, string> {\n this.responseFormat = 'csv';\n return this as unknown as PostgrestFilterBuilder<T, string>;\n }\n\n /** Return query execution plan */\n explain(options?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean }): this {\n this.explainMode = options ?? {};\n return this;\n }\n\n /** Override return type */\n returns<R>(): PostgrestFilterBuilder<R, R[]> {\n return this as unknown as PostgrestFilterBuilder<R, R[]>;\n }\n\n /** Execute and return exactly one row (throws if not exactly one) */\n single(): PostgrestFilterBuilder<T, T> {\n this.resultModifier = 'single';\n return this as unknown as PostgrestFilterBuilder<T, T>;\n }\n\n /** Execute and return zero or one row */\n maybeSingle(): PostgrestFilterBuilder<T, T | null> {\n this.resultModifier = 'maybeSingle';\n return this as unknown as PostgrestFilterBuilder<T, T | null>;\n }\n\n protected buildUrl(): string {\n const url = new URL(`/data/v1/${encodeURIComponent(this.table)}`, this.ctx.baseUrl);\n\n // Select\n url.searchParams.set('select', this.selectColumns);\n\n // Filters\n for (const filter of this.filters) {\n const prefix = filter.negated ? 'not.' : '';\n const value = filter.operator === 'in' || filter.operator === 'cs' || filter.operator === 'cd' || filter.operator === 'ov'\n ? encodeFilterValue(filter.value)\n : String(filter.value);\n url.searchParams.append(filter.column, `${prefix}${filter.operator}.${value}`);\n }\n\n // Order\n if (this.orderClauses.length > 0) {\n url.searchParams.set('order', this.orderClauses.join(','));\n }\n\n // Pagination\n if (this.limitValue !== undefined) {\n url.searchParams.set('limit', String(this.limitValue));\n }\n if (this.offsetValue !== undefined) {\n url.searchParams.set('offset', String(this.offsetValue));\n }\n\n return url.toString();\n }\n\n protected buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { ...this.customHeaders };\n\n if (this.countMode) {\n headers['Prefer'] = `count=${this.countMode}`;\n }\n\n if (this.responseFormat === 'csv') {\n headers['Accept'] = 'text/csv';\n }\n\n if (this.explainMode) {\n const parts = ['explain'];\n if (this.explainMode.analyze) parts.push('analyze');\n if (this.explainMode.verbose) parts.push('verbose');\n if (this.explainMode.costs !== false) parts.push('costs');\n if (this.explainMode.buffers) parts.push('buffers');\n headers['Accept'] = `application/vnd.pgrst.plan+${this.responseFormat === 'csv' ? 'text' : 'json'}`;\n }\n\n if (this.resultModifier === 'single' || this.resultModifier === 'maybeSingle') {\n headers['Accept'] = 'application/vnd.pgrst.object+json';\n }\n\n return headers;\n }\n\n /** Execute the query */\n async then<TResult1 = Result<ResultType>, TResult2 = never>(\n onfulfilled?: ((value: Result<ResultType>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not error\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n if (onfulfilled) {\n return onfulfilled(ok(null) as Result<ResultType>);\n }\n return ok(null) as unknown as TResult1;\n }\n\n if (onfulfilled) {\n return onfulfilled(result as Result<ResultType>);\n }\n return result as unknown as TResult1;\n }\n\n protected async execute(): Promise<Result<unknown>> {\n const url = this.buildUrl();\n const headers = this.buildHeaders();\n\n const result = await request<unknown>(this.ctx, url, {\n method: this.method,\n body: this.body,\n headers,\n signal: this.signalValue,\n responseType: this.responseFormat === 'csv' ? 'text' : 'json',\n });\n\n return result;\n }\n\n /** Throw on error instead of returning { data, error } */\n async throwOnError(): Promise<ResultType> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not throw\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n return null as ResultType;\n }\n\n if (result.error) {\n throw result.error;\n }\n return result.data as ResultType;\n }\n}\n\n/**\n * Builder for SELECT queries with column selection.\n */\nexport class PostgrestQueryBuilder<T> extends PostgrestFilterBuilder<T> {\n /** Select specific columns */\n select<Columns extends string = '*'>(\n columns?: Columns,\n options?: { count?: CountMode }\n ): PostgrestFilterBuilder<T> {\n this.selectColumns = columns ?? '*';\n this.countMode = options?.count;\n this.method = 'GET';\n return this;\n }\n\n /** Insert row(s) */\n insert(values: Partial<T> | Partial<T>[], options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Upsert row(s) */\n upsert(values: Partial<T> | Partial<T>[], options?: UpsertOptions): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n this.customHeaders['Prefer'] = `resolution=${options?.ignoreDuplicates ? 'ignore' : 'merge'}-duplicates`;\n if (options?.onConflict) {\n this.customHeaders['Prefer'] += `,on_conflict=${options.onConflict}`;\n }\n return this;\n }\n\n /** Update row(s) */\n update(values: Partial<T>, options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'PATCH';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Delete row(s) */\n delete(options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'DELETE';\n this.countMode = options?.count;\n return this;\n }\n}\n","import {\n type RequestContext,\n type Result,\n post,\n} from '@reactor-cloud/shared';\n\n/**\n * Call a database function via RPC.\n */\nexport async function rpc<Args extends Record<string, unknown>, Returns>(\n ctx: RequestContext,\n functionName: string,\n args: Args,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n): Promise<Result<Returns>> {\n return post<Returns>(\n ctx,\n `/data/v1/rpc/${encodeURIComponent(functionName)}`,\n args,\n {\n signal: options?.signal,\n headers: options?.headers,\n }\n );\n}\n\n/**\n * RPC builder for type-safe function calls.\n */\nexport class RpcBuilder<Args extends Record<string, unknown>, Returns> {\n private args?: Args;\n private signal?: AbortSignal;\n private customHeaders: Record<string, string> = {};\n\n constructor(\n private ctx: RequestContext,\n private functionName: string\n ) {}\n\n /** Set function arguments */\n call(args: Args): this {\n this.args = args;\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signal = signal;\n return this;\n }\n\n /** Set custom headers */\n headers(headers: Record<string, string>): this {\n this.customHeaders = { ...this.customHeaders, ...headers };\n return this;\n }\n\n /** Execute the RPC call */\n async then<TResult1 = Result<Returns>, TResult2 = never>(\n onfulfilled?: ((value: Result<Returns>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (onfulfilled) {\n return onfulfilled(result);\n }\n return result as unknown as TResult1;\n }\n\n /** Throw on error */\n async throwOnError(): Promise<Returns> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (result.error) {\n throw result.error;\n }\n return result.data;\n }\n}\n","import { type RequestContext } from '@reactor-cloud/shared';\nimport { PostgrestQueryBuilder } from './builder.js';\nimport { RpcBuilder } from './rpc.js';\nimport type { GenericSchema } from './types.js';\n\n/**\n * Data client for Reactor - PostgREST-style query builder.\n *\n * @example\n * ```ts\n * const client = new DataClient(ctx);\n *\n * // Select with filters\n * const { data, error } = await client\n * .from('posts')\n * .select('id, title, author:users(name)')\n * .eq('published', true)\n * .order('created_at', { ascending: false })\n * .limit(10);\n *\n * // Insert\n * const { data } = await client\n * .from('posts')\n * .insert({ title: 'Hello', body: 'World' })\n * .select()\n * .single();\n *\n * // RPC\n * const { data } = await client.rpc('search', { query: 'rust' });\n * ```\n */\nexport class DataClient<Schema extends GenericSchema = GenericSchema> {\n constructor(private ctx: RequestContext) {}\n\n /**\n * Start a query on a table.\n *\n * @param table - The table name\n * @returns A query builder\n */\n from<TableName extends keyof Schema['Tables'] & string>(\n table: TableName\n ): PostgrestQueryBuilder<Schema['Tables'][TableName]['Row']> {\n return new PostgrestQueryBuilder(this.ctx, table);\n }\n\n /**\n * Call a database function via RPC.\n *\n * @param functionName - The function name\n * @param args - Function arguments\n * @returns RPC builder\n */\n rpc<\n FunctionName extends keyof Schema['Functions'] & string,\n Args extends Schema['Functions'][FunctionName]['Args'],\n Returns = Schema['Functions'][FunctionName]['Returns']\n >(\n functionName: FunctionName,\n args?: Args\n ): RpcBuilder<Args, Returns> {\n const builder = new RpcBuilder<Args, Returns>(this.ctx, functionName);\n if (args) {\n builder.call(args);\n }\n return builder;\n }\n\n /**\n * Access a schema (for multi-schema support).\n * Currently returns self as we only support public schema.\n */\n schema(_name: string): DataClient<Schema> {\n // TODO: Implement multi-schema support when needed\n return this;\n }\n}\n\n/**\n * Create a data client with typed schema.\n */\nexport function createDataClient<Schema extends GenericSchema = GenericSchema>(\n ctx: RequestContext\n): DataClient<Schema> {\n return new DataClient<Schema>(ctx);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/builder.ts","../src/rpc.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n type RequestContext,\n type Result,\n request,\n ok,\n encodeFilterValue,\n} from '@reactor-cloud/shared';\n\nimport type {\n RealtimeClient,\n RealtimeChannel,\n RealtimeChangeEvent,\n RealtimePayload,\n} from '@reactor-cloud/realtime';\n\nimport type {\n CountMode,\n FilterOperator,\n FilterValue,\n OrderOptions,\n PendingFilter,\n TextSearchOptions,\n UpsertOptions,\n} from './types.js';\n\n/**\n * PostgrestFilterBuilder provides methods for building filter queries.\n */\nexport class PostgrestFilterBuilder<T, ResultType = T[]> {\n protected table: string;\n protected ctx: RequestContext;\n protected selectColumns: string = '*';\n protected filters: PendingFilter[] = [];\n protected orderClauses: string[] = [];\n protected limitValue?: number;\n protected offsetValue?: number;\n protected countMode?: CountMode;\n protected signalValue?: AbortSignal;\n protected customHeaders: Record<string, string> = {};\n protected responseFormat: 'json' | 'csv' = 'json';\n protected explainMode?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean };\n protected resultModifier?: 'single' | 'maybeSingle';\n protected method: 'GET' | 'POST' | 'PATCH' | 'DELETE' = 'GET';\n protected body?: unknown;\n\n constructor(ctx: RequestContext, table: string) {\n this.ctx = ctx;\n this.table = table;\n }\n\n /** Equal to */\n eq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Not equal to */\n neq<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'neq', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than */\n gt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Greater than or equal */\n gte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'gte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than */\n lt<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lt', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Less than or equal */\n lte<K extends keyof T & string>(column: K, value: T[K]): this {\n this.filters.push({ column, operator: 'lte', value: value as FilterValue, negated: false });\n return this;\n }\n\n /** Pattern match (LIKE) */\n like<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'like', value: pattern, negated: false });\n return this;\n }\n\n /** Case-insensitive pattern match (ILIKE) */\n ilike<K extends keyof T & string>(column: K, pattern: string): this {\n this.filters.push({ column, operator: 'ilike', value: pattern, negated: false });\n return this;\n }\n\n /** Is NULL or boolean */\n is<K extends keyof T & string>(column: K, value: null | boolean): this {\n this.filters.push({ column, operator: 'is', value, negated: false });\n return this;\n }\n\n /** In list */\n in<K extends keyof T & string>(column: K, values: T[K][]): this {\n this.filters.push({ column, operator: 'in', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contains */\n contains<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cs', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array contained by */\n containedBy<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'cd', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Array overlaps */\n overlaps<K extends keyof T & string>(column: K, values: unknown[]): this {\n this.filters.push({ column, operator: 'ov', value: values as FilterValue, negated: false });\n return this;\n }\n\n /** Full-text search */\n textSearch<K extends keyof T & string>(column: K, query: string, options?: TextSearchOptions): this {\n const { type = 'plain', config } = options ?? {};\n const value = config ? `${config}:${type}:${query}` : `${type}:${query}`;\n this.filters.push({ column, operator: 'fts', value, negated: false });\n return this;\n }\n\n /** Match multiple conditions (shorthand for multiple eq) */\n match(query: Partial<T>): this {\n for (const [column, value] of Object.entries(query)) {\n if (value !== undefined) {\n this.filters.push({ column, operator: 'eq', value: value as FilterValue, negated: false });\n }\n }\n return this;\n }\n\n /** Negate a filter */\n not<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: true });\n return this;\n }\n\n /** OR condition (raw string format) */\n or(conditions: string, options?: { foreignTable?: string }): this {\n const column = options?.foreignTable ? `${options.foreignTable}.or` : 'or';\n this.filters.push({ column, operator: 'eq', value: `(${conditions})`, negated: false });\n return this;\n }\n\n /** Generic filter (escape hatch) */\n filter<K extends keyof T & string>(column: K, operator: FilterOperator, value: FilterValue): this {\n this.filters.push({ column, operator, value, negated: false });\n return this;\n }\n\n /** Order results */\n order<K extends keyof T & string>(column: K, options?: OrderOptions): this {\n const parts = [column as string];\n if (options?.ascending === false) {\n parts.push('desc');\n }\n if (options?.nullsFirst !== undefined) {\n parts.push(options.nullsFirst ? 'nullsfirst' : 'nullslast');\n }\n if (options?.foreignTable) {\n this.orderClauses.push(`${options.foreignTable}(${parts.join('.')})`);\n } else {\n this.orderClauses.push(parts.join('.'));\n }\n return this;\n }\n\n /** Limit results */\n limit(count: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-limit`] = String(count);\n } else {\n this.limitValue = count;\n }\n return this;\n }\n\n /** Offset results (for pagination) */\n range(from: number, to: number, options?: { foreignTable?: string }): this {\n if (options?.foreignTable) {\n this.customHeaders[`${options.foreignTable}-offset`] = String(from);\n this.customHeaders[`${options.foreignTable}-limit`] = String(to - from + 1);\n } else {\n this.offsetValue = from;\n this.limitValue = to - from + 1;\n }\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signalValue = signal;\n return this;\n }\n\n /** Return CSV instead of JSON */\n csv(): PostgrestFilterBuilder<T, string> {\n this.responseFormat = 'csv';\n return this as unknown as PostgrestFilterBuilder<T, string>;\n }\n\n /** Return query execution plan */\n explain(options?: { analyze?: boolean; verbose?: boolean; costs?: boolean; buffers?: boolean }): this {\n this.explainMode = options ?? {};\n return this;\n }\n\n /** Override return type */\n returns<R>(): PostgrestFilterBuilder<R, R[]> {\n return this as unknown as PostgrestFilterBuilder<R, R[]>;\n }\n\n /** Execute and return exactly one row (throws if not exactly one) */\n single(): PostgrestFilterBuilder<T, T> {\n this.resultModifier = 'single';\n return this as unknown as PostgrestFilterBuilder<T, T>;\n }\n\n /** Execute and return zero or one row */\n maybeSingle(): PostgrestFilterBuilder<T, T | null> {\n this.resultModifier = 'maybeSingle';\n return this as unknown as PostgrestFilterBuilder<T, T | null>;\n }\n\n protected buildUrl(): string {\n const url = new URL(`/data/v1/${encodeURIComponent(this.table)}`, this.ctx.baseUrl);\n\n // Select\n url.searchParams.set('select', this.selectColumns);\n\n // Filters\n for (const filter of this.filters) {\n const prefix = filter.negated ? 'not.' : '';\n const value = filter.operator === 'in' || filter.operator === 'cs' || filter.operator === 'cd' || filter.operator === 'ov'\n ? encodeFilterValue(filter.value)\n : String(filter.value);\n url.searchParams.append(filter.column, `${prefix}${filter.operator}.${value}`);\n }\n\n // Order\n if (this.orderClauses.length > 0) {\n url.searchParams.set('order', this.orderClauses.join(','));\n }\n\n // Pagination\n if (this.limitValue !== undefined) {\n url.searchParams.set('limit', String(this.limitValue));\n }\n if (this.offsetValue !== undefined) {\n url.searchParams.set('offset', String(this.offsetValue));\n }\n\n return url.toString();\n }\n\n protected buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { ...this.customHeaders };\n\n if (this.countMode) {\n headers['Prefer'] = `count=${this.countMode}`;\n }\n\n if (this.responseFormat === 'csv') {\n headers['Accept'] = 'text/csv';\n }\n\n if (this.explainMode) {\n const parts = ['explain'];\n if (this.explainMode.analyze) parts.push('analyze');\n if (this.explainMode.verbose) parts.push('verbose');\n if (this.explainMode.costs !== false) parts.push('costs');\n if (this.explainMode.buffers) parts.push('buffers');\n headers['Accept'] = `application/vnd.pgrst.plan+${this.responseFormat === 'csv' ? 'text' : 'json'}`;\n }\n\n if (this.resultModifier === 'single' || this.resultModifier === 'maybeSingle') {\n headers['Accept'] = 'application/vnd.pgrst.object+json';\n }\n\n return headers;\n }\n\n /** Execute the query */\n async then<TResult1 = Result<ResultType>, TResult2 = never>(\n onfulfilled?: ((value: Result<ResultType>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not error\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n if (onfulfilled) {\n return onfulfilled(ok(null) as Result<ResultType>);\n }\n return ok(null) as unknown as TResult1;\n }\n\n if (onfulfilled) {\n return onfulfilled(result as Result<ResultType>);\n }\n return result as unknown as TResult1;\n }\n\n protected async execute(): Promise<Result<unknown>> {\n const url = this.buildUrl();\n const headers = this.buildHeaders();\n\n const result = await request<unknown>(this.ctx, url, {\n method: this.method,\n body: this.body,\n headers,\n signal: this.signalValue,\n responseType: this.responseFormat === 'csv' ? 'text' : 'json',\n });\n\n return result;\n }\n\n /** Throw on error instead of returning { data, error } */\n async throwOnError(): Promise<ResultType> {\n const result = await this.execute();\n\n // Handle maybeSingle - empty result should return null, not throw\n if (this.resultModifier === 'maybeSingle' && result.error && result.error.statusCode === 406) {\n return null as ResultType;\n }\n\n if (result.error) {\n throw result.error;\n }\n return result.data as ResultType;\n }\n}\n\n/**\n * Builder for SELECT queries with column selection.\n */\nexport class PostgrestQueryBuilder<T> extends PostgrestFilterBuilder<T> {\n private realtime?: RealtimeClient;\n\n constructor(ctx: RequestContext, table: string, realtime?: RealtimeClient) {\n super(ctx, table);\n this.realtime = realtime;\n }\n\n /**\n * Subscribe to row changes on this table over realtime (a convenience\n * wrapper over `reactor.realtime.channel(...).on('postgres_changes', ...)`).\n *\n * Filters applied with `.eq()` etc. are NOT applied to the subscription;\n * the server enforces RLS and per-record grants on the realtime stream.\n * Returns the underlying {@link RealtimeChannel} so callers can unsubscribe.\n */\n subscribe(\n callback: (payload: RealtimePayload) => void,\n options?: { event?: RealtimeChangeEvent; schema?: string }\n ): RealtimeChannel {\n if (!this.realtime) {\n throw new Error(\n 'Realtime is not configured. Use `createClient(...)` (which wires realtime into the data client) to call `.subscribe()`.'\n );\n }\n const schema = options?.schema ?? 'public';\n const event = options?.event ?? '*';\n const channel = this.realtime.channel(`db:${schema}.${this.table}`);\n channel.on('postgres_changes', { event, schema, table: this.table }, callback);\n void channel.subscribe();\n return channel;\n }\n\n /** Select specific columns */\n select<Columns extends string = '*'>(\n columns?: Columns,\n options?: { count?: CountMode }\n ): PostgrestFilterBuilder<T> {\n this.selectColumns = columns ?? '*';\n this.countMode = options?.count;\n this.method = 'GET';\n return this;\n }\n\n /** Insert row(s) */\n insert(values: Partial<T> | Partial<T>[], options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Upsert row(s) */\n upsert(values: Partial<T> | Partial<T>[], options?: UpsertOptions): PostgrestFilterBuilder<T> {\n this.method = 'POST';\n this.body = values;\n this.countMode = options?.count;\n this.customHeaders['Prefer'] = `resolution=${options?.ignoreDuplicates ? 'ignore' : 'merge'}-duplicates`;\n if (options?.onConflict) {\n this.customHeaders['Prefer'] += `,on_conflict=${options.onConflict}`;\n }\n return this;\n }\n\n /** Update row(s) */\n update(values: Partial<T>, options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'PATCH';\n this.body = values;\n this.countMode = options?.count;\n return this;\n }\n\n /** Delete row(s) */\n delete(options?: { count?: CountMode }): PostgrestFilterBuilder<T> {\n this.method = 'DELETE';\n this.countMode = options?.count;\n return this;\n }\n}\n","import {\n type RequestContext,\n type Result,\n post,\n} from '@reactor-cloud/shared';\n\n/**\n * Call a database function via RPC.\n */\nexport async function rpc<Args extends Record<string, unknown>, Returns>(\n ctx: RequestContext,\n functionName: string,\n args: Args,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n): Promise<Result<Returns>> {\n return post<Returns>(\n ctx,\n `/data/v1/rpc/${encodeURIComponent(functionName)}`,\n args,\n {\n signal: options?.signal,\n headers: options?.headers,\n }\n );\n}\n\n/**\n * RPC builder for type-safe function calls.\n */\nexport class RpcBuilder<Args extends Record<string, unknown>, Returns> {\n private args?: Args;\n private signal?: AbortSignal;\n private customHeaders: Record<string, string> = {};\n\n constructor(\n private ctx: RequestContext,\n private functionName: string\n ) {}\n\n /** Set function arguments */\n call(args: Args): this {\n this.args = args;\n return this;\n }\n\n /** Provide an AbortSignal */\n abortSignal(signal: AbortSignal): this {\n this.signal = signal;\n return this;\n }\n\n /** Set custom headers */\n headers(headers: Record<string, string>): this {\n this.customHeaders = { ...this.customHeaders, ...headers };\n return this;\n }\n\n /** Execute the RPC call */\n async then<TResult1 = Result<Returns>, TResult2 = never>(\n onfulfilled?: ((value: Result<Returns>) => TResult1 | PromiseLike<TResult1>) | null,\n _onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (onfulfilled) {\n return onfulfilled(result);\n }\n return result as unknown as TResult1;\n }\n\n /** Throw on error */\n async throwOnError(): Promise<Returns> {\n const result = await rpc<Args, Returns>(\n this.ctx,\n this.functionName,\n this.args ?? ({} as Args),\n {\n signal: this.signal,\n headers: this.customHeaders,\n }\n );\n\n if (result.error) {\n throw result.error;\n }\n return result.data;\n }\n}\n","import { type RequestContext } from '@reactor-cloud/shared';\nimport type { RealtimeClient } from '@reactor-cloud/realtime';\nimport { PostgrestQueryBuilder } from './builder.js';\nimport { RpcBuilder } from './rpc.js';\nimport type { GenericSchema } from './types.js';\n\n/**\n * Data client for Reactor - PostgREST-style query builder.\n *\n * @example\n * ```ts\n * const client = new DataClient(ctx);\n *\n * // Select with filters\n * const { data, error } = await client\n * .from('posts')\n * .select('id, title, author:users(name)')\n * .eq('published', true)\n * .order('created_at', { ascending: false })\n * .limit(10);\n *\n * // Insert\n * const { data } = await client\n * .from('posts')\n * .insert({ title: 'Hello', body: 'World' })\n * .select()\n * .single();\n *\n * // RPC\n * const { data } = await client.rpc('search', { query: 'rust' });\n * ```\n */\nexport class DataClient<Schema extends GenericSchema = GenericSchema> {\n constructor(\n private ctx: RequestContext,\n private realtime?: RealtimeClient\n ) {}\n\n /**\n * Start a query on a table.\n *\n * @param table - The table name\n * @returns A query builder\n */\n from<TableName extends keyof Schema['Tables'] & string>(\n table: TableName\n ): PostgrestQueryBuilder<Schema['Tables'][TableName]['Row']> {\n return new PostgrestQueryBuilder(this.ctx, table, this.realtime);\n }\n\n /**\n * Call a database function via RPC.\n *\n * @param functionName - The function name\n * @param args - Function arguments\n * @returns RPC builder\n */\n rpc<\n FunctionName extends keyof Schema['Functions'] & string,\n Args extends Schema['Functions'][FunctionName]['Args'],\n Returns = Schema['Functions'][FunctionName]['Returns']\n >(\n functionName: FunctionName,\n args?: Args\n ): RpcBuilder<Args, Returns> {\n const builder = new RpcBuilder<Args, Returns>(this.ctx, functionName);\n if (args) {\n builder.call(args);\n }\n return builder;\n }\n\n /**\n * Access a schema (for multi-schema support).\n * Currently returns self as we only support public schema.\n */\n schema(_name: string): DataClient<Schema> {\n // TODO: Implement multi-schema support when needed\n return this;\n }\n}\n\n/**\n * Create a data client with typed schema.\n */\nexport function createDataClient<Schema extends GenericSchema = GenericSchema>(\n ctx: RequestContext,\n realtime?: RealtimeClient\n): DataClient<Schema> {\n return new DataClient<Schema>(ctx, realtime);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactor-cloud/data",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Data client for Reactor JS SDK - PostgREST-style query builder",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"reactor",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"dist"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@reactor-cloud/
|
|
41
|
+
"@reactor-cloud/realtime": "0.3.0",
|
|
42
|
+
"@reactor-cloud/shared": "0.3.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"typescript": "^5.7.2",
|