Skip to content

Add PocketBase TypeGen support#10

Open
KevinBonnoron wants to merge 7 commits into
mainfrom
claude/add-pocketbase-typegen-011CUreMvrkZeA558XJfG3WH
Open

Add PocketBase TypeGen support#10
KevinBonnoron wants to merge 7 commits into
mainfrom
claude/add-pocketbase-typegen-011CUreMvrkZeA558XJfG3WH

Conversation

@KevinBonnoron
Copy link
Copy Markdown
Owner

@KevinBonnoron KevinBonnoron commented Nov 6, 2025

This commit adds full support for pocketbase-typegen, enabling automatic type inference for all hooks when using a typed Database schema.

Key features:

  • TypedPocketBase type for branding PocketBase instances
  • PocketBaseProvider 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:

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 #3

Summary by CodeRabbit

  • New Features

    • Full TypeScript typed-database support: typed provider and generics across hooks (collections, records, auth, create/update/delete mutations); new public type exports.
  • Behavioral Improvements

    • Mutation hooks (create/update/delete) expose richer state (isError, error, isSuccess) with improved async/error handling and clearer loading states.
  • Documentation

    • Added comprehensive Typed Database guide, README TypeScript section, and a TypeScript React example demonstrating typed collections, records, auth flows, and mutations.

✏️ Tip: You can customize this high-level summary in your review settings.

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]
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 6, 2025

Walkthrough

Adds 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

Cohort / File(s) Summary
Documentation & example
README.md, docs/TYPED-DATABASE.md, examples/typed-database-example.tsx
Adds TypeScript usage section, a comprehensive Typed Database guide, and a React TypeScript example demonstrating TypedPocketBase, PocketBaseProvider<Database>, and typed hooks.
Type system foundation
src/types/database.type.ts, src/types/index.ts, src/index.ts
Adds core types (DefaultDatabase, TypedPocketBase, ExtractDatabase, CollectionRecord, AuthCollectionRecord) and re-exports them via the types barrel and package index.
Provider & context
src/providers/PocketBaseProvider.tsx, src/context/PocketBaseContext.tsx
Genericizes provider/context over TDatabase; provider accepts `PocketBase
PocketBase access hook
src/hooks/usePocketBase.ts
Makes usePocketBase generic and returns TypedPocketBase<TDatabase> (casts returned instance).
Data access hooks
src/hooks/useCollection.ts, src/hooks/useRecord.ts
Adds overloads/generics to infer from a Database schema or accept explicit record types; internal state, fetchers, transformers, and realtime handlers are generic-typed.
Authentication hook
src/hooks/useAuth.ts
Introduces schema-aware and explicit-user overloads; useAuth becomes generic and internal state/returns are typed as TUser or AuthCollectionRecord.
Mutation hooks
src/hooks/useCreateMutation.ts, src/hooks/useUpdateMutation.ts, src/hooks/useDeleteMutation.ts
Adds schema-aware and explicit-record overloads, updates signatures to Partial<TRecord>/TRecord, and exposes isError/error/isSuccess with added runtime pending/error handling in mutate/mutateAsync.

Possibly related PRs

Pre-merge checks and finishing touches

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error)
Check name Status Explanation Resolution
Docstring Coverage ❌ Error Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding full support for pocketbase-typegen with typed database schema integration across all hooks.
Linked Issues check ✅ Passed The PR fully implements the objectives from issue #3: TypedPocketBase type enables direct use of typegen outputs [#3], collection names are type-checked with autocomplete, return types auto-infer from schemas [#3], and the typegen workflow is fully supported [#3].
Out of Scope Changes check ✅ Passed All changes are within scope: new database.type.ts and types exports support typegen integration [#3], context and provider generics enable typed databases [#3], hook overloads and implementations support type inference [#3], and documentation/examples demonstrate the feature [#3].
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/add-pocketbase-typegen-011CUreMvrkZeA558XJfG3WH

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 53f7625 and c819d3a.

📒 Files selected for processing (1)
  • src/hooks/useRecord.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
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.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.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.ts
🧠 Learnings (11)
📓 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/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/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.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.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.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.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.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.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.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.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/useRecord.ts
🧬 Code graph analysis (1)
src/hooks/useRecord.ts (5)
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)
🔇 Additional comments (2)
src/hooks/useRecord.ts (2)

9-20: Generic constraints properly applied.

The overload signatures correctly constrain TDatabase extends Record<string, RecordModel>, ensuring CollectionRecord<TDatabase, TCollection> resolves to a valid RecordModel. This addresses the TS2536/TS2344 errors from the previous review.


47-150: LGTM! Generic types consistently applied throughout.

The implementation correctly applies TRecord generics across all code paths:

  • Query state, transformers, and fetcher functions are properly typed
  • Both fetch methods (getOne and getFirstListItem) use TRecord generics
  • Real-time subscriptions for both ID-based and filter-based paths correctly typed
  • Transformer handling follows the correct ref pattern to prevent recreation
  • All coding guidelines followed: real-time subscriptions with cleanup, request cancellation support, memoized callbacks, functional setState, and default dateTransformer

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 usage

Earlier in this README the API is documented as useUpdateMutation('posts') followed by mutate(postId, data) (same for delete). This new example instead calls useUpdateMutation('posts', id) and useDeleteMutation('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 to TRecord, but the implementation still refers to Record, which no longer exists. This leaves unresolved identifiers in multiple spots and prevents the file from compiling. Please update the references to use TRecord.

@@
-  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 with TRecord generic to restore type safety.
Just like in useCreateMutation, the generic was renamed to TRecord but the function body still references Record. These stale identifiers break compilation. Switch them to TRecord so 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 unresolved Record type usage

Line 50 switches useQueryState to Record[], but Record is never defined in this scope (and the global Record<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 with TRecord to 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 undefined Record placeholder with TRecord

Line 58 introduces useQueryState<Record | null>, but Record is 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 every Record usage here for TRecord to 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

📥 Commits

Reviewing files that changed from the base of the PR and between ca6c307 and aac7f17.

📒 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.ts
  • src/hooks/useUpdateMutation.ts
  • src/context/PocketBaseContext.tsx
  • src/hooks/useCreateMutation.ts
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • src/types/database.type.ts
  • examples/typed-database-example.tsx
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/hooks/useRecord.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/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.ts
  • src/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.ts
  • src/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.ts
  • src/hooks/useUpdateMutation.ts
  • src/context/PocketBaseContext.tsx
  • README.md
  • src/hooks/useCreateMutation.ts
  • docs/TYPED-DATABASE.md
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • src/types/database.type.ts
  • examples/typed-database-example.tsx
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/hooks/useRecord.ts
  • src/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.ts
  • README.md
  • src/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.ts
  • src/hooks/useUpdateMutation.ts
  • src/context/PocketBaseContext.tsx
  • README.md
  • src/hooks/useCreateMutation.ts
  • docs/TYPED-DATABASE.md
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • examples/typed-database-example.tsx
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • docs/TYPED-DATABASE.md
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/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.ts
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • docs/TYPED-DATABASE.md
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/context/PocketBaseContext.tsx
  • README.md
  • src/hooks/useCreateMutation.ts
  • docs/TYPED-DATABASE.md
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • examples/typed-database-example.tsx
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/hooks/useRecord.ts
  • src/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.tsx
  • README.md
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • examples/typed-database-example.tsx
  • src/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.tsx
  • README.md
  • docs/TYPED-DATABASE.md
  • src/hooks/usePocketBase.ts
  • examples/typed-database-example.tsx
  • src/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.tsx
  • README.md
  • docs/TYPED-DATABASE.md
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • src/types/database.type.ts
  • examples/typed-database-example.tsx
  • src/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.tsx
  • README.md
  • docs/TYPED-DATABASE.md
  • src/hooks/usePocketBase.ts
  • src/types/database.type.ts
  • examples/typed-database-example.tsx
  • src/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.tsx
  • README.md
  • docs/TYPED-DATABASE.md
  • src/hooks/usePocketBase.ts
  • src/hooks/useAuth.ts
  • examples/typed-database-example.tsx
  • src/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.tsx
  • README.md
  • src/hooks/usePocketBase.ts
  • examples/typed-database-example.tsx
  • src/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.ts
  • src/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)

Comment thread docs/TYPED-DATABASE.md
Comment on lines +167 to +188
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>;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

Comment thread src/hooks/useAuth.ts Outdated
- 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
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aac7f17 and 9ec8c63.

📒 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.ts
  • src/hooks/useAuth.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • 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
**/*.{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.ts
  • src/hooks/useAuth.ts
  • src/hooks/useCollection.ts
  • src/index.ts
  • src/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.ts
  • src/hooks/useAuth.ts
  • src/hooks/useCollection.ts
  • src/index.ts
  • src/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.ts
  • src/hooks/useAuth.ts
  • src/hooks/useCollection.ts
  • src/index.ts
  • src/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.ts
  • src/hooks/useAuth.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • 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/{useCollection,useRecord}.{ts,tsx} : Support request cancellation via the requestKey option in useCollection and useRecord

Applied to files:

  • src/hooks/useRecord.ts
  • src/hooks/useCollection.ts
  • src/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.ts
  • src/hooks/useAuth.ts
  • src/hooks/useCollection.ts
  • src/index.ts
  • src/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.ts
  • src/hooks/useAuth.ts
  • src/hooks/useCollection.ts
  • src/index.ts
  • src/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.ts
  • 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 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.ts
  • 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/context/PocketBaseContext.tsx : Define the React context and usePocketBaseContext() hook in src/context/PocketBaseContext.tsx

Applied to files:

  • src/hooks/useAuth.ts
  • 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/providers/PocketBaseProvider.tsx : Implement PocketBaseProvider in src/providers/PocketBaseProvider.tsx to wrap consuming apps

Applied to files:

  • src/hooks/useAuth.ts
  • 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/**/*.{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 uses options?: UseAuthOptions with 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 generic RecordModel types, 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 TRecord is 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 useEffect with 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 recordIdOrFilter is missing (line 69-71), and properly dispatches to getOne for IDs or getFirstListItem for 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.

Comment on lines +55 to +56
const transformers = useRef(options.transformers ?? [dateTransformer<TRecord>()]);
transformers.current = options.transformers ?? [dateTransformer<TRecord>()];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
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)
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: isSuccess is true before any mutation runs.

isSuccess is derived from !isPending && !error, so the hook reports success immediately on mount. Track success in state so it only becomes true after 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.

RecordModel is 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

📥 Commits

Reviewing files that changed from the base of the PR and between 9ec8c63 and da331d2.

📒 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.tsx
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/hooks/useAuth.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/hooks/useUpdateMutation.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • src/hooks/useAuth.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/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.ts
  • src/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.tsx
  • src/hooks/useAuth.ts
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/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.tsx
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/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.tsx
  • src/hooks/useAuth.ts
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/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.tsx
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/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.tsx
  • src/hooks/useAuth.ts
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/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.tsx
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/hooks/useAuth.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/hooks/useUpdateMutation.ts
  • src/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.tsx
  • src/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.tsx
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/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.tsx
  • src/hooks/useDeleteMutation.ts
  • src/hooks/useCollection.ts
  • src/hooks/useAuth.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/hooks/useUpdateMutation.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • src/hooks/useAuth.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • src/hooks/useAuth.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • examples/typed-database-example.tsx
  • src/context/PocketBaseContext.tsx
  • src/hooks/useUpdateMutation.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • src/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.ts
  • src/hooks/useCollection.ts
  • src/hooks/useAuth.ts
  • src/hooks/useRecord.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/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.ts
  • 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/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.ts
  • 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: 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's TDatabase parameter. 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:

  1. Add explicit JSDoc warnings in usePocketBaseContext and usePocketBase explaining the phantom type limitation and requirement to match provider/hook type parameters
  2. Implement a runtime check (though this would require encoding type info at runtime)
  3. Clarify in contributing guidelines that this is an accepted trade-off

Comment thread examples/typed-database-example.tsx Outdated
Comment on lines +69 to +88
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>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
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`.

Comment thread src/hooks/useAuth.ts Outdated
Comment on lines +6 to +8
export function useAuth<TDatabase, TCollection extends keyof TDatabase & string = 'users'>(
options?: UseAuthOptions,
): UseAuthResult<AuthCollectionRecord<TDatabase, TCollection>>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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.

Suggested change
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.

Comment thread src/hooks/useCollection.ts Outdated
Comment thread src/hooks/useCreateMutation.ts Outdated
Comment thread src/hooks/useDeleteMutation.ts Outdated
Comment on lines +6 to +9
export function useDeleteMutation<TDatabase, TCollection extends keyof TDatabase & string>(
collectionName: TCollection,
id: CollectionRecord<TDatabase, TCollection>['id'] | null,
): UseDeleteMutationResult;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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.

Suggested change
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'.

Comment thread src/hooks/useRecord.ts Outdated
Comment thread src/hooks/useUpdateMutation.ts Outdated
claude and others added 3 commits November 6, 2025 17:02
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.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Error object 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: 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);
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 a useEffect.

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 TDatabase to be any type, so CollectionRecord<TDatabase, TCollection> may not extend RecordModel and might not have an id property. 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 arbitrary TDatabase. The implementation already provides a default for collectionName in 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 TDatabase to be any type, so CollectionRecord<TDatabase, TCollection> may not extend RecordModel and might not have an id property. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 534df68 and 53f7625.

📒 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.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/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.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/types/database.type.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/providers/PocketBaseProvider.tsx
  • src/hooks/useRecord.ts
  • src/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.ts
  • src/hooks/useUpdateMutation.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • 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/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.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • 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} : Provide generic type parameters for records in hooks, e.g., useCollection<Post>() and useAuth<User>()

Applied to files:

  • src/hooks/useCollection.ts
  • src/hooks/useCreateMutation.ts
  • src/types/database.type.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/providers/PocketBaseProvider.tsx
  • src/hooks/useRecord.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useDeleteMutation.ts
  • 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/{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.ts
  • 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/useCollection.ts
  • src/hooks/useCreateMutation.ts
  • src/types/database.type.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • src/providers/PocketBaseProvider.tsx
  • src/hooks/useRecord.ts
  • src/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.ts
  • src/hooks/useCreateMutation.ts
  • src/hooks/useUpdateMutation.ts
  • src/hooks/useAuth.ts
  • src/hooks/useDeleteMutation.ts
  • 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/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.ts
  • 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: 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.ts
  • src/hooks/useUpdateMutation.ts
  • src/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.ts
  • src/providers/PocketBaseProvider.tsx
  • src/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.ts
  • src/hooks/useAuth.ts
  • src/providers/PocketBaseProvider.tsx
  • src/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.ts
  • src/hooks/useAuth.ts
  • src/providers/PocketBaseProvider.tsx
  • src/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.ts
  • src/providers/PocketBaseProvider.tsx
  • src/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.ts
  • src/providers/PocketBaseProvider.tsx
  • src/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.ts
  • src/providers/PocketBaseProvider.tsx
  • 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/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.tsx
  • src/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 __database field 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 TUser generic 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 TypedPocketBase is 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 ensure CollectionRecord produces valid RecordModel types.


55-144: LGTM! Data fetching and real-time subscription logic is sound.

The hook correctly implements fetching (with getFullList or getList), 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> and TRecord 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.

Comment on lines 58 to 60
mutateAsync(bodyParams, options).catch(() => {
// Error is already handled in mutateAsync
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for libraries like pocketbase-typegen

2 participants