Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add temporary dedicated server features imports #805

Open
wants to merge 7 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -653,12 +653,9 @@ to do so in a type-safe manner.

```tsx
// searchParams.ts
import {
createSearchParamsCache,
parseAsInteger,
parseAsString
} from 'nuqs/server'
// Note: import from 'nuqs/server' to avoid the "use client" directive
import { createSearchParamsCache } from 'nuqs/server/cache'
import { parseAsInteger, parseAsString } from 'nuqs/server'
// Note: import parsers from 'nuqs/server' to avoid the "use client" directive

export const searchParamsCache = createSearchParamsCache({
// List your search param keys and associated parsers here:
Expand Down Expand Up @@ -700,7 +697,8 @@ parser declaration with `useQueryStates` for type-safety in client components:

```tsx
// searchParams.ts
import { parseAsFloat, createSearchParamsCache } from 'nuqs/server'
import { parseAsFloat } from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

export const coordinatesParsers = {
lat: parseAsFloat.withDefault(45.18),
Expand Down
8 changes: 2 additions & 6 deletions errors/NUQS-500.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@ Run the `parse` method and feed it the page's `searchParams`:

```tsx
// page.tsx
import {
createSearchParamsCache,
parseAsInteger,
parseAsString,
type SearchParams
} from 'nuqs/server'
import { parseAsInteger, parseAsString, type SearchParams } from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

const cache = createSearchParamsCache({
q: parseAsString,
Expand Down
26 changes: 15 additions & 11 deletions packages/docs/content/docs/server-side.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ The loader function will accept the following input types to parse search params
## Cache

<Callout>
This feature is available for Next.js only.
The `next/server/cache` feature is available for Next.js app router only.
</Callout>

If you wish to access the searchParams in a deeply nested Server Component
Expand All @@ -135,12 +135,9 @@ Think of it as a loader combined with a way to propagate the parsed values down
the RSC tree, like Context would on the client.

```ts title="searchParams.ts"
import {
createSearchParamsCache,
parseAsInteger,
parseAsString
} from 'nuqs/server'
// Note: import from 'nuqs/server' to avoid the "use client" directive
import { createSearchParamsCache } from 'nuqs/server/cache'
import { parseAsInteger, parseAsString } from 'nuqs/server'
// Note: import parsers from 'nuqs/server' to avoid the "use client" directive

export const searchParamsCache = createSearchParamsCache({
// List your search param keys and associated parsers here:
Expand Down Expand Up @@ -176,17 +173,24 @@ function Results() {
}
```

<Callout type="warn" title="Deprecation notice">
The cache feature is also accessible from `nuqs/server` in nuqs@^2, but
will be removed from that import in [email protected].
Please update your imports to `nuqs/server/cache` for a smoother transition.

This is to allow non-Next.js server code to use the `nuqs/server` import
without having to install React canary for the `cache` function.
</Callout>

The cache will only be valid for the current page render
(see React's [`cache`](https://react.dev/reference/react/cache) function).

Note: the cache only works for **server components**, but you may share your
parser declaration with `useQueryStates` for type-safety in client components:

```ts title="searchParams.ts"
import {
parseAsFloat,
createSearchParamsCache
} from 'nuqs/server'
import { parseAsFloat } from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

export const coordinatesParsers = {
lat: parseAsFloat.withDefault(45.18),
Expand Down
3 changes: 2 additions & 1 deletion packages/docs/src/app/(pages)/stats/searchParams.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createSearchParamsCache, parseAsStringLiteral } from 'nuqs/server'
import { parseAsStringLiteral } from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

export const pkgOptions = ['nuqs', 'next-usequerystate', 'both'] as const
export const pkgParser = parseAsStringLiteral(pkgOptions).withDefault('both')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
createSearchParamsCache,
createSerializer,
parseAsInteger,
parseAsStringLiteral
} from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

export const renderingOptions = ['server', 'client'] as const
export type RenderingOptions = (typeof renderingOptions)[number]
Expand Down
8 changes: 2 additions & 6 deletions packages/e2e/next/src/app/app/cache/searchParams.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import {
createSearchParamsCache,
parseAsBoolean,
parseAsInteger,
parseAsString
} from 'nuqs/server'
import { parseAsBoolean, parseAsInteger, parseAsString } from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

export const parsers = {
str: parseAsString,
Expand Down
3 changes: 2 additions & 1 deletion packages/e2e/next/src/app/app/push/searchParams.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createSearchParamsCache, parseAsInteger } from 'nuqs/server'
import { parseAsInteger } from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

export const parser = parseAsInteger.withDefault(0).withOptions({
history: 'push'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createSearchParamsCache, parseAsString } from 'nuqs/server'
import { parseAsString } from 'nuqs/server'
import { createSearchParamsCache } from 'nuqs/server/cache'

export const searchParams = {
injected: parseAsString.withDefault('null'),
Expand Down
2 changes: 1 addition & 1 deletion packages/e2e/next/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"alwaysStrict": false, // Don't emit "use strict" to avoid conflicts with "use client"
// Modules
"module": "ESNext",
"moduleResolution": "node",
"moduleResolution": "bundler",
"resolveJsonModule": true,
// Language & Environment
"target": "ESNext",
Expand Down
13 changes: 13 additions & 0 deletions packages/nuqs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
"files": [
"dist/",
"server.d.ts",
"server/cache.d.ts",
"server/serializer.d.ts",
"server/parsers.d.ts",
"adapters/react.d.ts",
"adapters/next.d.ts",
"adapters/next/app.d.ts",
Expand All @@ -60,6 +63,16 @@
"import": "./dist/server.js",
"require": "./esm-only.cjs"
},
"./server/cache": {
"types": "./dist/server/cache.d.ts",
"import": "./dist/server/cache.js",
"require": "./esm-only.cjs"
},
"./server/temporary-react-agnostic": {
"types": "./dist/server/temporary-react-agnostic.d.ts",
"import": "./dist/server/temporary-react-agnostic.js",
"require": "./esm-only.cjs"
},
"./adapters/react": {
"types": "./dist/adapters/react.d.ts",
"import": "./dist/adapters/react.js",
Expand Down
9 changes: 9 additions & 0 deletions packages/nuqs/server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Why just the cache here?

Those "top-level" .d.ts files are used to help projects with `moduleResolution: 'node'`
resolve the correct imports.

The other import under server, `nuqs/server/temporary-react-agnostic`
is temporary (as it says on the tin) and will be removed in [email protected].

Also, [email protected] will require a `moduleResolution: 'bundler' | 'nodeNext` setting in your tsconfig.json.
13 changes: 13 additions & 0 deletions packages/nuqs/server/cache.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This file is needed for projects that have `moduleResolution` set to `node`
// in their tsconfig.json to be able to `import {} from 'nuqs/server/cache'`.
// Other module resolutions strategies will look for the `exports` in `package.json`,
// but with `node`, TypeScript will look for a .d.ts file with that name at the
// root of the package.

export { createSearchParamsCache } from './dist/server/cache'
export type {
HistoryOptions,
Nullable,
Options,
SearchParams
} from './dist/server/cache'
1 change: 1 addition & 0 deletions packages/nuqs/src/index.server.cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { createSearchParamsCache } from './cache'
10 changes: 9 additions & 1 deletion packages/nuqs/src/index.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
export { createSearchParamsCache } from './cache'
export {
/** @deprecated Import createSearchParamsCache from 'nuqs/server/cache' instead.
*
* This export will be removed from 'nuqs/server' in [email protected],
* to allow non-Next.js server code to use the parsers, serializeres and other
* server-side utilities without depending on React canary for the `cache` function.
*/
createSearchParamsCache
} from './cache'
export type {
HistoryOptions,
Nullable,
Expand Down
15 changes: 15 additions & 0 deletions packages/nuqs/src/index.temporary-react-agnostic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export type {
HistoryOptions,
Nullable,
Options,
SearchParams,
UrlKeys
} from './defs'
export {
createLoader,
type LoaderFunction,
type LoaderInput,
type LoaderOptions
} from './loader'
export * from './parsers'
export { createSerializer } from './serializer'
2 changes: 1 addition & 1 deletion packages/nuqs/src/tests/cache.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { assertType, describe, expectTypeOf, it } from 'vitest'
import {
createSearchParamsCache,
parseAsBoolean,
parseAsInteger,
parseAsString
} from '../../dist/server'
import { createSearchParamsCache } from '../../dist/server/cache'

describe('types/cache', () => {
const cache = createSearchParamsCache({
Expand Down
4 changes: 3 additions & 1 deletion packages/nuqs/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ const entrypoints = {
'adapters/testing': 'src/adapters/testing.ts'
},
server: {
server: 'src/index.server.ts'
server: 'src/index.server.ts',
'server/cache': 'src/index.server.cache.ts',
'server/temporary-react-agnostic': 'src/index.temporary-react-agnostic.ts'
}
}

Expand Down
Loading