@marktiderman/genesis-core 1.0.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.
Files changed (55) hide show
  1. package/dist/chunk-65SXNHWE.js +3 -0
  2. package/dist/chunk-65SXNHWE.js.map +1 -0
  3. package/dist/chunk-6V2TIN3G.js +202 -0
  4. package/dist/chunk-6V2TIN3G.js.map +1 -0
  5. package/dist/chunk-7KOLYF27.js +50 -0
  6. package/dist/chunk-7KOLYF27.js.map +1 -0
  7. package/dist/chunk-EL7YGOTY.js +3 -0
  8. package/dist/chunk-EL7YGOTY.js.map +1 -0
  9. package/dist/chunk-F4FOTIJI.js +357 -0
  10. package/dist/chunk-F4FOTIJI.js.map +1 -0
  11. package/dist/chunk-LQEICXJS.js +122 -0
  12. package/dist/chunk-LQEICXJS.js.map +1 -0
  13. package/dist/chunk-PVT6FHAO.js +21 -0
  14. package/dist/chunk-PVT6FHAO.js.map +1 -0
  15. package/dist/chunk-RYEXWQFD.js +9 -0
  16. package/dist/chunk-RYEXWQFD.js.map +1 -0
  17. package/dist/chunk-XCX2TRBL.js +3 -0
  18. package/dist/chunk-XCX2TRBL.js.map +1 -0
  19. package/dist/chunk-ZU72FMDR.js +137 -0
  20. package/dist/chunk-ZU72FMDR.js.map +1 -0
  21. package/dist/chunk-ZYJUEJ4Z.js +59 -0
  22. package/dist/chunk-ZYJUEJ4Z.js.map +1 -0
  23. package/dist/form-types.d.ts +50 -0
  24. package/dist/form-types.js +3 -0
  25. package/dist/form-types.js.map +1 -0
  26. package/dist/hooks/index.d.ts +8 -0
  27. package/dist/hooks/index.js +10 -0
  28. package/dist/hooks/index.js.map +1 -0
  29. package/dist/hooks/use-one.d.ts +18 -0
  30. package/dist/hooks/use-one.js +5 -0
  31. package/dist/hooks/use-one.js.map +1 -0
  32. package/dist/hooks/use-resource-form.d.ts +38 -0
  33. package/dist/hooks/use-resource-form.js +7 -0
  34. package/dist/hooks/use-resource-form.js.map +1 -0
  35. package/dist/hooks/use-resource.d.ts +46 -0
  36. package/dist/hooks/use-resource.js +5 -0
  37. package/dist/hooks/use-resource.js.map +1 -0
  38. package/dist/hooks/use-wizard.d.ts +25 -0
  39. package/dist/hooks/use-wizard.js +3 -0
  40. package/dist/hooks/use-wizard.js.map +1 -0
  41. package/dist/index.d.ts +14 -0
  42. package/dist/index.js +13 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/provider/index.d.ts +78 -0
  45. package/dist/provider/index.js +5 -0
  46. package/dist/provider/index.js.map +1 -0
  47. package/dist/storage/index.d.ts +10 -0
  48. package/dist/storage/index.js +4 -0
  49. package/dist/storage/index.js.map +1 -0
  50. package/dist/types-BzcZrTjl.d.ts +119 -0
  51. package/dist/types-DKcxHXxq.d.ts +17 -0
  52. package/dist/utils.d.ts +8 -0
  53. package/dist/utils.js +3 -0
  54. package/dist/utils.js.map +1 -0
  55. package/package.json +67 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-resource-form.ts"],"names":[],"mappings":"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","file":"chunk-F4FOTIJI.js","sourcesContent":["import { useMemo, useCallback, useEffect } from \"react\";\nimport { useForm, type UseFormReturn, type Resolver } from \"react-hook-form\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { z } from \"zod\";\nimport { useOne } from \"./use-one\";\nimport { useDataProvider, useStorage } from \"../provider/context\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { titleCase } from \"../utils\";\nimport type { ResourceFormFieldDef, FieldType } from \"../form-types\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface UseResourceFormOptions {\n resource: string;\n action: \"create\" | \"edit\";\n id?: string;\n initialData?: Record<string, unknown>;\n fields?: ResourceFormFieldDef[];\n /** Full dataset used to auto-detect select fields from unique values. */\n listData?: Record<string, unknown>[];\n onSuccess?: (data: Record<string, unknown>) => void;\n onError?: (error: Error) => void;\n /** Pre-fill create form defaults from URL query params. Default true. */\n prefillFromUrl?: boolean;\n /** Validation trigger mode. Default \"onBlur\". */\n validationMode?: \"onBlur\" | \"onChange\" | \"onSubmit\";\n /** Enable autosave drafts to localStorage for create mode. */\n autosave?: boolean | { debounceMs?: number };\n}\n\nexport interface UseResourceFormReturn {\n form: UseFormReturn<Record<string, unknown>>;\n resolvedFields: ResourceFormFieldDef[];\n onSubmit: (e?: { preventDefault?: () => void }) => Promise<void>;\n /** Raw save handler — use with form.handleSubmit(handleSave, onInvalid). */\n handleSave: (data: Record<string, unknown>) => Promise<void>;\n isSaving: boolean;\n isLoading: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Infer a field type from a value */\nfunction inferFieldType(value: unknown): FieldType {\n if (typeof value === \"boolean\") return \"switch\";\n if (typeof value === \"number\") return \"number\";\n if (typeof value === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) return \"date\";\n if (value.includes(\"@\") && value.includes(\".\")) return \"email\";\n if (/^https?:\\/\\//.test(value)) return \"url\";\n if (value.length > 100) return \"textarea\";\n }\n return \"text\";\n}\n\n/** Try to infer a select field from unique values across the full dataset */\nfunction inferSelectFromData(\n key: string,\n allData: Record<string, unknown>[] | undefined,\n): { type: \"select\"; options: { value: string; label: string }[] } | null {\n if (!allData || allData.length === 0) return null;\n const uniqueValues = new Set<string>();\n for (const row of allData) {\n const v = row[key];\n if (typeof v === \"string\" && v.length > 0) uniqueValues.add(v);\n }\n if (uniqueValues.size > 0 && uniqueValues.size <= 10) {\n return {\n type: \"select\" as const,\n options: Array.from(uniqueValues)\n .sort()\n .map((v) => ({ value: v, label: v })),\n };\n }\n return null;\n}\n\n/** Generate a sensible placeholder for an auto-inferred field */\nfunction defaultPlaceholder(key: string, type: FieldType): string {\n switch (type) {\n case \"email\": return \"name@example.com\";\n case \"url\": return \"https://...\";\n case \"number\": return \"0\";\n case \"date\": return \"YYYY-MM-DD\";\n case \"textarea\": return `Enter ${titleCase(key).toLowerCase()}...`;\n default: return `Enter ${titleCase(key).toLowerCase()}`;\n }\n}\n\n/** Resolve fields from data keys when none provided */\nfunction resolveFields(\n fields: ResourceFormFieldDef[] | undefined,\n data: Record<string, unknown> | undefined,\n allData?: Record<string, unknown>[],\n): ResourceFormFieldDef[] {\n if (fields && fields.length > 0) {\n return fields.map((f) => {\n const inferred = f.type ?? (data ? inferFieldType(data[f.key]) : \"text\");\n return {\n ...f,\n label: f.label ?? titleCase(f.key),\n type: inferred,\n placeholder: f.placeholder ?? defaultPlaceholder(f.key, inferred),\n required: f.required ?? (inferred !== \"switch\" && inferred !== \"checkbox\" && inferred !== \"hidden\"),\n };\n });\n }\n\n if (!data) return [];\n\n return Object.keys(data)\n .filter((key) => key !== \"id\" && key !== \"created_at\" && key !== \"updated_at\")\n .map((key) => {\n // Check for select-like field first (string with few unique values)\n if (typeof data[key] === \"string\") {\n const selectInfo = inferSelectFromData(key, allData);\n if (selectInfo) {\n return {\n key,\n label: titleCase(key),\n type: selectInfo.type,\n options: selectInfo.options,\n placeholder: `Select ${titleCase(key).toLowerCase()}...`,\n required: true,\n };\n }\n }\n\n const inferred = inferFieldType(data[key]);\n return {\n key,\n label: titleCase(key),\n type: inferred,\n placeholder: defaultPlaceholder(key, inferred),\n required: inferred !== \"switch\" && inferred !== \"checkbox\" && inferred !== \"hidden\",\n };\n });\n}\n\n/** Build a zod schema from resolved fields */\nfunction buildSchema(fields: ResourceFormFieldDef[]) {\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const field of fields) {\n const fieldType = field.type ?? \"text\";\n\n if (field.hidden || fieldType === \"hidden\") continue;\n\n // File/image fields store File objects — z.any() is intentional here because\n // the File API shape varies by platform (browser File, React Native asset, etc.)\n // and form libraries may wrap files differently.\n if (fieldType === \"file\" || fieldType === \"image\") {\n shape[field.key] = field.required !== false ? z.unknown().refine((v) => v != null, { message: `${field.label ?? titleCase(field.key)} is required` }) : z.unknown().optional();\n continue;\n }\n\n switch (fieldType) {\n case \"number\": {\n let schema = z.coerce.number({ message: \"Must be a number\" });\n if (field.min != null) schema = schema.min(field.min);\n if (field.max != null) schema = schema.max(field.max);\n shape[field.key] = field.required !== false\n ? schema\n : schema.optional();\n break;\n }\n case \"array\": {\n if (field.arrayFields) {\n const itemShape: Record<string, z.ZodTypeAny> = {};\n for (const sub of field.arrayFields) {\n const subType = sub.type ?? \"text\";\n if (subType === \"number\") {\n let s = z.coerce.number({ message: \"Must be a number\" });\n if (sub.min != null) s = s.min(sub.min);\n if (sub.max != null) s = s.max(sub.max);\n itemShape[sub.key] = sub.required !== false ? s : s.optional();\n } else if (subType === \"switch\" || subType === \"checkbox\") {\n itemShape[sub.key] = z.boolean().optional();\n } else {\n let s = z.string();\n if (sub.required !== false) {\n s = s.min(1, `${sub.label ?? titleCase(sub.key)} is required`);\n }\n if (subType === \"email\") s = s.email(\"Invalid email address\");\n if (subType === \"url\") s = s.url(\"Invalid URL\");\n itemShape[sub.key] = sub.required === false ? s.optional().or(z.literal(\"\")) : s;\n }\n }\n let arraySchema: z.ZodTypeAny = z.array(z.object(itemShape));\n if (field.arrayMin != null) arraySchema = (arraySchema as z.ZodArray<z.ZodTypeAny>).min(field.arrayMin, `Minimum ${field.arrayMin} items required`);\n if (field.arrayMax != null) arraySchema = (arraySchema as z.ZodArray<z.ZodTypeAny>).max(field.arrayMax, `Maximum ${field.arrayMax} items allowed`);\n shape[field.key] = arraySchema;\n }\n break;\n }\n case \"switch\":\n case \"checkbox\": {\n shape[field.key] = z.boolean().optional();\n break;\n }\n default: {\n // text, email, url, textarea, date, select\n let schema = z.string();\n if (field.required !== false) {\n schema = schema.min(1, `${field.label ?? titleCase(field.key)} is required`);\n }\n if (fieldType === \"email\") {\n schema = schema.email(\"Invalid email address\");\n }\n if (fieldType === \"url\") {\n schema = schema.url(\"Invalid URL\");\n }\n shape[field.key] = field.required === false\n ? schema.optional().or(z.literal(\"\"))\n : schema;\n break;\n }\n }\n }\n\n return z.object(shape).passthrough();\n}\n\n/** Build default values for a single array item from its sub-field definitions */\nexport function buildArrayItemDefaults(\n arrayFields: ResourceFormFieldDef[],\n): Record<string, unknown> {\n const defaults: Record<string, unknown> = {};\n for (const sub of arrayFields) {\n const subType = sub.type ?? \"text\";\n if (subType === \"number\") defaults[sub.key] = undefined;\n else if (subType === \"switch\" || subType === \"checkbox\") defaults[sub.key] = false;\n else defaults[sub.key] = sub.defaultValue ?? \"\";\n }\n return defaults;\n}\n\n/** Build default values from fields and existing data */\nfunction buildDefaults(\n fields: ResourceFormFieldDef[],\n data: Record<string, unknown> | undefined,\n action: \"create\" | \"edit\",\n prefillFromUrl: boolean,\n): Record<string, unknown> {\n const defaults: Record<string, unknown> = {};\n for (const field of fields) {\n if (data && field.key in data) {\n defaults[field.key] = data[field.key];\n } else if (field.defaultValue !== undefined) {\n defaults[field.key] = field.defaultValue;\n } else {\n const fieldType = field.type ?? \"text\";\n switch (fieldType) {\n case \"array\":\n defaults[field.key] = field.arrayMin\n ? Array.from({ length: field.arrayMin }, () =>\n buildArrayItemDefaults(field.arrayFields ?? []),\n )\n : [];\n break;\n case \"number\":\n defaults[field.key] = undefined;\n break;\n case \"switch\":\n case \"checkbox\":\n defaults[field.key] = false;\n break;\n default:\n defaults[field.key] = \"\";\n break;\n }\n }\n }\n\n // URL pre-fill for create mode\n if (typeof window !== \"undefined\" && typeof window.location !== \"undefined\" && typeof window.location.search === \"string\" && action === \"create\" && prefillFromUrl !== false) {\n const params = new URLSearchParams(window.location.search);\n for (const field of fields) {\n const val = params.get(field.key);\n if (val != null) {\n defaults[field.key] = field.type === \"number\" ? Number(val) : val;\n }\n }\n }\n\n return defaults;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useResourceForm(options: UseResourceFormOptions): UseResourceFormReturn {\n const {\n resource,\n action,\n id,\n initialData,\n fields: fieldsProp,\n listData,\n onSuccess,\n onError,\n prefillFromUrl = true,\n validationMode,\n autosave,\n } = options;\n\n const autosaveEnabled = !!autosave;\n const debounceMs = typeof autosave === \"object\" ? autosave.debounceMs ?? 1000 : 1000;\n\n const provider = useDataProvider();\n const storage = useStorage();\n const queryClient = useQueryClient();\n\n // Fetch record for edit mode when no initialData\n const needsFetch = action === \"edit\" && !initialData && !!id;\n const fetchResult = useOne(\n resource,\n needsFetch ? id : undefined,\n { enabled: needsFetch },\n );\n\n const fetchedData = fetchResult.data ?? undefined;\n const effectiveData = initialData ?? fetchedData;\n const isLoading = needsFetch && fetchResult.isLoading;\n\n // Resolve fields\n const resolvedFields = useMemo(\n () => resolveFields(fieldsProp, effectiveData, listData),\n [fieldsProp, effectiveData, listData],\n );\n\n // Build schema\n const schema = useMemo(\n () => buildSchema(resolvedFields),\n [resolvedFields],\n );\n\n // Build defaults (with optional draft restoration)\n const defaultValues = useMemo(() => {\n const defaults = buildDefaults(resolvedFields, effectiveData, action, prefillFromUrl);\n if (autosaveEnabled && action === \"create\") {\n const key = `genesis-draft:${resource}:new`;\n const saved = storage.getItem(key);\n if (saved) {\n try {\n const draft = JSON.parse(saved);\n if (draft && typeof draft === \"object\" && !Array.isArray(draft)) {\n // Only restore keys that exist in the field definitions\n const validKeys = new Set(resolvedFields.map((f) => f.key));\n for (const k of Object.keys(draft)) {\n if (validKeys.has(k)) {\n defaults[k] = draft[k];\n }\n }\n } else {\n console.warn(`[useResourceForm] Draft for \"${resource}\" has unexpected shape, removing`);\n storage.removeItem(key);\n }\n } catch {\n console.warn(`[useResourceForm] Corrupt draft for \"${resource}\", removing`);\n storage.removeItem(key);\n }\n }\n }\n return defaults;\n }, [resolvedFields, effectiveData, action, prefillFromUrl, autosaveEnabled, resource, storage]);\n\n // Form\n // Cast the resolver because zod v4's passthrough() produces `unknown` for input,\n // but react-hook-form expects FieldValues (Record<string, any>).\n const resolver = useMemo(\n () => zodResolver(schema) as unknown as Resolver<Record<string, unknown>>,\n [schema],\n );\n\n const form = useForm<Record<string, unknown>>({\n resolver,\n defaultValues,\n values: action === \"edit\" ? defaultValues : undefined,\n mode: validationMode ?? \"onBlur\",\n reValidateMode: \"onChange\",\n shouldUnregister: true,\n });\n\n // Autosave effect — persist form values to storage for create mode\n useEffect(() => {\n if (!autosaveEnabled || action !== \"create\") return;\n const key = `genesis-draft:${resource}:new`;\n let timer: ReturnType<typeof setTimeout>;\n\n const subscription = form.watch((values) => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n try {\n storage.setItem(key, JSON.stringify(values));\n } catch (err) {\n console.warn(`[useResourceForm] Autosave failed for \"${resource}\":`, err instanceof Error ? err.message : String(err));\n }\n }, debounceMs);\n });\n\n return () => {\n clearTimeout(timer);\n subscription.unsubscribe();\n };\n }, [autosaveEnabled, resource, action, form, debounceMs, storage]);\n\n // Submit handler\n const handleSubmit = useCallback(\n async (formData: Record<string, unknown>) => {\n try {\n let result: Record<string, unknown>;\n if (action === \"create\") {\n const res = await provider.create(resource, { data: formData });\n result = res.data;\n } else {\n const recordId = id ?? String((effectiveData as Record<string, unknown>)?.id ?? \"\");\n if (!recordId) {\n throw new Error(\"Cannot update record: no ID available. Provide an id prop or ensure the record has an id field.\");\n }\n const res = await provider.update(resource, { id: recordId, data: formData });\n result = res.data;\n }\n // Clear draft on successful save\n if (autosaveEnabled && action === \"create\") {\n try {\n storage.removeItem(`genesis-draft:${resource}:new`);\n } catch (err) {\n console.warn(`[useResourceForm] Draft cleanup failed for \"${resource}\":`, err instanceof Error ? err.message : String(err));\n }\n }\n // Invalidate queries to refresh data\n await queryClient.invalidateQueries({ queryKey: [resource] });\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n form.setError(\"root\", { message: error.message });\n if (onError) {\n onError(error);\n } else {\n console.error(`[useResourceForm] ${action} failed for \"${resource}\":`, error);\n }\n }\n },\n // form is stable (from useForm) but included for correctness since we call form.setError\n [action, provider, resource, id, effectiveData, queryClient, onSuccess, onError, autosaveEnabled, form, storage],\n );\n\n const onSubmit = useCallback(\n (e?: { preventDefault?: () => void }) => form.handleSubmit(handleSubmit)(e as React.BaseSyntheticEvent),\n [form, handleSubmit],\n );\n\n const isSaving = form.formState.isSubmitting;\n\n return {\n form,\n resolvedFields,\n onSubmit,\n handleSave: handleSubmit,\n isSaving,\n isLoading,\n };\n}\n"]}
@@ -0,0 +1,122 @@
1
+ // src/provider/supabase-provider.ts
2
+ function escapeIlike(value) {
3
+ return value.replace(/[%_\\]/g, (char) => `\\${char}`);
4
+ }
5
+ function createSupabaseProvider(client) {
6
+ function applyFilters(query, filters) {
7
+ if (!filters) return query;
8
+ for (const f of filters) {
9
+ switch (f.operator) {
10
+ case "eq":
11
+ query = query.eq(f.field, f.value);
12
+ break;
13
+ case "neq":
14
+ query = query.neq(f.field, f.value);
15
+ break;
16
+ case "gt":
17
+ query = query.gt(f.field, f.value);
18
+ break;
19
+ case "lt":
20
+ query = query.lt(f.field, f.value);
21
+ break;
22
+ case "gte":
23
+ query = query.gte(f.field, f.value);
24
+ break;
25
+ case "lte":
26
+ query = query.lte(f.field, f.value);
27
+ break;
28
+ case "contains":
29
+ query = query.ilike(f.field, `%${escapeIlike(String(f.value))}%`);
30
+ break;
31
+ case "in":
32
+ query = query.in(f.field, f.value);
33
+ break;
34
+ case "is_null":
35
+ query = query.is(f.field, null);
36
+ break;
37
+ case "is_not_null":
38
+ query = query.not(f.field, "is", null);
39
+ break;
40
+ case "between": {
41
+ const [lo, hi] = f.value;
42
+ query = query.gte(f.field, lo).lte(f.field, hi);
43
+ break;
44
+ }
45
+ default:
46
+ throw new Error(`[SupabaseProvider] Unknown filter operator "${f.operator}"`);
47
+ }
48
+ }
49
+ return query;
50
+ }
51
+ function throwIfError(result) {
52
+ if (result.error) {
53
+ const pgError = result.error;
54
+ const message = pgError.message ?? String(result.error);
55
+ const err = new Error(message, { cause: result.error });
56
+ Object.assign(err, { code: pgError.code, hint: pgError.hint });
57
+ throw err;
58
+ }
59
+ }
60
+ const provider = {
61
+ async getList(resource, params) {
62
+ let query = client.from(resource).select(params.select ?? "*", { count: "exact" });
63
+ query = applyFilters(query, params.filters);
64
+ if (params.search && params.search.query && params.search.fields.length > 0) {
65
+ const escaped = escapeIlike(params.search.query);
66
+ const safeFieldPattern = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;
67
+ const clauses = params.search.fields.filter((f) => safeFieldPattern.test(f)).map((f) => `${f}.ilike.%${escaped}%`).join(",");
68
+ if (clauses) {
69
+ query = query.or(clauses);
70
+ }
71
+ }
72
+ if (params.sort) {
73
+ query = query.order(params.sort.field, {
74
+ ascending: params.sort.order === "asc"
75
+ });
76
+ }
77
+ if (params.pagination) {
78
+ const { page, perPage } = params.pagination;
79
+ const from = (page - 1) * perPage;
80
+ const to = from + perPage - 1;
81
+ query = query.range(from, to);
82
+ }
83
+ const result = await query;
84
+ throwIfError(result);
85
+ return { data: result.data ?? [], total: result.count ?? 0 };
86
+ },
87
+ async getOne(resource, params) {
88
+ const result = await client.from(resource).select(params.select ?? "*").eq("id", params.id).single();
89
+ throwIfError(result);
90
+ return { data: result.data };
91
+ },
92
+ async getMany(resource, params) {
93
+ if (params.ids.length === 0) return { data: [] };
94
+ const result = await client.from(resource).select("*").in("id", params.ids);
95
+ throwIfError(result);
96
+ return { data: result.data ?? [] };
97
+ },
98
+ async create(resource, params) {
99
+ const result = await client.from(resource).insert(params.data).select("*").single();
100
+ throwIfError(result);
101
+ return { data: result.data };
102
+ },
103
+ async update(resource, params) {
104
+ const result = await client.from(resource).update(params.data).eq("id", params.id).select("*").single();
105
+ throwIfError(result);
106
+ return { data: result.data };
107
+ },
108
+ async deleteOne(resource, params) {
109
+ const result = await client.from(resource).delete().eq("id", params.id).select("id").single();
110
+ throwIfError(result);
111
+ if (!result.data) {
112
+ throw new Error(`[SupabaseProvider] Delete failed: no row found with id "${params.id}" in "${resource}"`);
113
+ }
114
+ return { data: result.data };
115
+ }
116
+ };
117
+ return provider;
118
+ }
119
+
120
+ export { createSupabaseProvider };
121
+ //# sourceMappingURL=chunk-LQEICXJS.js.map
122
+ //# sourceMappingURL=chunk-LQEICXJS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider/supabase-provider.ts"],"names":[],"mappings":"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","file":"chunk-LQEICXJS.js","sourcesContent":["import type {\n DataProvider,\n FilterParam,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Minimal Supabase client shape — no hard dependency on @supabase/supabase-js\n// ---------------------------------------------------------------------------\n\n/** A chainable query builder returned by `client.from(table)`. */\ninterface SupabaseQueryBuilder {\n select(\n columns?: string,\n options?: { count?: \"exact\" | \"planned\" | \"estimated\" },\n ): SupabaseQueryBuilder;\n insert(data: Record<string, unknown> | Record<string, unknown>[]): SupabaseQueryBuilder;\n update(data: Record<string, unknown>): SupabaseQueryBuilder;\n delete(): SupabaseQueryBuilder;\n eq(column: string, value: unknown): SupabaseQueryBuilder;\n neq(column: string, value: unknown): SupabaseQueryBuilder;\n gt(column: string, value: unknown): SupabaseQueryBuilder;\n lt(column: string, value: unknown): SupabaseQueryBuilder;\n gte(column: string, value: unknown): SupabaseQueryBuilder;\n lte(column: string, value: unknown): SupabaseQueryBuilder;\n ilike(column: string, value: string): SupabaseQueryBuilder;\n in(column: string, values: unknown[]): SupabaseQueryBuilder;\n is(column: string, value: null): SupabaseQueryBuilder;\n not(column: string, operator: string, value: unknown): SupabaseQueryBuilder;\n or(filters: string): SupabaseQueryBuilder;\n order(column: string, options?: { ascending?: boolean }): SupabaseQueryBuilder;\n range(from: number, to: number): SupabaseQueryBuilder;\n single(): SupabaseQueryBuilder;\n then: Promise<{ data: unknown; error: unknown; count?: number | null }>[\"then\"];\n}\n\n/** Minimal Supabase client interface accepted by the provider. */\nexport interface SupabaseClient {\n from(table: string): SupabaseQueryBuilder;\n}\n\n// ---------------------------------------------------------------------------\n// Provider factory\n// ---------------------------------------------------------------------------\n\nfunction escapeIlike(value: string): string {\n return value.replace(/[%_\\\\]/g, (char) => `\\\\${char}`);\n}\n\nexport function createSupabaseProvider(client: SupabaseClient): DataProvider {\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n function applyFilters(\n query: SupabaseQueryBuilder,\n filters: FilterParam[] | undefined,\n ): SupabaseQueryBuilder {\n if (!filters) return query;\n for (const f of filters) {\n switch (f.operator) {\n case \"eq\":\n query = query.eq(f.field, f.value);\n break;\n case \"neq\":\n query = query.neq(f.field, f.value);\n break;\n case \"gt\":\n query = query.gt(f.field, f.value);\n break;\n case \"lt\":\n query = query.lt(f.field, f.value);\n break;\n case \"gte\":\n query = query.gte(f.field, f.value);\n break;\n case \"lte\":\n query = query.lte(f.field, f.value);\n break;\n case \"contains\":\n query = query.ilike(f.field, `%${escapeIlike(String(f.value))}%`);\n break;\n case \"in\":\n query = query.in(f.field, f.value);\n break;\n case \"is_null\":\n query = query.is(f.field, null);\n break;\n case \"is_not_null\":\n query = query.not(f.field, \"is\", null);\n break;\n case \"between\": {\n const [lo, hi] = f.value;\n query = query.gte(f.field, lo).lte(f.field, hi);\n break;\n }\n default:\n throw new Error(`[SupabaseProvider] Unknown filter operator \"${(f as FilterParam).operator}\"`);\n break;\n }\n }\n return query;\n }\n\n function throwIfError(result: { error: unknown }): void {\n if (result.error) {\n const pgError = result.error as { message?: string; code?: string; hint?: string };\n const message = pgError.message ?? String(result.error);\n const err = new Error(message, { cause: result.error });\n Object.assign(err, { code: pgError.code, hint: pgError.hint });\n throw err;\n }\n }\n\n // ---------------------------------------------------------------------------\n // DataProvider implementation\n // ---------------------------------------------------------------------------\n\n const provider: DataProvider = {\n async getList(resource, params) {\n let query = client\n .from(resource)\n .select(params.select ?? \"*\", { count: \"exact\" });\n\n query = applyFilters(query, params.filters);\n\n // Search — convert to OR of ilike.\n if (params.search && params.search.query && params.search.fields.length > 0) {\n const escaped = escapeIlike(params.search.query);\n const safeFieldPattern = /^[a-zA-Z_][a-zA-Z0-9_.]*$/;\n const clauses = params.search.fields\n .filter((f) => safeFieldPattern.test(f))\n .map((f) => `${f}.ilike.%${escaped}%`)\n .join(\",\");\n if (clauses) {\n query = query.or(clauses);\n }\n }\n\n // Sort.\n if (params.sort) {\n query = query.order(params.sort.field, {\n ascending: params.sort.order === \"asc\",\n });\n }\n\n // Pagination (offset).\n if (params.pagination) {\n const { page, perPage } = params.pagination;\n const from = (page - 1) * perPage;\n const to = from + perPage - 1;\n query = query.range(from, to);\n }\n\n const result = (await query) as {\n data: unknown[];\n error: unknown;\n count?: number | null;\n };\n throwIfError(result);\n\n return { data: result.data ?? [], total: result.count ?? 0 } as never;\n },\n\n async getOne(resource, params) {\n const result = (await client\n .from(resource)\n .select(params.select ?? \"*\")\n .eq(\"id\", params.id)\n .single()) as { data: unknown; error: unknown };\n throwIfError(result);\n return { data: result.data } as never;\n },\n\n async getMany(resource, params) {\n if (params.ids.length === 0) return { data: [] } as never;\n const result = (await client\n .from(resource)\n .select(\"*\")\n .in(\"id\", params.ids)) as { data: unknown[]; error: unknown };\n throwIfError(result);\n return { data: result.data ?? [] } as never;\n },\n\n async create(resource, params) {\n const result = (await client\n .from(resource)\n .insert(params.data as Record<string, unknown>)\n .select(\"*\")\n .single()) as { data: unknown; error: unknown };\n throwIfError(result);\n return { data: result.data } as never;\n },\n\n async update(resource, params) {\n const result = (await client\n .from(resource)\n .update(params.data as Record<string, unknown>)\n .eq(\"id\", params.id)\n .select(\"*\")\n .single()) as { data: unknown; error: unknown };\n throwIfError(result);\n return { data: result.data } as never;\n },\n\n async deleteOne(resource, params) {\n const result = (await client\n .from(resource)\n .delete()\n .eq(\"id\", params.id)\n .select(\"id\")\n .single()) as { data: { id: string | number } | null; error: unknown };\n throwIfError(result);\n if (!result.data) {\n throw new Error(`[SupabaseProvider] Delete failed: no row found with id \"${params.id}\" in \"${resource}\"`);\n }\n return { data: result.data };\n },\n };\n\n return provider;\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { useDataProvider } from './chunk-6V2TIN3G.js';
2
+ import { useQuery } from '@tanstack/react-query';
3
+
4
+ function useOne(resource, id, options = {}) {
5
+ const provider = useDataProvider();
6
+ const { select, enabled } = options;
7
+ const isEnabled = enabled ?? !!id;
8
+ return useQuery({
9
+ queryKey: [resource, "detail", id],
10
+ queryFn: async () => {
11
+ if (id == null) throw new Error("Missing id");
12
+ const result = await provider.getOne(resource, { id, select });
13
+ return result.data;
14
+ },
15
+ enabled: isEnabled
16
+ });
17
+ }
18
+
19
+ export { useOne };
20
+ //# sourceMappingURL=chunk-PVT6FHAO.js.map
21
+ //# sourceMappingURL=chunk-PVT6FHAO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-one.ts"],"names":[],"mappings":";;;AAyBO,SAAS,MAAA,CACd,QAAA,EACA,EAAA,EACA,OAAA,GAAyB,EAAC,EACP;AACnB,EAAA,MAAM,WAAW,eAAA,EAAgB;AAEjC,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAQ,GAAI,OAAA;AAC5B,EAAA,MAAM,SAAA,GAAY,OAAA,IAAW,CAAC,CAAC,EAAA;AAE/B,EAAA,OAAO,QAAA,CAAY;AAAA,IACjB,QAAA,EAAU,CAAC,QAAA,EAAU,QAAA,EAAU,EAAE,CAAA;AAAA,IACjC,SAAS,YAAY;AACnB,MAAA,IAAI,EAAA,IAAM,IAAA,EAAM,MAAM,IAAI,MAAM,YAAY,CAAA;AAC5C,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,MAAA,CAAU,UAAU,EAAE,EAAA,EAAI,QAAQ,CAAA;AAChE,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB,CAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACV,CAAA;AACH","file":"chunk-PVT6FHAO.js","sourcesContent":["import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useDataProvider } from \"../provider/context\";\nimport type { BaseRecord, Identifier } from \"../provider/types\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface UseOneOptions {\n /** Supabase select/join syntax, e.g. \"*, author:profiles(name)\". */\n select?: string;\n /** Defaults to `!!id` — won't fetch when id is falsy. */\n enabled?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch a single record by id, powered by TanStack Query.\n *\n * Returns the full `UseQueryResult<T>` with the data unwrapped from the\n * provider's `GetOneResult` wrapper.\n */\nexport function useOne<T extends BaseRecord = BaseRecord>(\n resource: string,\n id: Identifier | undefined | null,\n options: UseOneOptions = {},\n): UseQueryResult<T> {\n const provider = useDataProvider();\n\n const { select, enabled } = options;\n const isEnabled = enabled ?? !!id;\n\n return useQuery<T>({\n queryKey: [resource, \"detail\", id],\n queryFn: async () => {\n if (id == null) throw new Error(\"Missing id\");\n const result = await provider.getOne<T>(resource, { id, select });\n return result.data;\n },\n enabled: isEnabled,\n });\n}\n"]}
@@ -0,0 +1,9 @@
1
+ // src/utils.ts
2
+ function titleCase(str) {
3
+ const words = str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").split(/\s+/).filter(Boolean);
4
+ return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
5
+ }
6
+
7
+ export { titleCase };
8
+ //# sourceMappingURL=chunk-RYEXWQFD.js.map
9
+ //# sourceMappingURL=chunk-RYEXWQFD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"names":[],"mappings":";AAKO,SAAS,UAAU,GAAA,EAAqB;AAE7C,EAAA,MAAM,KAAA,GAAQ,GAAA,CACX,OAAA,CAAQ,iBAAA,EAAmB,OAAO,CAAA,CAClC,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAA,CACpB,KAAA,CAAM,KAAK,CAAA,CACX,OAAO,OAAO,CAAA;AAEjB,EAAA,OAAO,MACJ,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,aAAa,CAAA,CAC/D,KAAK,GAAG,CAAA;AACb","file":"chunk-RYEXWQFD.js","sourcesContent":["/**\n * Convert a key string to title case.\n * \"created_at\" -> \"Created At\"\n * \"firstName\" -> \"First Name\"\n */\nexport function titleCase(str: string): string {\n // Split on underscores, hyphens, and camelCase boundaries\n const words = str\n .replace(/([a-z])([A-Z])/g, \"$1 $2\") // camelCase -> camel Case\n .replace(/[_-]/g, \" \") // snake_case / kebab-case -> spaces\n .split(/\\s+/)\n .filter(Boolean);\n\n return words\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n .join(\" \");\n}\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-XCX2TRBL.js.map
3
+ //# sourceMappingURL=chunk-XCX2TRBL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-XCX2TRBL.js"}
@@ -0,0 +1,137 @@
1
+ import { useDataProvider } from './chunk-6V2TIN3G.js';
2
+ import { useState, useCallback, useMemo } from 'react';
3
+ import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
4
+
5
+ function useResource(resource, options = {}) {
6
+ const {
7
+ defaultSort,
8
+ defaultFilters,
9
+ defaultPerPage = 25,
10
+ select,
11
+ searchFields: searchFieldsOption,
12
+ enabled = true,
13
+ onCreateSuccess,
14
+ onUpdateSuccess,
15
+ onDeleteSuccess,
16
+ onError
17
+ } = options;
18
+ const provider = useDataProvider();
19
+ const queryClient = useQueryClient();
20
+ const [sort, setSortRaw] = useState(defaultSort);
21
+ const [filters, setFiltersRaw] = useState(defaultFilters ?? []);
22
+ const [page, setPage] = useState(1);
23
+ const [perPage, setPerPageRaw] = useState(defaultPerPage);
24
+ const [searchQuery, setSearchQuery] = useState("");
25
+ const setSort = useCallback((s) => {
26
+ setSortRaw(s);
27
+ setPage(1);
28
+ }, []);
29
+ const setFilters = useCallback((f) => {
30
+ setFiltersRaw(f);
31
+ setPage(1);
32
+ }, []);
33
+ const setPerPage = useCallback((value) => {
34
+ setPerPageRaw(value);
35
+ setPage(1);
36
+ }, []);
37
+ const setSearch = useCallback((query) => {
38
+ setSearchQuery(query);
39
+ setPage(1);
40
+ }, []);
41
+ const params = useMemo(() => {
42
+ const p = {
43
+ pagination: { page, perPage },
44
+ sort,
45
+ filters: filters.length > 0 ? filters : void 0,
46
+ select
47
+ };
48
+ if (searchQuery && searchFieldsOption && searchFieldsOption.length > 0) {
49
+ p.search = { query: searchQuery, fields: searchFieldsOption };
50
+ }
51
+ return p;
52
+ }, [page, perPage, sort, filters, select, searchQuery, searchFieldsOption]);
53
+ const listQueryKey = useMemo(
54
+ () => [resource, "list", params],
55
+ [resource, params]
56
+ );
57
+ const list = useQuery({
58
+ queryKey: listQueryKey,
59
+ queryFn: () => provider.getList(resource, params),
60
+ enabled
61
+ });
62
+ const invalidateResource = useCallback(
63
+ () => queryClient.invalidateQueries({ queryKey: [resource] }),
64
+ [queryClient, resource]
65
+ );
66
+ const defaultOnError = useCallback(
67
+ (error) => {
68
+ console.error(`[useResource] ${resource} mutation failed:`, error.message);
69
+ },
70
+ [resource]
71
+ );
72
+ const createMutation = useMutation({
73
+ mutationFn: async (data) => {
74
+ const result = await provider.create(resource, { data });
75
+ return result.data;
76
+ },
77
+ onSuccess: (data) => {
78
+ invalidateResource();
79
+ onCreateSuccess?.(data);
80
+ },
81
+ onError: onError ?? defaultOnError
82
+ });
83
+ const updateMutation = useMutation({
84
+ mutationFn: async ({ id, data }) => {
85
+ const result = await provider.update(resource, { id, data });
86
+ return result.data;
87
+ },
88
+ onSuccess: (data) => {
89
+ invalidateResource();
90
+ onUpdateSuccess?.(data);
91
+ },
92
+ onError: onError ?? defaultOnError
93
+ });
94
+ const deleteMutation = useMutation({
95
+ mutationFn: async (id) => {
96
+ await provider.deleteOne(resource, { id });
97
+ },
98
+ onSuccess: () => {
99
+ invalidateResource();
100
+ onDeleteSuccess?.();
101
+ },
102
+ onError: onError ?? defaultOnError
103
+ });
104
+ const create = useCallback(
105
+ (data) => createMutation.mutateAsync(data),
106
+ [createMutation]
107
+ );
108
+ const update = useCallback(
109
+ (id, data) => updateMutation.mutateAsync({ id, data }),
110
+ [updateMutation]
111
+ );
112
+ const remove = useCallback(
113
+ (id) => deleteMutation.mutateAsync(id),
114
+ [deleteMutation]
115
+ );
116
+ const isMutating = createMutation.isPending || updateMutation.isPending || deleteMutation.isPending;
117
+ return {
118
+ list,
119
+ params,
120
+ setSort,
121
+ setFilters,
122
+ setPage,
123
+ setPerPage,
124
+ setSearch,
125
+ create,
126
+ update,
127
+ remove,
128
+ isMutating,
129
+ createMutation,
130
+ updateMutation,
131
+ deleteMutation
132
+ };
133
+ }
134
+
135
+ export { useResource };
136
+ //# sourceMappingURL=chunk-ZU72FMDR.js.map
137
+ //# sourceMappingURL=chunk-ZU72FMDR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-resource.ts"],"names":[],"mappings":"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","file":"chunk-ZU72FMDR.js","sourcesContent":["import { useState, useCallback, useMemo } from \"react\";\nimport {\n useQuery,\n useMutation,\n useQueryClient,\n type UseQueryResult,\n type UseMutationResult,\n} from \"@tanstack/react-query\";\nimport { useDataProvider } from \"../provider/context\";\nimport type {\n BaseRecord,\n Identifier,\n SortParam,\n FilterParam,\n ListParams,\n ListResult,\n} from \"../provider/types\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface UseResourceOptions<T> {\n defaultSort?: SortParam;\n defaultFilters?: FilterParam[];\n defaultPerPage?: number;\n /** Supabase select/join syntax, e.g. \"*, author:profiles(name)\". */\n select?: string;\n /** Fields to search across when setSearch is called. Required for server-side search. */\n searchFields?: string[];\n /** Disable auto-fetching. */\n enabled?: boolean;\n onCreateSuccess?: (data: T) => void;\n onUpdateSuccess?: (data: T) => void;\n onDeleteSuccess?: () => void;\n onError?: (error: Error) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Return type\n// ---------------------------------------------------------------------------\n\nexport interface UseResourceReturn<T> {\n /** TanStack Query result for the list query. */\n list: UseQueryResult<ListResult<T>>;\n /** Current list params (pagination, sort, filters, search). */\n params: ListParams;\n setSort: (sort: SortParam | undefined) => void;\n setFilters: (filters: FilterParam[]) => void;\n setPage: (page: number) => void;\n setPerPage: (perPage: number) => void;\n setSearch: (query: string) => void;\n /** Create a new record. Returns the created item. */\n create: (data: Partial<T>) => Promise<T>;\n /** Update an existing record by id. Returns the updated item. */\n update: (id: Identifier, data: Partial<T>) => Promise<T>;\n /** Delete a record by id. */\n remove: (id: Identifier) => Promise<void>;\n /** True when any mutation is in-flight. */\n isMutating: boolean;\n createMutation: UseMutationResult<T, Error, Partial<T>>;\n updateMutation: UseMutationResult<T, Error, { id: Identifier; data: Partial<T> }>;\n deleteMutation: UseMutationResult<void, Error, Identifier>;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useResource<T extends BaseRecord = BaseRecord>(\n resource: string,\n options: UseResourceOptions<T> = {},\n): UseResourceReturn<T> {\n const {\n defaultSort,\n defaultFilters,\n defaultPerPage = 25,\n select,\n searchFields: searchFieldsOption,\n enabled = true,\n onCreateSuccess,\n onUpdateSuccess,\n onDeleteSuccess,\n onError,\n } = options;\n\n const provider = useDataProvider();\n const queryClient = useQueryClient();\n\n // -------------------------------------------------------------------------\n // State\n // -------------------------------------------------------------------------\n\n const [sort, setSortRaw] = useState<SortParam | undefined>(defaultSort);\n const [filters, setFiltersRaw] = useState<FilterParam[]>(defaultFilters ?? []);\n const [page, setPage] = useState(1);\n const [perPage, setPerPageRaw] = useState(defaultPerPage);\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n const setSort = useCallback((s: SortParam | undefined) => {\n setSortRaw(s);\n setPage(1);\n }, []);\n\n const setFilters = useCallback((f: FilterParam[]) => {\n setFiltersRaw(f);\n setPage(1);\n }, []);\n\n const setPerPage = useCallback((value: number) => {\n setPerPageRaw(value);\n setPage(1);\n }, []);\n\n const setSearch = useCallback((query: string) => {\n setSearchQuery(query);\n setPage(1);\n }, []);\n\n // -------------------------------------------------------------------------\n // Params\n // -------------------------------------------------------------------------\n\n const params = useMemo<ListParams>(() => {\n const p: ListParams = {\n pagination: { page, perPage },\n sort,\n filters: filters.length > 0 ? filters : undefined,\n select,\n };\n if (searchQuery && searchFieldsOption && searchFieldsOption.length > 0) {\n p.search = { query: searchQuery, fields: searchFieldsOption };\n }\n return p;\n }, [page, perPage, sort, filters, select, searchQuery, searchFieldsOption]);\n\n // -------------------------------------------------------------------------\n // List query\n // -------------------------------------------------------------------------\n\n const listQueryKey = useMemo(\n () => [resource, \"list\", params] as const,\n [resource, params],\n );\n\n const list = useQuery<ListResult<T>>({\n queryKey: listQueryKey,\n queryFn: () => provider.getList<T>(resource, params),\n enabled,\n });\n\n // -------------------------------------------------------------------------\n // Mutations\n // -------------------------------------------------------------------------\n\n const invalidateResource = useCallback(\n () => queryClient.invalidateQueries({ queryKey: [resource] }),\n [queryClient, resource],\n );\n\n const defaultOnError = useCallback(\n (error: Error) => {\n console.error(`[useResource] ${resource} mutation failed:`, error.message);\n },\n [resource],\n );\n\n const createMutation = useMutation<T, Error, Partial<T>>({\n mutationFn: async (data) => {\n const result = await provider.create<T>(resource, { data });\n return result.data;\n },\n onSuccess: (data) => {\n invalidateResource();\n onCreateSuccess?.(data);\n },\n onError: onError ?? defaultOnError,\n });\n\n const updateMutation = useMutation<\n T,\n Error,\n { id: Identifier; data: Partial<T> }\n >({\n mutationFn: async ({ id, data }) => {\n const result = await provider.update<T>(resource, { id, data });\n return result.data;\n },\n onSuccess: (data) => {\n invalidateResource();\n onUpdateSuccess?.(data);\n },\n onError: onError ?? defaultOnError,\n });\n\n const deleteMutation = useMutation<void, Error, Identifier>({\n mutationFn: async (id) => {\n await provider.deleteOne(resource, { id });\n },\n onSuccess: () => {\n invalidateResource();\n onDeleteSuccess?.();\n },\n onError: onError ?? defaultOnError,\n });\n\n // -------------------------------------------------------------------------\n // Convenience wrappers\n // -------------------------------------------------------------------------\n\n const create = useCallback(\n (data: Partial<T>) => createMutation.mutateAsync(data),\n [createMutation],\n );\n\n const update = useCallback(\n (id: Identifier, data: Partial<T>) =>\n updateMutation.mutateAsync({ id, data }),\n [updateMutation],\n );\n\n const remove = useCallback(\n (id: Identifier) => deleteMutation.mutateAsync(id),\n [deleteMutation],\n );\n\n const isMutating =\n createMutation.isPending ||\n updateMutation.isPending ||\n deleteMutation.isPending;\n\n return {\n list,\n params,\n setSort,\n setFilters,\n setPage,\n setPerPage,\n setSearch,\n create,\n update,\n remove,\n isMutating,\n createMutation,\n updateMutation,\n deleteMutation,\n };\n}\n"]}
@@ -0,0 +1,59 @@
1
+ // src/storage/adapters.ts
2
+ function createLocalStorageAdapter() {
3
+ return {
4
+ getItem(key) {
5
+ if (typeof window === "undefined" || typeof localStorage === "undefined") return null;
6
+ try {
7
+ return localStorage.getItem(key);
8
+ } catch (err) {
9
+ console.warn(`[StorageAdapter] Failed to read "${key}":`, err instanceof Error ? err.message : String(err));
10
+ return null;
11
+ }
12
+ },
13
+ setItem(key, value) {
14
+ if (typeof window === "undefined" || typeof localStorage === "undefined") return;
15
+ try {
16
+ localStorage.setItem(key, value);
17
+ } catch (err) {
18
+ console.warn(`[StorageAdapter] Failed to write "${key}":`, err instanceof Error ? err.message : String(err));
19
+ }
20
+ },
21
+ removeItem(key) {
22
+ if (typeof window === "undefined" || typeof localStorage === "undefined") return;
23
+ try {
24
+ localStorage.removeItem(key);
25
+ } catch (err) {
26
+ console.warn(`[StorageAdapter] Failed to remove "${key}":`, err instanceof Error ? err.message : String(err));
27
+ }
28
+ }
29
+ };
30
+ }
31
+ function createMemoryStorageAdapter() {
32
+ const store = /* @__PURE__ */ new Map();
33
+ return {
34
+ getItem(key) {
35
+ return store.get(key) ?? null;
36
+ },
37
+ setItem(key, value) {
38
+ store.set(key, value);
39
+ },
40
+ removeItem(key) {
41
+ store.delete(key);
42
+ }
43
+ };
44
+ }
45
+ function createNoopStorageAdapter() {
46
+ return {
47
+ getItem() {
48
+ return null;
49
+ },
50
+ setItem() {
51
+ },
52
+ removeItem() {
53
+ }
54
+ };
55
+ }
56
+
57
+ export { createLocalStorageAdapter, createMemoryStorageAdapter, createNoopStorageAdapter };
58
+ //# sourceMappingURL=chunk-ZYJUEJ4Z.js.map
59
+ //# sourceMappingURL=chunk-ZYJUEJ4Z.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/adapters.ts"],"names":[],"mappings":";AAGO,SAAS,yBAAA,GAA4C;AAC1D,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,EAAK;AACX,MAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,YAAA,KAAiB,aAAa,OAAO,IAAA;AACjF,MAAA,IAAI;AACF,QAAA,OAAO,YAAA,CAAa,QAAQ,GAAG,CAAA;AAAA,MACjC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,iCAAA,EAAoC,GAAG,CAAA,EAAA,CAAA,EAAM,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAC1G,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAA;AAAA,IACA,OAAA,CAAQ,KAAK,KAAA,EAAO;AAClB,MAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,iBAAiB,WAAA,EAAa;AAC1E,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,MACjC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,kCAAA,EAAqC,GAAG,CAAA,EAAA,CAAA,EAAM,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,MAC7G;AAAA,IACF,CAAA;AAAA,IACA,WAAW,GAAA,EAAK;AACd,MAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,iBAAiB,WAAA,EAAa;AAC1E,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,MAC7B,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,mCAAA,EAAsC,GAAG,CAAA,EAAA,CAAA,EAAM,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,MAC9G;AAAA,IACF;AAAA,GACF;AACF;AAGO,SAAS,0BAAA,GAA6C;AAC3D,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAoB;AACtC,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,EAAK;AACX,MAAA,OAAO,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,IAAK,IAAA;AAAA,IAC3B,CAAA;AAAA,IACA,OAAA,CAAQ,KAAK,KAAA,EAAO;AAClB,MAAA,KAAA,CAAM,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,IACtB,CAAA;AAAA,IACA,WAAW,GAAA,EAAK;AACd,MAAA,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,IAClB;AAAA,GACF;AACF;AAGO,SAAS,wBAAA,GAA2C;AACzD,EAAA,OAAO;AAAA,IACL,OAAA,GAAU;AACR,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAA,GAAU;AAAA,IAAC,CAAA;AAAA,IACX,UAAA,GAAa;AAAA,IAAC;AAAA,GAChB;AACF","file":"chunk-ZYJUEJ4Z.js","sourcesContent":["import type { StorageAdapter } from \"./types\";\n\n/** localStorage adapter with SSR safety. */\nexport function createLocalStorageAdapter(): StorageAdapter {\n return {\n getItem(key) {\n if (typeof window === \"undefined\" || typeof localStorage === \"undefined\") return null;\n try {\n return localStorage.getItem(key);\n } catch (err) {\n console.warn(`[StorageAdapter] Failed to read \"${key}\":`, err instanceof Error ? err.message : String(err));\n return null;\n }\n },\n setItem(key, value) {\n if (typeof window === \"undefined\" || typeof localStorage === \"undefined\") return;\n try {\n localStorage.setItem(key, value);\n } catch (err) {\n console.warn(`[StorageAdapter] Failed to write \"${key}\":`, err instanceof Error ? err.message : String(err));\n }\n },\n removeItem(key) {\n if (typeof window === \"undefined\" || typeof localStorage === \"undefined\") return;\n try {\n localStorage.removeItem(key);\n } catch (err) {\n console.warn(`[StorageAdapter] Failed to remove \"${key}\":`, err instanceof Error ? err.message : String(err));\n }\n },\n };\n}\n\n/** In-memory adapter for testing and SSR. */\nexport function createMemoryStorageAdapter(): StorageAdapter {\n const store = new Map<string, string>();\n return {\n getItem(key) {\n return store.get(key) ?? null;\n },\n setItem(key, value) {\n store.set(key, value);\n },\n removeItem(key) {\n store.delete(key);\n },\n };\n}\n\n/** No-op adapter — all operations silently do nothing. */\nexport function createNoopStorageAdapter(): StorageAdapter {\n return {\n getItem() {\n return null;\n },\n setItem() {},\n removeItem() {},\n };\n}\n"]}
@@ -0,0 +1,50 @@
1
+ type FieldType = "text" | "number" | "email" | "url" | "textarea" | "select" | "checkbox" | "switch" | "date" | "hidden" | "relation" | "file" | "image" | "array";
2
+ interface SelectOption {
3
+ value: string;
4
+ label: string;
5
+ }
6
+ interface ResourceFormFieldDef {
7
+ key: string;
8
+ label?: string;
9
+ type?: FieldType;
10
+ placeholder?: string;
11
+ required?: boolean;
12
+ defaultValue?: unknown;
13
+ options?: SelectOption[];
14
+ hidden?: boolean;
15
+ readOnlyOnEdit?: boolean;
16
+ description?: string;
17
+ min?: number;
18
+ max?: number;
19
+ rows?: number;
20
+ /** Relation field configuration. */
21
+ relation?: {
22
+ resource: string;
23
+ labelField: string;
24
+ valueField?: string;
25
+ searchable?: boolean;
26
+ allowCreate?: boolean;
27
+ };
28
+ /** Accepted file types, e.g. "image/*", ".pdf,.doc". */
29
+ accept?: string;
30
+ /** Max file size in bytes. Default 10MB. */
31
+ maxSize?: number;
32
+ /** Allow multiple files. */
33
+ multiple?: boolean;
34
+ /** Sub-field definitions for array (child records) fields. */
35
+ arrayFields?: ResourceFormFieldDef[];
36
+ /** Minimum number of array items. */
37
+ arrayMin?: number;
38
+ /** Maximum number of array items. */
39
+ arrayMax?: number;
40
+ /** Group heading for field grouping in the form. */
41
+ group?: string;
42
+ /** Column span in 2-column layout. Default 1. */
43
+ colSpan?: 1 | 2;
44
+ /** Return false to hide this field based on current form values. */
45
+ visible?: (values: Record<string, unknown>) => boolean;
46
+ /** Return true to disable this field based on current form values. */
47
+ disabled?: (values: Record<string, unknown>) => boolean;
48
+ }
49
+
50
+ export type { FieldType, ResourceFormFieldDef, SelectOption };
@@ -0,0 +1,3 @@
1
+ import './chunk-65SXNHWE.js';
2
+ //# sourceMappingURL=form-types.js.map
3
+ //# sourceMappingURL=form-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"form-types.js"}
@@ -0,0 +1,8 @@
1
+ export { UseResourceOptions, UseResourceReturn, useResource } from './use-resource.js';
2
+ export { UseOneOptions, useOne } from './use-one.js';
3
+ export { UseResourceFormOptions, UseResourceFormReturn, buildArrayItemDefaults, useResourceForm } from './use-resource-form.js';
4
+ export { UseWizardReturn, WizardStep, useWizard } from './use-wizard.js';
5
+ import '@tanstack/react-query';
6
+ import '../types-BzcZrTjl.js';
7
+ import 'react-hook-form';
8
+ import '../form-types.js';
@@ -0,0 +1,10 @@
1
+ import '../chunk-EL7YGOTY.js';
2
+ export { buildArrayItemDefaults, useResourceForm } from '../chunk-F4FOTIJI.js';
3
+ import '../chunk-RYEXWQFD.js';
4
+ export { useOne } from '../chunk-PVT6FHAO.js';
5
+ export { useResource } from '../chunk-ZU72FMDR.js';
6
+ import '../chunk-6V2TIN3G.js';
7
+ import '../chunk-ZYJUEJ4Z.js';
8
+ export { useWizard } from '../chunk-7KOLYF27.js';
9
+ //# sourceMappingURL=index.js.map
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,18 @@
1
+ import { UseQueryResult } from '@tanstack/react-query';
2
+ import { B as BaseRecord, I as Identifier } from '../types-BzcZrTjl.js';
3
+
4
+ interface UseOneOptions {
5
+ /** Supabase select/join syntax, e.g. "*, author:profiles(name)". */
6
+ select?: string;
7
+ /** Defaults to `!!id` — won't fetch when id is falsy. */
8
+ enabled?: boolean;
9
+ }
10
+ /**
11
+ * Fetch a single record by id, powered by TanStack Query.
12
+ *
13
+ * Returns the full `UseQueryResult<T>` with the data unwrapped from the
14
+ * provider's `GetOneResult` wrapper.
15
+ */
16
+ declare function useOne<T extends BaseRecord = BaseRecord>(resource: string, id: Identifier | undefined | null, options?: UseOneOptions): UseQueryResult<T>;
17
+
18
+ export { type UseOneOptions, useOne };
@@ -0,0 +1,5 @@
1
+ export { useOne } from '../chunk-PVT6FHAO.js';
2
+ import '../chunk-6V2TIN3G.js';
3
+ import '../chunk-ZYJUEJ4Z.js';
4
+ //# sourceMappingURL=use-one.js.map
5
+ //# sourceMappingURL=use-one.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"use-one.js"}