Skip to content
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a38af84
feat: implement queryOptions export pattern for GET methods
kyleamazza-fq Jun 14, 2025
87d7e2e
docs: Update documentation for queryOptions export pattern
kyleamazza-fq Jun 14, 2025
d9fa0dd
Complete Task Group 4: Final verification and release preparation
kyleamazza-fq Jun 14, 2025
d300bdf
refactor: preserve full operation names in query options
kyleamazza-fq Jun 15, 2025
dec74f9
feat: implement type-safe query key builder generator
kyleamazza-fq Jun 15, 2025
02af6ca
feat: enhance query key builder with improved matchQueryKey support
kyleamazza-fq Jun 15, 2025
33b6acb
refactor: rename query-key-builder-file.ts to query-key-builder.ts
kyleamazza-fq Jun 15, 2025
5ae0718
test: add comprehensive tests for query key builder and update docume…
kyleamazza-fq Jun 15, 2025
015214a
docs: update changelog for v0.2.0 with matchQueryKey feature
kyleamazza-fq Jun 15, 2025
9925b21
Remove plan/ and CLAUDE.md from tracking and add to .gitignore
kyleamazza-fq Jun 15, 2025
79e6135
refactor: use service-specific names instead of generic names
kyleamazza-fq Jun 15, 2025
028af00
fix: keep full method names for infinite query options
kyleamazza-fq Jun 15, 2025
c1af9b1
test: add coverage for infinite query options generation
kyleamazza-fq Jun 15, 2025
1c82078
docs: update CHANGELOG for v0.2.0 with complete feature list
kyleamazza-fq Jun 15, 2025
cda04f4
style: apply prettier formatting
kyleamazza-fq Jun 15, 2025
5bd1ffb
doc: update basketry URL to doc website
kyleamazza-fq Jun 15, 2025
7e80c01
fix: remove non-null assertion in query key builder
kyleamazza-fq Jun 15, 2025
85e52ac
chore: lint
kyleamazza-fq Jun 16, 2025
ebff0d2
0.2.0-alpha.0
kyleamazza Jun 27, 2025
3d9c6f5
feat: re-enable hook name generation for deprecated patterns
kyleamazza-fq Jul 17, 2025
7789c6e
feat: add deprecated hook wrappers for backwards compatibility
kyleamazza-fq Jul 17, 2025
a44997f
feat: add tests for deprecated hook generation (Task Group 4)
kyleamazza-fq Jul 17, 2025
fcf1046
feat: prepare v0.2.0-alpha.1 release with documentation
kyleamazza-fq Jul 17, 2025
7163b88
feat: add jscodeshift codemod for v0.2 migration
kyleamazza-fq Jul 17, 2025
4dcc25b
docs: add codemod reference to migration guide
kyleamazza-fq Jul 17, 2025
c023bf8
docs: add npx jscodeshift command to migration guide
kyleamazza-fq Jul 17, 2025
5d5d830
chore: prepare for v0.2.0-alpha.1 release
kyleamazza-fq Jul 17, 2025
e8df9af
fix: revert version to 0.2.0-alpha.0
kyleamazza-fq Jul 17, 2025
215adfd
0.2.0-alpha.1
kyleamazza Jul 17, 2025
035a7c4
fix: handle Get prefix removal for backwards compatibility
kyleamazza-fq Jul 18, 2025
5a225eb
Merge branch 'export-query-options' of personal-github:basketry/react…
kyleamazza-fq Jul 18, 2025
50833b1
style: apply prettier formatting
kyleamazza-fq Jul 18, 2025
d949488
0.2.0-alpha.2
kyleamazza Jul 18, 2025
6c5a439
fix: restore v0.1.0 hook patterns with options parameters
kyleamazza-fq Jul 18, 2025
c548a49
Merge branch 'export-query-options' of personal-github:basketry/react…
kyleamazza-fq Jul 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,7 @@ dist
.pnp.*

lib/

# Project-specific files
plan/
CLAUDE.md
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Changelog
Comment thread
kyleamazza marked this conversation as resolved.

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.0] - 2025-06-14

### Changed

- **BREAKING**: Migrated from wrapper hooks to queryOptions/mutationOptions export pattern
- Changed from `useWidgets()` to `widgetsQueryOptions()`
- Changed from `useCreateWidget()` to `createWidgetMutationOptions()`
- Changed from `useInfiniteWidgets()` to `widgetsInfiniteQueryOptions()`
- **BREAKING**: Updated query key structure for better cache management
- From: `['/widgets', compact({ status: params?.status })].filter(Boolean)`
- To: `['widget', 'getWidgets', params || {}] as const`
- Added non-hook service getters in context for use in queryOptions
- Simplified runtime utilities by removing complex filtering logic

### Added

- Type-safe `matchQueryKey` function for building query keys with IntelliSense support
- Supports partial query matching at service, operation, or full parameter levels
- Provides compile-time type safety and autocomplete for all query operations
- Enables flexible cache invalidation patterns
- Comprehensive migration guide (MIGRATION.md)
- Support for direct composition with React Query hooks
- Better TypeScript inference with queryOptions pattern

### Removed

- Wrapper hook functions (use queryOptions with React Query hooks directly)
- Complex query key filtering logic

## [0.1.x] - Previous versions

Initial implementation with wrapper hooks pattern.
159 changes: 159 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Migration Guide: v0.1.x to v0.2.0
Comment thread
kyleamazza marked this conversation as resolved.
Outdated

This guide helps you migrate from the wrapper hooks pattern (v0.1.x) to the queryOptions export pattern (v0.2.0).

## Overview of Changes

### Before (v0.1.x) - Wrapper Hooks

```typescript
import { useWidgets, useCreateWidget } from './api/hooks/widgets';

function MyComponent() {
const { data } = useWidgets({ status: 'active' });
const createMutation = useCreateWidget();
}
```

### After (v0.2.0) - Query/Mutation Options

```typescript
import { useQuery, useMutation } from '@tanstack/react-query';
import {
widgetsQueryOptions,
createWidgetMutationOptions,
} from './api/hooks/widgets';

function MyComponent() {
const { data } = useQuery(widgetsQueryOptions({ status: 'active' }));
const createMutation = useMutation(createWidgetMutationOptions());
}
```

## Step-by-Step Migration

### 1. Update imports

Replace hook imports with React Query hooks and options imports:

```diff
- import { useWidgets, useCreateWidget } from './api/hooks/widgets';
+ import { useQuery, useMutation } from '@tanstack/react-query';
+ import { widgetsQueryOptions, createWidgetMutationOptions } from './api/hooks/widgets';
```

### 2. Update query usage

Replace wrapper hooks with React Query hooks + options:

```diff
- const { data, error, isLoading } = useWidgets({ status: 'active' });
+ const { data, error, isLoading } = useQuery(widgetsQueryOptions({ status: 'active' }));
```

### 3. Update mutations

Replace mutation hooks with useMutation + options:

```diff
- const createMutation = useCreateWidget();
+ const createMutation = useMutation(createWidgetMutationOptions());
```

### 4. Update infinite queries

For paginated endpoints:

```diff
- import { useInfiniteWidgets } from './api/hooks/widgets';
- const infiniteQuery = useInfiniteWidgets();
+ import { useInfiniteQuery } from '@tanstack/react-query';
+ import { widgetsInfiniteQueryOptions } from './api/hooks/widgets';
+ const infiniteQuery = useInfiniteQuery(widgetsInfiniteQueryOptions());
```

### 5. Custom query options

The new pattern makes it easier to override options:

```typescript
// Before - Limited customization
const { data } = useWidgets(
{ status: 'active' },
{
staleTime: 5 * 60 * 1000,
},
);

// After - Full control
const { data } = useQuery({
...widgetsQueryOptions({ status: 'active' }),
staleTime: 5 * 60 * 1000,
// Add any React Query option
gcTime: 10 * 60 * 1000,
refetchOnWindowFocus: false,
});
```

## Benefits of the New Pattern

1. **Better Tree-Shaking**: Import only what you use
2. **More Flexibility**: Full access to all React Query options
3. **Type Safety**: Better TypeScript inference
4. **Standardization**: Follows React Query team recommendations
5. **Composability**: Easier to create custom hooks on top

## Query Key Changes

The query key structure has been improved for better cache management:

```typescript
// Before
['widgets', { status: 'active' }][
// After
('widget', 'getWidgets', { status: 'active' })
];
```

This enables more precise cache invalidation:

```typescript
// Invalidate all widget queries
queryClient.invalidateQueries({ queryKey: ['widget'] });

// Invalidate specific method
queryClient.invalidateQueries({ queryKey: ['widget', 'getWidgets'] });
```

## Service Access Pattern

The context now provides non-hook getters for use in queryOptions:

```typescript
// The service getter is used internally by queryOptions
import { getWidgetService } from './api/hooks/context';

// You can also use it directly if needed
const widgetService = getWidgetService();
```

## Troubleshooting

### Error: "Service not initialized"

Make sure your app is wrapped with the ServiceProvider:

```tsx
<ServiceProvider widgetService={widgetService}>
<App />
</ServiceProvider>
```

### TypeScript errors

Ensure you're using React Query v5 or later, as the queryOptions pattern requires v5+.

## Need Help?

- Check the [README](./README.md) for complete examples
- File an issue on [GitHub](https://github.com/basketry/react-query/issues)
Loading