@pol-studios/db 1.0.50 → 1.0.51

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.
@@ -107,8 +107,10 @@ function useDbQuery(table, options = {}) {
107
107
  limit: queryOptions.limit,
108
108
  offset: queryOptions.offset
109
109
  }), [serializedOptions]);
110
+ const lastUsedAdapterNameRef = useRef("unknown");
110
111
  const queryFn = useCallback(async () => {
111
112
  const currentAdapter = registry.getAdapter(tableName);
113
+ lastUsedAdapterNameRef.current = currentAdapter.name;
112
114
  const result = await currentAdapter.query(tableName, memoizedQueryOptions);
113
115
  return result;
114
116
  }, [registry, tableName, memoizedQueryOptions]);
@@ -171,14 +173,14 @@ function useDbQuery(table, options = {}) {
171
173
  };
172
174
  }, [realtime, registry, tableName, memoizedQueryOptions, queryClient, queryKey, debouncedInvalidate]);
173
175
  useEffect(() => {
174
- const adapterName = adapter?.name ?? "unknown";
176
+ const adapterName = lastUsedAdapterNameRef.current;
175
177
  if (query.isError && query.error) {
176
178
  devWarn("useDbQuery", `${tableName} via ${adapterName}: Error - ${query.error.message}`);
177
179
  }
178
180
  if (query.isSuccess && query.data?.data?.length === 0) {
179
181
  devLog("useDbQuery", `${tableName} via ${adapterName}: 0 results`);
180
182
  }
181
- }, [query.isError, query.error, query.isSuccess, query.data, tableName, adapter]);
183
+ }, [query.isError, query.error, query.isSuccess, query.data, tableName]);
182
184
  const refetch = useCallback(async () => {
183
185
  await query.refetch();
184
186
  }, [query]);
@@ -200,7 +202,7 @@ function useDbQuery(table, options = {}) {
200
202
  }
201
203
 
202
204
  // src/hooks/useDbQueryById.ts
203
- import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2 } from "react";
205
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2 } from "react";
204
206
  import { useQuery as useQuery2 } from "@tanstack/react-query";
205
207
  function buildQueryKey2(table, id, select) {
206
208
  return ["v3", "queryById", table, id, select ?? "*"];
@@ -223,19 +225,19 @@ function useDbQueryById(table, id, options = {}) {
223
225
  }
224
226
  }, [registry, table]);
225
227
  const queryKey = useMemo2(() => buildQueryKey2(table, id, select), [table, id, select]);
228
+ const lastUsedAdapterNameRef = useRef2("unknown");
226
229
  const queryFn = useCallback2(async () => {
227
- if (!adapter) {
228
- throw new Error(`Adapter not available for table: ${table}`);
229
- }
230
230
  if (id == null) {
231
231
  return null;
232
232
  }
233
- if (adapter.queryById) {
234
- return adapter.queryById(table, String(id), {
233
+ const currentAdapter = registry.getAdapter(table);
234
+ lastUsedAdapterNameRef.current = currentAdapter.name;
235
+ if (currentAdapter.queryById) {
236
+ return currentAdapter.queryById(table, String(id), {
235
237
  select
236
238
  });
237
239
  }
238
- const result = await adapter.query(table, {
240
+ const result = await currentAdapter.query(table, {
239
241
  select,
240
242
  where: {
241
243
  id
@@ -243,7 +245,7 @@ function useDbQueryById(table, id, options = {}) {
243
245
  limit: 1
244
246
  });
245
247
  return result.data[0] ?? null;
246
- }, [adapter, table, id, select]);
248
+ }, [registry, table, id, select]);
247
249
  const query = useQuery2({
248
250
  queryKey,
249
251
  queryFn,
@@ -251,14 +253,14 @@ function useDbQueryById(table, id, options = {}) {
251
253
  staleTime
252
254
  });
253
255
  useEffect2(() => {
254
- const adapterName = adapter?.name ?? "unknown";
256
+ const adapterName = lastUsedAdapterNameRef.current;
255
257
  if (query.isError && query.error) {
256
258
  devWarn("useDbQueryById", `${table}(${id}) via ${adapterName}: Error - ${query.error.message}`);
257
259
  }
258
260
  if (query.isSuccess && query.data === null) {
259
261
  devLog("useDbQueryById", `${table}(${id}) via ${adapterName}: not found`);
260
262
  }
261
- }, [query.isError, query.error, query.isSuccess, query.data, table, id, adapter]);
263
+ }, [query.isError, query.error, query.isSuccess, query.data, table, id]);
262
264
  const refetch = useCallback2(async () => {
263
265
  await query.refetch();
264
266
  }, [query]);
@@ -286,4 +288,4 @@ export {
286
288
  useDbQuery,
287
289
  useDbQueryById
288
290
  };
289
- //# sourceMappingURL=chunk-AIYPSXIO.js.map
291
+ //# sourceMappingURL=chunk-WQLIGVQR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/providers/DataLayerContext.ts","../src/hooks/useDataLayer.ts","../src/hooks/useDbQuery.ts","../src/utils/dev-log.ts","../src/hooks/useDbQueryById.ts"],"sourcesContent":["/**\n * V3 Data Layer Context\n *\n * Defines the React context and types for the V3 data layer provider.\n * This context provides access to adapters, sync status, and core instances.\n *\n * PERFORMANCE OPTIMIZATION:\n * The context is split into two separate contexts to prevent unnecessary re-renders:\n * - DataLayerCoreContext: Stable values that don't change after initialization\n * - DataLayerStatusContext: Dynamic values that change during runtime\n *\n * The original DataLayerContext is kept for backward compatibility.\n */\n\nimport { createContext } from \"react\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { AdapterRegistry } from \"../adapters/registry\";\nimport type { PowerSyncDatabase } from \"../query/executor\";\nimport type { DatabaseSchema, SyncStatus, SyncControl } from \"../core/types\";\nimport type { BackendStatus, AutoDetectionResult } from \"../adapters/auto-detector\";\nimport type { TableDataAdapter } from \"../adapters/types\";\n\n// =============================================================================\n// Status Types\n// =============================================================================\n\n/**\n * Status of the data layer initialization\n */\nexport interface DataLayerStatus {\n /** Whether the data layer is fully initialized */\n isInitialized: boolean;\n /** Current active backend */\n currentBackend: \"powersync\" | \"supabase\" | null;\n /** PowerSync connection status */\n powerSyncStatus: BackendStatus;\n /** Whether device is online */\n isOnline: boolean;\n /** Last auto-detection result */\n lastDetection: AutoDetectionResult | null;\n /** Initialization error if any */\n error: Error | null;\n /** Whether initial sync has completed (from PowerSync) */\n hasSynced: boolean;\n}\n\n// =============================================================================\n// Split Context Types (Performance Optimization)\n// =============================================================================\n\n/**\n * STABLE core context - values that don't change after initialization\n *\n * Use useDataLayerCore() to access these values in query/mutation hooks\n * to avoid re-renders when sync status changes.\n */\nexport interface DataLayerCoreContextValue {\n /** Adapter registry for getting table adapters */\n registry: AdapterRegistry;\n /** Get adapter for a specific table (defaults to 'read' operation) */\n getAdapter: (table: string, operation?: 'read' | 'write') => TableDataAdapter;\n /** PowerSync database instance (null when not available) */\n powerSync: PowerSyncDatabase | null;\n /** Supabase client (always available) */\n supabase: SupabaseClient;\n /** React Query client */\n queryClient: QueryClient;\n /** Database schema */\n schema: DatabaseSchema;\n /** Sync controls (for PowerSync, no-op for Supabase-only) - stable reference */\n syncControl: SyncControl;\n}\n\n/**\n * DYNAMIC status context - values that change during runtime\n *\n * Use useDataLayerStatus() for UI components that display sync status,\n * online indicator, etc. Components using this WILL re-render when status changes.\n */\nexport interface DataLayerStatusContextValue {\n /** Current status */\n status: DataLayerStatus;\n /** Sync status (for PowerSync, no-op for Supabase-only) */\n syncStatus: SyncStatus;\n}\n\n// =============================================================================\n// Combined Context Value Type (Backward Compatibility)\n// =============================================================================\n\n/**\n * Context value for the data layer (combines core and status)\n *\n * @deprecated Prefer using useDataLayerCore() or useDataLayerStatus() for better performance.\n * This combined interface is kept for backward compatibility.\n */\nexport interface DataLayerContextValue {\n /** Adapter registry for getting table adapters */\n registry: AdapterRegistry;\n\n /** Get adapter for a specific table (defaults to 'read' operation) */\n getAdapter: (table: string, operation?: 'read' | 'write') => TableDataAdapter;\n\n /** PowerSync database instance (null when not available) */\n powerSync: PowerSyncDatabase | null;\n\n /** Supabase client (always available) */\n supabase: SupabaseClient;\n\n /** React Query client */\n queryClient: QueryClient;\n\n /** Database schema */\n schema: DatabaseSchema;\n\n /** Current status */\n status: DataLayerStatus;\n\n /** Sync status (for PowerSync, no-op for Supabase-only) */\n syncStatus: SyncStatus;\n\n /** Sync controls (for PowerSync, no-op for Supabase-only) */\n syncControl: SyncControl;\n}\n\n// =============================================================================\n// Context Creation\n// =============================================================================\n\n/**\n * STABLE Core context - values that don't change after initialization\n *\n * Use useDataLayerCore() hook to access. Components consuming this context\n * will NOT re-render when sync status or network status changes.\n */\nexport const DataLayerCoreContext = createContext<DataLayerCoreContextValue | null>(null);\nDataLayerCoreContext.displayName = \"DataLayerCoreContext\";\n\n/**\n * DYNAMIC Status context - values that change during runtime\n *\n * Use useDataLayerStatus() hook to access. Components consuming this context\n * WILL re-render when sync status or network status changes.\n */\nexport const DataLayerStatusContext = createContext<DataLayerStatusContextValue | null>(null);\nDataLayerStatusContext.displayName = \"DataLayerStatusContext\";\n\n/**\n * Combined data layer context (backward compatibility)\n *\n * @deprecated Prefer using DataLayerCoreContext or DataLayerStatusContext for better performance.\n * Provides access to the V3 data layer throughout the React component tree.\n * Must be accessed via the useDataLayer hook or similar consumer.\n */\nexport const DataLayerContext = createContext<DataLayerContextValue | null>(null);\nDataLayerContext.displayName = \"DataLayerContext\";","/**\n * V3 Data Layer Hooks\n *\n * Provides access to the V3 data layer context for components.\n * This module provides three hooks for different use cases:\n *\n * - useDataLayerCore(): Stable values only (registry, adapters, clients)\n * Use in query/mutation hooks to avoid re-renders on status changes.\n *\n * - useDataLayerStatus(): Dynamic values only (status, syncStatus, syncControl)\n * Use for UI components that display sync status, online indicator, etc.\n *\n * - useDataLayer(): Combined access (backward compatible)\n * Use when you need both core and status values.\n */\n\nimport { useContext } from \"react\";\nimport { DataLayerContext, DataLayerCoreContext, DataLayerStatusContext, type DataLayerContextValue, type DataLayerCoreContextValue, type DataLayerStatusContextValue } from \"../providers/DataLayerContext\";\n\n// =============================================================================\n// PERFORMANCE-OPTIMIZED HOOKS (Recommended)\n// =============================================================================\n\n/**\n * Hook to access ONLY the stable core values (registry, adapters, clients)\n *\n * PERFORMANCE BENEFIT: Components using this hook will NOT re-render when\n * network status or sync status changes. Use this in query/mutation hooks.\n *\n * Provides access to:\n * - registry: Adapter registry for getting table adapters\n * - getAdapter: Function to get adapter for a specific table\n * - powerSync: PowerSync database instance (null when not available)\n * - supabase: Supabase client (always available)\n * - queryClient: React Query client\n * - schema: Database schema\n *\n * @throws Error if used outside of DataLayerProvider\n *\n * @example\n * const { getAdapter, supabase } = useDataLayerCore();\n * const adapter = getAdapter(\"Task\");\n * // This component won't re-render on sync status changes\n */\nexport function useDataLayerCore() {\n const context = useContext(DataLayerCoreContext);\n if (!context) {\n throw new Error(\"useDataLayerCore must be used within a DataLayerProvider. Make sure you have wrapped your app with <DataLayerProvider>.\");\n }\n return context;\n}\n\n/**\n * Hook to access ONLY the STABLE core context (optional version).\n * Returns null if DataLayerProvider is not present, rather than throwing.\n * Use this when you need graceful fallback behavior.\n *\n * @example\n * const dataLayerCore = useDataLayerCoreOptional();\n * if (dataLayerCore) {\n * // Use V3 adapter pattern\n * } else {\n * // Fall back to Supabase\n * }\n */\nexport function useDataLayerCoreOptional() {\n return useContext(DataLayerCoreContext);\n}\n\n/**\n * Hook to access ONLY the dynamic status values\n *\n * PERFORMANCE BENEFIT: Only components that actually need status information\n * will re-render when status changes. Use for UI components that display\n * sync status, online indicator, pending uploads count, etc.\n *\n * Provides access to:\n * - status: Current initialization and connection status\n * - syncStatus: Sync status for PowerSync\n * - syncControl: Sync controls for PowerSync\n *\n * @throws Error if used outside of DataLayerProvider\n *\n * @example\n * const { status, syncStatus } = useDataLayerStatus();\n *\n * return (\n * <StatusBar\n * isOnline={status.isOnline}\n * pendingUploads={syncStatus.pendingUploads}\n * />\n * );\n */\nexport function useDataLayerStatus() {\n const context = useContext(DataLayerStatusContext);\n if (!context) {\n throw new Error(\"useDataLayerStatus must be used within a DataLayerProvider. Make sure you have wrapped your app with <DataLayerProvider>.\");\n }\n return context;\n}\n\n// =============================================================================\n// BACKWARD COMPATIBLE HOOKS\n// =============================================================================\n\n/**\n * Hook to access the V3 data layer context (combined core + status)\n *\n * NOTE: Consider using useDataLayerCore() or useDataLayerStatus() instead\n * for better render performance. This hook re-renders on ALL status changes.\n *\n * Provides access to:\n * - registry: Adapter registry for getting table adapters\n * - getAdapter: Function to get adapter for a specific table\n * - powerSync: PowerSync database instance (null when not available)\n * - supabase: Supabase client (always available)\n * - queryClient: React Query client\n * - schema: Database schema\n * - status: Current initialization and connection status\n * - syncStatus: Sync status for PowerSync\n * - syncControl: Sync controls for PowerSync\n *\n * @throws Error if used outside of DataLayerProvider\n *\n * @example\n * const { getAdapter, status } = useDataLayer();\n *\n * if (status.isInitialized) {\n * const adapter = getAdapter(\"Task\");\n * // Use adapter...\n * }\n */\nexport function useDataLayer() {\n const context = useContext(DataLayerContext);\n if (!context) {\n throw new Error(\"useDataLayer must be used within a DataLayerProvider. Make sure you have wrapped your app with <DataLayerProvider>.\");\n }\n return context;\n}\n\n/**\n * Hook to safely access data layer context (returns null if not in provider)\n *\n * Use this when you need to check if the data layer is available\n * without throwing an error. Useful for conditional rendering or\n * components that may be rendered outside the provider context.\n *\n * @example\n * const dataLayer = useDataLayerOptional();\n *\n * if (dataLayer) {\n * // Safe to use data layer\n * } else {\n * // Render fallback UI\n * }\n */\nexport function useDataLayerOptional() {\n return useContext(DataLayerContext);\n}\nexport default useDataLayer;","/**\n * V3 useDbQuery Hook\n *\n * React hook for querying multiple records from a table.\n * Works identically whether PowerSync or Supabase is the backend.\n * Uses React Query for state management and caching.\n *\n * Types are automatically inferred from table names when you augment\n * the DatabaseTypes interface with your app's Database type.\n *\n * @example\n * // In your app's types/db.d.ts:\n * declare module \"@pol-studios/db\" {\n * interface DatabaseTypes {\n * database: import(\"@/database.types\").Database;\n * }\n * }\n *\n * // Then usage auto-infers types:\n * const { data } = useDbQuery(\"EquipmentFixtureUnit\", { ... });\n * // data is typed as Tables<\"EquipmentFixtureUnit\">[]\n */\n\nimport { useMemo, useEffect, useCallback, useRef } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useDataLayerCore } from \"./useDataLayer\";\nimport type { QueryOptions } from \"../core/types\";\nimport { devLog, devWarn } from \"../utils/dev-log\";\n\n// =============================================================================\n// Module Augmentation Interface\n// =============================================================================\n\n/**\n * Augment this interface in your app to enable automatic type inference.\n *\n * @example\n * // In types/db.d.ts\n * declare module \"@pol-studios/db\" {\n * interface DatabaseTypes {\n * database: import(\"@/database.types\").Database;\n * }\n * }\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface DatabaseTypes {}\n\n// =============================================================================\n// Database Type Helpers\n// =============================================================================\n\n/**\n * The configured Database type, or a generic fallback\n */\ntype ConfiguredDatabase = DatabaseTypes extends {\n database: infer DB;\n} ? DB : GenericSchema;\n\n/**\n * Generic schema structure for fallback\n */\ntype GenericSchema = {\n public: {\n Tables: Record<string, {\n Row: Record<string, unknown>;\n }>;\n Views: Record<string, {\n Row: Record<string, unknown>;\n }>;\n };\n [schema: string]: {\n Tables: Record<string, {\n Row: Record<string, unknown>;\n }>;\n Views?: Record<string, {\n Row: Record<string, unknown>;\n }>;\n };\n};\n\n/**\n * Default schema from Database (usually \"public\")\n */\ntype DefaultSchema = ConfiguredDatabase extends {\n public: infer S;\n} ? S : never;\n\n/**\n * Extract all valid table names from the default schema\n */\nexport type PublicTableNames = DefaultSchema extends {\n Tables: infer T;\n} ? keyof T & string : string;\n\n/**\n * Extract all valid schema names\n */\nexport type SchemaNames = keyof ConfiguredDatabase & string;\n\n/**\n * Extract table names for a specific schema\n */\nexport type SchemaTableNames<S extends string> = ConfiguredDatabase extends { [K in S]: {\n Tables: infer T;\n} } ? keyof T & string : string;\n\n/**\n * Build dot notation strings for all schema.table combinations\n */\ntype SchemaDotTable = { [S in SchemaNames]: S extends \"public\" ? never // Skip public schema for dot notation\n: `${S}.${SchemaTableNames<S>}` }[SchemaNames];\n\n/**\n * Table identifier - provides autocomplete for valid table names\n *\n * Supports:\n * - \"TableName\" - public schema tables\n * - \"schema.TableName\" - dot notation for other schemas\n * - { schema, table } - object format for other schemas\n */\nexport type TableIdentifier = PublicTableNames | SchemaDotTable | { [S in Exclude<SchemaNames, \"public\">]: {\n schema: S;\n table: SchemaTableNames<S>;\n} }[Exclude<SchemaNames, \"public\">];\n\n/**\n * Resolve row type from a table identifier\n *\n * Supports:\n * - \"TableName\" → public schema\n * - \"schema.TableName\" → specified schema (dot notation)\n * - { schema: \"schema\", table: \"TableName\" } → specified schema (object)\n */\nexport type ResolveRowType<T extends TableIdentifier> = T extends string ?\n// Check for dot notation first (e.g., \"core.Profile\")\nT extends `${infer Schema}.${infer Table}` ? ConfiguredDatabase extends { [K in Schema]: {\n Tables: { [K2 in Table]: {\n Row: infer R;\n } };\n} } ? R : Record<string, unknown> :\n// Plain string - look in public schema\nDefaultSchema extends {\n Tables: { [K in T]: {\n Row: infer R;\n } };\n} ? R : DefaultSchema extends {\n Views: { [K in T]: {\n Row: infer R;\n } };\n} ? R : Record<string, unknown> : T extends {\n schema: infer S;\n table: infer TN;\n} ?\n// Object with schema - look in specified schema\nS extends string ? TN extends string ? ConfiguredDatabase extends { [K in S]: {\n Tables: { [K2 in TN]: {\n Row: infer R;\n } };\n} } ? R : Record<string, unknown> : Record<string, unknown> : Record<string, unknown> : Record<string, unknown>;\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Options for useDbQuery hook\n */\nexport interface UseDbQueryOptions extends Omit<QueryOptions, \"enabled\"> {\n /** Whether the query is enabled (default: true) */\n enabled?: boolean;\n /**\n * React Query stale time in ms\n * Default depends on backend:\n * - PowerSync (offline): 0 - always refetch from SQLite (disk is fast)\n * - Supabase (online): 30000 - use normal caching\n */\n staleTime?: number;\n /** React Query gcTime (cache time) in ms (default: 300000 - 5 minutes) */\n gcTime?: number;\n /** Whether to refetch on window focus (default: true) */\n refetchOnWindowFocus?: boolean;\n /**\n * Whether to refetch on mount\n * Default depends on backend:\n * - PowerSync (offline): \"always\" - always query SQLite\n * - Supabase (online): true - refetch if stale\n */\n refetchOnMount?: boolean | \"always\";\n /** Whether to enable real-time subscriptions (if adapter supports) */\n realtime?: boolean;\n /** If true, returns single item instead of array (for compatibility with V2) */\n single?: boolean;\n}\n\n/**\n * Result from useDbQuery hook\n */\nexport interface UseDbQueryResult<T> {\n /** Query data */\n data: T[] | undefined;\n /** Whether query is loading (initial load) */\n isLoading: boolean;\n /** Whether query is in pending state */\n isPending: boolean;\n /** Whether query is currently fetching (including refetch) */\n isFetching: boolean;\n /** Whether query is currently refetching (alias for isFetching for V2 compatibility) */\n isRefetching: boolean;\n /** Whether query completed successfully */\n isSuccess: boolean;\n /** Whether query errored */\n isError: boolean;\n /** Query error if any */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n /** Total count (if pagination is used) */\n count?: number;\n /** Whether data is stale */\n isStale: boolean;\n /** Timestamp of last data update */\n dataUpdatedAt: number | null;\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Build a query key for React Query\n *\n * Creates a stable, unique key for caching based on table and query options.\n * Keys are namespaced with \"v3\" to avoid collisions with V2 queries.\n *\n * NOTE: Backend is intentionally NOT included in the key. The data is the same\n * regardless of whether it comes from Supabase or PowerSync - switching backends\n * should NOT invalidate the cache. This is critical for offline-first UX.\n */\nfunction buildQueryKey(table: string, options: UseDbQueryOptions): unknown[] {\n return [\"v3\", \"query\", table, options.select ?? \"*\", JSON.stringify(options.where ?? {}), JSON.stringify(options.orderBy ?? []), options.limit, options.offset];\n}\n\n/**\n * Serialize query options for dependency tracking\n */\nfunction serializeQueryOptions(options: UseDbQueryOptions): string {\n return JSON.stringify({\n select: options.select,\n where: options.where,\n orderBy: options.orderBy,\n limit: options.limit,\n offset: options.offset\n });\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\n/**\n * Helper to resolve table name from TableIdentifier\n */\nfunction resolveTableName(table: TableIdentifier): string {\n if (typeof table === \"string\") {\n return table;\n }\n return `${table.schema}.${table.table}`;\n}\n\n/**\n * Hook for querying multiple records from a table\n *\n * This hook provides a unified interface for querying data that works\n * identically whether the backend is PowerSync (offline-first) or\n * Supabase (online-only). It uses React Query for caching and state management.\n *\n * Features:\n * - Automatic type inference from table names (when DatabaseTypes is augmented)\n * - Automatic backend selection based on DataLayerProvider configuration\n * - React Query integration for caching, deduplication, and background updates\n * - Optional real-time subscriptions (when adapter supports it)\n * - Pagination support with count\n *\n * @param table - Table name (string) or { schema, table } object\n * @param options - Query options (select, where, orderBy, limit, offset, etc.)\n * @returns Query result with data, loading states, error, and refetch function\n *\n * @example\n * // Basic query - types auto-inferred from table name\n * const { data } = useDbQuery(\"EquipmentFixtureUnit\");\n * // data is typed as Tables<\"EquipmentFixtureUnit\">[]\n *\n * @example\n * // Query from non-public schema\n * const { data } = useDbQuery({ schema: \"core\", table: \"Profile\" });\n * // data is typed as Tables<{ schema: \"core\" }, \"Profile\">[]\n *\n * @example\n * // Query with filters and sorting\n * const { data } = useDbQuery(\"Task\", {\n * select: \"*, Project(*)\",\n * where: { status: \"active\" },\n * orderBy: [{ field: \"createdAt\", direction: \"desc\" }],\n * limit: 10,\n * });\n */\n/**\n * Main hook signature with auto-inferred types from table identifiers\n */\nexport function useDbQuery<T extends TableIdentifier>(table: T, options?: UseDbQueryOptions): UseDbQueryResult<ResolveRowType<T>>;\n\n/**\n * Overload for explicit type parameter when table name is a string literal\n */\nexport function useDbQuery<T>(table: string, options?: UseDbQueryOptions): UseDbQueryResult<T>;\n\n// Implementation signature - uses any to satisfy both overloads\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useDbQuery<T = any>(table: TableIdentifier | string, options: UseDbQueryOptions = {}): UseDbQueryResult<T> {\n const tableName = typeof table === \"string\" ? table : resolveTableName(table as TableIdentifier);\n const {\n registry,\n queryClient,\n powerSync\n } = useDataLayerCore();\n\n // Determine if using PowerSync (offline/SQLite) or Supabase (online)\n const isPowerSync = powerSync !== null;\n\n // Backend-aware defaults:\n // - PowerSync: staleTime=0, refetchOnMount=\"always\" (SQLite is fast, always query disk)\n // - Supabase: staleTime=30000, refetchOnMount=true (use normal React Query caching)\n // - realtime: PowerSync=true (use watch() for live updates), Supabase=false (no streaming)\n const {\n enabled = true,\n staleTime = isPowerSync ? 0 : 30000,\n gcTime = 300000,\n // 5 minutes - keep in memory for instant display while refetching\n refetchOnWindowFocus = true,\n refetchOnMount = isPowerSync ? \"always\" : true,\n realtime = isPowerSync,\n // Enable real-time subscriptions by default for PowerSync\n ...queryOptions\n } = options;\n\n // Get adapter for this table\n // No isInitialized check needed - if we get here, core context exists = initialized\n const adapter = useMemo(() => {\n try {\n return registry.getAdapter(tableName);\n } catch {\n return null;\n }\n }, [registry, tableName]);\n\n // Serialize options into a stable memoized value BEFORE using in other dependencies\n const serializedOptions = useMemo(() => serializeQueryOptions(options), [options.select, options.where, options.orderBy, options.limit, options.offset]);\n\n // Build query key - memoized to prevent unnecessary re-renders\n // Backend is NOT included - cache persists across backend switches for offline-first UX\n const queryKey = useMemo(() => buildQueryKey(tableName, options), [tableName, serializedOptions]);\n\n // Memoize query options to prevent re-creating on every render\n const memoizedQueryOptions = useMemo(() => ({\n select: queryOptions.select,\n where: queryOptions.where,\n orderBy: queryOptions.orderBy,\n limit: queryOptions.limit,\n offset: queryOptions.offset\n }), [serializedOptions]);\n\n // Query function - resolve adapter lazily at query time to ensure we always\n // have the latest adapter instance (the memoized adapter may be stale)\n const queryFn = useCallback(async () => {\n // Use currentAdapter directly - registry.getAdapter() throws if unavailable\n const currentAdapter = registry.getAdapter(tableName);\n const result = await currentAdapter.query(tableName, memoizedQueryOptions);\n return result;\n }, [registry, tableName, memoizedQueryOptions]);\n\n // Execute query with React Query\n // Backend-aware caching strategy:\n // - PowerSync: SQLite is source of truth, always refetch from disk (it's fast)\n // - Supabase: Use normal React Query caching to avoid unnecessary network requests\n const query = useQuery({\n queryKey,\n queryFn,\n enabled: enabled && adapter !== null,\n staleTime,\n gcTime,\n refetchOnWindowFocus,\n refetchOnMount\n });\n\n // Create debounced invalidation function for subscriptions\n const invalidateTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const debouncedInvalidate = useCallback(() => {\n if (invalidateTimeoutRef.current) {\n clearTimeout(invalidateTimeoutRef.current);\n }\n invalidateTimeoutRef.current = setTimeout(() => {\n queryClient.invalidateQueries({\n queryKey\n });\n }, 100);\n }, [queryClient, queryKey]);\n\n // Clean up timeout on unmount\n useEffect(() => {\n return () => {\n if (invalidateTimeoutRef.current) {\n clearTimeout(invalidateTimeoutRef.current);\n }\n };\n }, []);\n\n // Set up real-time subscription if enabled\n useEffect(() => {\n // Resolve adapter lazily to get current backend\n let currentAdapter_0;\n try {\n currentAdapter_0 = registry.getAdapter(tableName);\n } catch {\n return; // Adapter not available yet\n }\n if (!realtime || !currentAdapter_0?.subscribe) {\n return;\n }\n\n // Only skip first callback for PowerSync adapter (which fires immediately with current data)\n // SupabaseAdapter's subscribe only fires on actual database changes\n // Use currentAdapter.name for the isFirstCallback check (survives minification)\n const isPowerSyncAdapter = currentAdapter_0.name === \"powersync\";\n let isFirstCallback = isPowerSyncAdapter;\n const unsubscribe = currentAdapter_0.subscribe(tableName, memoizedQueryOptions, data => {\n // Skip the first callback since initial query handles it\n if (isFirstCallback) {\n isFirstCallback = false;\n return;\n }\n\n // Check if query has relations (contains parentheses like \"Table(*)\")\n const hasRelations = memoizedQueryOptions.select?.includes(\"(\");\n if (hasRelations) {\n // Has relations - use debounced invalidation to prevent rapid successive invalidations\n debouncedInvalidate();\n } else {\n // No relations - safe to directly update cache with flat data\n queryClient.setQueryData(queryKey, {\n data,\n count: data.length\n });\n }\n });\n return () => {\n unsubscribe?.();\n };\n }, [realtime, registry, tableName, memoizedQueryOptions, queryClient, queryKey, debouncedInvalidate]);\n\n // Dev logging for debugging\n useEffect(() => {\n const adapterName = adapter?.name ?? \"unknown\";\n\n // Log errors\n if (query.isError && query.error) {\n devWarn(\"useDbQuery\", `${tableName} via ${adapterName}: Error - ${query.error.message}`);\n }\n\n // Log empty results (only after successful fetch, not during loading)\n if (query.isSuccess && query.data?.data?.length === 0) {\n devLog(\"useDbQuery\", `${tableName} via ${adapterName}: 0 results`);\n }\n }, [query.isError, query.error, query.isSuccess, query.data, tableName, adapter]);\n\n // Build refetch function\n const refetch = useCallback(async () => {\n await query.refetch();\n }, [query]);\n return {\n data: query.data?.data as T[] | undefined,\n isLoading: query.isLoading,\n isPending: query.isPending,\n isFetching: query.isFetching,\n isRefetching: query.isFetching,\n // Alias for V2 compatibility\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error as Error | null,\n refetch,\n count: query.data?.count,\n isStale: query.isStale,\n dataUpdatedAt: query.dataUpdatedAt ?? null\n };\n}\nexport default useDbQuery;","/**\n * Development-only logging utility for V3 hooks\n *\n * Logs are only output when __DEV__ is true (development builds).\n * In production builds, these calls are no-ops.\n */\n\ndeclare const __DEV__: boolean;\n\n/**\n * Log a message with a prefix, only in development\n *\n * @param prefix - Hook or component name (e.g., \"useDbQuery\")\n * @param message - Message to log\n *\n * @example\n * devLog(\"useDbQuery\", \"EquipmentUnit via PowerSync: 0 results\");\n * // Output: [useDbQuery] EquipmentUnit via PowerSync: 0 results\n */\nexport function devLog(prefix: string, message: string): void {\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.log(`[${prefix}] ${message}`);\n }\n}\n\n/**\n * Log a warning with a prefix, only in development\n */\nexport function devWarn(prefix: string, message: string): void {\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.warn(`[${prefix}] ${message}`);\n }\n}\n\n/**\n * Log an error with a prefix, only in development\n */\nexport function devError(prefix: string, message: string, error?: unknown): void {\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n if (error) {\n console.error(`[${prefix}] ${message}`, error);\n } else {\n console.error(`[${prefix}] ${message}`);\n }\n }\n}","/**\n * V3 useDbQueryById Hook\n *\n * React hook for querying a single record by ID from a table.\n * Works identically whether PowerSync or Supabase is the backend.\n * Uses React Query for state management and caching.\n */\n\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useDataLayerCore } from \"./useDataLayer\";\nimport type { WhereClause } from \"../core/types\";\nimport { devLog, devWarn } from \"../utils/dev-log\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Options for useDbQueryById hook\n */\nexport interface UseDbQueryByIdOptions {\n /** Columns to select (Supabase-style select string) */\n select?: string;\n /** Whether the query is enabled (default: true if id is provided) */\n enabled?: boolean;\n /** React Query stale time in ms (default: 30000) */\n staleTime?: number;\n}\n\n/**\n * Result from useDbQueryById hook\n */\nexport interface UseDbQueryByIdResult<T> {\n /** Query data (undefined while loading, null if not found) */\n data: T | null | undefined;\n /** Whether query is loading (initial load) */\n isLoading: boolean;\n /** Whether query is in pending state */\n isPending: boolean;\n /** Whether query is currently fetching (including refetch) */\n isFetching: boolean;\n /** Query error if any */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Build a query key for React Query\n *\n * Creates a stable, unique key for caching based on table, ID, and select.\n * Keys are namespaced with \"v3\" to avoid collisions with V2 queries.\n */\nfunction buildQueryKey(table: string, id: string | number | null | undefined, select?: string): unknown[] {\n return [\"v3\", \"queryById\", table, id, select ?? \"*\"];\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\n/**\n * Hook for querying a single record by ID\n *\n * This hook provides a unified interface for fetching a single record that works\n * identically whether the backend is PowerSync (offline-first) or\n * Supabase (online-only). It uses React Query for caching and state management.\n *\n * Features:\n * - Automatic backend selection based on DataLayerProvider configuration\n * - React Query integration for caching, deduplication, and background updates\n * - Automatic disabling when ID is null/undefined\n * - Fallback to query with where clause if adapter doesn't support queryById\n * - Type-safe with generic type parameter\n *\n * @param table - The table name to query\n * @param id - The record ID (query is disabled if null/undefined)\n * @param options - Query options (select, enabled, staleTime)\n * @returns Query result with data, loading states, error, and refetch function\n *\n * @example\n * // Basic query by ID\n * const { data, isLoading, error } = useDbQueryById<Task>(\"Task\", taskId);\n *\n * @example\n * // Query with relations\n * const { data, isLoading, error } = useDbQueryById<Task>(\"Task\", taskId, {\n * select: \"*, Project(*), AssignedUser:User(*)\",\n * });\n *\n * @example\n * // Conditional query based on other state\n * const { data } = useDbQueryById<Project>(\"Project\", selectedProjectId, {\n * enabled: hasPermission && !!selectedProjectId,\n * });\n *\n * @example\n * // With custom stale time\n * const { data } = useDbQueryById<User>(\"User\", userId, {\n * staleTime: 60000, // 1 minute\n * });\n */\nexport function useDbQueryById<T = Record<string, unknown>>(table: string, id: string | number | null | undefined, options: UseDbQueryByIdOptions = {}): UseDbQueryByIdResult<T> {\n const {\n registry\n } = useDataLayerCore();\n const {\n select,\n enabled = id != null,\n staleTime = 30000\n } = options;\n\n // Get adapter for this table\n // No isInitialized check needed - if we get here, core context exists = initialized\n const adapter = useMemo(() => {\n try {\n return registry.getAdapter(table);\n } catch (error) {\n devWarn(\"useDbQueryById\", `Failed to get adapter for ${table}: ${(error as Error).message}`);\n return null;\n }\n }, [registry, table]);\n\n // Build query key - memoized to prevent unnecessary re-renders\n const queryKey = useMemo(() => buildQueryKey(table, id, select), [table, id, select]);\n\n // Query function\n const queryFn = useCallback(async (): Promise<T | null> => {\n if (!adapter) {\n throw new Error(`Adapter not available for table: ${table}`);\n }\n if (id == null) {\n return null;\n }\n\n // Use queryById if available, otherwise fall back to query with where\n if (adapter.queryById) {\n return adapter.queryById<T>(table, String(id), {\n select\n });\n }\n\n // Fallback: use query with where clause\n const result = await adapter.query<T>(table, {\n select,\n where: {\n id\n } as WhereClause,\n limit: 1\n });\n return result.data[0] ?? null;\n }, [adapter, table, id, select]);\n\n // Execute query with React Query\n const query = useQuery({\n queryKey,\n queryFn,\n enabled: enabled && adapter !== null && id != null,\n staleTime\n });\n\n // Dev logging for debugging\n useEffect(() => {\n const adapterName = adapter?.name ?? \"unknown\";\n\n // Log errors\n if (query.isError && query.error) {\n devWarn(\"useDbQueryById\", `${table}(${id}) via ${adapterName}: Error - ${query.error.message}`);\n }\n\n // Log not found (only after successful fetch, not during loading)\n if (query.isSuccess && query.data === null) {\n devLog(\"useDbQueryById\", `${table}(${id}) via ${adapterName}: not found`);\n }\n }, [query.isError, query.error, query.isSuccess, query.data, table, id, adapter]);\n\n // Build refetch function\n const refetch = useCallback(async () => {\n await query.refetch();\n }, [query]);\n return {\n data: query.data,\n isLoading: query.isLoading,\n isPending: query.isPending,\n isFetching: query.isFetching,\n error: query.error as Error | null,\n refetch\n };\n}\nexport default useDbQueryById;"],"mappings":"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","names":["useCallback","useEffect","useMemo","useQuery","buildQueryKey","useMemo","useCallback","useQuery","useEffect"]}
1
+ {"version":3,"sources":["../src/providers/DataLayerContext.ts","../src/hooks/useDataLayer.ts","../src/hooks/useDbQuery.ts","../src/utils/dev-log.ts","../src/hooks/useDbQueryById.ts"],"sourcesContent":["/**\n * V3 Data Layer Context\n *\n * Defines the React context and types for the V3 data layer provider.\n * This context provides access to adapters, sync status, and core instances.\n *\n * PERFORMANCE OPTIMIZATION:\n * The context is split into two separate contexts to prevent unnecessary re-renders:\n * - DataLayerCoreContext: Stable values that don't change after initialization\n * - DataLayerStatusContext: Dynamic values that change during runtime\n *\n * The original DataLayerContext is kept for backward compatibility.\n */\n\nimport { createContext } from \"react\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { AdapterRegistry } from \"../adapters/registry\";\nimport type { PowerSyncDatabase } from \"../query/executor\";\nimport type { DatabaseSchema, SyncStatus, SyncControl } from \"../core/types\";\nimport type { BackendStatus, AutoDetectionResult } from \"../adapters/auto-detector\";\nimport type { TableDataAdapter } from \"../adapters/types\";\n\n// =============================================================================\n// Status Types\n// =============================================================================\n\n/**\n * Status of the data layer initialization\n */\nexport interface DataLayerStatus {\n /** Whether the data layer is fully initialized */\n isInitialized: boolean;\n /** Current active backend */\n currentBackend: \"powersync\" | \"supabase\" | null;\n /** PowerSync connection status */\n powerSyncStatus: BackendStatus;\n /** Whether device is online */\n isOnline: boolean;\n /** Last auto-detection result */\n lastDetection: AutoDetectionResult | null;\n /** Initialization error if any */\n error: Error | null;\n /** Whether initial sync has completed (from PowerSync) */\n hasSynced: boolean;\n}\n\n// =============================================================================\n// Split Context Types (Performance Optimization)\n// =============================================================================\n\n/**\n * STABLE core context - values that don't change after initialization\n *\n * Use useDataLayerCore() to access these values in query/mutation hooks\n * to avoid re-renders when sync status changes.\n */\nexport interface DataLayerCoreContextValue {\n /** Adapter registry for getting table adapters */\n registry: AdapterRegistry;\n /** Get adapter for a specific table (defaults to 'read' operation) */\n getAdapter: (table: string, operation?: 'read' | 'write') => TableDataAdapter;\n /** PowerSync database instance (null when not available) */\n powerSync: PowerSyncDatabase | null;\n /** Supabase client (always available) */\n supabase: SupabaseClient;\n /** React Query client */\n queryClient: QueryClient;\n /** Database schema */\n schema: DatabaseSchema;\n /** Sync controls (for PowerSync, no-op for Supabase-only) - stable reference */\n syncControl: SyncControl;\n}\n\n/**\n * DYNAMIC status context - values that change during runtime\n *\n * Use useDataLayerStatus() for UI components that display sync status,\n * online indicator, etc. Components using this WILL re-render when status changes.\n */\nexport interface DataLayerStatusContextValue {\n /** Current status */\n status: DataLayerStatus;\n /** Sync status (for PowerSync, no-op for Supabase-only) */\n syncStatus: SyncStatus;\n}\n\n// =============================================================================\n// Combined Context Value Type (Backward Compatibility)\n// =============================================================================\n\n/**\n * Context value for the data layer (combines core and status)\n *\n * @deprecated Prefer using useDataLayerCore() or useDataLayerStatus() for better performance.\n * This combined interface is kept for backward compatibility.\n */\nexport interface DataLayerContextValue {\n /** Adapter registry for getting table adapters */\n registry: AdapterRegistry;\n\n /** Get adapter for a specific table (defaults to 'read' operation) */\n getAdapter: (table: string, operation?: 'read' | 'write') => TableDataAdapter;\n\n /** PowerSync database instance (null when not available) */\n powerSync: PowerSyncDatabase | null;\n\n /** Supabase client (always available) */\n supabase: SupabaseClient;\n\n /** React Query client */\n queryClient: QueryClient;\n\n /** Database schema */\n schema: DatabaseSchema;\n\n /** Current status */\n status: DataLayerStatus;\n\n /** Sync status (for PowerSync, no-op for Supabase-only) */\n syncStatus: SyncStatus;\n\n /** Sync controls (for PowerSync, no-op for Supabase-only) */\n syncControl: SyncControl;\n}\n\n// =============================================================================\n// Context Creation\n// =============================================================================\n\n/**\n * STABLE Core context - values that don't change after initialization\n *\n * Use useDataLayerCore() hook to access. Components consuming this context\n * will NOT re-render when sync status or network status changes.\n */\nexport const DataLayerCoreContext = createContext<DataLayerCoreContextValue | null>(null);\nDataLayerCoreContext.displayName = \"DataLayerCoreContext\";\n\n/**\n * DYNAMIC Status context - values that change during runtime\n *\n * Use useDataLayerStatus() hook to access. Components consuming this context\n * WILL re-render when sync status or network status changes.\n */\nexport const DataLayerStatusContext = createContext<DataLayerStatusContextValue | null>(null);\nDataLayerStatusContext.displayName = \"DataLayerStatusContext\";\n\n/**\n * Combined data layer context (backward compatibility)\n *\n * @deprecated Prefer using DataLayerCoreContext or DataLayerStatusContext for better performance.\n * Provides access to the V3 data layer throughout the React component tree.\n * Must be accessed via the useDataLayer hook or similar consumer.\n */\nexport const DataLayerContext = createContext<DataLayerContextValue | null>(null);\nDataLayerContext.displayName = \"DataLayerContext\";","/**\n * V3 Data Layer Hooks\n *\n * Provides access to the V3 data layer context for components.\n * This module provides three hooks for different use cases:\n *\n * - useDataLayerCore(): Stable values only (registry, adapters, clients)\n * Use in query/mutation hooks to avoid re-renders on status changes.\n *\n * - useDataLayerStatus(): Dynamic values only (status, syncStatus, syncControl)\n * Use for UI components that display sync status, online indicator, etc.\n *\n * - useDataLayer(): Combined access (backward compatible)\n * Use when you need both core and status values.\n */\n\nimport { useContext } from \"react\";\nimport { DataLayerContext, DataLayerCoreContext, DataLayerStatusContext, type DataLayerContextValue, type DataLayerCoreContextValue, type DataLayerStatusContextValue } from \"../providers/DataLayerContext\";\n\n// =============================================================================\n// PERFORMANCE-OPTIMIZED HOOKS (Recommended)\n// =============================================================================\n\n/**\n * Hook to access ONLY the stable core values (registry, adapters, clients)\n *\n * PERFORMANCE BENEFIT: Components using this hook will NOT re-render when\n * network status or sync status changes. Use this in query/mutation hooks.\n *\n * Provides access to:\n * - registry: Adapter registry for getting table adapters\n * - getAdapter: Function to get adapter for a specific table\n * - powerSync: PowerSync database instance (null when not available)\n * - supabase: Supabase client (always available)\n * - queryClient: React Query client\n * - schema: Database schema\n *\n * @throws Error if used outside of DataLayerProvider\n *\n * @example\n * const { getAdapter, supabase } = useDataLayerCore();\n * const adapter = getAdapter(\"Task\");\n * // This component won't re-render on sync status changes\n */\nexport function useDataLayerCore() {\n const context = useContext(DataLayerCoreContext);\n if (!context) {\n throw new Error(\"useDataLayerCore must be used within a DataLayerProvider. Make sure you have wrapped your app with <DataLayerProvider>.\");\n }\n return context;\n}\n\n/**\n * Hook to access ONLY the STABLE core context (optional version).\n * Returns null if DataLayerProvider is not present, rather than throwing.\n * Use this when you need graceful fallback behavior.\n *\n * @example\n * const dataLayerCore = useDataLayerCoreOptional();\n * if (dataLayerCore) {\n * // Use V3 adapter pattern\n * } else {\n * // Fall back to Supabase\n * }\n */\nexport function useDataLayerCoreOptional() {\n return useContext(DataLayerCoreContext);\n}\n\n/**\n * Hook to access ONLY the dynamic status values\n *\n * PERFORMANCE BENEFIT: Only components that actually need status information\n * will re-render when status changes. Use for UI components that display\n * sync status, online indicator, pending uploads count, etc.\n *\n * Provides access to:\n * - status: Current initialization and connection status\n * - syncStatus: Sync status for PowerSync\n * - syncControl: Sync controls for PowerSync\n *\n * @throws Error if used outside of DataLayerProvider\n *\n * @example\n * const { status, syncStatus } = useDataLayerStatus();\n *\n * return (\n * <StatusBar\n * isOnline={status.isOnline}\n * pendingUploads={syncStatus.pendingUploads}\n * />\n * );\n */\nexport function useDataLayerStatus() {\n const context = useContext(DataLayerStatusContext);\n if (!context) {\n throw new Error(\"useDataLayerStatus must be used within a DataLayerProvider. Make sure you have wrapped your app with <DataLayerProvider>.\");\n }\n return context;\n}\n\n// =============================================================================\n// BACKWARD COMPATIBLE HOOKS\n// =============================================================================\n\n/**\n * Hook to access the V3 data layer context (combined core + status)\n *\n * NOTE: Consider using useDataLayerCore() or useDataLayerStatus() instead\n * for better render performance. This hook re-renders on ALL status changes.\n *\n * Provides access to:\n * - registry: Adapter registry for getting table adapters\n * - getAdapter: Function to get adapter for a specific table\n * - powerSync: PowerSync database instance (null when not available)\n * - supabase: Supabase client (always available)\n * - queryClient: React Query client\n * - schema: Database schema\n * - status: Current initialization and connection status\n * - syncStatus: Sync status for PowerSync\n * - syncControl: Sync controls for PowerSync\n *\n * @throws Error if used outside of DataLayerProvider\n *\n * @example\n * const { getAdapter, status } = useDataLayer();\n *\n * if (status.isInitialized) {\n * const adapter = getAdapter(\"Task\");\n * // Use adapter...\n * }\n */\nexport function useDataLayer() {\n const context = useContext(DataLayerContext);\n if (!context) {\n throw new Error(\"useDataLayer must be used within a DataLayerProvider. Make sure you have wrapped your app with <DataLayerProvider>.\");\n }\n return context;\n}\n\n/**\n * Hook to safely access data layer context (returns null if not in provider)\n *\n * Use this when you need to check if the data layer is available\n * without throwing an error. Useful for conditional rendering or\n * components that may be rendered outside the provider context.\n *\n * @example\n * const dataLayer = useDataLayerOptional();\n *\n * if (dataLayer) {\n * // Safe to use data layer\n * } else {\n * // Render fallback UI\n * }\n */\nexport function useDataLayerOptional() {\n return useContext(DataLayerContext);\n}\nexport default useDataLayer;","/**\n * V3 useDbQuery Hook\n *\n * React hook for querying multiple records from a table.\n * Works identically whether PowerSync or Supabase is the backend.\n * Uses React Query for state management and caching.\n *\n * Types are automatically inferred from table names when you augment\n * the DatabaseTypes interface with your app's Database type.\n *\n * @example\n * // In your app's types/db.d.ts:\n * declare module \"@pol-studios/db\" {\n * interface DatabaseTypes {\n * database: import(\"@/database.types\").Database;\n * }\n * }\n *\n * // Then usage auto-infers types:\n * const { data } = useDbQuery(\"EquipmentFixtureUnit\", { ... });\n * // data is typed as Tables<\"EquipmentFixtureUnit\">[]\n */\n\nimport { useMemo, useEffect, useCallback, useRef } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useDataLayerCore } from \"./useDataLayer\";\nimport type { QueryOptions } from \"../core/types\";\nimport { devLog, devWarn } from \"../utils/dev-log\";\n\n// =============================================================================\n// Module Augmentation Interface\n// =============================================================================\n\n/**\n * Augment this interface in your app to enable automatic type inference.\n *\n * @example\n * // In types/db.d.ts\n * declare module \"@pol-studios/db\" {\n * interface DatabaseTypes {\n * database: import(\"@/database.types\").Database;\n * }\n * }\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface DatabaseTypes {}\n\n// =============================================================================\n// Database Type Helpers\n// =============================================================================\n\n/**\n * The configured Database type, or a generic fallback\n */\ntype ConfiguredDatabase = DatabaseTypes extends {\n database: infer DB;\n} ? DB : GenericSchema;\n\n/**\n * Generic schema structure for fallback\n */\ntype GenericSchema = {\n public: {\n Tables: Record<string, {\n Row: Record<string, unknown>;\n }>;\n Views: Record<string, {\n Row: Record<string, unknown>;\n }>;\n };\n [schema: string]: {\n Tables: Record<string, {\n Row: Record<string, unknown>;\n }>;\n Views?: Record<string, {\n Row: Record<string, unknown>;\n }>;\n };\n};\n\n/**\n * Default schema from Database (usually \"public\")\n */\ntype DefaultSchema = ConfiguredDatabase extends {\n public: infer S;\n} ? S : never;\n\n/**\n * Extract all valid table names from the default schema\n */\nexport type PublicTableNames = DefaultSchema extends {\n Tables: infer T;\n} ? keyof T & string : string;\n\n/**\n * Extract all valid schema names\n */\nexport type SchemaNames = keyof ConfiguredDatabase & string;\n\n/**\n * Extract table names for a specific schema\n */\nexport type SchemaTableNames<S extends string> = ConfiguredDatabase extends { [K in S]: {\n Tables: infer T;\n} } ? keyof T & string : string;\n\n/**\n * Build dot notation strings for all schema.table combinations\n */\ntype SchemaDotTable = { [S in SchemaNames]: S extends \"public\" ? never // Skip public schema for dot notation\n: `${S}.${SchemaTableNames<S>}` }[SchemaNames];\n\n/**\n * Table identifier - provides autocomplete for valid table names\n *\n * Supports:\n * - \"TableName\" - public schema tables\n * - \"schema.TableName\" - dot notation for other schemas\n * - { schema, table } - object format for other schemas\n */\nexport type TableIdentifier = PublicTableNames | SchemaDotTable | { [S in Exclude<SchemaNames, \"public\">]: {\n schema: S;\n table: SchemaTableNames<S>;\n} }[Exclude<SchemaNames, \"public\">];\n\n/**\n * Resolve row type from a table identifier\n *\n * Supports:\n * - \"TableName\" → public schema\n * - \"schema.TableName\" → specified schema (dot notation)\n * - { schema: \"schema\", table: \"TableName\" } → specified schema (object)\n */\nexport type ResolveRowType<T extends TableIdentifier> = T extends string ?\n// Check for dot notation first (e.g., \"core.Profile\")\nT extends `${infer Schema}.${infer Table}` ? ConfiguredDatabase extends { [K in Schema]: {\n Tables: { [K2 in Table]: {\n Row: infer R;\n } };\n} } ? R : Record<string, unknown> :\n// Plain string - look in public schema\nDefaultSchema extends {\n Tables: { [K in T]: {\n Row: infer R;\n } };\n} ? R : DefaultSchema extends {\n Views: { [K in T]: {\n Row: infer R;\n } };\n} ? R : Record<string, unknown> : T extends {\n schema: infer S;\n table: infer TN;\n} ?\n// Object with schema - look in specified schema\nS extends string ? TN extends string ? ConfiguredDatabase extends { [K in S]: {\n Tables: { [K2 in TN]: {\n Row: infer R;\n } };\n} } ? R : Record<string, unknown> : Record<string, unknown> : Record<string, unknown> : Record<string, unknown>;\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Options for useDbQuery hook\n */\nexport interface UseDbQueryOptions extends Omit<QueryOptions, \"enabled\"> {\n /** Whether the query is enabled (default: true) */\n enabled?: boolean;\n /**\n * React Query stale time in ms\n * Default depends on backend:\n * - PowerSync (offline): 0 - always refetch from SQLite (disk is fast)\n * - Supabase (online): 30000 - use normal caching\n */\n staleTime?: number;\n /** React Query gcTime (cache time) in ms (default: 300000 - 5 minutes) */\n gcTime?: number;\n /** Whether to refetch on window focus (default: true) */\n refetchOnWindowFocus?: boolean;\n /**\n * Whether to refetch on mount\n * Default depends on backend:\n * - PowerSync (offline): \"always\" - always query SQLite\n * - Supabase (online): true - refetch if stale\n */\n refetchOnMount?: boolean | \"always\";\n /** Whether to enable real-time subscriptions (if adapter supports) */\n realtime?: boolean;\n /** If true, returns single item instead of array (for compatibility with V2) */\n single?: boolean;\n}\n\n/**\n * Result from useDbQuery hook\n */\nexport interface UseDbQueryResult<T> {\n /** Query data */\n data: T[] | undefined;\n /** Whether query is loading (initial load) */\n isLoading: boolean;\n /** Whether query is in pending state */\n isPending: boolean;\n /** Whether query is currently fetching (including refetch) */\n isFetching: boolean;\n /** Whether query is currently refetching (alias for isFetching for V2 compatibility) */\n isRefetching: boolean;\n /** Whether query completed successfully */\n isSuccess: boolean;\n /** Whether query errored */\n isError: boolean;\n /** Query error if any */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n /** Total count (if pagination is used) */\n count?: number;\n /** Whether data is stale */\n isStale: boolean;\n /** Timestamp of last data update */\n dataUpdatedAt: number | null;\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Build a query key for React Query\n *\n * Creates a stable, unique key for caching based on table and query options.\n * Keys are namespaced with \"v3\" to avoid collisions with V2 queries.\n *\n * NOTE: Backend is intentionally NOT included in the key. The data is the same\n * regardless of whether it comes from Supabase or PowerSync - switching backends\n * should NOT invalidate the cache. This is critical for offline-first UX.\n */\nfunction buildQueryKey(table: string, options: UseDbQueryOptions): unknown[] {\n return [\"v3\", \"query\", table, options.select ?? \"*\", JSON.stringify(options.where ?? {}), JSON.stringify(options.orderBy ?? []), options.limit, options.offset];\n}\n\n/**\n * Serialize query options for dependency tracking\n */\nfunction serializeQueryOptions(options: UseDbQueryOptions): string {\n return JSON.stringify({\n select: options.select,\n where: options.where,\n orderBy: options.orderBy,\n limit: options.limit,\n offset: options.offset\n });\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\n/**\n * Helper to resolve table name from TableIdentifier\n */\nfunction resolveTableName(table: TableIdentifier): string {\n if (typeof table === \"string\") {\n return table;\n }\n return `${table.schema}.${table.table}`;\n}\n\n/**\n * Hook for querying multiple records from a table\n *\n * This hook provides a unified interface for querying data that works\n * identically whether the backend is PowerSync (offline-first) or\n * Supabase (online-only). It uses React Query for caching and state management.\n *\n * Features:\n * - Automatic type inference from table names (when DatabaseTypes is augmented)\n * - Automatic backend selection based on DataLayerProvider configuration\n * - React Query integration for caching, deduplication, and background updates\n * - Optional real-time subscriptions (when adapter supports it)\n * - Pagination support with count\n *\n * @param table - Table name (string) or { schema, table } object\n * @param options - Query options (select, where, orderBy, limit, offset, etc.)\n * @returns Query result with data, loading states, error, and refetch function\n *\n * @example\n * // Basic query - types auto-inferred from table name\n * const { data } = useDbQuery(\"EquipmentFixtureUnit\");\n * // data is typed as Tables<\"EquipmentFixtureUnit\">[]\n *\n * @example\n * // Query from non-public schema\n * const { data } = useDbQuery({ schema: \"core\", table: \"Profile\" });\n * // data is typed as Tables<{ schema: \"core\" }, \"Profile\">[]\n *\n * @example\n * // Query with filters and sorting\n * const { data } = useDbQuery(\"Task\", {\n * select: \"*, Project(*)\",\n * where: { status: \"active\" },\n * orderBy: [{ field: \"createdAt\", direction: \"desc\" }],\n * limit: 10,\n * });\n */\n/**\n * Main hook signature with auto-inferred types from table identifiers\n */\nexport function useDbQuery<T extends TableIdentifier>(table: T, options?: UseDbQueryOptions): UseDbQueryResult<ResolveRowType<T>>;\n\n/**\n * Overload for explicit type parameter when table name is a string literal\n */\nexport function useDbQuery<T>(table: string, options?: UseDbQueryOptions): UseDbQueryResult<T>;\n\n// Implementation signature - uses any to satisfy both overloads\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useDbQuery<T = any>(table: TableIdentifier | string, options: UseDbQueryOptions = {}): UseDbQueryResult<T> {\n const tableName = typeof table === \"string\" ? table : resolveTableName(table as TableIdentifier);\n const {\n registry,\n queryClient,\n powerSync\n } = useDataLayerCore();\n\n // Determine if using PowerSync (offline/SQLite) or Supabase (online)\n const isPowerSync = powerSync !== null;\n\n // Backend-aware defaults:\n // - PowerSync: staleTime=0, refetchOnMount=\"always\" (SQLite is fast, always query disk)\n // - Supabase: staleTime=30000, refetchOnMount=true (use normal React Query caching)\n // - realtime: PowerSync=true (use watch() for live updates), Supabase=false (no streaming)\n const {\n enabled = true,\n staleTime = isPowerSync ? 0 : 30000,\n gcTime = 300000,\n // 5 minutes - keep in memory for instant display while refetching\n refetchOnWindowFocus = true,\n refetchOnMount = isPowerSync ? \"always\" : true,\n realtime = isPowerSync,\n // Enable real-time subscriptions by default for PowerSync\n ...queryOptions\n } = options;\n\n // Get adapter for this table\n // No isInitialized check needed - if we get here, core context exists = initialized\n const adapter = useMemo(() => {\n try {\n return registry.getAdapter(tableName);\n } catch {\n return null;\n }\n }, [registry, tableName]);\n\n // Serialize options into a stable memoized value BEFORE using in other dependencies\n const serializedOptions = useMemo(() => serializeQueryOptions(options), [options.select, options.where, options.orderBy, options.limit, options.offset]);\n\n // Build query key - memoized to prevent unnecessary re-renders\n // Backend is NOT included - cache persists across backend switches for offline-first UX\n const queryKey = useMemo(() => buildQueryKey(tableName, options), [tableName, serializedOptions]);\n\n // Memoize query options to prevent re-creating on every render\n const memoizedQueryOptions = useMemo(() => ({\n select: queryOptions.select,\n where: queryOptions.where,\n orderBy: queryOptions.orderBy,\n limit: queryOptions.limit,\n offset: queryOptions.offset\n }), [serializedOptions]);\n\n // Track the adapter name that was actually used for the most recent query\n // This is used for accurate logging since the memoized adapter may be stale\n const lastUsedAdapterNameRef = useRef<string>(\"unknown\");\n\n // Query function - resolve adapter lazily at query time to ensure we always\n // have the latest adapter instance (the memoized adapter may be stale)\n const queryFn = useCallback(async () => {\n // Use currentAdapter directly - registry.getAdapter() throws if unavailable\n const currentAdapter = registry.getAdapter(tableName);\n\n // Track which adapter was actually used for accurate logging\n lastUsedAdapterNameRef.current = currentAdapter.name;\n const result = await currentAdapter.query(tableName, memoizedQueryOptions);\n return result;\n }, [registry, tableName, memoizedQueryOptions]);\n\n // Execute query with React Query\n // Backend-aware caching strategy:\n // - PowerSync: SQLite is source of truth, always refetch from disk (it's fast)\n // - Supabase: Use normal React Query caching to avoid unnecessary network requests\n const query = useQuery({\n queryKey,\n queryFn,\n enabled: enabled && adapter !== null,\n staleTime,\n gcTime,\n refetchOnWindowFocus,\n refetchOnMount\n });\n\n // Create debounced invalidation function for subscriptions\n const invalidateTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const debouncedInvalidate = useCallback(() => {\n if (invalidateTimeoutRef.current) {\n clearTimeout(invalidateTimeoutRef.current);\n }\n invalidateTimeoutRef.current = setTimeout(() => {\n queryClient.invalidateQueries({\n queryKey\n });\n }, 100);\n }, [queryClient, queryKey]);\n\n // Clean up timeout on unmount\n useEffect(() => {\n return () => {\n if (invalidateTimeoutRef.current) {\n clearTimeout(invalidateTimeoutRef.current);\n }\n };\n }, []);\n\n // Set up real-time subscription if enabled\n useEffect(() => {\n // Resolve adapter lazily to get current backend\n let currentAdapter_0;\n try {\n currentAdapter_0 = registry.getAdapter(tableName);\n } catch {\n return; // Adapter not available yet\n }\n if (!realtime || !currentAdapter_0?.subscribe) {\n return;\n }\n\n // Only skip first callback for PowerSync adapter (which fires immediately with current data)\n // SupabaseAdapter's subscribe only fires on actual database changes\n // Use currentAdapter.name for the isFirstCallback check (survives minification)\n const isPowerSyncAdapter = currentAdapter_0.name === \"powersync\";\n let isFirstCallback = isPowerSyncAdapter;\n const unsubscribe = currentAdapter_0.subscribe(tableName, memoizedQueryOptions, data => {\n // Skip the first callback since initial query handles it\n if (isFirstCallback) {\n isFirstCallback = false;\n return;\n }\n\n // Check if query has relations (contains parentheses like \"Table(*)\")\n const hasRelations = memoizedQueryOptions.select?.includes(\"(\");\n if (hasRelations) {\n // Has relations - use debounced invalidation to prevent rapid successive invalidations\n debouncedInvalidate();\n } else {\n // No relations - safe to directly update cache with flat data\n queryClient.setQueryData(queryKey, {\n data,\n count: data.length\n });\n }\n });\n return () => {\n unsubscribe?.();\n };\n }, [realtime, registry, tableName, memoizedQueryOptions, queryClient, queryKey, debouncedInvalidate]);\n\n // Dev logging for debugging\n // Uses lastUsedAdapterNameRef to log the adapter that was ACTUALLY used for the query,\n // not the memoized adapter from render time (which may be stale due to auto-detection)\n useEffect(() => {\n const adapterName = lastUsedAdapterNameRef.current;\n\n // Log errors\n if (query.isError && query.error) {\n devWarn(\"useDbQuery\", `${tableName} via ${adapterName}: Error - ${query.error.message}`);\n }\n\n // Log empty results (only after successful fetch, not during loading)\n if (query.isSuccess && query.data?.data?.length === 0) {\n devLog(\"useDbQuery\", `${tableName} via ${adapterName}: 0 results`);\n }\n }, [query.isError, query.error, query.isSuccess, query.data, tableName]);\n\n // Build refetch function\n const refetch = useCallback(async () => {\n await query.refetch();\n }, [query]);\n return {\n data: query.data?.data as T[] | undefined,\n isLoading: query.isLoading,\n isPending: query.isPending,\n isFetching: query.isFetching,\n isRefetching: query.isFetching,\n // Alias for V2 compatibility\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error as Error | null,\n refetch,\n count: query.data?.count,\n isStale: query.isStale,\n dataUpdatedAt: query.dataUpdatedAt ?? null\n };\n}\nexport default useDbQuery;","/**\n * Development-only logging utility for V3 hooks\n *\n * Logs are only output when __DEV__ is true (development builds).\n * In production builds, these calls are no-ops.\n */\n\ndeclare const __DEV__: boolean;\n\n/**\n * Log a message with a prefix, only in development\n *\n * @param prefix - Hook or component name (e.g., \"useDbQuery\")\n * @param message - Message to log\n *\n * @example\n * devLog(\"useDbQuery\", \"EquipmentUnit via PowerSync: 0 results\");\n * // Output: [useDbQuery] EquipmentUnit via PowerSync: 0 results\n */\nexport function devLog(prefix: string, message: string): void {\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.log(`[${prefix}] ${message}`);\n }\n}\n\n/**\n * Log a warning with a prefix, only in development\n */\nexport function devWarn(prefix: string, message: string): void {\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.warn(`[${prefix}] ${message}`);\n }\n}\n\n/**\n * Log an error with a prefix, only in development\n */\nexport function devError(prefix: string, message: string, error?: unknown): void {\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n if (error) {\n console.error(`[${prefix}] ${message}`, error);\n } else {\n console.error(`[${prefix}] ${message}`);\n }\n }\n}","/**\n * V3 useDbQueryById Hook\n *\n * React hook for querying a single record by ID from a table.\n * Works identically whether PowerSync or Supabase is the backend.\n * Uses React Query for state management and caching.\n */\n\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useDataLayerCore } from \"./useDataLayer\";\nimport type { WhereClause } from \"../core/types\";\nimport { devLog, devWarn } from \"../utils/dev-log\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Options for useDbQueryById hook\n */\nexport interface UseDbQueryByIdOptions {\n /** Columns to select (Supabase-style select string) */\n select?: string;\n /** Whether the query is enabled (default: true if id is provided) */\n enabled?: boolean;\n /** React Query stale time in ms (default: 30000) */\n staleTime?: number;\n}\n\n/**\n * Result from useDbQueryById hook\n */\nexport interface UseDbQueryByIdResult<T> {\n /** Query data (undefined while loading, null if not found) */\n data: T | null | undefined;\n /** Whether query is loading (initial load) */\n isLoading: boolean;\n /** Whether query is in pending state */\n isPending: boolean;\n /** Whether query is currently fetching (including refetch) */\n isFetching: boolean;\n /** Query error if any */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Build a query key for React Query\n *\n * Creates a stable, unique key for caching based on table, ID, and select.\n * Keys are namespaced with \"v3\" to avoid collisions with V2 queries.\n */\nfunction buildQueryKey(table: string, id: string | number | null | undefined, select?: string): unknown[] {\n return [\"v3\", \"queryById\", table, id, select ?? \"*\"];\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\n/**\n * Hook for querying a single record by ID\n *\n * This hook provides a unified interface for fetching a single record that works\n * identically whether the backend is PowerSync (offline-first) or\n * Supabase (online-only). It uses React Query for caching and state management.\n *\n * Features:\n * - Automatic backend selection based on DataLayerProvider configuration\n * - React Query integration for caching, deduplication, and background updates\n * - Automatic disabling when ID is null/undefined\n * - Fallback to query with where clause if adapter doesn't support queryById\n * - Type-safe with generic type parameter\n *\n * @param table - The table name to query\n * @param id - The record ID (query is disabled if null/undefined)\n * @param options - Query options (select, enabled, staleTime)\n * @returns Query result with data, loading states, error, and refetch function\n *\n * @example\n * // Basic query by ID\n * const { data, isLoading, error } = useDbQueryById<Task>(\"Task\", taskId);\n *\n * @example\n * // Query with relations\n * const { data, isLoading, error } = useDbQueryById<Task>(\"Task\", taskId, {\n * select: \"*, Project(*), AssignedUser:User(*)\",\n * });\n *\n * @example\n * // Conditional query based on other state\n * const { data } = useDbQueryById<Project>(\"Project\", selectedProjectId, {\n * enabled: hasPermission && !!selectedProjectId,\n * });\n *\n * @example\n * // With custom stale time\n * const { data } = useDbQueryById<User>(\"User\", userId, {\n * staleTime: 60000, // 1 minute\n * });\n */\nexport function useDbQueryById<T = Record<string, unknown>>(table: string, id: string | number | null | undefined, options: UseDbQueryByIdOptions = {}): UseDbQueryByIdResult<T> {\n const {\n registry\n } = useDataLayerCore();\n const {\n select,\n enabled = id != null,\n staleTime = 30000\n } = options;\n\n // Get adapter for this table\n // No isInitialized check needed - if we get here, core context exists = initialized\n const adapter = useMemo(() => {\n try {\n return registry.getAdapter(table);\n } catch (error) {\n devWarn(\"useDbQueryById\", `Failed to get adapter for ${table}: ${(error as Error).message}`);\n return null;\n }\n }, [registry, table]);\n\n // Build query key - memoized to prevent unnecessary re-renders\n const queryKey = useMemo(() => buildQueryKey(table, id, select), [table, id, select]);\n\n // Track the adapter name that was actually used for the most recent query\n // This is used for accurate logging since the memoized adapter may be stale\n const lastUsedAdapterNameRef = useRef<string>(\"unknown\");\n\n // Query function - resolve adapter lazily at query time to ensure we always\n // have the latest adapter instance (the memoized adapter may be stale)\n const queryFn = useCallback(async (): Promise<T | null> => {\n if (id == null) {\n return null;\n }\n\n // Use currentAdapter directly - registry.getAdapter() throws if unavailable\n const currentAdapter = registry.getAdapter(table);\n\n // Track which adapter was actually used for accurate logging\n lastUsedAdapterNameRef.current = currentAdapter.name;\n\n // Use queryById if available, otherwise fall back to query with where\n if (currentAdapter.queryById) {\n return currentAdapter.queryById<T>(table, String(id), {\n select\n });\n }\n\n // Fallback: use query with where clause\n const result = await currentAdapter.query<T>(table, {\n select,\n where: {\n id\n } as WhereClause,\n limit: 1\n });\n return result.data[0] ?? null;\n }, [registry, table, id, select]);\n\n // Execute query with React Query\n const query = useQuery({\n queryKey,\n queryFn,\n enabled: enabled && adapter !== null && id != null,\n staleTime\n });\n\n // Dev logging for debugging\n // Uses lastUsedAdapterNameRef to log the adapter that was ACTUALLY used for the query,\n // not the memoized adapter from render time (which may be stale due to auto-detection)\n useEffect(() => {\n const adapterName = lastUsedAdapterNameRef.current;\n\n // Log errors\n if (query.isError && query.error) {\n devWarn(\"useDbQueryById\", `${table}(${id}) via ${adapterName}: Error - ${query.error.message}`);\n }\n\n // Log not found (only after successful fetch, not during loading)\n if (query.isSuccess && query.data === null) {\n devLog(\"useDbQueryById\", `${table}(${id}) via ${adapterName}: not found`);\n }\n }, [query.isError, query.error, query.isSuccess, query.data, table, id]);\n\n // Build refetch function\n const refetch = useCallback(async () => {\n await query.refetch();\n }, [query]);\n return {\n data: query.data,\n isLoading: query.isLoading,\n isPending: query.isPending,\n isFetching: query.isFetching,\n error: query.error as Error | null,\n refetch\n };\n}\nexport default useDbQueryById;"],"mappings":"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","names":["useCallback","useEffect","useMemo","useRef","useQuery","buildQueryKey","useMemo","useRef","useCallback","useQuery","useEffect"]}
@@ -9,7 +9,7 @@ import {
9
9
  useOnlineStatus,
10
10
  useSyncControl,
11
11
  useSyncStatus
12
- } from "../chunk-RJIVXO4U.js";
12
+ } from "../chunk-3Q74DK5K.js";
13
13
  import {
14
14
  useDataLayer,
15
15
  useDataLayerCore,
@@ -18,7 +18,7 @@ import {
18
18
  useDataLayerStatus,
19
19
  useDbQuery,
20
20
  useDbQueryById
21
- } from "../chunk-AIYPSXIO.js";
21
+ } from "../chunk-WQLIGVQR.js";
22
22
  import "../chunk-GC3TBUWE.js";
23
23
  import "../chunk-J4ZVCXZ4.js";
24
24
  import "../chunk-DMVUEJG2.js";
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  useHasConflicts,
25
25
  usePendingConflicts,
26
26
  useSupabaseUpload
27
- } from "./chunk-WBMZDH2U.js";
27
+ } from "./chunk-G6E25CWV.js";
28
28
  import {
29
29
  ADAPTER_STRATEGIES,
30
30
  AdapterAutoDetector,
@@ -77,7 +77,7 @@ import {
77
77
  useUpsertChangelog,
78
78
  useUpsertChangelogEntry,
79
79
  useUpsertChangelogMedia
80
- } from "./chunk-7CLN4ORU.js";
80
+ } from "./chunk-PGTRDT5K.js";
81
81
  import {
82
82
  LiveChangeContext,
83
83
  LiveChangeContextProvider,
@@ -88,7 +88,7 @@ import {
88
88
  useUserMetadataState,
89
89
  useUserMetadataValue,
90
90
  userMetadataContext
91
- } from "./chunk-GY7HDOBA.js";
91
+ } from "./chunk-FIAXWEBK.js";
92
92
  import {
93
93
  PostgrestFilter,
94
94
  binarySearch,
@@ -128,7 +128,7 @@ import {
128
128
  useOnlineStatus,
129
129
  useSyncControl,
130
130
  useSyncStatus
131
- } from "./chunk-RJIVXO4U.js";
131
+ } from "./chunk-3Q74DK5K.js";
132
132
  import {
133
133
  Constants,
134
134
  createCombinedStatus
@@ -321,12 +321,12 @@ import {
321
321
  UserMetadata
322
322
  } from "./chunk-SM73S2DY.js";
323
323
  import "./chunk-NSIAAYW3.js";
324
- import "./chunk-FLGHJCW3.js";
324
+ import "./chunk-FMYXG4VN.js";
325
325
  import {
326
326
  DEFAULT_QUERY_TIMEOUT,
327
327
  TIMEOUT_ERROR_MESSAGE,
328
328
  isTimeoutError
329
- } from "./chunk-DKUF2FKB.js";
329
+ } from "./chunk-DP3YEVSX.js";
330
330
  import {
331
331
  DataLayerContext,
332
332
  DataLayerCoreContext,
@@ -337,7 +337,7 @@ import {
337
337
  useDataLayerStatus,
338
338
  useDbQuery,
339
339
  useDbQueryById
340
- } from "./chunk-AIYPSXIO.js";
340
+ } from "./chunk-WQLIGVQR.js";
341
341
  import "./chunk-RT4O5H2E.js";
342
342
  import "./chunk-QJZUIAHA.js";
343
343
  import {
@@ -13,7 +13,7 @@ import {
13
13
  useHasConflicts,
14
14
  usePendingConflicts,
15
15
  useSupabaseUpload
16
- } from "./chunk-WBMZDH2U.js";
16
+ } from "./chunk-G6E25CWV.js";
17
17
  import {
18
18
  ADAPTER_STRATEGIES,
19
19
  AdapterAutoDetector,
@@ -65,7 +65,7 @@ import {
65
65
  useUpsertChangelog,
66
66
  useUpsertChangelogEntry,
67
67
  useUpsertChangelogMedia
68
- } from "./chunk-7CLN4ORU.js";
68
+ } from "./chunk-PGTRDT5K.js";
69
69
  import {
70
70
  LiveChangeContext,
71
71
  LiveChangeContextProvider,
@@ -76,7 +76,7 @@ import {
76
76
  useUserMetadataState,
77
77
  useUserMetadataValue,
78
78
  userMetadataContext
79
- } from "./chunk-GY7HDOBA.js";
79
+ } from "./chunk-FIAXWEBK.js";
80
80
  import {
81
81
  PostgrestFilter,
82
82
  binarySearch,
@@ -116,7 +116,7 @@ import {
116
116
  useOnlineStatus,
117
117
  useSyncControl,
118
118
  useSyncStatus
119
- } from "./chunk-RJIVXO4U.js";
119
+ } from "./chunk-3Q74DK5K.js";
120
120
  import {
121
121
  Constants,
122
122
  createCombinedStatus,
@@ -310,12 +310,12 @@ import {
310
310
  UserMetadata
311
311
  } from "./chunk-SM73S2DY.js";
312
312
  import "./chunk-NSIAAYW3.js";
313
- import "./chunk-FLGHJCW3.js";
313
+ import "./chunk-FMYXG4VN.js";
314
314
  import {
315
315
  DEFAULT_QUERY_TIMEOUT,
316
316
  TIMEOUT_ERROR_MESSAGE,
317
317
  isTimeoutError
318
- } from "./chunk-DKUF2FKB.js";
318
+ } from "./chunk-DP3YEVSX.js";
319
319
  import {
320
320
  DataLayerContext,
321
321
  DataLayerCoreContext,
@@ -326,7 +326,7 @@ import {
326
326
  useDataLayerStatus,
327
327
  useDbQuery,
328
328
  useDbQueryById
329
- } from "./chunk-AIYPSXIO.js";
329
+ } from "./chunk-WQLIGVQR.js";
330
330
  import "./chunk-RT4O5H2E.js";
331
331
  import "./chunk-QJZUIAHA.js";
332
332
  import {
package/dist/index.web.js CHANGED
@@ -56,7 +56,7 @@ import {
56
56
  useUpsertChangelog,
57
57
  useUpsertChangelogEntry,
58
58
  useUpsertChangelogMedia
59
- } from "./chunk-7CLN4ORU.js";
59
+ } from "./chunk-PGTRDT5K.js";
60
60
  import {
61
61
  LiveChangeContext,
62
62
  LiveChangeContextProvider,
@@ -67,7 +67,7 @@ import {
67
67
  useUserMetadataState,
68
68
  useUserMetadataValue,
69
69
  userMetadataContext
70
- } from "./chunk-GY7HDOBA.js";
70
+ } from "./chunk-FIAXWEBK.js";
71
71
  import {
72
72
  PostgrestFilter,
73
73
  binarySearch,
@@ -104,7 +104,7 @@ import {
104
104
  useDbInsert,
105
105
  useDbUpdate,
106
106
  useDbUpsert
107
- } from "./chunk-RJIVXO4U.js";
107
+ } from "./chunk-3Q74DK5K.js";
108
108
  import {
109
109
  Constants,
110
110
  createCombinedStatus,
@@ -299,20 +299,20 @@ import {
299
299
  UserMetadata
300
300
  } from "./chunk-SM73S2DY.js";
301
301
  import "./chunk-NSIAAYW3.js";
302
- import "./chunk-FLGHJCW3.js";
302
+ import "./chunk-FMYXG4VN.js";
303
303
  import {
304
304
  DEFAULT_QUERY_TIMEOUT,
305
305
  TIMEOUT_ERROR_MESSAGE,
306
306
  isTimeoutError,
307
307
  useDbQuery as useDbQuery2
308
- } from "./chunk-DKUF2FKB.js";
308
+ } from "./chunk-DP3YEVSX.js";
309
309
  import {
310
310
  DataLayerContext,
311
311
  useDataLayer,
312
312
  useDataLayerOptional,
313
313
  useDbQuery,
314
314
  useDbQueryById
315
- } from "./chunk-AIYPSXIO.js";
315
+ } from "./chunk-WQLIGVQR.js";
316
316
  import "./chunk-RT4O5H2E.js";
317
317
  import {
318
318
  useAdvancedFilterQuery,
@@ -5,20 +5,20 @@ import {
5
5
  useUserMetadataState,
6
6
  useUserMetadataValue,
7
7
  userMetadataContext
8
- } from "../chunk-GY7HDOBA.js";
8
+ } from "../chunk-FIAXWEBK.js";
9
9
  import {
10
10
  useDbUpsert
11
- } from "../chunk-RJIVXO4U.js";
11
+ } from "../chunk-3Q74DK5K.js";
12
12
  import "../chunk-SM73S2DY.js";
13
13
  import "../chunk-NSIAAYW3.js";
14
14
  import {
15
15
  useAuth,
16
16
  useSetupAuth
17
- } from "../chunk-FLGHJCW3.js";
17
+ } from "../chunk-FMYXG4VN.js";
18
18
  import {
19
19
  useDbQuery
20
- } from "../chunk-DKUF2FKB.js";
21
- import "../chunk-AIYPSXIO.js";
20
+ } from "../chunk-DP3YEVSX.js";
21
+ import "../chunk-WQLIGVQR.js";
22
22
  import "../chunk-RT4O5H2E.js";
23
23
  import {
24
24
  getSupabaseUrl
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pol-studios/db",
3
- "version": "1.0.50",
3
+ "version": "1.0.51",
4
4
  "description": "Database layer for React applications with Supabase and PowerSync support",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",