Add PocketBase TypeGen support#10
Conversation
This commit adds full support for pocketbase-typegen, enabling automatic
type inference for all hooks when using a typed Database schema.
Key features:
- TypedPocketBase<TDatabase> type for branding PocketBase instances
- PocketBaseProvider<TDatabase> accepts generic Database type
- All hooks (useCollection, useRecord, useAuth, mutations) support type inference
- Collection names are type-checked and autocompleted
- Return types are automatically inferred from collection names
- 100% backward compatible - existing code works without changes
Changes:
- Add src/types/database.type.ts with TypedPocketBase and helper types
- Update Context to support TypedPocketBase with any Database
- Update Provider to accept Database generic parameter
- Add function overloads to all hooks for type inference
- Update all hooks to support both explicit types and inference
- Add comprehensive documentation in docs/TYPED-DATABASE.md
- Add example usage in examples/typed-database-example.tsx
- Update README.md with TypeScript support section
Usage:
```typescript
const pb = new PocketBase(url) as TypedPocketBase<Database>;
<PocketBaseProvider<Database> pocketBase={pb}>
<App />
</PocketBaseProvider>
// Types are automatically inferred!
const { data } = useCollection('posts'); // data: PostsResponse[]
```
Closes #[issue-number]
WalkthroughAdds compile-time TypeScript typings and generics across the library: new database type utilities, TypedPocketBase, provider/context generics, schema-aware overloads for hooks (collection, record, auth, mutations), docs, and a typed example. Most changes are type-level; small runtime pending/error handling added to mutation hooks. Changes
Possibly related PRs
Pre-merge checks and finishing touchesImportant Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (4)src/hooks/**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/hooks/{useCollection,useRecord}.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/hooks/useRecord.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (11)📓 Common learnings📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:11.415ZApplied to files:
📚 Learning: 2025-10-18T12:22:42.070ZApplied to files:
📚 Learning: 2025-10-18T12:22:42.070ZApplied to files:
🧬 Code graph analysis (1)src/hooks/useRecord.ts (5)
🔇 Additional comments (2)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
README.md (1)
167-188: Align mutation hook usageEarlier in this README the API is documented as
useUpdateMutation('posts')followed bymutate(postId, data)(same for delete). This new example instead callsuseUpdateMutation('posts', id)anduseDeleteMutation('posts', id), which doesn’t match the described surface and will mislead users unless the runtime API actually changed. Please update the examples (and the Typed Database guide) to reflect the real signature or adjust the hook implementation accordingly.src/hooks/useCreateMutation.ts (1)
41-77: Fix renamed generic references; currently breaks compilation.
We renamed the type parameter toTRecord, but the implementation still refers toRecord, which no longer exists. This leaves unresolved identifiers in multiple spots and prevents the file from compiling. Please update the references to useTRecord.@@ - const mutateAsync = useCallback( - async (bodyParams: Partial<Record>, options?: RecordOptions): Promise<Record> => { + const mutateAsync = useCallback( + async (bodyParams: Partial<TRecord>, options?: RecordOptions): Promise<TRecord> => { @@ - const record = options ? await recordService.create(bodyParams, options) : await recordService.create(bodyParams); - return record as Record; + const record = options ? await recordService.create(bodyParams, options) : await recordService.create(bodyParams); + return record as TRecord; @@ - const mutate = useCallback( - (bodyParams: Partial<Record>, options?: RecordOptions): void => { + const mutate = useCallback( + (bodyParams: Partial<TRecord>, options?: RecordOptions): void => { @@ - return useMemo( - (): UseCreateMutationResult<Record> => ({ + return useMemo( + (): UseCreateMutationResult<TRecord> => ({src/hooks/useUpdateMutation.ts (1)
43-83: Align implementation withTRecordgeneric to restore type safety.
Just like inuseCreateMutation, the generic was renamed toTRecordbut the function body still referencesRecord. These stale identifiers break compilation. Switch them toTRecordso the hook type-checks again.@@ - const mutateAsync = useCallback( - async (bodyParams: Partial<Record>, options?: RecordOptions): Promise<Record> => { + const mutateAsync = useCallback( + async (bodyParams: Partial<TRecord>, options?: RecordOptions): Promise<TRecord> => { @@ - const record = options ? await recordService.update(id, bodyParams, options) : await recordService.update(id, bodyParams); - return record as Record; + const record = options ? await recordService.update(id, bodyParams, options) : await recordService.update(id, bodyParams); + return record as TRecord; @@ - const mutate = useCallback( - (bodyParams: Partial<Record>, options?: RecordOptions): void => { + const mutate = useCallback( + (bodyParams: Partial<TRecord>, options?: RecordOptions): void => { @@ - return useMemo( - (): UseUpdateMutationResult<Record> => ({ + return useMemo( + (): UseUpdateMutationResult<TRecord> => ({src/hooks/useCollection.ts (1)
50-138: Fix unresolvedRecordtype usageLine 50 switches
useQueryStatetoRecord[], butRecordis never defined in this scope (and the globalRecord<K, T>requires two type arguments). The same placeholder appears on Line 65, Line 77, Line 94, and the subscribe call, so the file no longer compiles. Replace all of those occurrences withTRecordto align the implementation with the overload generics.- const queryState = useQueryState<Record[]>({ + const queryState = useQueryState<TRecord[]>({ @@ - const transformers = useRef(options.transformers ?? [dateTransformer<Record>()]); - transformers.current = options.transformers ?? [dateTransformer<Record>()]; + const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]); + transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; @@ - let result: Record[] | null; + let result: TRecord[] | null; @@ - result = await recordService.getFullList<Record>({ + result = await recordService.getFullList<TRecord>({ @@ - const { items } = await recordService.getList<Record>(page ?? 1, perPage ?? 20, { + const { items } = await recordService.getList<TRecord>(page ?? 1, perPage ?? 20, { @@ - const unsubscribe = recordService.subscribe<Record>( + const unsubscribe = recordService.subscribe<TRecord>(src/hooks/useRecord.ts (1)
58-148: Replace undefinedRecordplaceholder withTRecordLine 58 introduces
useQueryState<Record | null>, butRecordis not defined, so TypeScript reports “Generic type 'Record<K, T>' requires 2 type argument(s)”. This placeholder recurs in the transformer ref, fetcher return type,getOne/getFirstListItem, and both subscribe calls, breaking compilation. Swap everyRecordusage here forTRecordto keep the implementation consistent with the overload generics.- const queryState = useQueryState<Record | null>({ + const queryState = useQueryState<TRecord | null>({ @@ - const transformers = useRef(options.transformers ?? [dateTransformer<Record>()]); + const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]); @@ - const fetcher = useCallback(async (): Promise<Record> => { + const fetcher = useCallback(async (): Promise<TRecord> => { @@ - return await recordService.getOne<Record>(recordIdOrFilter, { + return await recordService.getOne<TRecord>(recordIdOrFilter, { @@ - return await recordService.getFirstListItem<Record>(recordIdOrFilter, { + return await recordService.getFirstListItem<TRecord>(recordIdOrFilter, { @@ - const unsubscribe = recordService.subscribe<Record>( + const unsubscribe = recordService.subscribe<TRecord>( @@ - const unsubscribe = recordService.subscribe<Record>( + const unsubscribe = recordService.subscribe<TRecord>(
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
README.md(1 hunks)docs/TYPED-DATABASE.md(1 hunks)examples/typed-database-example.tsx(1 hunks)src/context/PocketBaseContext.tsx(2 hunks)src/hooks/useAuth.ts(7 hunks)src/hooks/useCollection.ts(1 hunks)src/hooks/useCreateMutation.ts(1 hunks)src/hooks/useDeleteMutation.ts(1 hunks)src/hooks/usePocketBase.ts(2 hunks)src/hooks/useRecord.ts(1 hunks)src/hooks/useUpdateMutation.ts(1 hunks)src/providers/PocketBaseProvider.tsx(3 hunks)src/types/database.type.ts(1 hunks)src/types/index.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: TypeScript strictness: avoid any; prefer unknown when type is uncertain
Never add comments in code
**/*.{ts,tsx}: Enable strict typing and avoid any; prefer unknown when necessary
Use proper type guards to ensure runtime type safety
Files:
src/types/index.tssrc/hooks/useUpdateMutation.tssrc/context/PocketBaseContext.tsxsrc/hooks/useCreateMutation.tssrc/hooks/usePocketBase.tssrc/hooks/useAuth.tssrc/types/database.type.tsexamples/typed-database-example.tsxsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.tssrc/providers/PocketBaseProvider.tsx
src/types/index.ts
📄 CodeRabbit inference engine (CLAUDE.md)
All exported types must be explicitly defined in src/types/index.ts and referenced by hooks and utilities
Files:
src/types/index.ts
src/hooks/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/**/*.{ts,tsx}: All data-fetching hooks must return a discriminated union QueryResult with isLoading, isSuccess, isError, data, and error states
Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Support request cancellation by accepting requestKey and using pb.cancelRequest(key) where applicable
Use TanStack Query-style naming: isLoading/isSuccess/isError for query hooks; isPending for mutations; fields data and error
Use useEffect for data fetching/subscriptions and always return a cleanup function for subscriptions
Memoize fetcher functions passed into useEffect with useCallback and avoid inline object/array creation in dependency arrays
Implement React StrictMode cancellation pattern: useRef for default values and a cancelled flag in async effects to prevent stale updates
In subscription handlers, use functional setState form setData(current => ...) to avoid adding data to effect dependencies
Provide generic type parameters for records in hooks, e.g., useCollection() and useAuth()
Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
src/hooks/**/*.{ts,tsx}: Follow TanStack Query state names in hooks: use isLoading, isSuccess, isError, error, data (not isPending)
Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Implement real-time subscriptions in hooks with proper cleanup
Use useEffect for side effects; do not use useCallback for data fetching
Ensure hooks surface graceful error states and meaningful error messages
Ensure cleanup of real-time subscriptions to prevent memory leaks
Files:
src/hooks/useUpdateMutation.tssrc/hooks/useCreateMutation.tssrc/hooks/usePocketBase.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.ts
src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Files:
src/hooks/useUpdateMutation.tssrc/hooks/useCreateMutation.tssrc/hooks/useDeleteMutation.ts
src/context/PocketBaseContext.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Files:
src/context/PocketBaseContext.tsx
src/context/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Define React Contexts for dependency injection
Files:
src/context/PocketBaseContext.tsx
README.md
📄 CodeRabbit inference engine (.cursorrules)
Provide README in English with clear TypeScript examples
Files:
README.md
src/hooks/useAuth.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Files:
src/hooks/useAuth.ts
examples/**/*
📄 CodeRabbit inference engine (.cursorrules)
Maintain examples directory with basic/advanced usage and TypeScript imports
Files:
examples/typed-database-example.tsx
src/hooks/{useCollection,useRecord}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/{useCollection,useRecord}.{ts,tsx}: useCollection and useRecord must support a transformers option (array of RecordTransformer) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Support request cancellation via the requestKey option in useCollection and useRecord
By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
src/hooks/useCollection.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Files:
src/hooks/useCollection.ts
src/hooks/useRecord.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Files:
src/hooks/useRecord.ts
src/providers/PocketBaseProvider.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Files:
src/providers/PocketBaseProvider.tsx
src/providers/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Implement Provider components to supply contexts
Files:
src/providers/PocketBaseProvider.tsx
🧠 Learnings (26)
📓 Common learnings
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/context/PocketBaseContext.tsx : Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Use React Context (PocketBaseContext) with a PocketBaseProvider to inject the PocketBase client across the tree
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Mock PocketBase client methods with Vitest vi.fn() and test loading, success, and error states
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to package.json : Set peerDependencies to React >=19.0.0 and PocketBase ^0.26.2
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/types/index.ts : All exported types must be explicitly defined in src/types/index.ts and referenced by hooks and utilities
Applied to files:
src/types/index.tssrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:42.057Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to src/index.ts : Export all public APIs from the main entry point
Applied to files:
src/types/index.ts
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Applied to files:
src/types/index.tssrc/hooks/useUpdateMutation.tssrc/context/PocketBaseContext.tsxREADME.mdsrc/hooks/useCreateMutation.tsdocs/TYPED-DATABASE.mdsrc/hooks/usePocketBase.tssrc/hooks/useAuth.tssrc/types/database.type.tsexamples/typed-database-example.tsxsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.tssrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/useAuth.{ts,tsx} : useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Applied to files:
src/types/index.tsREADME.mdsrc/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
Applied to files:
src/types/index.tssrc/hooks/useUpdateMutation.tssrc/context/PocketBaseContext.tsxREADME.mdsrc/hooks/useCreateMutation.tsdocs/TYPED-DATABASE.mdsrc/hooks/usePocketBase.tssrc/hooks/useAuth.tsexamples/typed-database-example.tsxsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:42.057Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to src/providers/**/*.{ts,tsx} : Implement Provider components to supply contexts
Applied to files:
src/types/index.tssrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : useCollection and useRecord must support a transformers option (array of RecordTransformer<T>) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Applied to files:
src/hooks/useUpdateMutation.tssrc/hooks/useCreateMutation.tsdocs/TYPED-DATABASE.mdsrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx} : Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Applied to files:
src/hooks/useUpdateMutation.tssrc/hooks/useCreateMutation.tssrc/hooks/useDeleteMutation.ts
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : Support request cancellation via the requestKey option in useCollection and useRecord
Applied to files:
src/hooks/useUpdateMutation.tssrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/useRecord.{ts,tsx} : useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Applied to files:
src/hooks/useUpdateMutation.tssrc/hooks/usePocketBase.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/useCollection.{ts,tsx} : useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Applied to files:
src/hooks/useUpdateMutation.tssrc/hooks/useCreateMutation.tsdocs/TYPED-DATABASE.mdsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Applied to files:
src/hooks/useUpdateMutation.tssrc/context/PocketBaseContext.tsxREADME.mdsrc/hooks/useCreateMutation.tsdocs/TYPED-DATABASE.mdsrc/hooks/usePocketBase.tssrc/hooks/useAuth.tsexamples/typed-database-example.tsxsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.tssrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/context/PocketBaseContext.tsx : Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Applied to files:
src/context/PocketBaseContext.tsxREADME.mdsrc/hooks/usePocketBase.tssrc/hooks/useAuth.tsexamples/typed-database-example.tsxsrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Use React Context (PocketBaseContext) with a PocketBaseProvider to inject the PocketBase client across the tree
Applied to files:
src/context/PocketBaseContext.tsxREADME.mddocs/TYPED-DATABASE.mdsrc/hooks/usePocketBase.tsexamples/typed-database-example.tsxsrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Applied to files:
src/context/PocketBaseContext.tsxREADME.mddocs/TYPED-DATABASE.mdsrc/hooks/usePocketBase.tssrc/hooks/useAuth.tssrc/types/database.type.tsexamples/typed-database-example.tsxsrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:42.057Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Applied to files:
src/context/PocketBaseContext.tsxREADME.mddocs/TYPED-DATABASE.mdsrc/hooks/usePocketBase.tssrc/types/database.type.tsexamples/typed-database-example.tsxsrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
Applied to files:
src/context/PocketBaseContext.tsxREADME.mddocs/TYPED-DATABASE.mdsrc/hooks/usePocketBase.tssrc/hooks/useAuth.tsexamples/typed-database-example.tsxsrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:42.057Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to src/context/**/*.{ts,tsx} : Define React Contexts for dependency injection
Applied to files:
src/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to package.json : Set peerDependencies to React >=19.0.0 and PocketBase ^0.26.2
Applied to files:
src/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to package.json : Mark React, React DOM, and PocketBase as external and peerDependencies (not bundled)
Applied to files:
src/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Mock PocketBase client methods with Vitest vi.fn() and test loading, success, and error states
Applied to files:
src/context/PocketBaseContext.tsxREADME.mdsrc/hooks/usePocketBase.tsexamples/typed-database-example.tsxsrc/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:42.057Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to README.md : Provide README in English with clear TypeScript examples
Applied to files:
README.md
📚 Learning: 2025-10-18T12:22:42.057Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Applied to files:
src/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:42.057Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.057Z
Learning: Applies to examples/**/* : Maintain examples directory with basic/advanced usage and TypeScript imports
Applied to files:
examples/typed-database-example.tsx
📚 Learning: 2025-10-18T12:22:11.405Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.405Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Applied to files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
🧬 Code graph analysis (10)
src/hooks/useUpdateMutation.ts (2)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useUpdateMutation.type.ts (1)
UseUpdateMutationResult(9-25)
src/context/PocketBaseContext.tsx (1)
src/types/database.type.ts (2)
TypedPocketBase(6-8)DefaultDatabase(4-4)
src/hooks/useCreateMutation.ts (2)
src/types/useCreateMutation.type.ts (1)
UseCreateMutationResult(9-25)src/types/database.type.ts (1)
CollectionRecord(12-12)
src/hooks/usePocketBase.ts (2)
src/types/database.type.ts (2)
DefaultDatabase(4-4)TypedPocketBase(6-8)src/context/PocketBaseContext.tsx (1)
PocketBaseContext(12-12)
src/hooks/useAuth.ts (3)
src/types/useAuth.type.ts (2)
UseAuthOptions(7-17)UseAuthResult(24-124)src/types/database.type.ts (1)
AuthCollectionRecord(14-16)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
examples/typed-database-example.tsx (5)
src/types/database.type.ts (1)
TypedPocketBase(6-8)src/providers/PocketBaseProvider.tsx (1)
PocketBaseProvider(61-63)src/hooks/useCollection.ts (1)
useCollection(44-147)src/hooks/useRecord.ts (1)
useRecord(51-153)src/hooks/useAuth.ts (1)
useAuth(40-238)
src/hooks/useDeleteMutation.ts (2)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useDeleteMutation.type.ts (1)
UseDeleteMutationResult(7-21)
src/hooks/useCollection.ts (2)
src/types/useCollection.type.ts (2)
UseCollectionOptions(10-55)UseCollectionResult(62-62)src/types/database.type.ts (1)
CollectionRecord(12-12)
src/hooks/useRecord.ts (2)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useRecord.type.ts (2)
UseRecordOptions(10-25)UseRecordResult(32-32)
src/providers/PocketBaseProvider.tsx (2)
src/types/database.type.ts (2)
DefaultDatabase(4-4)TypedPocketBase(6-8)src/context/PocketBaseContext.tsx (1)
PocketBaseContext(12-12)
| function EditPost({ id }: { id: string }) { | ||
| // ✅ Type inferred from collection name | ||
| const { mutateAsync } = useUpdateMutation('posts', id); | ||
|
|
||
| const handleUpdate = async () => { | ||
| // ✅ Partial<PostsResponse> is inferred | ||
| await mutateAsync({ title: 'Updated Title' }); | ||
| }; | ||
|
|
||
| return <button onClick={handleUpdate}>Update</button>; | ||
| } | ||
| ``` | ||
|
|
||
| ### useDeleteMutation | ||
|
|
||
| ```typescript | ||
| function DeletePost({ id }: { id: string }) { | ||
| // ✅ Collection name is type-checked | ||
| const { mutateAsync } = useDeleteMutation('posts', id); | ||
|
|
||
| return <button onClick={() => mutateAsync()}>Delete</button>; | ||
| } |
There was a problem hiding this comment.
Keep mutation examples consistent with the API
These snippets also call useUpdateMutation('posts', id) / useDeleteMutation('posts', id), whereas the library docs above still describe the original API where the hook only takes the collection name and the returned mutate function accepts the record ID. Please bring the examples back in sync with the actual hook signature (or document the new signature everywhere if it really changed).
🤖 Prompt for AI Agents
docs/TYPED-DATABASE.md lines 167-188: the examples currently call
useUpdateMutation('posts', id) and useDeleteMutation('posts', id) but the docs
describe the original API where the hook only accepts the collection name and
the returned mutate function receives the record ID (or payload) — revert the
examples to that original signature: call useUpdateMutation('posts') and
useDeleteMutation('posts') and update the mutateAsync invocations to pass the id
(and update payload where appropriate) to the returned mutate function so the
example matches the documented API.
- Export TypedPocketBase, DefaultDatabase, CollectionRecord, AuthCollectionRecord - Rename generic type parameter from Record to TRecord to avoid conflict with TypeScript built-in Record<K, V> - Fix useAuth overload to accept zero arguments for useAuth<User>() calls - Fix Database interface in example to extend Record<string, RecordModel> - Add null check in example to handle posts potentially being null Fixes all type-check errors reported by CI.
The constraint `TDatabase extends Record<string, RecordModel>` was too strict
and prevented interfaces with mixed RecordModel/AuthRecord fields from being used.
Changes:
- Remove `extends Record<string, RecordModel>` constraint from all type parameters
- Change to generic `TDatabase` without constraint (more flexible)
- Update TypedPocketBase, CollectionRecord, AuthCollectionRecord to accept any type
- Fix verbatimModuleSyntax error by importing TypedPocketBase with type import
- Remove `extends Record<string, RecordModel>` from Database interface in example
- Fix remaining Record -> TRecord renames in useCreateMutation
This allows users to define Database interfaces with any structure:
interface Database {
posts: PostsResponse; // RecordModel
users: UsersResponse; // AuthRecord
}
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
examples/typed-database-example.tsx(1 hunks)src/hooks/useAuth.ts(7 hunks)src/hooks/useCollection.ts(4 hunks)src/hooks/useRecord.ts(3 hunks)src/hooks/useUpdateMutation.ts(4 hunks)src/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- examples/typed-database-example.tsx
🧰 Additional context used
📓 Path-based instructions (8)
src/hooks/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/**/*.{ts,tsx}: All data-fetching hooks must return a discriminated union QueryResult with isLoading, isSuccess, isError, data, and error states
Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Support request cancellation by accepting requestKey and using pb.cancelRequest(key) where applicable
Use TanStack Query-style naming: isLoading/isSuccess/isError for query hooks; isPending for mutations; fields data and error
Use useEffect for data fetching/subscriptions and always return a cleanup function for subscriptions
Memoize fetcher functions passed into useEffect with useCallback and avoid inline object/array creation in dependency arrays
Implement React StrictMode cancellation pattern: useRef for default values and a cancelled flag in async effects to prevent stale updates
In subscription handlers, use functional setState form setData(current => ...) to avoid adding data to effect dependencies
Provide generic type parameters for records in hooks, e.g., useCollection() and useAuth()
Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
src/hooks/**/*.{ts,tsx}: Follow TanStack Query state names in hooks: use isLoading, isSuccess, isError, error, data (not isPending)
Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Implement real-time subscriptions in hooks with proper cleanup
Use useEffect for side effects; do not use useCallback for data fetching
Ensure hooks surface graceful error states and meaningful error messages
Ensure cleanup of real-time subscriptions to prevent memory leaks
Files:
src/hooks/useRecord.tssrc/hooks/useAuth.tssrc/hooks/useCollection.tssrc/hooks/useUpdateMutation.ts
src/hooks/{useCollection,useRecord}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/{useCollection,useRecord}.{ts,tsx}: useCollection and useRecord must support a transformers option (array of RecordTransformer) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Support request cancellation via the requestKey option in useCollection and useRecord
By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Files:
src/hooks/useRecord.tssrc/hooks/useCollection.ts
src/hooks/useRecord.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Files:
src/hooks/useRecord.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: TypeScript strictness: avoid any; prefer unknown when type is uncertain
Never add comments in code
**/*.{ts,tsx}: Enable strict typing and avoid any; prefer unknown when necessary
Use proper type guards to ensure runtime type safety
Files:
src/hooks/useRecord.tssrc/hooks/useAuth.tssrc/hooks/useCollection.tssrc/index.tssrc/hooks/useUpdateMutation.ts
src/hooks/useAuth.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Files:
src/hooks/useAuth.ts
src/hooks/useCollection.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Files:
src/hooks/useCollection.ts
src/index.ts
📄 CodeRabbit inference engine (.cursorrules)
Export all public APIs from the main entry point
Files:
src/index.ts
src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Files:
src/hooks/useUpdateMutation.ts
🧠 Learnings (26)
📓 Common learnings
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/context/PocketBaseContext.tsx : Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Use React Context (PocketBaseContext) with a PocketBaseProvider to inject the PocketBase client across the tree
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Mock PocketBase client methods with Vitest vi.fn() and test loading, success, and error states
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to package.json : Set peerDependencies to React >=19.0.0 and PocketBase ^0.26.2
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : useCollection and useRecord must support a transformers option (array of RecordTransformer<T>) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Applied to files:
src/hooks/useRecord.tssrc/hooks/useAuth.tssrc/hooks/useCollection.tssrc/index.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Applied to files:
src/hooks/useRecord.tssrc/hooks/useAuth.tssrc/hooks/useCollection.tssrc/index.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useRecord.{ts,tsx} : useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Applied to files:
src/hooks/useRecord.tssrc/hooks/useAuth.tssrc/hooks/useCollection.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useCollection.{ts,tsx} : useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Applied to files:
src/hooks/useRecord.tssrc/hooks/useCollection.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Applied to files:
src/hooks/useRecord.tssrc/hooks/useCollection.tssrc/index.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : Support request cancellation via the requestKey option in useCollection and useRecord
Applied to files:
src/hooks/useRecord.tssrc/hooks/useCollection.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
Applied to files:
src/hooks/useRecord.tssrc/hooks/useAuth.tssrc/hooks/useCollection.tssrc/index.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/lib/utils.ts : Keep shared utilities like sortRecords and applyTransformers in src/lib/utils.ts
Applied to files:
src/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Applied to files:
src/hooks/useRecord.tssrc/hooks/useAuth.tssrc/hooks/useCollection.tssrc/index.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Implement real-time subscriptions in hooks with proper cleanup
Applied to files:
src/hooks/useRecord.tssrc/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useAuth.{ts,tsx} : useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Applied to files:
src/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Applied to files:
src/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
Applied to files:
src/hooks/useAuth.tssrc/index.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/context/PocketBaseContext.tsx : Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Applied to files:
src/hooks/useAuth.tssrc/index.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Applied to files:
src/hooks/useAuth.tssrc/index.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : All data-fetching hooks must return a discriminated union QueryResult<T> with isLoading, isSuccess, isError, data, and error states
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Real-time subscriptions are enabled by default but can be disabled with realtime: false; expose isError and error for graceful error states
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Ensure cleanup of real-time subscriptions to prevent memory leaks
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Verify real-time subscription setup and cleanup in tests
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : In subscription handlers, use functional setState form setData(current => ...) to avoid adding data to effect dependencies
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/types/index.ts : All exported types must be explicitly defined in src/types/index.ts and referenced by hooks and utilities
Applied to files:
src/index.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Applied to files:
src/index.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/index.ts : Export all public APIs from the main entry point
Applied to files:
src/index.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Use React Context (PocketBaseContext) with a PocketBaseProvider to inject the PocketBase client across the tree
Applied to files:
src/index.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx} : Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Applied to files:
src/hooks/useUpdateMutation.ts
🧬 Code graph analysis (4)
src/hooks/useRecord.ts (6)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useRecord.type.ts (2)
UseRecordOptions(10-25)UseRecordResult(32-32)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)src/hooks/internal/useQueryState.ts (1)
useQueryState(51-108)src/transformers/date.transformer.ts (1)
dateTransformer(8-20)src/lib/utils.ts (1)
applyTransformers(40-49)
src/hooks/useAuth.ts (3)
src/types/useAuth.type.ts (2)
UseAuthOptions(7-17)UseAuthResult(24-124)src/types/database.type.ts (1)
AuthCollectionRecord(14-16)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
src/hooks/useCollection.ts (5)
src/types/useCollection.type.ts (2)
UseCollectionOptions(10-55)UseCollectionResult(62-62)src/types/database.type.ts (1)
CollectionRecord(12-12)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)src/hooks/internal/useQueryState.ts (1)
useQueryState(51-108)src/transformers/date.transformer.ts (1)
dateTransformer(8-20)
src/hooks/useUpdateMutation.ts (3)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useUpdateMutation.type.ts (1)
UseUpdateMutationResult(9-25)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
🔇 Additional comments (11)
src/index.ts (1)
8-23: LGTM! Type exports properly expanded.The new type exports (AuthCollectionRecord, CollectionRecord, DefaultDatabase, TypedPocketBase) are correctly integrated into the public API surface, enabling consumers to use the typed database functionality introduced in this PR.
src/hooks/useAuth.ts (2)
6-10: Verify the past review concern is resolved.The past review flagged line 11 (now line 10) for requiring a default value to allow zero-argument calls like
useAuth<User>(). The current code usesoptions?: UseAuthOptionswith the optional marker?, which should permit calls without arguments. The implementation on line 39 has= {}to provide the default value.This should work correctly—the
?makes the parameter optional in the overload, and the implementation provides the default. However, if the original issue persists, please verify with a type check or test.Based on past review comments.
39-236: LGTM! Implementation correctly uses the TUser generic.The type assertions throughout (
as TUser) are necessary and acceptable for this pattern. PocketBase SDK returns genericRecordModeltypes, so the wrapper must cast to the user-provided type. This is standard practice for typed wrappers and maintains runtime safety while providing compile-time type inference.src/hooks/useCollection.ts (2)
9-14: LGTM! Overloads enable database schema type inference.The overload signatures correctly support both database-schema-based usage (with automatic type inference) and explicit type parameters, aligning with the PR objectives for pocketbase-typegen integration.
44-146: LGTM! Implementation correctly handles typed collections.The generic type parameter
TRecordis used consistently throughout fetching, transforming, and real-time subscriptions. The discriminated union return type and cleanup logic align with coding guidelines.src/hooks/useUpdateMutation.ts (2)
6-11: LGTM! Overloads support database schema type inference.The overload signatures correctly enable both database-schema-driven type inference and explicit type parameters for mutation operations.
36-84: LGTM! Implementation has robust error handling.The mutation implementation properly handles errors with try/catch/finally blocks, exposes all required state fields (isPending, isError, error, isSuccess), and correctly validates that the ID is present before attempting updates. The type assertions are necessary and acceptable for this pattern.
src/hooks/useRecord.ts (4)
9-24: LGTM! Comprehensive overloads cover all use cases.The four overload signatures correctly handle the matrix of database-schema/explicit-type and ID/filter approaches, enabling full type inference for both query patterns while maintaining backward compatibility.
63-66: LGTM! Transformers properly managed in useEffect.The transformer ref is correctly updated inside a
useEffectwith proper dependencies, ensuring stable identity and avoiding unnecessary re-allocations on every render.
68-85: LGTM! Fetcher validates input and handles both query patterns.The fetcher correctly throws an error when
recordIdOrFilteris missing (line 69-71), and properly dispatches togetOnefor IDs orgetFirstListItemfor filters based on the runtime check. The generic typing is consistent throughout.
125-148: LGTM! Wildcard subscription correctly handles filter-based queries.The wildcard subscription for non-ID queries (lines 125-143) properly handles create/update/delete events with the filter option, and correctly checks record identity before clearing data on delete (line 134). Cleanup properly unsubscribes via the Promise pattern.
| const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]); | ||
| transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Move transformer ref update into useEffect.
Line 56 updates the transformer ref on every render outside any effect, which defeats the purpose of using a ref and creates unnecessary allocations. This is inconsistent with useRecord (lines 63-66), which correctly updates the ref inside a useEffect with [options.transformers] as a dependency.
Apply this diff:
const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]);
-transformers.current = options.transformers ?? [dateTransformer<TRecord>()];
+useEffect(() => {
+ transformers.current = options.transformers ?? [dateTransformer<TRecord>()];
+}, [options.transformers]);As per coding guidelines.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]); | |
| transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; | |
| const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]); | |
| useEffect(() => { | |
| transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; | |
| }, [options.transformers]); |
🤖 Prompt for AI Agents
In src/hooks/useCollection.ts around lines 55 to 56, the transformers ref is
being reassigned on every render (transformers.current = options.transformers ??
[dateTransformer<TRecord>()]) which defeats the ref and causes unnecessary
allocations; move that reassignment into a useEffect that runs when
options.transformers changes (useEffect(() => { transformers.current =
options.transformers ?? [dateTransformer<TRecord>()]; },
[options.transformers])), leaving the initial useRef(...) call as the one-time
initializer.
Reverting the removal of constraints which broke type inference completely.
The constraints are necessary for TypeScript to properly infer types.
The key insight: User Database interfaces should NOT use `extends Record<string, RecordModel>`,
but the library's type parameters MUST have this constraint for proper inference.
Example usage:
```typescript
// ✅ User defines Database without extends
interface Database {
posts: PostsResponse;
users: UsersResponse; // AuthRecord extends RecordModel - works!
}
// ✅ Library types have constraints
<TDatabase extends Record<string, RecordModel>>
```
Changes:
- Restore `extends Record<string, RecordModel>` to all type parameters
- Keep example Database interface simple (no extends)
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/hooks/useDeleteMutation.ts (1)
72-80:isSuccessistruebefore any mutation runs.
isSuccessis derived from!isPending && !error, so the hook reports success immediately on mount. Track success in state so it only becomestrueafter a successful delete, and reset it when a new mutation starts.-const [isPending, setIsPending] = useState(false); -const [error, setError] = useState<string | null>(null); +const [isPending, setIsPending] = useState(false); +const [error, setError] = useState<string | null>(null); +const [isSuccess, setIsSuccess] = useState(false); … try { setIsPending(true); setError(null); + setIsSuccess(false); await recordService.delete(id, options); + setIsSuccess(true); } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Error deleting record'; setError(errorMessage); + setIsSuccess(false); throw new Error(errorMessage); } finally { setIsPending(false); } … - (): UseDeleteMutationResult => ({ + (): UseDeleteMutationResult => ({ mutate, mutateAsync, isPending, - isError: !!error, + isError: error !== null, error, - isSuccess: !isPending && !error, + isSuccess, }), - [mutate, mutateAsync, isPending, error], + [mutate, mutateAsync, isPending, error, isSuccess], );
♻️ Duplicate comments (1)
src/hooks/useCollection.ts (1)
55-56: Move transformer ref update into useEffect.Line 56 updates the transformer ref on every render outside any effect, which defeats the purpose of using a ref and creates unnecessary allocations. This issue was flagged in a previous review.
As per coding guidelines.
Apply this diff:
const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]); -transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; +useEffect(() => { + transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; +}, [options.transformers]);
🧹 Nitpick comments (1)
src/context/PocketBaseContext.tsx (1)
1-1: Remove unused import.
RecordModelis imported but never used in this file.Apply this diff:
-import type { RecordModel } from 'pocketbase'; import type PocketBase from 'pocketbase';
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
examples/typed-database-example.tsx(1 hunks)src/context/PocketBaseContext.tsx(2 hunks)src/hooks/useAuth.ts(7 hunks)src/hooks/useCollection.ts(4 hunks)src/hooks/useCreateMutation.ts(3 hunks)src/hooks/useDeleteMutation.ts(1 hunks)src/hooks/usePocketBase.ts(2 hunks)src/hooks/useRecord.ts(3 hunks)src/hooks/useUpdateMutation.ts(4 hunks)src/providers/PocketBaseProvider.tsx(3 hunks)src/types/database.type.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/types/database.type.ts
🧰 Additional context used
📓 Path-based instructions (12)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: TypeScript strictness: avoid any; prefer unknown when type is uncertain
Never add comments in code
**/*.{ts,tsx}: Enable strict typing and avoid any; prefer unknown when necessary
Use proper type guards to ensure runtime type safety
Files:
src/providers/PocketBaseProvider.tsxsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useAuth.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tsexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/useUpdateMutation.tssrc/hooks/usePocketBase.ts
src/providers/PocketBaseProvider.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Files:
src/providers/PocketBaseProvider.tsx
src/providers/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Implement Provider components to supply contexts
Files:
src/providers/PocketBaseProvider.tsx
src/hooks/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/**/*.{ts,tsx}: All data-fetching hooks must return a discriminated union QueryResult with isLoading, isSuccess, isError, data, and error states
Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Support request cancellation by accepting requestKey and using pb.cancelRequest(key) where applicable
Use TanStack Query-style naming: isLoading/isSuccess/isError for query hooks; isPending for mutations; fields data and error
Use useEffect for data fetching/subscriptions and always return a cleanup function for subscriptions
Memoize fetcher functions passed into useEffect with useCallback and avoid inline object/array creation in dependency arrays
Implement React StrictMode cancellation pattern: useRef for default values and a cancelled flag in async effects to prevent stale updates
In subscription handlers, use functional setState form setData(current => ...) to avoid adding data to effect dependencies
Provide generic type parameters for records in hooks, e.g., useCollection() and useAuth()
Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
src/hooks/**/*.{ts,tsx}: Follow TanStack Query state names in hooks: use isLoading, isSuccess, isError, error, data (not isPending)
Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Implement real-time subscriptions in hooks with proper cleanup
Use useEffect for side effects; do not use useCallback for data fetching
Ensure hooks surface graceful error states and meaningful error messages
Ensure cleanup of real-time subscriptions to prevent memory leaks
Files:
src/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useAuth.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/usePocketBase.ts
src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Files:
src/hooks/useDeleteMutation.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.ts
src/hooks/{useCollection,useRecord}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/{useCollection,useRecord}.{ts,tsx}: useCollection and useRecord must support a transformers option (array of RecordTransformer) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Support request cancellation via the requestKey option in useCollection and useRecord
By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
src/hooks/useCollection.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Files:
src/hooks/useCollection.ts
src/hooks/useAuth.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Files:
src/hooks/useAuth.ts
src/hooks/useRecord.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Files:
src/hooks/useRecord.ts
examples/**/*
📄 CodeRabbit inference engine (.cursorrules)
Maintain examples directory with basic/advanced usage and TypeScript imports
Files:
examples/typed-database-example.tsx
src/context/PocketBaseContext.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Files:
src/context/PocketBaseContext.tsx
src/context/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Define React Contexts for dependency injection
Files:
src/context/PocketBaseContext.tsx
🧠 Learnings (35)
📓 Common learnings
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Applied to files:
src/providers/PocketBaseProvider.tsxsrc/hooks/useAuth.tsexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Use React Context (PocketBaseContext) with a PocketBaseProvider to inject the PocketBase client across the tree
Applied to files:
src/providers/PocketBaseProvider.tsxexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
Applied to files:
src/providers/PocketBaseProvider.tsxsrc/hooks/useAuth.tsexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Applied to files:
src/providers/PocketBaseProvider.tsxexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/context/PocketBaseContext.tsx : Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Applied to files:
src/providers/PocketBaseProvider.tsxsrc/hooks/useAuth.tsexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/providers/**/*.{ts,tsx} : Implement Provider components to supply contexts
Applied to files:
src/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Applied to files:
src/providers/PocketBaseProvider.tsxsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useAuth.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tsexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/useUpdateMutation.tssrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to package.json : Set peerDependencies to React >=19.0.0 and PocketBase ^0.26.2
Applied to files:
src/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Mock PocketBase client methods with Vitest vi.fn() and test loading, success, and error states
Applied to files:
src/providers/PocketBaseProvider.tsxexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Applied to files:
src/providers/PocketBaseProvider.tsxsrc/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useAuth.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tsexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/useUpdateMutation.tssrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : useCollection and useRecord must support a transformers option (array of RecordTransformer<T>) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Applied to files:
src/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useAuth.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx} : Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Applied to files:
src/hooks/useDeleteMutation.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
Applied to files:
src/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useAuth.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tsexamples/typed-database-example.tsxsrc/context/PocketBaseContext.tsxsrc/hooks/useUpdateMutation.tssrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useCollection.{ts,tsx} : useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Applied to files:
src/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : Support request cancellation via the requestKey option in useCollection and useRecord
Applied to files:
src/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useRecord.{ts,tsx} : useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Applied to files:
src/hooks/useDeleteMutation.tssrc/hooks/useCollection.tssrc/hooks/useAuth.tssrc/hooks/useRecord.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/usePocketBase.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Applied to files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/lib/utils.ts : applyTransformers() must catch transformer errors, log to console, and return the original record to avoid breaking flow
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/lib/utils.ts : Keep shared utilities like sortRecords and applyTransformers in src/lib/utils.ts
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/transformers/**/*.{ts,tsx} : Define built-in transformers (e.g., dateTransformer) under src/transformers/
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Memoize fetcher functions passed into useEffect with useCallback and avoid inline object/array creation in dependency arrays
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : In subscription handlers, use functional setState form setData(current => ...) to avoid adding data to effect dependencies
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Implement React StrictMode cancellation pattern: useRef for default values and a cancelled flag in async effects to prevent stale updates
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : All data-fetching hooks must return a discriminated union QueryResult<T> with isLoading, isSuccess, isError, data, and error states
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Implement real-time subscriptions in hooks with proper cleanup
Applied to files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Real-time subscriptions are enabled by default but can be disabled with realtime: false; expose isError and error for graceful error states
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Ensure cleanup of real-time subscriptions to prevent memory leaks
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Verify real-time subscription setup and cleanup in tests
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useAuth.{ts,tsx} : useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Applied to files:
src/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Applied to files:
src/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Use TanStack Query-style naming: isLoading/isSuccess/isError for query hooks; isPending for mutations; fields data and error
Applied to files:
src/hooks/useCreateMutation.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to examples/**/* : Maintain examples directory with basic/advanced usage and TypeScript imports
Applied to files:
examples/typed-database-example.tsx
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to README.md : Provide README in English with clear TypeScript examples
Applied to files:
examples/typed-database-example.tsx
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/context/**/*.{ts,tsx} : Define React Contexts for dependency injection
Applied to files:
src/context/PocketBaseContext.tsx
🧬 Code graph analysis (10)
src/providers/PocketBaseProvider.tsx (2)
src/types/database.type.ts (2)
DefaultDatabase(4-4)TypedPocketBase(6-8)src/context/PocketBaseContext.tsx (1)
PocketBaseContext(12-12)
src/hooks/useDeleteMutation.ts (2)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useDeleteMutation.type.ts (1)
UseDeleteMutationResult(7-21)
src/hooks/useCollection.ts (5)
src/types/useCollection.type.ts (2)
UseCollectionOptions(10-55)UseCollectionResult(62-62)src/types/database.type.ts (1)
CollectionRecord(12-12)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)src/hooks/internal/useQueryState.ts (1)
useQueryState(51-108)src/transformers/date.transformer.ts (1)
dateTransformer(8-20)
src/hooks/useAuth.ts (3)
src/types/useAuth.type.ts (2)
UseAuthOptions(7-17)UseAuthResult(24-124)src/types/database.type.ts (1)
AuthCollectionRecord(14-16)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
src/hooks/useRecord.ts (6)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useRecord.type.ts (2)
UseRecordOptions(10-25)UseRecordResult(32-32)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)src/hooks/internal/useQueryState.ts (1)
useQueryState(51-108)src/transformers/date.transformer.ts (1)
dateTransformer(8-20)src/lib/utils.ts (1)
applyTransformers(40-49)
src/hooks/useCreateMutation.ts (3)
src/types/useCreateMutation.type.ts (1)
UseCreateMutationResult(9-25)src/types/database.type.ts (1)
CollectionRecord(12-12)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
examples/typed-database-example.tsx (5)
src/types/database.type.ts (1)
TypedPocketBase(6-8)src/providers/PocketBaseProvider.tsx (1)
PocketBaseProvider(61-63)src/hooks/useCollection.ts (1)
useCollection(44-147)src/hooks/useRecord.ts (1)
useRecord(51-151)src/hooks/useAuth.ts (1)
useAuth(39-237)
src/context/PocketBaseContext.tsx (1)
src/types/database.type.ts (2)
TypedPocketBase(6-8)DefaultDatabase(4-4)
src/hooks/useUpdateMutation.ts (3)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useUpdateMutation.type.ts (1)
UseUpdateMutationResult(9-25)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
src/hooks/usePocketBase.ts (2)
src/types/database.type.ts (2)
DefaultDatabase(4-4)TypedPocketBase(6-8)src/context/PocketBaseContext.tsx (1)
PocketBaseContext(12-12)
🪛 GitHub Actions: CI
src/hooks/useDeleteMutation.ts
[error] 8-8: TS2536: Type '"id"' cannot be used to index type 'CollectionRecord<TDatabase, TCollection>'.
src/hooks/useCollection.ts
[error] 11-11: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
[error] 12-12: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
src/hooks/useAuth.ts
[error] 6-6: TS2344: Type 'string' does not satisfy the constraint 'keyof TDatabase & string'.
src/hooks/useRecord.ts
[error] 11-11: TS2536: Type '"id"' cannot be used to index type 'CollectionRecord<TDatabase, TCollection>'.
[error] 12-12: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
[error] 13-13: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
[error] 18-18: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
[error] 19-19: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
src/hooks/useCreateMutation.ts
[error] 8-8: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
examples/typed-database-example.tsx
[error] 13-13: TS2312: An interface can only extend an object type or intersection of object types with statically known members.
[error] 74-74: TS2339: Property 'username' does not exist on type 'never'.
[error] 82-82: TS2339: Property 'name' does not exist on type 'never'.
src/hooks/useUpdateMutation.ts
[error] 8-8: TS2536: Type '"id"' cannot be used to index type 'CollectionRecord<TDatabase, TCollection>'.
[error] 9-9: TS2344: Type 'CollectionRecord<TDatabase, TCollection>' does not satisfy the constraint 'RecordModel'.
🔇 Additional comments (1)
src/context/PocketBaseContext.tsx (1)
28-34: Document the phantom type trade-off or add runtime validation for database type alignment.The concern in the original review is valid. The hook performs an unsafe cast (
as TypedPocketBase<TDatabase>) with no runtime enforcement that the context's actual database type matches the caller'sTDatabaseparameter. While the phantom type design intentionally prioritizes compile-time inference over runtime safety, this contradicts the project's coding guideline requiring "proper type guards to ensure runtime type safety."Recommend one of:
- Add explicit JSDoc warnings in
usePocketBaseContextandusePocketBaseexplaining the phantom type limitation and requirement to match provider/hook type parameters- Implement a runtime check (though this would require encoding type info at runtime)
- Clarify in contributing guidelines that this is an accepted trade-off
| const { user, signIn, signOut } = useAuth(); | ||
|
|
||
| const handleLogin = async () => { | ||
| const user = await signIn.email('test@example.com', 'password'); | ||
| if (user) { | ||
| console.log('Logged in as:', user.username); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <div> | ||
| {user ? ( | ||
| <div> | ||
| <p>Welcome, {user.name}!</p> | ||
| <button onClick={signOut}>Sign Out</button> | ||
| </div> | ||
| ) : ( | ||
| <button onClick={handleLogin}>Sign In</button> | ||
| )} | ||
| </div> |
There was a problem hiding this comment.
Pass the typed collection to useAuth so user isn’t never.
Calling useAuth() without a type argument leaves TUser unresolved, which is why user.username/user.name report TS2339. Provide the typed collection (and re-use your UsersResponse) so the hook resolves to the generated auth record.
-function Auth() {
- const { user, signIn, signOut } = useAuth();
+function Auth() {
+ const { user, signIn, signOut } = useAuth<UsersResponse>({ collectionName: 'users' });Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 GitHub Actions: CI
[error] 74-74: TS2339: Property 'username' does not exist on type 'never'.
[error] 82-82: TS2339: Property 'name' does not exist on type 'never'.
🤖 Prompt for AI Agents
In examples/typed-database-example.tsx around lines 69 to 88, the call to
useAuth() is untyped so TUser resolves to never; update the call to pass the
typed collection (reuse your generated UsersResponse type and the Users
collection object) as the generic/argument to useAuth so the hook returns the
correct typed user record, then update occurrences of user.username/user.name to
the actual fields on UsersResponse if names differ.
| * @internal | ||
| */ | ||
| export const PocketBaseContext: Context<PocketBase | null> = createContext<PocketBase | null>(null); | ||
| export const PocketBaseContext: Context<TypedPocketBase<any> | null> = createContext<TypedPocketBase<any> | null>(null); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Replace any with unknown for stricter typing.
The context is typed as TypedPocketBase<any>, which violates the coding guideline to avoid any and prefer unknown when the type is uncertain.
As per coding guidelines.
Apply this diff:
-export const PocketBaseContext: Context<TypedPocketBase<any> | null> = createContext<TypedPocketBase<any> | null>(null);
+export const PocketBaseContext: Context<TypedPocketBase<unknown> | null> = createContext<TypedPocketBase<unknown> | null>(null);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const PocketBaseContext: Context<TypedPocketBase<any> | null> = createContext<TypedPocketBase<any> | null>(null); | |
| export const PocketBaseContext: Context<TypedPocketBase<unknown> | null> = createContext<TypedPocketBase<unknown> | null>(null); |
🤖 Prompt for AI Agents
In src/context/PocketBaseContext.tsx around line 12, the context is declared as
TypedPocketBase<any> which uses `any`; replace `any` with `unknown` so the
declaration becomes TypedPocketBase<unknown> (and keep the nullability),
ensuring stricter typing and compliance with the coding guideline to avoid
`any`.
| export function useAuth<TDatabase, TCollection extends keyof TDatabase & string = 'users'>( | ||
| options?: UseAuthOptions, | ||
| ): UseAuthResult<AuthCollectionRecord<TDatabase, TCollection>>; |
There was a problem hiding this comment.
Fix type constraint violation causing build failure.
The first overload specifies TCollection extends keyof TDatabase & string = 'users', but TypeScript cannot guarantee that the string literal 'users' is a valid key in an arbitrary TDatabase. This causes the pipeline failure: "Type 'string' does not satisfy the constraint 'keyof TDatabase & string'."
Remove the default value from the generic parameter. The implementation already provides a default for collectionName in the options object.
Apply this diff:
-export function useAuth<TDatabase, TCollection extends keyof TDatabase & string = 'users'>(
+export function useAuth<TDatabase, TCollection extends keyof TDatabase & string>(
options?: UseAuthOptions,
): UseAuthResult<AuthCollectionRecord<TDatabase, TCollection>>;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function useAuth<TDatabase, TCollection extends keyof TDatabase & string = 'users'>( | |
| options?: UseAuthOptions, | |
| ): UseAuthResult<AuthCollectionRecord<TDatabase, TCollection>>; | |
| export function useAuth<TDatabase, TCollection extends keyof TDatabase & string>( | |
| options?: UseAuthOptions, | |
| ): UseAuthResult<AuthCollectionRecord<TDatabase, TCollection>>; |
🧰 Tools
🪛 GitHub Actions: CI
[error] 6-6: TS2344: Type 'string' does not satisfy the constraint 'keyof TDatabase & string'.
🤖 Prompt for AI Agents
In src/hooks/useAuth.ts around lines 6 to 8, the first overload sets TCollection
with a default of 'users' which can violate the constraint keyof TDatabase &
string; remove the default so the generic reads TCollection extends keyof
TDatabase & string (no = 'users'), leaving the implementation to continue
providing the collectionName default via the options object.
| export function useDeleteMutation<TDatabase, TCollection extends keyof TDatabase & string>( | ||
| collectionName: TCollection, | ||
| id: CollectionRecord<TDatabase, TCollection>['id'] | null, | ||
| ): UseDeleteMutationResult; |
There was a problem hiding this comment.
Restore id inference without indexing CollectionRecord directly.
The new overload indexes CollectionRecord<TDatabase, TCollection> with 'id', but CollectionRecord is just TDatabase[TCollection] and TypeScript can’t prove that those mapped records expose an id property. This is the CI failure (TS2536). Use a conditional type to extract the id when present and fall back to RecordModel['id'] instead of indexing directly.
-export function useDeleteMutation<TDatabase, TCollection extends keyof TDatabase & string>(
- collectionName: TCollection,
- id: CollectionRecord<TDatabase, TCollection>['id'] | null,
-): UseDeleteMutationResult;
+export function useDeleteMutation<TDatabase, TCollection extends keyof TDatabase & string>(
+ collectionName: TCollection,
+ id: CollectionRecord<TDatabase, TCollection> extends { id: infer TId }
+ ? TId | null
+ : RecordModel['id'] | null,
+): UseDeleteMutationResult;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function useDeleteMutation<TDatabase, TCollection extends keyof TDatabase & string>( | |
| collectionName: TCollection, | |
| id: CollectionRecord<TDatabase, TCollection>['id'] | null, | |
| ): UseDeleteMutationResult; | |
| export function useDeleteMutation<TDatabase, TCollection extends keyof TDatabase & string>( | |
| collectionName: TCollection, | |
| id: CollectionRecord<TDatabase, TCollection> extends { id: infer TId } | |
| ? TId | null | |
| : RecordModel['id'] | null, | |
| ): UseDeleteMutationResult; |
🧰 Tools
🪛 GitHub Actions: CI
[error] 8-8: TS2536: Type '"id"' cannot be used to index type 'CollectionRecord<TDatabase, TCollection>'.
🤖 Prompt for AI Agents
In src/hooks/useDeleteMutation.ts around lines 6 to 9, the overload currently
indexes CollectionRecord<TDatabase, TCollection> with 'id' which fails when the
collection type doesn't explicitly expose an id property; replace that direct
indexing with a conditional type that extracts the id if present (e.g. T extends
{ id: infer I } ? I : fallback) and fall back to RecordModel['id'] otherwise,
then use that conditional type for the id parameter so TypeScript can infer id
without assuming every record has an 'id'.
TypeScript's Record<string, RecordModel> constraint requires types to have
an index signature [key: string]: RecordModel. Using `type` instead of
`interface` for the Database definition satisfies this constraint.
Changes:
- Update example to use `type Database = { ... }` instead of `interface`
- Use type intersections (&) instead of extends for responses
- Update documentation to emphasize using `type` not `interface`
- Add troubleshooting section for "Index signature" error
- Update README example to show type-only import for TypedPocketBase
Example:
```typescript
// ✅ Correct
type Database = {
posts: PostsResponse;
users: UsersResponse;
};
// ❌ Wrong - causes "Index signature" error
interface Database {
posts: PostsResponse;
}
```
This resolves all remaining TypeScript compilation errors.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/hooks/useCreateMutation.ts (1)
45-48: Preserve original error information when re-throwing.Creating a new
Errorobject discards the original error's stack trace, type, and properties, making debugging significantly harder.Apply this diff to re-throw the original error:
} catch (err) { const errorMessage = err instanceof Error ? err.message : 'Error creating record'; setError(errorMessage); - throw new Error(errorMessage); + throw err; } finally {This preserves the full error context for callers while still setting the sanitized message for UI display.
♻️ Duplicate comments (5)
src/context/PocketBaseContext.tsx (1)
12-12: Replaceanywithunknownfor stricter typing.The context is typed as
TypedPocketBase<any>, which violates the coding guideline to avoidanyand preferunknownwhen the type is uncertain.As per coding guidelines.
Apply this diff:
-export const PocketBaseContext: Context<TypedPocketBase<any> | null> = createContext<TypedPocketBase<any> | null>(null); +export const PocketBaseContext: Context<TypedPocketBase<unknown> | null> = createContext<TypedPocketBase<unknown> | null>(null);src/hooks/useCollection.ts (1)
52-53: Move transformer ref update into useEffect.Line 53 updates the transformer ref on every render outside any effect, which defeats the purpose of using a ref and creates unnecessary allocations. This is inconsistent with
useRecord(lines 60-62), which correctly updates the ref inside auseEffect.Apply this diff:
const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]); -transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; +useEffect(() => { + transformers.current = options.transformers ?? [dateTransformer<TRecord>()]; +}, [options.transformers]);As per coding guidelines.
src/hooks/useUpdateMutation.ts (1)
6-6: Add missing constraint to fix type safety.Line 6 allows
TDatabaseto be any type, soCollectionRecord<TDatabase, TCollection>may not extendRecordModeland might not have anidproperty. Add the constraint to ensure type safety.Apply this diff:
-export function useUpdateMutation<TDatabase, TCollection extends keyof TDatabase & string>(collectionName: TCollection, id: CollectionRecord<TDatabase, TCollection>['id'] | null): UseUpdateMutationResult<CollectionRecord<TDatabase, TCollection>>; +export function useUpdateMutation<TDatabase extends Record<string, RecordModel>, TCollection extends keyof TDatabase & string>(collectionName: TCollection, id: CollectionRecord<TDatabase, TCollection>['id'] | null): UseUpdateMutationResult<CollectionRecord<TDatabase, TCollection>>;src/hooks/useAuth.ts (1)
6-6: Remove the default generic value causing type constraint violation.Line 6 specifies
TCollection extends keyof TDatabase & string = 'users', but TypeScript cannot guarantee that the string literal'users'is a valid key in an arbitraryTDatabase. The implementation already provides a default forcollectionNamein the options object.Apply this diff:
-export function useAuth<TDatabase extends Record<string, RecordModel>, TCollection extends keyof TDatabase & string = 'users'>(options?: UseAuthOptions): UseAuthResult<AuthCollectionRecord<TDatabase, TCollection>>; +export function useAuth<TDatabase extends Record<string, RecordModel>, TCollection extends keyof TDatabase & string>(options?: UseAuthOptions): UseAuthResult<AuthCollectionRecord<TDatabase, TCollection>>;src/hooks/useDeleteMutation.ts (1)
6-6: Add missing constraint to fix type safety.Line 6 allows
TDatabaseto be any type, soCollectionRecord<TDatabase, TCollection>may not extendRecordModeland might not have anidproperty. Add the constraint to ensure type safety.Apply this diff:
-export function useDeleteMutation<TDatabase, TCollection extends keyof TDatabase & string>(collectionName: TCollection, id: CollectionRecord<TDatabase, TCollection>['id'] | null): UseDeleteMutationResult; +export function useDeleteMutation<TDatabase extends Record<string, RecordModel>, TCollection extends keyof TDatabase & string>(collectionName: TCollection, id: CollectionRecord<TDatabase, TCollection>['id'] | null): UseDeleteMutationResult;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
examples/typed-database-example.tsx(1 hunks)src/context/PocketBaseContext.tsx(2 hunks)src/hooks/useAuth.ts(7 hunks)src/hooks/useCollection.ts(4 hunks)src/hooks/useCreateMutation.ts(3 hunks)src/hooks/useDeleteMutation.ts(1 hunks)src/hooks/usePocketBase.ts(2 hunks)src/hooks/useRecord.ts(3 hunks)src/hooks/useUpdateMutation.ts(4 hunks)src/providers/PocketBaseProvider.tsx(3 hunks)src/types/database.type.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/hooks/usePocketBase.ts
- examples/typed-database-example.tsx
🧰 Additional context used
📓 Path-based instructions (11)
src/hooks/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/**/*.{ts,tsx}: All data-fetching hooks must return a discriminated union QueryResult with isLoading, isSuccess, isError, data, and error states
Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Support request cancellation by accepting requestKey and using pb.cancelRequest(key) where applicable
Use TanStack Query-style naming: isLoading/isSuccess/isError for query hooks; isPending for mutations; fields data and error
Use useEffect for data fetching/subscriptions and always return a cleanup function for subscriptions
Memoize fetcher functions passed into useEffect with useCallback and avoid inline object/array creation in dependency arrays
Implement React StrictMode cancellation pattern: useRef for default values and a cancelled flag in async effects to prevent stale updates
In subscription handlers, use functional setState form setData(current => ...) to avoid adding data to effect dependencies
Provide generic type parameters for records in hooks, e.g., useCollection() and useAuth()
Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
src/hooks/**/*.{ts,tsx}: Follow TanStack Query state names in hooks: use isLoading, isSuccess, isError, error, data (not isPending)
Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Implement real-time subscriptions in hooks with proper cleanup
Use useEffect for side effects; do not use useCallback for data fetching
Ensure hooks surface graceful error states and meaningful error messages
Ensure cleanup of real-time subscriptions to prevent memory leaks
Files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/hooks/useRecord.ts
src/hooks/{useCollection,useRecord}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/hooks/{useCollection,useRecord}.{ts,tsx}: useCollection and useRecord must support a transformers option (array of RecordTransformer) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Support request cancellation via the requestKey option in useCollection and useRecord
By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
src/hooks/useCollection.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Files:
src/hooks/useCollection.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: TypeScript strictness: avoid any; prefer unknown when type is uncertain
Never add comments in code
**/*.{ts,tsx}: Enable strict typing and avoid any; prefer unknown when necessary
Use proper type guards to ensure runtime type safety
Files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/types/database.type.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/providers/PocketBaseProvider.tsxsrc/hooks/useRecord.tssrc/context/PocketBaseContext.tsx
src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Files:
src/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useDeleteMutation.ts
src/hooks/useAuth.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Files:
src/hooks/useAuth.ts
src/providers/PocketBaseProvider.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Files:
src/providers/PocketBaseProvider.tsx
src/providers/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Implement Provider components to supply contexts
Files:
src/providers/PocketBaseProvider.tsx
src/hooks/useRecord.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Files:
src/hooks/useRecord.ts
src/context/PocketBaseContext.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Files:
src/context/PocketBaseContext.tsx
src/context/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Define React Contexts for dependency injection
Files:
src/context/PocketBaseContext.tsx
🧠 Learnings (36)
📓 Common learnings
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : useCollection and useRecord must support a transformers option (array of RecordTransformer<T>) applied sequentially (reduce) to initial fetch and real-time updates; default include dateTransformer()
Applied to files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useCollection.{ts,tsx} : useCollection should fetch with getFullList() or getList() based on fetchAll, handle real-time create/update/delete, and re-sort as needed
Applied to files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()
Applied to files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/types/database.type.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/providers/PocketBaseProvider.tsxsrc/hooks/useRecord.tssrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place all custom hooks (useAuth, useCollection, useRecord, useCreateMutation, useUpdateMutation, useDeleteMutation, usePocketBase) in src/hooks/
Applied to files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : Support request cancellation via the requestKey option in useCollection and useRecord
Applied to files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useDeleteMutation.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCollection,useRecord}.{ts,tsx} : By default, apply dateTransformer() to convert created/updated fields to Date objects; allow custom transformers or none via transformers: []
Applied to files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Hooks must set up PocketBase real-time subscriptions via pb.collection().subscribe() and clean up subscriptions in useEffect
Applied to files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/types/database.type.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/providers/PocketBaseProvider.tsxsrc/hooks/useRecord.tssrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useRecord.{ts,tsx} : useRecord should fetch a single record with getOne() or getFirstListItem() and subscribe to that record’s changes
Applied to files:
src/hooks/useCollection.tssrc/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useAuth.tssrc/hooks/useDeleteMutation.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/lib/utils.ts : applyTransformers() must catch transformer errors, log to console, and return the original record to avoid breaking flow
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/lib/utils.ts : Keep shared utilities like sortRecords and applyTransformers in src/lib/utils.ts
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/transformers/**/*.{ts,tsx} : Define built-in transformers (e.g., dateTransformer) under src/transformers/
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Memoize fetcher functions passed into useEffect with useCallback and avoid inline object/array creation in dependency arrays
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : In subscription handlers, use functional setState form setData(current => ...) to avoid adding data to effect dependencies
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Implement React StrictMode cancellation pattern: useRef for default values and a cancelled flag in async effects to prevent stale updates
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to **/*.{ts,tsx} : Use proper type guards to ensure runtime type safety
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : All data-fetching hooks must return a discriminated union QueryResult<T> with isLoading, isSuccess, isError, data, and error states
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Implement real-time subscriptions in hooks with proper cleanup
Applied to files:
src/hooks/useCollection.tssrc/hooks/useRecord.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Real-time subscriptions are enabled by default but can be disabled with realtime: false; expose isError and error for graceful error states
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Ensure cleanup of real-time subscriptions to prevent memory leaks
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Verify real-time subscription setup and cleanup in tests
Applied to files:
src/hooks/useCollection.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/{useCreateMutation,useUpdateMutation,useDeleteMutation}.{ts,tsx} : Mutation hooks must expose mutate() and state flags isPending, isSuccess, isError, error
Applied to files:
src/hooks/useCreateMutation.tssrc/hooks/useUpdateMutation.tssrc/hooks/useDeleteMutation.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Use TanStack Query-style naming: isLoading/isSuccess/isError for query hooks; isPending for mutations; fields data and error
Applied to files:
src/hooks/useCreateMutation.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to tests/**/*.{ts,tsx} : Mock PocketBase methods comprehensively in tests
Applied to files:
src/types/database.type.tssrc/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps
Applied to files:
src/types/database.type.tssrc/hooks/useAuth.tssrc/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/context/PocketBaseContext.tsx : Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx
Applied to files:
src/types/database.type.tssrc/hooks/useAuth.tssrc/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Mock PocketBase client methods with Vitest vi.fn() and test loading, success, and error states
Applied to files:
src/types/database.type.tssrc/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Use React Context (PocketBaseContext) with a PocketBaseProvider to inject the PocketBase client across the tree
Applied to files:
src/types/database.type.tssrc/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to src/hooks/useAuth.{ts,tsx} : useAuth must listen to pb.authStore.onChange(), provide signIn.email(), signIn.social(), signUp.email(), and signOut(), and expose the authenticated user via pb.authStore.model
Applied to files:
src/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Use signIn/signOut for auth hooks (not login/logout) and signUp (not register)
Applied to files:
src/hooks/useAuth.ts
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to tests/hooks/**/*.{test,spec}.{ts,tsx} : Use renderHook from testing-library/react and wrap hooks with PocketBaseProvider using a mocked client
Applied to files:
src/hooks/useAuth.tssrc/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/providers/**/*.{ts,tsx} : Implement Provider components to supply contexts
Applied to files:
src/providers/PocketBaseProvider.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to package.json : Set peerDependencies to React >=19.0.0 and PocketBase ^0.26.2
Applied to files:
src/providers/PocketBaseProvider.tsxsrc/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:11.415Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-18T12:22:11.415Z
Learning: Applies to **/*.{ts,tsx} : TypeScript strictness: avoid any; prefer unknown when type is uncertain
Applied to files:
src/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to **/*.{ts,tsx} : Enable strict typing and avoid any; prefer unknown when necessary
Applied to files:
src/context/PocketBaseContext.tsx
📚 Learning: 2025-10-18T12:22:42.070Z
Learnt from: CR
Repo: KevinBonnoron/pocketbase-react-hooks PR: 0
File: .cursorrules:0-0
Timestamp: 2025-10-18T12:22:42.070Z
Learning: Applies to src/context/**/*.{ts,tsx} : Define React Contexts for dependency injection
Applied to files:
src/context/PocketBaseContext.tsx
🧬 Code graph analysis (8)
src/hooks/useCollection.ts (5)
src/types/useCollection.type.ts (2)
UseCollectionOptions(10-55)UseCollectionResult(62-62)src/types/database.type.ts (1)
CollectionRecord(12-12)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)src/hooks/internal/useQueryState.ts (1)
useQueryState(51-108)src/transformers/date.transformer.ts (1)
dateTransformer(8-20)
src/hooks/useCreateMutation.ts (3)
src/types/useCreateMutation.type.ts (1)
UseCreateMutationResult(9-25)src/types/database.type.ts (1)
CollectionRecord(12-12)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
src/hooks/useUpdateMutation.ts (3)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useUpdateMutation.type.ts (1)
UseUpdateMutationResult(9-25)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
src/hooks/useAuth.ts (3)
src/types/useAuth.type.ts (2)
UseAuthOptions(7-17)UseAuthResult(24-124)src/types/database.type.ts (1)
AuthCollectionRecord(14-14)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)
src/hooks/useDeleteMutation.ts (2)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useDeleteMutation.type.ts (1)
UseDeleteMutationResult(7-21)
src/providers/PocketBaseProvider.tsx (2)
src/types/database.type.ts (2)
DefaultDatabase(4-4)TypedPocketBase(6-8)src/context/PocketBaseContext.tsx (1)
PocketBaseContext(12-12)
src/hooks/useRecord.ts (6)
src/types/database.type.ts (1)
CollectionRecord(12-12)src/types/useRecord.type.ts (2)
UseRecordOptions(10-25)UseRecordResult(32-32)src/hooks/usePocketBase.ts (1)
usePocketBase(26-33)src/hooks/internal/useQueryState.ts (1)
useQueryState(51-108)src/transformers/date.transformer.ts (1)
dateTransformer(8-20)src/lib/utils.ts (1)
applyTransformers(40-49)
src/context/PocketBaseContext.tsx (1)
src/types/database.type.ts (2)
TypedPocketBase(6-8)DefaultDatabase(4-4)
🔇 Additional comments (10)
src/providers/PocketBaseProvider.tsx (1)
2-2: LGTM! Generic typing correctly implemented.The provider now accepts a database schema generic and properly types the PocketBase instance. The cast to
TypedPocketBase<TDatabase>on line 62 is safe because it only adds a phantom__databasefield for type branding.Also applies to: 5-5, 10-10, 19-19, 61-62
src/context/PocketBaseContext.tsx (1)
28-33: LGTM! Generic hook implementation is correct.The hook properly retrieves the context and casts it to the desired database type, with appropriate error handling for usage outside the provider.
src/hooks/useAuth.ts (1)
37-234: LGTM! Authentication logic correctly updated for generics.The implementation properly propagates the
TUsergeneric throughout sign-in flows, sign-up, refresh, and real-time subscription handling. Type casts are appropriate given PocketBase's runtime behavior.src/types/database.type.ts (1)
1-14: LGTM! Type definitions are well-designed.The phantom field pattern in
TypedPocketBaseis an idiomatic TypeScript technique for type branding. The helper types (CollectionRecord,AuthCollectionRecord) enable type-safe inference across the hook API.src/hooks/useDeleteMutation.ts (1)
33-80: LGTM! Mutation logic with proper error handling.The implementation correctly validates the ID, manages loading/error states, and exposes both synchronous and asynchronous mutation functions as required by the coding guidelines.
src/hooks/useCollection.ts (2)
9-11: LGTM! Type constraints correctly applied.The overload properly constrains
TDatabase extends Record<string, RecordModel>to ensureCollectionRecordproduces validRecordModeltypes.
55-144: LGTM! Data fetching and real-time subscription logic is sound.The hook correctly implements fetching (with
getFullListorgetList), applies transformers, and handles real-time create/update/delete events with proper cleanup.src/hooks/useUpdateMutation.ts (1)
33-81: LGTM! Update mutation correctly implemented.The hook properly validates the ID, manages state, handles errors, and exposes the required mutation interface with both sync and async variants.
src/hooks/useRecord.ts (2)
9-20: LGTM! All overload signatures properly constrained.The four overloads correctly constrain
TDatabase extends Record<string, RecordModel>andTRecord extends RecordModel, ensuring type safety for both ID-based and filter-based record fetching.
47-147: LGTM! Comprehensive record fetching and subscription logic.The implementation correctly handles both ID and filter-based fetching, applies transformers via
useEffect(lines 60-62), and subscribes to real-time updates with proper cleanup. The generic typing is consistently applied throughout.
| mutateAsync(bodyParams, options).catch(() => { | ||
| // Error is already handled in mutateAsync | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Remove inline comment.
As per coding guidelines.
Apply this diff:
mutateAsync(bodyParams, options).catch(() => {
- // Error is already handled in mutateAsync
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| mutateAsync(bodyParams, options).catch(() => { | |
| // Error is already handled in mutateAsync | |
| }); | |
| mutateAsync(bodyParams, options).catch(() => { | |
| }); |
🤖 Prompt for AI Agents
In src/hooks/useCreateMutation.ts around lines 58 to 60, remove the inline
comment inside the catch block that says "// Error is already handled in
mutateAsync" so the catch becomes an empty block (or remove the entire catch if
redundant) and ensure formatting/linting remains correct; do not add any other
comments or code.
This commit adds full support for pocketbase-typegen, enabling automatic type inference for all hooks when using a typed Database schema.
Key features:
Changes:
Usage:
Closes #3
Summary by CodeRabbit
New Features
Behavioral Improvements
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.