summaryrefslogtreecommitdiff
path: root/components/client-table-v2/adapter/create-table-service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'components/client-table-v2/adapter/create-table-service.ts')
-rw-r--r--components/client-table-v2/adapter/create-table-service.ts101
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))
+ };
+ };
+}