diff options
Diffstat (limited to 'components/client-table-v2/adapter/create-table-service.ts')
| -rw-r--r-- | components/client-table-v2/adapter/create-table-service.ts | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/components/client-table-v2/adapter/create-table-service.ts b/components/client-table-v2/adapter/create-table-service.ts new file mode 100644 index 00000000..41c38906 --- /dev/null +++ b/components/client-table-v2/adapter/create-table-service.ts @@ -0,0 +1,101 @@ +import { PgTable } from "drizzle-orm/pg-core"; +import { DrizzleTableAdapter, DrizzleTableState } from "./drizzle-table-adapter"; +import { ColumnDef } from "@tanstack/react-table"; +import { SQL, and, count } from "drizzle-orm"; + +// Define a minimal DB interface that we need +// Adjust this to match your actual db instance type +interface DbInstance { + select: (args?: any) => any; +} + +export interface CreateTableServiceConfig<TData> { + /** + * Drizzle Database Instance + */ + db: DbInstance; + + /** + * Drizzle Table Schema (e.g. users, orders) + */ + schema: PgTable; // Using PgTable as base, works for most Drizzle tables + + /** + * React Table Columns Definition + * Used to map accessorKeys to DB columns + */ + columns: ColumnDef<TData, any>[]; + + /** + * Optional: Custom WHERE clause to always apply (e.g. deleted_at IS NULL) + */ + defaultWhere?: SQL; + + /** + * Optional: Custom query modifier + * Allows joining other tables or selecting specific fields + */ + customQuery?: (queryBuilder: any) => any; +} + +/** + * Factory function to create a standardized server action for a table. + * + * @example + * export const getUsers = createTableService({ + * db, + * schema: users, + * columns: userColumns + * }); + */ +export function createTableService<TData>(config: CreateTableServiceConfig<TData>) { + const { db, schema, columns, defaultWhere, customQuery } = config; + + // Return the actual Server Action function + return async function getTableData(tableState: DrizzleTableState) { + const adapter = new DrizzleTableAdapter(schema, columns); + const { where, orderBy, limit, offset, groupBy } = adapter.getQueryParts(tableState); + + // Merge defaultWhere with dynamic where + const finalWhere = defaultWhere + ? (where ? and(defaultWhere, where) : defaultWhere) + : where; + + // 1. Build Data Query + let dataQuery = db.select() + .from(schema) + .where(finalWhere) + .orderBy(...orderBy) + .limit(limit) + .offset(offset); + + if (groupBy && groupBy.length > 0) { + dataQuery = dataQuery.groupBy(...groupBy); + } + + // Apply custom query modifications (joins, etc) + if (customQuery) { + dataQuery = customQuery(dataQuery); + } + + // 2. Build Count Query + const countQuery = db.select({ count: count() }) + .from(schema) + .where(finalWhere); + + // Execute queries + // We use Promise.all to run them in parallel + const [data, countResult] = await Promise.all([ + dataQuery, + countQuery + ]); + + const totalRows = Number(countResult[0]?.count ?? 0); + + return { + data: data as TData[], + totalRows, + pageCount: Math.ceil(totalRows / (tableState.pagination?.pageSize ?? 10)) + }; + }; +} |
