Skip to content

Commit

Permalink
feat: Add support for urlKeys in cache (#725)
Browse files Browse the repository at this point in the history
* feat: Add support for urlKeys in cache

This bridges the API gap for this feature, along with #720 which defines
it for the serializer.

* test: Add test case
  • Loading branch information
franky47 authored Oct 30, 2024
1 parent 4c2b46a commit b8dcc6f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
22 changes: 22 additions & 0 deletions packages/docs/content/docs/server-side.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,25 @@ export function Client() {
// ...
}
```

### Shorter search params keys

Just like [`useQueryStates`](./batching#shorter-search-params-keys), you can
define a `urlKeys` object to map the variable names defined by the parser to
shorter keys in the URL. They will be translated on read and your codebase
can only refer to variable names that make sense for your domain or business logic.

```ts title="searchParams.ts"
export const coordinatesParsers = {
// Use human-readable variable names throughout your codebase
latitude: parseAsFloat.withDefault(45.18),
longitude: parseAsFloat.withDefault(5.72)
}
export const coordinatesCache = createSearchParamsCache(coordinatesParsers, {
urlKeys: {
// Remap them to read from shorter keys in the URL
latitude: 'lat',
longitude: 'lng'
}
})
```
42 changes: 42 additions & 0 deletions packages/nuqs/src/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,48 @@ describe('cache', () => {
// cache still works though
expect(cache.all()).toBe(all)
})

it('supports urlKeys', () => {
const cache = createSearchParamsCache(
{
string: parseAsString
},
{
urlKeys: {
string: 'str'
}
}
)
const parseOutput = cache.parse({
str: 'this one is used',
string: 'not this one'
})
expect(parseOutput.string).toBe('this one is used')
// @ts-expect-error - Making sure types & runtime are in sync
expect(parseOutput.str).toBeUndefined()
expect(cache.all().string).toBe('this one is used')
expect(cache.get('string')).toBe('this one is used')
})

it('supports partial urlKeys', () => {
const cache = createSearchParamsCache(
{
foo: parseAsString,
bar: parseAsString
},
{
urlKeys: {
foo: 'f'
}
}
)
const parseOutput = cache.parse({
f: 'foo',
bar: 'bar'
})
expect(parseOutput.foo).toBe('foo')
expect(parseOutput.bar).toBe('bar')
})
})

describe('compareSearchParams', () => {
Expand Down
8 changes: 6 additions & 2 deletions packages/nuqs/src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ const $input: unique symbol = Symbol('Input')

export function createSearchParamsCache<
Parsers extends Record<string, ParserBuilder<any>>
>(parsers: Parsers) {
>(
parsers: Parsers,
{ urlKeys = {} }: { urlKeys?: Partial<Record<keyof Parsers, string>> } = {}
) {
type Keys = keyof Parsers
type ParsedSearchParams = {
readonly [K in Keys]: inferParserType<Parsers[K]>
Expand Down Expand Up @@ -44,7 +47,8 @@ export function createSearchParamsCache<
}
for (const key in parsers) {
const parser = parsers[key]!
c.searchParams[key] = parser.parseServerSide(searchParams[key])
const urlKey = urlKeys[key] ?? key
c.searchParams[key] = parser.parseServerSide(searchParams[urlKey])
}
c[$input] = searchParams
return Object.freeze(c.searchParams) as ParsedSearchParams
Expand Down

0 comments on commit b8dcc6f

Please sign in to comment.