summaryrefslogtreecommitdiff
path: root/lib/parsers.ts
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-03-25 15:55:45 +0900
committerjoonhoekim <26rote@gmail.com>2025-03-25 15:55:45 +0900
commit1a2241c40e10193c5ff7008a7b7b36cc1d855d96 (patch)
tree8a5587f10ca55b162d7e3254cb088b323a34c41b /lib/parsers.ts
initial commit
Diffstat (limited to 'lib/parsers.ts')
-rw-r--r--lib/parsers.ts94
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/parsers.ts b/lib/parsers.ts
new file mode 100644
index 00000000..20f3107b
--- /dev/null
+++ b/lib/parsers.ts
@@ -0,0 +1,94 @@
+import type { ExtendedSortingState, Filter } from "@/types/table"
+import { type Row } from "@tanstack/react-table"
+import { createParser } from "nuqs/server"
+import { z } from "zod"
+
+import { dataTableConfig } from "@/config/data-table"
+
+export const sortingItemSchema = z.object({
+ id: z.string(),
+ desc: z.boolean(),
+})
+
+/**
+ * Creates a parser for TanStack Table sorting state.
+ * @param originalRow The original row data to validate sorting keys against.
+ * @returns A parser for TanStack Table sorting state.
+ */
+export const getSortingStateParser = <TData>(
+ originalRow?: Row<TData>["original"]
+) => {
+ const validKeys = originalRow ? new Set(Object.keys(originalRow)) : null
+
+ return createParser<ExtendedSortingState<TData>>({
+ parse: (value) => {
+ try {
+ const parsed = JSON.parse(value)
+ const result = z.array(sortingItemSchema).safeParse(parsed)
+
+ if (!result.success) return null
+
+ if (validKeys && result.data.some((item) => !validKeys.has(item.id))) {
+ return null
+ }
+
+ return result.data as ExtendedSortingState<TData>
+ } catch {
+ return null
+ }
+ },
+ serialize: (value) => JSON.stringify(value),
+ eq: (a, b) =>
+ a.length === b.length &&
+ a.every(
+ (item, index) =>
+ item.id === b[index]?.id && item.desc === b[index]?.desc
+ ),
+ })
+}
+
+export const filterSchema = z.object({
+ id: z.string(),
+ value: z.union([z.string(), z.array(z.string())]),
+ type: z.enum(dataTableConfig.columnTypes),
+ operator: z.enum(dataTableConfig.globalOperators),
+ rowId: z.string(),
+})
+
+/**
+ * Create a parser for data table filters.
+ * @param originalRow The original row data to create the parser for.
+ * @returns A parser for data table filters state.
+ */
+export const getFiltersStateParser = <T>(originalRow?: Row<T>["original"]) => {
+ const validKeys = originalRow ? new Set(Object.keys(originalRow)) : null
+
+ return createParser<Filter<T>[]>({
+ parse: (value) => {
+ try {
+ const parsed = JSON.parse(value)
+ const result = z.array(filterSchema).safeParse(parsed)
+
+ if (!result.success) return null
+
+ if (validKeys && result.data.some((item) => !validKeys.has(item.id))) {
+ return null
+ }
+
+ return result.data as Filter<T>[]
+ } catch {
+ return null
+ }
+ },
+ serialize: (value) => JSON.stringify(value),
+ eq: (a, b) =>
+ a.length === b.length &&
+ a.every(
+ (filter, index) =>
+ filter.id === b[index]?.id &&
+ filter.value === b[index]?.value &&
+ filter.type === b[index]?.type &&
+ filter.operator === b[index]?.operator
+ ),
+ })
+}