state-in-url 7.0.0 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.es.md +51 -1
- package/README.fr.md +51 -1
- package/README.ja.md +50 -1
- package/README.ko.md +51 -3
- package/README.md +47 -0
- package/README.pt-BR.md +51 -1
- package/README.ru.md +51 -1
- package/README.vi.md +51 -1
- package/README.zh-CN.md +50 -3
- package/dist/astro/index.cjs +1 -0
- package/dist/astro/useUrlState/{index.js → index.cjs} +1 -1
- package/dist/constants/constants.cjs +1 -0
- package/dist/constants/constants.mjs +1 -1
- package/dist/constants/index.cjs +1 -0
- package/dist/encodeState/encodeState.cjs +1 -0
- package/dist/encodeState/index.cjs +1 -0
- package/dist/encoder/encoder.cjs +1 -0
- package/dist/encoder/index.cjs +1 -0
- package/dist/index.cjs +1 -0
- package/dist/next/index.cjs +1 -0
- package/dist/next/useUrlState/index.cjs +1 -0
- package/dist/next/useUrlState/useUrlState.cjs +1 -0
- package/dist/next/useUrlState/useUrlState.mjs +1 -1
- package/dist/package.json +44 -24
- package/dist/parseSPObj.cjs +1 -0
- package/dist/react/index.cjs +1 -0
- package/dist/react/useUrlState/index.cjs +1 -0
- package/dist/react/useUrlState/useUrlState.cjs +1 -0
- package/dist/react-router/index.cjs +1 -0
- package/dist/react-router/useUrlState/index.cjs +1 -0
- package/dist/react-router/useUrlState/useUrlState.cjs +1 -0
- package/dist/react-router/useUrlState/useUrlState.d.ts +1 -1
- package/dist/react-router/useUrlState/useUrlState.mjs +1 -1
- package/dist/react-router6/index.cjs +1 -0
- package/dist/react-router6/useUrlState/index.cjs +1 -0
- package/dist/react-router6/useUrlState/useUrlState.cjs +1 -0
- package/dist/react-router6/useUrlState/useUrlState.d.ts +1 -1
- package/dist/react-router6/useUrlState/useUrlState.mjs +1 -1
- package/dist/remix/index.cjs +1 -0
- package/dist/remix/useUrlState/index.cjs +1 -0
- package/dist/remix/useUrlState/useUrlState.cjs +1 -0
- package/dist/remix/useUrlState/useUrlState.d.ts +1 -1
- package/dist/remix/useUrlState/useUrlState.mjs +1 -1
- package/dist/useIsomorphicLayoutEffect.cjs +1 -0
- package/dist/useIsomorphicLayoutEffect.mjs +1 -1
- package/dist/useLinkProps/hrefWithState.cjs +1 -0
- package/dist/useLinkProps/index.cjs +1 -0
- package/dist/useLinkProps/useLinkProps.cjs +1 -0
- package/dist/useLinkProps/useLinkProps.mjs +1 -1
- package/dist/useSharedState/index.cjs +1 -0
- package/dist/useSharedState/useSharedState.cjs +1 -0
- package/dist/useUrlEncode/index.cjs +1 -0
- package/dist/useUrlEncode/useUrlEncode.cjs +1 -0
- package/dist/useUrlStateBase/index.cjs +1 -0
- package/dist/useUrlStateBase/useUrlStateBase.cjs +1 -0
- package/dist/useUrlStateBase/useUrlStateBase.mjs +1 -1
- package/dist/utils.cjs +1 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.mjs +1 -1
- package/package.json +44 -24
- package/skills/astro-setup/SKILL.md +1 -1
- package/skills/feature-state-hook/SKILL.md +1 -1
- package/skills/form-library-integration/SKILL.md +1 -1
- package/skills/input-handling/SKILL.md +1 -1
- package/skills/nextjs-ssr/SKILL.md +1 -1
- package/skills/react-no-router/SKILL.md +1 -1
- package/skills/react-router-remix-setup/SKILL.md +55 -1
- package/skills/shared-state-no-url/SKILL.md +1 -1
- package/dist/astro/index.js +0 -1
- package/dist/constants/constants.js +0 -1
- package/dist/constants/index.js +0 -1
- package/dist/encodeState/encodeState.js +0 -1
- package/dist/encodeState/index.js +0 -1
- package/dist/encoder/encoder.js +0 -1
- package/dist/encoder/index.js +0 -1
- package/dist/index.js +0 -1
- package/dist/next/index.js +0 -1
- package/dist/next/useUrlState/index.js +0 -1
- package/dist/next/useUrlState/useUrlState.js +0 -1
- package/dist/parseSPObj.js +0 -1
- package/dist/react/index.js +0 -1
- package/dist/react/useUrlState/index.js +0 -1
- package/dist/react/useUrlState/useUrlState.js +0 -1
- package/dist/react-router/index.js +0 -1
- package/dist/react-router/useUrlState/index.js +0 -1
- package/dist/react-router/useUrlState/useUrlState.js +0 -1
- package/dist/react-router6/index.js +0 -1
- package/dist/react-router6/useUrlState/index.js +0 -1
- package/dist/react-router6/useUrlState/useUrlState.js +0 -1
- package/dist/remix/index.js +0 -1
- package/dist/remix/useUrlState/index.js +0 -1
- package/dist/remix/useUrlState/useUrlState.js +0 -1
- package/dist/useIsomorphicLayoutEffect.js +0 -1
- package/dist/useLinkProps/hrefWithState.js +0 -1
- package/dist/useLinkProps/index.js +0 -1
- package/dist/useLinkProps/useLinkProps.js +0 -1
- package/dist/useSharedState/index.js +0 -1
- package/dist/useSharedState/useSharedState.js +0 -1
- package/dist/useUrlEncode/index.js +0 -1
- package/dist/useUrlEncode/useUrlEncode.js +0 -1
- package/dist/useUrlStateBase/index.js +0 -1
- package/dist/useUrlStateBase/useUrlStateBase.js +0 -1
- package/dist/utils.js +0 -1
- /package/dist/{subscribers.js → subscribers.cjs} +0 -0
package/README.es.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- i18n:start -->
|
|
2
2
|
[English](./README.md) · [简体中文](./README.zh-CN.md) · [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · Español · [Português (BR)](./README.pt-BR.md) · [Français](./README.fr.md) · [Tiếng Việt](./README.vi.md)
|
|
3
|
-
<!-- i18n:meta locale=es source=README.md source-blob=
|
|
3
|
+
<!-- i18n:meta locale=es source=README.md source-blob=8b11ee8f8c8b83c207a940455766e24376508130 status=translated -->
|
|
4
4
|
<!-- i18n:end -->
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
@@ -138,6 +138,7 @@ La comparación completa — la misma feature en ambas, otras alternativas (TanS
|
|
|
138
138
|
- [Instalación](#instalación)
|
|
139
139
|
- [1. Instalar el paquete](#1-instalar-el-paquete)
|
|
140
140
|
- [2. Editar tsconfig.json](#2-editar-tsconfigjson)
|
|
141
|
+
- [3. Nota: este paquete se resuelve solo como ESM](#3-nota-este-paquete-se-resuelve-solo-como-esm)
|
|
141
142
|
- [Uso con agentes de codificación con IA](#uso-con-agentes-de-codificación-con-ia)
|
|
142
143
|
- [useUrlState](#useurlstate)
|
|
143
144
|
- [Hook useUrlState para Next.js](#hook-useurlstate-para-nextjs)
|
|
@@ -197,6 +198,20 @@ pnpm add state-in-url
|
|
|
197
198
|
En `tsconfig.json`, en `compilerOptions`, establece `"moduleResolution": "Bundler"`, o `"moduleResolution": "Node16"`, o `"moduleResolution": "NodeNext"`.
|
|
198
199
|
Posiblemente necesites establecer `"module": "ES2022"`, o `"module": "ESNext"`
|
|
199
200
|
|
|
201
|
+
### 3. Nota: este paquete se resuelve solo como ESM
|
|
202
|
+
|
|
203
|
+
Next.js, Vite, Astro y Remix lo empaquetan sin ninguna configuración, y
|
|
204
|
+
`require()` desde Node puro funciona en Node `^20.19` o `>=22.12`, donde
|
|
205
|
+
`require(esm)` no necesita flag.
|
|
206
|
+
|
|
207
|
+
En `dist/` también se publica una compilación CommonJS con extensión `.cjs`, pero
|
|
208
|
+
el mapa `exports` no apunta a ella, así que ninguna resolución llega allí por
|
|
209
|
+
accidente. Está para los casos límite — Node antiguo, o Jest sin flag — y solo se
|
|
210
|
+
alcanza mediante una ruta explícita.
|
|
211
|
+
|
|
212
|
+
**En cualquiera de los dos casos Jest necesita una línea de configuración** —
|
|
213
|
+
consulta el punto 5 de [Trampas](#trampas).
|
|
214
|
+
|
|
200
215
|
## Uso con agentes de codificación con IA
|
|
201
216
|
|
|
202
217
|
`state-in-url` incluye archivos de habilidades (skills) para [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview), de modo que los agentes de IA (Claude Code, Cursor, Copilot, Codex, etc.) carguen los patrones correctos y eviten errores comunes al usar la biblioteca. Tras instalar `state-in-url`, ejecuta una vez en tu proyecto:
|
|
@@ -982,6 +997,41 @@ export const useUserState = () => {
|
|
|
982
997
|
2. Los servidores de Vercel limitan el tamaño de las cabeceras (la cadena de consulta y demás) a **14KB**, así que mantén el estado de tu URL por debajo de ~5000 palabras. <https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
983
998
|
3. Probado con `next.js` 14/15/16 con app router; no hay planes de soportar pages.
|
|
984
999
|
|
|
1000
|
+
4. **Vitest + react-router 7**: si una prueba que renderiza un componente dentro de `<BrowserRouter>` lanza `useNavigate() may be used only in the context of a <Router> component` con el provider justo ahí, actualiza a `react-router@8` o incorpora este paquete en línea:
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
// vitest.config.ts
|
|
1004
|
+
test: { server: { deps: { inline: ['state-in-url'] } } }
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
Vitest externaliza `node_modules`, así que Node carga `state-in-url` mientras Vite carga tu archivo de prueba. En `react-router@7` la condición de exportación `node` apunta `module`/`module-sync` a `index.mjs` y `default` a `index.js`, y los dos resolutores eligen distinto: react-router se carga dos veces, su contexto de React existe por duplicado y el provider escribe en la copia que el hook no lee. Incorporarlo en línea pone ambos lados en el resolutor de Vite.
|
|
1008
|
+
|
|
1009
|
+
`react-router@8` apunta `default` y `module-sync` al mismo archivo, de modo que ningún resolutor puede discrepar y no hace falta nada. El error nunca menciona `state-in-url`, por eso esto está aquí.
|
|
1010
|
+
|
|
1011
|
+
5. **Jest**: este paquete se resuelve solo como ESM y Jest ejecuta las pruebas como CommonJS por defecto, así que un `require()` simple falla con `Must use import to load ES Module`. Jest no hereda el `require(esm)` sin flag de Node — usa su propia API síncrona `vm` —, así que en **Node 24.9+** pásale el flag:
|
|
1012
|
+
|
|
1013
|
+
```json
|
|
1014
|
+
// package.json
|
|
1015
|
+
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" }
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
Si prefieres no pasar un flag, `dist/` también incluye una compilación CommonJS. Está deliberadamente fuera del mapa `exports`, así que nada se resuelve a ella por accidente: apunta Jest a ella de forma explícita:
|
|
1019
|
+
|
|
1020
|
+
```js
|
|
1021
|
+
// jest.config.js
|
|
1022
|
+
moduleNameMapper: {
|
|
1023
|
+
'^state-in-url$': '<rootDir>/node_modules/state-in-url/dist/index.cjs',
|
|
1024
|
+
'^state-in-url/utils$': '<rootDir>/node_modules/state-in-url/dist/utils.cjs',
|
|
1025
|
+
'^state-in-url/(.*)$': '<rootDir>/node_modules/state-in-url/dist/$1/index.cjs',
|
|
1026
|
+
},
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
Eso sustituye la compilación por la de CJS en todo el proceso de pruebas, y es seguro. No mezcles las dos en un mismo proceso: este paquete guarda su almacén de estado compartido en el ámbito del módulo, así que dos copias significan dos almacenes y `useSharedState` deja de compartir sin avisar.
|
|
1030
|
+
|
|
1031
|
+
Una diferencia más: `jest.mock()` no se aplica a los módulos ES. Usa `jest.unstable_mockModule()` si haces mock de este paquete.
|
|
1032
|
+
|
|
1033
|
+
Vitest, Next.js, Vite, Astro y Remix no necesitan nada de esta configuración de Jest. El único paso adicional de Vitest es el `server.deps.inline` de arriba, y solo con `react-router@7`.
|
|
1034
|
+
|
|
985
1035
|
## Otros
|
|
986
1036
|
|
|
987
1037
|
### Contribuir y/o ejecutar localmente
|
package/README.fr.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- i18n:start -->
|
|
2
2
|
[English](./README.md) · [简体中文](./README.zh-CN.md) · [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · [Español](./README.es.md) · [Português (BR)](./README.pt-BR.md) · Français · [Tiếng Việt](./README.vi.md)
|
|
3
|
-
<!-- i18n:meta locale=fr source=README.md source-blob=
|
|
3
|
+
<!-- i18n:meta locale=fr source=README.md source-blob=8b11ee8f8c8b83c207a940455766e24376508130 status=translated -->
|
|
4
4
|
<!-- i18n:end -->
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
@@ -138,6 +138,7 @@ La comparaison complète — la même fonctionnalité dans les deux, d’autres
|
|
|
138
138
|
- [Installation](#installation)
|
|
139
139
|
- [1. Installer le paquet](#1-installer-le-paquet)
|
|
140
140
|
- [2. Modifier tsconfig.json](#2-modifier-tsconfigjson)
|
|
141
|
+
- [3. Remarque : ce paquet ne se résout qu'en ESM](#3-remarque--ce-paquet-ne-se-résout-quen-esm)
|
|
141
142
|
- [Utilisation avec des agents de codage IA](#utilisation-avec-des-agents-de-codage-ia)
|
|
142
143
|
- [useUrlState](#useurlstate)
|
|
143
144
|
- [Hook useUrlState pour Next.js](#hook-useurlstate-pour-nextjs)
|
|
@@ -197,6 +198,20 @@ pnpm add state-in-url
|
|
|
197
198
|
Dans `tsconfig.json`, dans `compilerOptions`, définissez `"moduleResolution": "Bundler"`, ou `"moduleResolution": "Node16"`, ou `"moduleResolution": "NodeNext"`.
|
|
198
199
|
Il peut être nécessaire de définir `"module": "ES2022"`, ou `"module": "ESNext"`
|
|
199
200
|
|
|
201
|
+
### 3. Remarque : ce paquet ne se résout qu'en ESM
|
|
202
|
+
|
|
203
|
+
Next.js, Vite, Astro et Remix l'empaquettent sans aucune configuration, et
|
|
204
|
+
`require()` depuis Node seul fonctionne sur Node `^20.19` ou `>=22.12`, où
|
|
205
|
+
`require(esm)` ne demande pas de drapeau.
|
|
206
|
+
|
|
207
|
+
Une build CommonJS est également publiée dans `dist/` avec l'extension `.cjs`,
|
|
208
|
+
mais la table `exports` ne pointe pas dessus : aucune résolution n'y aboutit par
|
|
209
|
+
accident. Elle existe pour les cas limites — un Node ancien, ou Jest sans
|
|
210
|
+
drapeau — et on ne l'atteint que par un chemin explicite.
|
|
211
|
+
|
|
212
|
+
**Dans les deux cas, Jest demande une ligne de configuration** — voir le point 5
|
|
213
|
+
des [Pièges](#pièges).
|
|
214
|
+
|
|
200
215
|
## Utilisation avec des agents de codage IA
|
|
201
216
|
|
|
202
217
|
`state-in-url` fournit des fichiers de compétences (skills) pour [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview), afin que les agents IA (Claude Code, Cursor, Copilot, Codex, etc.) chargent les bons modèles et évitent les erreurs courantes lors de l'utilisation de la bibliothèque. Après avoir installé `state-in-url`, exécutez une fois dans votre projet :
|
|
@@ -982,6 +997,41 @@ export const useUserState = () => {
|
|
|
982
997
|
2. Les serveurs Vercel limitent la taille des en-têtes (chaîne de requête et autres) à **14KB**, gardez donc l'état de votre URL sous ~5000 mots. <https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
983
998
|
3. Testé avec `next.js` 14/15/16 avec app router ; pas de plan pour prendre en charge pages.
|
|
984
999
|
|
|
1000
|
+
4. **Vitest + react-router 7** : si un test qui rend un composant à l'intérieur de `<BrowserRouter>` lève `useNavigate() may be used only in the context of a <Router> component` alors que le provider est juste là, passez à `react-router@8` ou intégrez ce paquet en ligne :
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
// vitest.config.ts
|
|
1004
|
+
test: { server: { deps: { inline: ['state-in-url'] } } }
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
Vitest externalise `node_modules`, donc Node charge `state-in-url` tandis que Vite charge votre fichier de test. Dans `react-router@7`, la condition d'export `node` pointe `module`/`module-sync` vers `index.mjs` et `default` vers `index.js`, et les deux résolveurs n'en choisissent pas le même : react-router est chargé deux fois, son contexte React existe en double, et le provider écrit dans la copie que le hook ne lit pas. L'intégration en ligne place les deux côtés sur le résolveur de Vite.
|
|
1008
|
+
|
|
1009
|
+
`react-router@8` pointe `default` et `module-sync` vers le même fichier : aucun résolveur ne peut diverger et rien n'est nécessaire. L'erreur ne nomme jamais `state-in-url`, d'où la présence de ce point ici.
|
|
1010
|
+
|
|
1011
|
+
5. **Jest** : ce paquet ne se résout qu'en ESM, et Jest exécute les tests en CommonJS par défaut ; un simple `require()` échoue donc avec `Must use import to load ES Module`. Jest n'hérite pas du `require(esm)` sans drapeau de Node — il utilise sa propre API synchrone `vm` — donc sur **Node 24.9+**, passez-lui le drapeau :
|
|
1012
|
+
|
|
1013
|
+
```json
|
|
1014
|
+
// package.json
|
|
1015
|
+
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" }
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
Si vous préférez éviter le drapeau, `dist/` contient aussi une build CommonJS. Elle est délibérément absente de la table `exports`, si bien que rien ne s'y résout par accident : pointez Jest dessus explicitement :
|
|
1019
|
+
|
|
1020
|
+
```js
|
|
1021
|
+
// jest.config.js
|
|
1022
|
+
moduleNameMapper: {
|
|
1023
|
+
'^state-in-url$': '<rootDir>/node_modules/state-in-url/dist/index.cjs',
|
|
1024
|
+
'^state-in-url/utils$': '<rootDir>/node_modules/state-in-url/dist/utils.cjs',
|
|
1025
|
+
'^state-in-url/(.*)$': '<rootDir>/node_modules/state-in-url/dist/$1/index.cjs',
|
|
1026
|
+
},
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
Cela substitue la build CJS pour tout le processus de test, et c'est sans danger. Ne mélangez pas les deux dans un même processus : ce paquet garde son magasin d'état partagé dans la portée du module, donc deux copies signifient deux magasins et `useSharedState` cesse de partager sans rien signaler.
|
|
1030
|
+
|
|
1031
|
+
Autre différence : `jest.mock()` ne s'applique pas aux modules ES. Utilisez `jest.unstable_mockModule()` si vous mockez ce paquet.
|
|
1032
|
+
|
|
1033
|
+
Vitest, Next.js, Vite, Astro et Remix n'ont besoin de rien de cette configuration Jest. La seule étape supplémentaire pour Vitest est le `server.deps.inline` ci-dessus, et uniquement avec `react-router@7`.
|
|
1034
|
+
|
|
985
1035
|
## Autres
|
|
986
1036
|
|
|
987
1037
|
### Contribuer et/ou exécuter localement
|
package/README.ja.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- i18n:start -->
|
|
2
2
|
[English](./README.md) · [简体中文](./README.zh-CN.md) · 日本語 · [한국어](./README.ko.md) · [Русский](./README.ru.md) · [Español](./README.es.md) · [Português (BR)](./README.pt-BR.md) · [Français](./README.fr.md) · [Tiếng Việt](./README.vi.md)
|
|
3
|
-
<!-- i18n:meta locale=ja source=README.md source-blob=
|
|
3
|
+
<!-- i18n:meta locale=ja source=README.md source-blob=8b11ee8f8c8b83c207a940455766e24376508130 status=translated -->
|
|
4
4
|
<!-- i18n:end -->
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
@@ -138,6 +138,7 @@ nuqs も優れたライブラリです。値ごとに読みやすいクエリパ
|
|
|
138
138
|
- [インストール](#インストール)
|
|
139
139
|
- [1. パッケージのインストール](#1-パッケージのインストール)
|
|
140
140
|
- [2. tsconfig.json の編集](#2-tsconfigjson-の編集)
|
|
141
|
+
- [3. 補足: このパッケージは ESM としてのみ解決されます](#3-補足-このパッケージは-esm-としてのみ解決されます)
|
|
141
142
|
- [AI コーディングエージェントと使う](#ai-コーディングエージェントと使う)
|
|
142
143
|
- [useUrlState](#useurlstate)
|
|
143
144
|
- [Next.js 向け useUrlState フック](#nextjs-向け-useurlstate-フック)
|
|
@@ -197,6 +198,19 @@ pnpm add state-in-url
|
|
|
197
198
|
`tsconfig.json` の `compilerOptions` に `"moduleResolution": "Bundler"`、または `"moduleResolution": "Node16"`、または `"moduleResolution": "NodeNext"` を設定します。
|
|
198
199
|
`"module": "ES2022"` または `"module": "ESNext"` の設定が必要になる場合があります。
|
|
199
200
|
|
|
201
|
+
### 3. 補足: このパッケージは ESM としてのみ解決されます
|
|
202
|
+
|
|
203
|
+
Next.js、Vite、Astro、Remix は設定なしでバンドルできます。また `require(esm)` が
|
|
204
|
+
フラグなしで使える Node `^20.19` または `>=22.12` であれば、素の Node からの
|
|
205
|
+
`require()` も動作します。
|
|
206
|
+
|
|
207
|
+
`dist/` には `.cjs` という拡張子で CommonJS ビルドも同梱されていますが、`exports`
|
|
208
|
+
マップはそれを指していないため、解決が偶然そちらへ向かうことはありません。これは
|
|
209
|
+
例外的なケース——古い Node、あるいはフラグなしの Jest——のためのもので、明示的な
|
|
210
|
+
パスでのみ参照できます。
|
|
211
|
+
|
|
212
|
+
**どちらの場合も Jest には 1 行の設定が必要です**——[注意点](#注意点)の 5 番を参照してください。
|
|
213
|
+
|
|
200
214
|
## AI コーディングエージェントと使う
|
|
201
215
|
|
|
202
216
|
`state-in-url` は [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview) 向けのスキルファイルを同梱しています。AI エージェント(Claude Code、Cursor、Copilot、Codex など)がライブラリ使用時の正しいパターンを読み込み、よくあるミスを避けられます。`state-in-url` をインストールした後、プロジェクトで一度実行してください:
|
|
@@ -982,6 +996,41 @@ export const useUserState = () => {
|
|
|
982
996
|
2. Vercel サーバーはヘッダー(クエリ文字列など)のサイズを **14KB** に制限しているため、URL の状態は約 5000 語未満に保ってください。<https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
983
997
|
3. app router 付きの `next.js` 14/15/16 でテスト済みです。pages をサポートする予定はありません。
|
|
984
998
|
|
|
999
|
+
4. **Vitest + react-router 7**: provider がすぐそこにあるのに、`<BrowserRouter>` の内側でコンポーネントを描画するテストが `useNavigate() may be used only in the context of a <Router> component` を投げる場合は、`react-router@8` に上げるか、このパッケージをインライン化してください:
|
|
1000
|
+
|
|
1001
|
+
```ts
|
|
1002
|
+
// vitest.config.ts
|
|
1003
|
+
test: { server: { deps: { inline: ['state-in-url'] } } }
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
Vitest は `node_modules` を外部化するため、`state-in-url` は Node が、テストファイルは Vite が読み込みます。`react-router@7` では `node` エクスポート条件が `module`/`module-sync` を `index.mjs` に、`default` を `index.js` に向けており、2 つのリゾルバがそれぞれ別のものを選びます。その結果 react-router が二重に読み込まれ、React context も二つ存在し、provider が書き込むのは hook が読まない方のコピーになります。インライン化すると双方が Vite のリゾルバに揃います。
|
|
1007
|
+
|
|
1008
|
+
`react-router@8` は `default` と `module-sync` を同じファイルに向けているので、どのリゾルバも食い違いようがなく、何も必要ありません。エラーメッセージに `state-in-url` の名前は出てこないため、ここに書いてあります。
|
|
1009
|
+
|
|
1010
|
+
5. **Jest**: このパッケージは ESM としてのみ解決されますが、Jest は既定でテストを CommonJS として実行するため、素の `require()` は `Must use import to load ES Module` で失敗します。Jest は Node のフラグ不要な `require(esm)` を引き継がず、独自の同期 `vm` API を使うので、**Node 24.9+** ではフラグを渡してください:
|
|
1011
|
+
|
|
1012
|
+
```json
|
|
1013
|
+
// package.json
|
|
1014
|
+
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" }
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
フラグを渡したくない場合、`dist/` には CommonJS ビルドも同梱されています。`exports` マップからは意図的に外してあるため偶然解決されることはありません——Jest を明示的にそこへ向けてください:
|
|
1018
|
+
|
|
1019
|
+
```js
|
|
1020
|
+
// jest.config.js
|
|
1021
|
+
moduleNameMapper: {
|
|
1022
|
+
'^state-in-url$': '<rootDir>/node_modules/state-in-url/dist/index.cjs',
|
|
1023
|
+
'^state-in-url/utils$': '<rootDir>/node_modules/state-in-url/dist/utils.cjs',
|
|
1024
|
+
'^state-in-url/(.*)$': '<rootDir>/node_modules/state-in-url/dist/$1/index.cjs',
|
|
1025
|
+
},
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
これはテストプロセス全体を CJS ビルドに差し替えるもので、安全です。一つのプロセス内で両方を混在させないでください——このパッケージは共有ステートのストアをモジュールスコープに置いているため、コピーが二つあればストアも二つになり、`useSharedState` は何も告げずに共有をやめます。
|
|
1029
|
+
|
|
1030
|
+
もう一つの違いとして、`jest.mock()` は ES モジュールには効きません。このパッケージをモックするなら `jest.unstable_mockModule()` を使ってください。
|
|
1031
|
+
|
|
1032
|
+
Vitest、Next.js、Vite、Astro、Remix はいずれもこの Jest 向けの設定を必要としません。Vitest で追加が必要なのは上記の `server.deps.inline` だけで、しかも `react-router@7` の場合のみです。
|
|
1033
|
+
|
|
985
1034
|
## その他
|
|
986
1035
|
|
|
987
1036
|
### 貢献、またはローカルでの実行
|
package/README.ko.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- i18n:start -->
|
|
2
2
|
[English](./README.md) · [简体中文](./README.zh-CN.md) · [日本語](./README.ja.md) · 한국어 · [Русский](./README.ru.md) · [Español](./README.es.md) · [Português (BR)](./README.pt-BR.md) · [Français](./README.fr.md) · [Tiếng Việt](./README.vi.md)
|
|
3
|
-
<!-- i18n:meta locale=ko source=README.md source-blob=
|
|
3
|
+
<!-- i18n:meta locale=ko source=README.md source-blob=8b11ee8f8c8b83c207a940455766e24376508130 status=translated -->
|
|
4
4
|
<!-- i18n:end -->
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
@@ -95,7 +95,7 @@ Next.js, react-router, Remix, Astro용 `useUrlState` 훅과 그 외 JS 환경을
|
|
|
95
95
|
- **호환성**: 서드파티 쿼리 매개변수를 그대로 유지
|
|
96
96
|
- **유연성**: 동일한 페이지에서 1개 이상의 상태 객체 사용 가능, 다른 키만 사용하면 됨
|
|
97
97
|
- **빠름**: 최소한의 리렌더링, 큰 객체 인코딩 및 디코딩에 약 [1ms](https://github.com/asmyshlyaev177/state-in-url/blob/87c8c7c995c5cd7d9e7aa039c30bfe64b24abe4b/packages/urlstate/encoder/encoder.test.ts#L185) 소요
|
|
98
|
-
- **서버 사이드 렌더링**: 서버 컴포넌트에서 사용 가능, Next.js 14 및
|
|
98
|
+
- **서버 사이드 렌더링**: 서버 컴포넌트에서 사용 가능, Next.js 14, 15 및 16 지원
|
|
99
99
|
- **경량**: 의존성 없음, 라이브러리 크기 2KB 미만
|
|
100
100
|
- **개발자 경험**: 좋은 개발자 경험, 문서, JSDoc 주석 및 예제
|
|
101
101
|
- **프레임워크 유연성**: `Next.js`, `react-router`, `Remix`, `Astro`용 훅, 다른 프레임워크나 순수 JS와 함께 사용할 수 있는 헬퍼
|
|
@@ -138,6 +138,7 @@ nuqs도 훌륭한 라이브러리입니다. 값마다 읽기 쉬운 쿼리 파
|
|
|
138
138
|
- [설치](#설치)
|
|
139
139
|
- [1. 패키지 설치](#1-패키지-설치)
|
|
140
140
|
- [2. tsconfig.json 수정](#2-tsconfigjson-수정)
|
|
141
|
+
- [3. 참고: 이 패키지는 ESM으로만 해석됩니다](#3-참고-이-패키지는-esm으로만-해석됩니다)
|
|
141
142
|
- [AI 코딩 에이전트와 함께 사용](#ai-코딩-에이전트와-함께-사용)
|
|
142
143
|
- [useUrlState](#useurlstate)
|
|
143
144
|
- [Next.js용 useUrlState 훅](#nextjs용-useurlstate-훅)
|
|
@@ -197,6 +198,18 @@ pnpm add state-in-url
|
|
|
197
198
|
`tsconfig.json`의 `compilerOptions`에서 `"moduleResolution": "Bundler"`, 또는 `"moduleResolution": "Node16"`, 또는 `"moduleResolution": "NodeNext"`로 설정하세요.
|
|
198
199
|
`"module": "ES2022"` 또는 `"module": "ESNext"` 설정이 필요할 수 있습니다.
|
|
199
200
|
|
|
201
|
+
### 3. 참고: 이 패키지는 ESM으로만 해석됩니다
|
|
202
|
+
|
|
203
|
+
Next.js, Vite, Astro, Remix는 설정 없이 번들링하며, `require(esm)`이 플래그 없이
|
|
204
|
+
동작하는 Node `^20.19` 또는 `>=22.12`에서는 순수 Node의 `require()`도 동작합니다.
|
|
205
|
+
|
|
206
|
+
`dist/`에는 `.cjs` 확장자의 CommonJS 빌드도 함께 들어 있지만 `exports` 맵이 이를
|
|
207
|
+
가리키지 않으므로 해석이 실수로 그쪽으로 향하는 일은 없습니다. 이는 예외적인
|
|
208
|
+
경우——구버전 Node, 또는 플래그 없는 Jest——를 위한 것이며 명시적인 경로로만
|
|
209
|
+
접근할 수 있습니다.
|
|
210
|
+
|
|
211
|
+
**어느 쪽이든 Jest에는 설정 한 줄이 필요합니다**——[주의사항](#주의사항) 5번을 참고하세요.
|
|
212
|
+
|
|
200
213
|
## AI 코딩 에이전트와 함께 사용
|
|
201
214
|
|
|
202
215
|
`state-in-url`은 [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview)용 스킬 파일을 함께 제공합니다. AI 에이전트(Claude Code, Cursor, Copilot, Codex 등)가 라이브러리를 사용할 때 올바른 패턴을 불러오고 흔한 실수를 피할 수 있습니다. `state-in-url`을 설치한 후 프로젝트에서 한 번 실행하세요:
|
|
@@ -975,7 +988,42 @@ export const useUserState = () => {
|
|
|
975
988
|
|
|
976
989
|
1. 직렬화 가능한 값만 전달할 수 있습니다. `Function`, `BigInt` 또는 `Symbol`은 작동하지 않으며, `ArrayBuffer`와 같은 것도 마찬가지일 것입니다. JSON으로 직렬화할 수 있는 모든 것은 작동합니다.
|
|
977
990
|
2. Vercel 서버는 헤더(쿼리 문자열 및 기타 항목) 크기를 **14KB**로 제한하므로 URL 상태를 약 5000단어 미만으로 유지하세요. <https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
978
|
-
3. app router를 사용하는 `next.js` 14/15
|
|
991
|
+
3. app router를 사용하는 `next.js` 14/15/16으로 테스트되었으며, pages를 지원할 계획은 없습니다.
|
|
992
|
+
|
|
993
|
+
4. **Vitest + react-router 7**: provider가 바로 거기 있는데도 `<BrowserRouter>` 안에서 컴포넌트를 렌더링하는 테스트가 `useNavigate() may be used only in the context of a <Router> component`를 던진다면, `react-router@8`로 올리거나 이 패키지를 인라인하세요:
|
|
994
|
+
|
|
995
|
+
```ts
|
|
996
|
+
// vitest.config.ts
|
|
997
|
+
test: { server: { deps: { inline: ['state-in-url'] } } }
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
Vitest는 `node_modules`를 외부화하므로 `state-in-url`은 Node가, 테스트 파일은 Vite가 로드합니다. `react-router@7`에서는 `node` 내보내기 조건이 `module`/`module-sync`를 `index.mjs`로, `default`를 `index.js`로 가리키고 두 리졸버가 서로 다른 것을 고릅니다——그래서 react-router가 두 번 로드되고 React context도 두 개가 되며, provider는 hook이 읽지 않는 쪽 사본에 씁니다. 인라인하면 양쪽 모두 Vite의 리졸버를 쓰게 됩니다.
|
|
1001
|
+
|
|
1002
|
+
`react-router@8`은 `default`와 `module-sync`를 같은 파일로 가리키므로 어떤 리졸버도 어긋날 수 없고 아무것도 필요하지 않습니다. 오류 메시지에는 `state-in-url`이 전혀 나오지 않기 때문에 이 항목이 여기 있습니다.
|
|
1003
|
+
|
|
1004
|
+
5. **Jest**: 이 패키지는 ESM으로만 해석되는데 Jest는 기본적으로 테스트를 CommonJS로 실행하므로, 그냥 `require()`하면 `Must use import to load ES Module`로 실패합니다. Jest는 Node의 플래그 없는 `require(esm)`을 물려받지 않고 자체 동기 `vm` API를 사용하므로, **Node 24.9+**에서는 플래그를 주세요:
|
|
1005
|
+
|
|
1006
|
+
```json
|
|
1007
|
+
// package.json
|
|
1008
|
+
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" }
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
플래그를 주고 싶지 않다면 `dist/`에 CommonJS 빌드도 들어 있습니다. `exports` 맵에서 의도적으로 빠져 있어 실수로 해석되는 일이 없으니, Jest가 이를 명시적으로 가리키게 하세요:
|
|
1012
|
+
|
|
1013
|
+
```js
|
|
1014
|
+
// jest.config.js
|
|
1015
|
+
moduleNameMapper: {
|
|
1016
|
+
'^state-in-url$': '<rootDir>/node_modules/state-in-url/dist/index.cjs',
|
|
1017
|
+
'^state-in-url/utils$': '<rootDir>/node_modules/state-in-url/dist/utils.cjs',
|
|
1018
|
+
'^state-in-url/(.*)$': '<rootDir>/node_modules/state-in-url/dist/$1/index.cjs',
|
|
1019
|
+
},
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
이는 테스트 프로세스 전체를 CJS 빌드로 바꾸는 것이라 안전합니다. 한 프로세스 안에서 둘을 섞지 마세요——이 패키지는 공유 상태 저장소를 모듈 스코프에 두므로, 사본이 둘이면 저장소도 둘이 되어 `useSharedState`가 조용히 공유를 멈춥니다.
|
|
1023
|
+
|
|
1024
|
+
한 가지 차이가 더 있습니다: `jest.mock()`은 ES 모듈에 적용되지 않습니다. 이 패키지를 목으로 만들 때는 `jest.unstable_mockModule()`을 사용하세요.
|
|
1025
|
+
|
|
1026
|
+
Vitest, Next.js, Vite, Astro, Remix는 모두 이런 Jest 설정이 필요 없습니다. Vitest에서 추가로 필요한 것은 위의 `server.deps.inline` 하나뿐이며, `react-router@7`에서만 필요합니다.
|
|
979
1027
|
|
|
980
1028
|
## 기타
|
|
981
1029
|
|
package/README.md
CHANGED
|
@@ -137,6 +137,7 @@ The full comparison — the same feature built in both, other alternatives (TanS
|
|
|
137
137
|
- [installation](#installation)
|
|
138
138
|
- [1. Install package](#1-install-package)
|
|
139
139
|
- [2. Edit tsconfig.json](#2-edit-tsconfigjson)
|
|
140
|
+
- [3. Note: this package resolves as ESM only](#3-note-this-package-resolves-as-esm-only)
|
|
140
141
|
- [Using with AI coding agents](#using-with-ai-coding-agents)
|
|
141
142
|
- [useUrlState](#useurlstate)
|
|
142
143
|
- [useUrlState hook for Next.js](#useurlstate-hook-for-nextjs)
|
|
@@ -196,6 +197,18 @@ pnpm add state-in-url
|
|
|
196
197
|
In `tsconfig.json` in `compilerOptions` set `"moduleResolution": "Bundler"`, or`"moduleResolution": "Node16"`, or `"moduleResolution": "NodeNext"`.
|
|
197
198
|
Possibly need to set `"module": "ES2022"`, or `"module": "ESNext"`
|
|
198
199
|
|
|
200
|
+
### 3. Note: this package resolves as ESM only
|
|
201
|
+
|
|
202
|
+
Next.js, Vite, Astro and Remix bundle it with no configuration, and `require()`
|
|
203
|
+
from plain Node works on Node `^20.19` or `>=22.12`, where `require(esm)` is
|
|
204
|
+
unflagged.
|
|
205
|
+
|
|
206
|
+
A CommonJS build ships in `dist/` as `.cjs`, but the `exports` map does not point
|
|
207
|
+
at it, so nothing resolves to it by accident. It is there for the edge cases —
|
|
208
|
+
older Node, or Jest without a flag — and you reach it by explicit path.
|
|
209
|
+
|
|
210
|
+
**Jest needs one line of config either way** — see [Gotchas](#gotchas) item 5.
|
|
211
|
+
|
|
199
212
|
## Using with AI coding agents
|
|
200
213
|
|
|
201
214
|
`state-in-url` ships skill files for [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview), so AI agents (Claude Code, Cursor, Copilot, Codex, etc.) load the right patterns and avoid common mistakes when using the library. After installing `state-in-url`, run once in your project:
|
|
@@ -980,6 +993,40 @@ export const useUserState = () => {
|
|
|
980
993
|
1. Can pass only serializable values, `Function`, `BigInt` or `Symbol` won't work, probably things like `ArrayBuffer` neither. Everything that can be serialized to JSON will work.
|
|
981
994
|
2. Vercel servers limit size of headers (query string and other stuff) to **14KB**, so keep your URL state under ~5000 words. <https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
982
995
|
3. Tested with `next.js` 14/15/16 with app router, no plans to support pages.
|
|
996
|
+
4. **Vitest + react-router 7**: if a test rendering a component inside `<BrowserRouter>` throws `useNavigate() may be used only in the context of a <Router> component` with the provider right there, either upgrade to `react-router@8` or inline this package:
|
|
997
|
+
|
|
998
|
+
```ts
|
|
999
|
+
// vitest.config.ts
|
|
1000
|
+
test: { server: { deps: { inline: ['state-in-url'] } } }
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
Vitest externalizes `node_modules`, so Node loads `state-in-url` while Vite loads your test file. In `react-router@7` the `node` export condition points `module`/`module-sync` at `index.mjs` and `default` at `index.js`, and the two resolvers pick different ones — so react-router loads twice, its React context exists twice, and the provider writes to the copy the hook does not read. Inlining puts both sides on Vite's resolver.
|
|
1004
|
+
|
|
1005
|
+
`react-router@8` points `default` and `module-sync` at the same file, so no resolver can disagree and nothing is needed. The error never names `state-in-url`, which is why this is here.
|
|
1006
|
+
|
|
1007
|
+
5. **Jest**: this package resolves as ESM only, and Jest runs tests as CommonJS by default, so a bare `require()` fails with `Must use import to load ES Module`. Jest does not inherit Node's unflagged `require(esm)` — it uses its own synchronous `vm` API — so on **Node 24.9+** give it the flag:
|
|
1008
|
+
|
|
1009
|
+
```json
|
|
1010
|
+
// package.json
|
|
1011
|
+
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" }
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
If you would rather not pass a flag, `dist/` also ships a CommonJS build. It is deliberately absent from the `exports` map, so nothing resolves to it by accident — point Jest at it explicitly:
|
|
1015
|
+
|
|
1016
|
+
```js
|
|
1017
|
+
// jest.config.js
|
|
1018
|
+
moduleNameMapper: {
|
|
1019
|
+
'^state-in-url$': '<rootDir>/node_modules/state-in-url/dist/index.cjs',
|
|
1020
|
+
'^state-in-url/utils$': '<rootDir>/node_modules/state-in-url/dist/utils.cjs',
|
|
1021
|
+
'^state-in-url/(.*)$': '<rootDir>/node_modules/state-in-url/dist/$1/index.cjs',
|
|
1022
|
+
},
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
That substitutes the CJS build for the whole test process, which is safe. Do not mix the two in one process — this package keeps its shared-state store in module scope, so two copies means two stores and `useSharedState` quietly stops sharing.
|
|
1026
|
+
|
|
1027
|
+
One more difference: `jest.mock()` does not apply to ES modules. Use `jest.unstable_mockModule()` if you mock this package.
|
|
1028
|
+
|
|
1029
|
+
Vitest, Next.js, Vite, Astro and Remix all need none of this Jest setup. Vitest's one extra step is the `server.deps.inline` above, and only with `react-router@7`.
|
|
983
1030
|
|
|
984
1031
|
## Other
|
|
985
1032
|
|
package/README.pt-BR.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- i18n:start -->
|
|
2
2
|
[English](./README.md) · [简体中文](./README.zh-CN.md) · [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · [Español](./README.es.md) · Português (BR) · [Français](./README.fr.md) · [Tiếng Việt](./README.vi.md)
|
|
3
|
-
<!-- i18n:meta locale=pt-BR source=README.md source-blob=
|
|
3
|
+
<!-- i18n:meta locale=pt-BR source=README.md source-blob=8b11ee8f8c8b83c207a940455766e24376508130 status=translated -->
|
|
4
4
|
<!-- i18n:end -->
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
@@ -138,6 +138,7 @@ A comparação completa — a mesma feature nas duas, outras alternativas (TanSt
|
|
|
138
138
|
- [Instalação](#instalação)
|
|
139
139
|
- [1. Instalar o pacote](#1-instalar-o-pacote)
|
|
140
140
|
- [2. Editar o tsconfig.json](#2-editar-o-tsconfigjson)
|
|
141
|
+
- [3. Observação: este pacote resolve apenas como ESM](#3-observação-este-pacote-resolve-apenas-como-esm)
|
|
141
142
|
- [Uso com agentes de codificação de IA](#uso-com-agentes-de-codificação-de-ia)
|
|
142
143
|
- [useUrlState](#useurlstate)
|
|
143
144
|
- [Hook useUrlState para Next.js](#hook-useurlstate-para-nextjs)
|
|
@@ -197,6 +198,20 @@ pnpm add state-in-url
|
|
|
197
198
|
No `tsconfig.json`, em `compilerOptions`, defina `"moduleResolution": "Bundler"`, ou `"moduleResolution": "Node16"`, ou `"moduleResolution": "NodeNext"`.
|
|
198
199
|
Possivelmente será necessário definir `"module": "ES2022"`, ou `"module": "ESNext"`
|
|
199
200
|
|
|
201
|
+
### 3. Observação: este pacote resolve apenas como ESM
|
|
202
|
+
|
|
203
|
+
Next.js, Vite, Astro e Remix o empacotam sem nenhuma configuração, e o
|
|
204
|
+
`require()` do Node puro funciona no Node `^20.19` ou `>=22.12`, onde
|
|
205
|
+
`require(esm)` dispensa flag.
|
|
206
|
+
|
|
207
|
+
Em `dist/` também é publicada uma build CommonJS com extensão `.cjs`, mas o mapa
|
|
208
|
+
`exports` não aponta para ela, então nenhuma resolução chega lá por acidente. Ela
|
|
209
|
+
existe para os casos extremos — Node antigo, ou Jest sem flag — e só é alcançada
|
|
210
|
+
por um caminho explícito.
|
|
211
|
+
|
|
212
|
+
**Em qualquer um dos casos o Jest precisa de uma linha de configuração** — veja o
|
|
213
|
+
item 5 em [Pegadinhas](#pegadinhas).
|
|
214
|
+
|
|
200
215
|
## Uso com agentes de codificação de IA
|
|
201
216
|
|
|
202
217
|
O `state-in-url` inclui arquivos de habilidades (skills) para o [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview), para que os agentes de IA (Claude Code, Cursor, Copilot, Codex, etc.) carreguem os padrões corretos e evitem erros comuns ao usar a biblioteca. Após instalar o `state-in-url`, execute uma vez no seu projeto:
|
|
@@ -982,6 +997,41 @@ export const useUserState = () => {
|
|
|
982
997
|
2. Os servidores da Vercel limitam o tamanho dos cabeçalhos (string de consulta e outras coisas) a **14KB**, então mantenha o estado da sua URL abaixo de ~5000 palavras. <https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
983
998
|
3. Testado com `next.js` 14/15/16 com app router; sem planos de suportar pages.
|
|
984
999
|
|
|
1000
|
+
4. **Vitest + react-router 7**: se um teste que renderiza um componente dentro de `<BrowserRouter>` lança `useNavigate() may be used only in the context of a <Router> component` com o provider bem ali, atualize para `react-router@8` ou inclua este pacote inline:
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
// vitest.config.ts
|
|
1004
|
+
test: { server: { deps: { inline: ['state-in-url'] } } }
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
O Vitest externaliza `node_modules`, então o Node carrega `state-in-url` enquanto o Vite carrega o seu arquivo de teste. No `react-router@7` a condição de exportação `node` aponta `module`/`module-sync` para `index.mjs` e `default` para `index.js`, e os dois resolvedores escolhem coisas diferentes: o react-router é carregado duas vezes, o React context dele existe em duplicata e o provider escreve na cópia que o hook não lê. Incluir inline coloca os dois lados no resolvedor do Vite.
|
|
1008
|
+
|
|
1009
|
+
O `react-router@8` aponta `default` e `module-sync` para o mesmo arquivo, então nenhum resolvedor pode divergir e nada é necessário. O erro nunca cita `state-in-url`, e é por isso que este item está aqui.
|
|
1010
|
+
|
|
1011
|
+
5. **Jest**: este pacote resolve apenas como ESM e o Jest executa os testes como CommonJS por padrão, então um `require()` simples falha com `Must use import to load ES Module`. O Jest não herda o `require(esm)` sem flag do Node — ele usa a própria API síncrona `vm` —, então no **Node 24.9+** passe a flag:
|
|
1012
|
+
|
|
1013
|
+
```json
|
|
1014
|
+
// package.json
|
|
1015
|
+
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" }
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
Se preferir não passar flag, `dist/` também traz uma build CommonJS. Ela está deliberadamente fora do mapa `exports`, então nada resolve para ela por acidente: aponte o Jest para ela explicitamente:
|
|
1019
|
+
|
|
1020
|
+
```js
|
|
1021
|
+
// jest.config.js
|
|
1022
|
+
moduleNameMapper: {
|
|
1023
|
+
'^state-in-url$': '<rootDir>/node_modules/state-in-url/dist/index.cjs',
|
|
1024
|
+
'^state-in-url/utils$': '<rootDir>/node_modules/state-in-url/dist/utils.cjs',
|
|
1025
|
+
'^state-in-url/(.*)$': '<rootDir>/node_modules/state-in-url/dist/$1/index.cjs',
|
|
1026
|
+
},
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
Isso substitui pela build CJS em todo o processo de teste, e é seguro. Não misture as duas em um mesmo processo: este pacote guarda o armazenamento de estado compartilhado no escopo do módulo, então duas cópias significam dois armazenamentos e o `useSharedState` para de compartilhar sem avisar.
|
|
1030
|
+
|
|
1031
|
+
Mais uma diferença: `jest.mock()` não se aplica a módulos ES. Use `jest.unstable_mockModule()` se você fizer mock deste pacote.
|
|
1032
|
+
|
|
1033
|
+
Vitest, Next.js, Vite, Astro e Remix não precisam de nada dessa configuração do Jest. O único passo adicional do Vitest é o `server.deps.inline` acima, e apenas com `react-router@7`.
|
|
1034
|
+
|
|
985
1035
|
## Outros
|
|
986
1036
|
|
|
987
1037
|
### Contribuir e/ou executar localmente
|
package/README.ru.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- i18n:start -->
|
|
2
2
|
[English](./README.md) · [简体中文](./README.zh-CN.md) · [日本語](./README.ja.md) · [한국어](./README.ko.md) · Русский · [Español](./README.es.md) · [Português (BR)](./README.pt-BR.md) · [Français](./README.fr.md) · [Tiếng Việt](./README.vi.md)
|
|
3
|
-
<!-- i18n:meta locale=ru source=README.md source-blob=
|
|
3
|
+
<!-- i18n:meta locale=ru source=README.md source-blob=8b11ee8f8c8b83c207a940455766e24376508130 status=translated -->
|
|
4
4
|
<!-- i18n:end -->
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
@@ -138,6 +138,7 @@ nuqs — достойная библиотека: берите её, если х
|
|
|
138
138
|
- [Установка](#установка)
|
|
139
139
|
- [1. Установка пакета](#1-установка-пакета)
|
|
140
140
|
- [2. Правка tsconfig.json](#2-правка-tsconfigjson)
|
|
141
|
+
- [3. Примечание: этот пакет разрешается только как ESM](#3-примечание-этот-пакет-разрешается-только-как-esm)
|
|
141
142
|
- [Использование с AI-агентами для кодинга](#использование-с-ai-агентами-для-кодинга)
|
|
142
143
|
- [useUrlState](#useurlstate)
|
|
143
144
|
- [Hook useUrlState для Next.js](#hook-useurlstate-для-nextjs)
|
|
@@ -197,6 +198,20 @@ pnpm add state-in-url
|
|
|
197
198
|
В `tsconfig.json` в `compilerOptions` задайте `"moduleResolution": "Bundler"`, либо `"moduleResolution": "Node16"`, либо `"moduleResolution": "NodeNext"`.
|
|
198
199
|
Возможно, понадобится задать `"module": "ES2022"` или `"module": "ESNext"`
|
|
199
200
|
|
|
201
|
+
### 3. Примечание: этот пакет разрешается только как ESM
|
|
202
|
+
|
|
203
|
+
Next.js, Vite, Astro и Remix собирают его без какой-либо настройки, а `require()`
|
|
204
|
+
из обычного Node работает на Node `^20.19` или `>=22.12`, где `require(esm)`
|
|
205
|
+
доступен без флага.
|
|
206
|
+
|
|
207
|
+
В `dist/` также поставляется сборка CommonJS с расширением `.cjs`, но карта
|
|
208
|
+
`exports` на неё не указывает, поэтому разрешение не попадёт на неё случайно.
|
|
209
|
+
Она существует для пограничных случаев — старый Node или Jest без флага — и
|
|
210
|
+
обратиться к ней можно только по явному пути.
|
|
211
|
+
|
|
212
|
+
**В обоих случаях Jest требует одной строки настройки** — см. пункт 5 в разделе
|
|
213
|
+
[Подводные камни](#подводные-камни).
|
|
214
|
+
|
|
200
215
|
## Использование с AI-агентами для кодинга
|
|
201
216
|
|
|
202
217
|
`state-in-url` поставляется с файлами навыков (skills) для [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview), поэтому AI-агенты (Claude Code, Cursor, Copilot, Codex и т. д.) загружают правильные паттерны и избегают типичных ошибок при работе с библиотекой. После установки `state-in-url` выполните один раз в своём проекте:
|
|
@@ -982,6 +997,41 @@ export const useUserState = () => {
|
|
|
982
997
|
2. Серверы Vercel ограничивают размер заголовков (строка запроса и прочее) **14KB**, поэтому держите состояние в URL в пределах ~5000 слов. <https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
983
998
|
3. Протестировано с `next.js` 14/15/16 с app router; поддержка pages не планируется.
|
|
984
999
|
|
|
1000
|
+
4. **Vitest + react-router 7**: если тест, рендерящий компонент внутри `<BrowserRouter>`, выбрасывает `useNavigate() may be used only in the context of a <Router> component`, хотя provider стоит прямо там, — либо обновитесь до `react-router@8`, либо подключите этот пакет инлайном:
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
// vitest.config.ts
|
|
1004
|
+
test: { server: { deps: { inline: ['state-in-url'] } } }
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
Vitest выносит `node_modules` наружу, поэтому `state-in-url` загружает Node, а ваш тестовый файл — Vite. В `react-router@7` условие экспорта `node` указывает `module`/`module-sync` на `index.mjs`, а `default` — на `index.js`, и два резолвера выбирают разное: react-router загружается дважды, его React context существует в двух экземплярах, и provider пишет в ту копию, которую хук не читает. Инлайн переводит обе стороны на резолвер Vite.
|
|
1008
|
+
|
|
1009
|
+
`react-router@8` указывает `default` и `module-sync` на один и тот же файл, поэтому резолверы не могут разойтись и делать ничего не нужно. В тексте ошибки `state-in-url` не упоминается — поэтому этот пункт здесь.
|
|
1010
|
+
|
|
1011
|
+
5. **Jest**: этот пакет разрешается только как ESM, а Jest по умолчанию выполняет тесты как CommonJS, поэтому обычный `require()` падает с `Must use import to load ES Module`. Jest не наследует от Node `require(esm)`, работающий без флага, — он использует собственный синхронный API `vm`, — поэтому на **Node 24.9+** передайте ему флаг:
|
|
1012
|
+
|
|
1013
|
+
```json
|
|
1014
|
+
// package.json
|
|
1015
|
+
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" }
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
Если флаг передавать не хочется, в `dist/` также лежит сборка CommonJS. Она намеренно отсутствует в карте `exports`, так что случайно на неё ничего не разрешится, — укажите Jest на неё явно:
|
|
1019
|
+
|
|
1020
|
+
```js
|
|
1021
|
+
// jest.config.js
|
|
1022
|
+
moduleNameMapper: {
|
|
1023
|
+
'^state-in-url$': '<rootDir>/node_modules/state-in-url/dist/index.cjs',
|
|
1024
|
+
'^state-in-url/utils$': '<rootDir>/node_modules/state-in-url/dist/utils.cjs',
|
|
1025
|
+
'^state-in-url/(.*)$': '<rootDir>/node_modules/state-in-url/dist/$1/index.cjs',
|
|
1026
|
+
},
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
Это подменяет сборку на CJS для всего тестового процесса, и так делать безопасно. Не смешивайте обе в одном процессе: пакет держит хранилище общего состояния в области модуля, поэтому две копии означают два хранилища, и `useSharedState` тихо перестаёт делиться состоянием.
|
|
1030
|
+
|
|
1031
|
+
Ещё одно отличие: `jest.mock()` не действует на ES-модули. Если вы мокаете этот пакет, используйте `jest.unstable_mockModule()`.
|
|
1032
|
+
|
|
1033
|
+
Vitest, Next.js, Vite, Astro и Remix ничего из этой настройки Jest не требуют. Единственный дополнительный шаг для Vitest — это `server.deps.inline` выше, и только с `react-router@7`.
|
|
1034
|
+
|
|
985
1035
|
## Прочее
|
|
986
1036
|
|
|
987
1037
|
### Участие и/или локальный запуск
|