@asteby/metacore-runtime-react 41.0.0 → 42.0.0
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/CHANGELOG.md +17 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/use-persisted-query.d.ts +53 -0
- package/dist/use-persisted-query.d.ts.map +1 -0
- package/dist/use-persisted-query.js +92 -0
- package/package.json +5 -5
- package/src/__tests__/use-persisted-query.test.tsx +132 -0
- package/src/index.ts +8 -0
- package/src/use-persisted-query.ts +152 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 42.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7128a39: Primer pintado estable del shell al recargar.
|
|
8
|
+
|
|
9
|
+
- runtime-react: `usePersistedQuery` y `createPersistedSnapshot`. Una query sembrada desde localStorage (versionada y con scope por org/usuario): el primer render ya tiene el último valor, se revalida una vez por carga en segundo plano y cada valor nuevo (refetch o `setQueryData`) se vuelve a guardar.
|
|
10
|
+
- ui: `resolveIconName` guarda los datos de cada glifo Lucide cargado y en la siguiente carga lo dibuja sin Suspense, sin pasar por el ícono de reserva. Los nombres con dígito (`Undo2`) resuelven a su glifo (`undo-2`). Las carpetas del sidebar que el usuario dejó abiertas siguen abiertas al recargar.
|
|
11
|
+
- sdk: `MetacoreProvider` acepta `cacheScope` y exporta `catalogCacheKey(scope)`, para que el catálogo persistido no se comparta entre orgs o usuarios del mismo origen.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [7128a39]
|
|
16
|
+
- Updated dependencies [9292ef9]
|
|
17
|
+
- @asteby/metacore-ui@2.22.0
|
|
18
|
+
- @asteby/metacore-sdk@3.9.0
|
|
19
|
+
|
|
3
20
|
## 41.0.0
|
|
4
21
|
|
|
5
22
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export { useDynamicFilters, type UseDynamicFiltersOptions, type UseDynamicFilter
|
|
|
17
17
|
export { useDebouncedValue, SEARCH_DEBOUNCE_MS } from './use-debounced-value';
|
|
18
18
|
export { useOptimisticMutation, type UseOptimisticMutationOptions, type UseOptimisticMutationResult, } from './use-optimistic-mutation';
|
|
19
19
|
export { useFlipAnimation, type UseFlipAnimationOptions } from './use-flip-animation';
|
|
20
|
+
export { usePersistedQuery, createPersistedSnapshot, type UsePersistedQueryOptions, type PersistedSnapshot, type PersistedSnapshotOptions, type PersistedEntry, } from './use-persisted-query';
|
|
20
21
|
export { motionDuration, motionEasing, prefersReducedMotion, MOTION_DEFAULTS, type MotionDuration, type MotionEasing, } from './motion';
|
|
21
22
|
export { useResource, useMutation, type ResourceState, type MutationState, } from './use-resource';
|
|
22
23
|
export * from './dynamic-form';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,cAAc,wBAAwB,CAAA;AACtC,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,WAAW,CAAA;AAClB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,UAAU,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,yBAAyB,EACzB,KAAK,cAAc,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AACnG,OAAO,EACH,sBAAsB,EACtB,yBAAyB,EACzB,4BAA4B,EAC5B,mBAAmB,EACnB,iBAAiB,GACpB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACnC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC9B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,oBAAoB,GAC5B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,GAC/B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,gBAAgB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC/B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC7E,OAAO,EACH,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,GACnC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AACrF,OAAO,EACH,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,YAAY,GACpB,MAAM,UAAU,CAAA;AACjB,OAAO,EACH,WAAW,EACX,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,aAAa,GACrB,MAAM,gBAAgB,CAAA;AACvB,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,cAAc,EACd,KAAK,mBAAmB,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,GACxB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,KAAK,uBAAuB,EAC5B,KAAK,eAAe,GACvB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,mBAAmB,EACnB,MAAM,EACN,oBAAoB,EACpB,OAAO,EACP,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,KAAK,EACV,KAAK,wBAAwB,GAChC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,GACzB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACzF,OAAO,EACH,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,OAAO,EACZ,KAAK,SAAS,GACjB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,oBAAoB,EACpB,KAAK,yBAAyB,GACjC,MAAM,0BAA0B,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,GAC9B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,8BAA8B,GACtC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,WAAW,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC9B,MAAM,yBAAyB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EACR,kBAAkB,EAClB,YAAY,IAAI,yBAAyB,EACzC,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,qBAAqB,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AACjF,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AACnE,OAAO,EACH,OAAO,EACP,QAAQ,EACR,cAAc,EACd,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,UAAU,EACV,KAAK,mBAAmB,EACxB,KAAK,SAAS,IAAI,uBAAuB,GAC5C,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC5G,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,YAAY,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GAC3B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACH,2BAA2B,EAC3B,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,EAC7B,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,GAC5B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACH,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,QAAQ,EACR,aAAa,EACb,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,wBAAwB,EACxB,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,SAAS,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,+BAA+B,EAC/B,wBAAwB,EACxB,qBAAqB,EACrB,QAAQ,GACX,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,mBAAmB,GAC3B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACH,qBAAqB,EACrB,KAAK,0BAA0B,GAClC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,gBAAgB,EAChB,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,aAAa,EACb,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC/D,YAAY,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,UAAU,EACV,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,KAAK,iBAAiB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,cAAc,EACd,cAAc,EACd,SAAS,EACT,UAAU,EACV,KAAK,mBAAmB,GAC3B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,UAAU,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,KAAK,eAAe,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,EACZ,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACpE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACnH,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ export { useDynamicFilters, } from './use-dynamic-filters';
|
|
|
22
22
|
export { useDebouncedValue, SEARCH_DEBOUNCE_MS } from './use-debounced-value';
|
|
23
23
|
export { useOptimisticMutation, } from './use-optimistic-mutation';
|
|
24
24
|
export { useFlipAnimation } from './use-flip-animation';
|
|
25
|
+
export { usePersistedQuery, createPersistedSnapshot, } from './use-persisted-query';
|
|
25
26
|
export { motionDuration, motionEasing, prefersReducedMotion, MOTION_DEFAULTS, } from './motion';
|
|
26
27
|
export { useResource, useMutation, } from './use-resource';
|
|
27
28
|
export * from './dynamic-form';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type QueryKey, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
/**
|
|
3
|
+
* A versioned, scoped copy of a value in localStorage. Shell data that decides
|
|
4
|
+
* the first paint (navigation, the org's menu layout, installed presets,
|
|
5
|
+
* permissions) is read from here synchronously, so a reload paints the last
|
|
6
|
+
* known state instead of a default that reorders when the network answers.
|
|
7
|
+
*
|
|
8
|
+
* The entry lives under `<key>:v<version>:<scope>`. Bump `version` when the
|
|
9
|
+
* stored shape changes; old entries are simply never read again. `scope` keeps
|
|
10
|
+
* one org or user from seeing another's copy on a shared browser.
|
|
11
|
+
*/
|
|
12
|
+
export interface PersistedSnapshotOptions {
|
|
13
|
+
key: string;
|
|
14
|
+
version: number;
|
|
15
|
+
/** Entries older than this are ignored (default: 30 days). */
|
|
16
|
+
maxAgeMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface PersistedEntry<T> {
|
|
19
|
+
data: T;
|
|
20
|
+
/** When the data was fetched (ms epoch). */
|
|
21
|
+
ts: number;
|
|
22
|
+
}
|
|
23
|
+
export interface PersistedSnapshot<T> {
|
|
24
|
+
read(scope: string): PersistedEntry<T> | undefined;
|
|
25
|
+
write(scope: string, data: T, meta?: {
|
|
26
|
+
ts?: number;
|
|
27
|
+
}): void;
|
|
28
|
+
clear(scope: string): void;
|
|
29
|
+
}
|
|
30
|
+
export declare function createPersistedSnapshot<T>({ key, version, maxAgeMs, }: PersistedSnapshotOptions): PersistedSnapshot<T>;
|
|
31
|
+
export type UsePersistedQueryOptions<TQueryFnData, TData, TQueryKey extends QueryKey> = UseQueryOptions<TQueryFnData, Error, TData, TQueryKey> & {
|
|
32
|
+
persist: {
|
|
33
|
+
snapshot: PersistedSnapshot<TQueryFnData>;
|
|
34
|
+
/**
|
|
35
|
+
* Org/user the data belongs to. Without a scope nothing is read or
|
|
36
|
+
* written (e.g. before sign-in).
|
|
37
|
+
*/
|
|
38
|
+
scope: string | null | undefined;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* `useQuery` seeded from a {@link PersistedSnapshot}: the first render already
|
|
43
|
+
* has the last fetched value (stale-while-revalidate), and every later value —
|
|
44
|
+
* a refetch, or a `setQueryData` from a mutation — is written back. The seed is
|
|
45
|
+
* stale from the start: every page load revalidates it once in the background,
|
|
46
|
+
* so a change made elsewhere (a plantilla applied, an addon installed,
|
|
47
|
+
* permissions edited) shows on the next load even inside `staleTime`.
|
|
48
|
+
*
|
|
49
|
+
* Persist the raw server payload and derive UI shapes with `select`; the
|
|
50
|
+
* snapshot must be JSON.
|
|
51
|
+
*/
|
|
52
|
+
export declare function usePersistedQuery<TQueryFnData, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UsePersistedQueryOptions<TQueryFnData, TData, TQueryKey>): UseQueryResult<TData, Error>;
|
|
53
|
+
//# sourceMappingURL=use-persisted-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-persisted-query.d.ts","sourceRoot":"","sources":["../src/use-persisted-query.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAA;AAE9B;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAA;IACP,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;IAClD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC3D,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAYD,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,EACzC,GAAG,EACH,OAAO,EACP,QAA6B,GAC9B,EAAE,wBAAwB,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAgCjD;AAED,MAAM,MAAM,wBAAwB,CAAC,YAAY,EAAE,KAAK,EAAE,SAAS,SAAS,QAAQ,IAAI,eAAe,CACrG,YAAY,EACZ,KAAK,EACL,KAAK,EACL,SAAS,CACV,GAAG;IACF,OAAO,EAAE;QACP,QAAQ,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAA;QACzC;;;WAGG;QACH,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;KACjC,CAAA;CACF,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EACZ,KAAK,GAAG,YAAY,EACpB,SAAS,SAAS,QAAQ,GAAG,QAAQ,EAErC,OAAO,EAAE,wBAAwB,CAAC,YAAY,EAAE,KAAK,EAAE,SAAS,CAAC,GAChE,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CA+B9B"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useEffect, useMemo } from 'react';
|
|
2
|
+
import { useQuery, useQueryClient, } from '@tanstack/react-query';
|
|
3
|
+
const DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;
|
|
4
|
+
function storage() {
|
|
5
|
+
try {
|
|
6
|
+
return typeof localStorage === 'undefined' ? null : localStorage;
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function createPersistedSnapshot({ key, version, maxAgeMs = DEFAULT_MAX_AGE_MS, }) {
|
|
13
|
+
const slot = (scope) => `${key}:v${version}:${scope}`;
|
|
14
|
+
return {
|
|
15
|
+
read(scope) {
|
|
16
|
+
const s = storage();
|
|
17
|
+
if (!s)
|
|
18
|
+
return undefined;
|
|
19
|
+
try {
|
|
20
|
+
const raw = s.getItem(slot(scope));
|
|
21
|
+
if (!raw)
|
|
22
|
+
return undefined;
|
|
23
|
+
const parsed = JSON.parse(raw);
|
|
24
|
+
if (typeof parsed?.ts !== 'number' || !('data' in parsed))
|
|
25
|
+
return undefined;
|
|
26
|
+
if (Date.now() - parsed.ts > maxAgeMs)
|
|
27
|
+
return undefined;
|
|
28
|
+
return { data: parsed.data, ts: parsed.ts };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
write(scope, data, { ts = Date.now() } = {}) {
|
|
35
|
+
try {
|
|
36
|
+
storage()?.setItem(slot(scope), JSON.stringify({ data, ts }));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// quota / private mode: the snapshot is an optimization, never fatal
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
clear(scope) {
|
|
43
|
+
try {
|
|
44
|
+
storage()?.removeItem(slot(scope));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
/* ignore */
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* `useQuery` seeded from a {@link PersistedSnapshot}: the first render already
|
|
54
|
+
* has the last fetched value (stale-while-revalidate), and every later value —
|
|
55
|
+
* a refetch, or a `setQueryData` from a mutation — is written back. The seed is
|
|
56
|
+
* stale from the start: every page load revalidates it once in the background,
|
|
57
|
+
* so a change made elsewhere (a plantilla applied, an addon installed,
|
|
58
|
+
* permissions edited) shows on the next load even inside `staleTime`.
|
|
59
|
+
*
|
|
60
|
+
* Persist the raw server payload and derive UI shapes with `select`; the
|
|
61
|
+
* snapshot must be JSON.
|
|
62
|
+
*/
|
|
63
|
+
export function usePersistedQuery(options) {
|
|
64
|
+
const { persist, ...queryOptions } = options;
|
|
65
|
+
const { snapshot, scope } = persist;
|
|
66
|
+
const seed = useMemo(() => (scope ? snapshot.read(scope) : undefined), [snapshot, scope]);
|
|
67
|
+
const query = useQuery({
|
|
68
|
+
...queryOptions,
|
|
69
|
+
...(seed && queryOptions.initialData === undefined
|
|
70
|
+
? { initialData: seed.data, initialDataUpdatedAt: 0 }
|
|
71
|
+
: {}),
|
|
72
|
+
});
|
|
73
|
+
const queryClient = useQueryClient();
|
|
74
|
+
const { dataUpdatedAt, status, isPlaceholderData } = query;
|
|
75
|
+
const queryKey = queryOptions.queryKey;
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (!scope || status !== 'success' || isPlaceholderData)
|
|
78
|
+
return;
|
|
79
|
+
// Still the seed: nothing new to store.
|
|
80
|
+
if (dataUpdatedAt === 0)
|
|
81
|
+
return;
|
|
82
|
+
// `query.data` is the selected shape; persist the raw cache value.
|
|
83
|
+
const raw = queryClient.getQueryData(queryKey);
|
|
84
|
+
if (raw === undefined)
|
|
85
|
+
return;
|
|
86
|
+
snapshot.write(scope, raw, { ts: dataUpdatedAt });
|
|
87
|
+
// queryKey is compared by react-query's hash, not identity: a new array
|
|
88
|
+
// each render must not rewrite the snapshot.
|
|
89
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
90
|
+
}, [queryClient, scope, snapshot, seed, status, isPlaceholderData, dataUpdatedAt]);
|
|
91
|
+
return query;
|
|
92
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "42.0.0",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"zod": "^4.3.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@asteby/metacore-sdk": "^3.
|
|
30
|
-
"@asteby/metacore-ui": "^2.
|
|
29
|
+
"@asteby/metacore-sdk": "^3.9.0",
|
|
30
|
+
"@asteby/metacore-ui": "^2.22.0",
|
|
31
31
|
"@tanstack/react-query": ">=5",
|
|
32
32
|
"@tanstack/react-router": ">=1.100",
|
|
33
33
|
"@tanstack/react-table": ">=8",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@asteby/metacore-sdk": "3.
|
|
54
|
-
"@asteby/metacore-ui": "2.
|
|
53
|
+
"@asteby/metacore-sdk": "3.9.0",
|
|
54
|
+
"@asteby/metacore-ui": "2.22.0",
|
|
55
55
|
"@tanstack/react-query": "^5.95.0",
|
|
56
56
|
"@tanstack/react-router": "^1.168.0",
|
|
57
57
|
"@tanstack/react-table": "^8.20.0",
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { describe, expect, it, beforeEach, vi } from 'vitest'
|
|
3
|
+
import { act, renderHook, waitFor } from '@testing-library/react'
|
|
4
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
5
|
+
import type { ReactNode } from 'react'
|
|
6
|
+
import { createPersistedSnapshot, usePersistedQuery } from '../use-persisted-query'
|
|
7
|
+
|
|
8
|
+
type Layout = { order: string[] }
|
|
9
|
+
|
|
10
|
+
function deferred<T>() {
|
|
11
|
+
let resolve!: (v: T) => void
|
|
12
|
+
const promise = new Promise<T>((res) => {
|
|
13
|
+
resolve = res
|
|
14
|
+
})
|
|
15
|
+
return { promise, resolve }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function wrapperFor(qc: QueryClient) {
|
|
19
|
+
return ({ children }: { children: ReactNode }) => (
|
|
20
|
+
<QueryClientProvider client={qc}>{children}</QueryClientProvider>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const newClient = () => new QueryClient({ defaultOptions: { queries: { retry: false } } })
|
|
25
|
+
|
|
26
|
+
describe('createPersistedSnapshot', () => {
|
|
27
|
+
beforeEach(() => localStorage.clear())
|
|
28
|
+
|
|
29
|
+
it('round-trips per scope and version', () => {
|
|
30
|
+
const snap = createPersistedSnapshot<Layout>({ key: 'test:layout', version: 1 })
|
|
31
|
+
const ts = Date.now() - 1000
|
|
32
|
+
snap.write('org-a', { order: ['a'] }, { ts })
|
|
33
|
+
expect(snap.read('org-a')).toEqual({ data: { order: ['a'] }, ts })
|
|
34
|
+
expect(snap.read('org-b')).toBeUndefined()
|
|
35
|
+
const v2 = createPersistedSnapshot<Layout>({ key: 'test:layout', version: 2 })
|
|
36
|
+
expect(v2.read('org-a')).toBeUndefined()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('ignores expired and corrupt entries', () => {
|
|
40
|
+
const snap = createPersistedSnapshot<Layout>({ key: 'test:layout', version: 1, maxAgeMs: 1000 })
|
|
41
|
+
snap.write('org-a', { order: ['a'] }, { ts: Date.now() - 5000 })
|
|
42
|
+
expect(snap.read('org-a')).toBeUndefined()
|
|
43
|
+
localStorage.setItem('test:layout:v1:org-b', '{not json')
|
|
44
|
+
expect(snap.read('org-b')).toBeUndefined()
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe('usePersistedQuery', () => {
|
|
49
|
+
beforeEach(() => localStorage.clear())
|
|
50
|
+
|
|
51
|
+
it('paints the persisted value on the first render, then revalidates and persists', async () => {
|
|
52
|
+
const snap = createPersistedSnapshot<Layout>({ key: 'test:layout', version: 1 })
|
|
53
|
+
snap.write('org-a', { order: ['cached'] }, { ts: Date.now() - 60_000 })
|
|
54
|
+
const net = deferred<Layout>()
|
|
55
|
+
const renders: (Layout | undefined)[] = []
|
|
56
|
+
const { result } = renderHook(
|
|
57
|
+
() => {
|
|
58
|
+
const q = usePersistedQuery({
|
|
59
|
+
queryKey: ['layout'],
|
|
60
|
+
queryFn: () => net.promise,
|
|
61
|
+
staleTime: 1000,
|
|
62
|
+
persist: { snapshot: snap, scope: 'org-a' },
|
|
63
|
+
})
|
|
64
|
+
renders.push(q.data)
|
|
65
|
+
return q
|
|
66
|
+
},
|
|
67
|
+
{ wrapper: wrapperFor(newClient()) },
|
|
68
|
+
)
|
|
69
|
+
expect(renders[0]).toEqual({ order: ['cached'] })
|
|
70
|
+
await act(async () => net.resolve({ order: ['fresh'] }))
|
|
71
|
+
await waitFor(() => expect(result.current.data).toEqual({ order: ['fresh'] }))
|
|
72
|
+
expect(snap.read('org-a')?.data).toEqual({ order: ['fresh'] })
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('revalidates a seed once per load even when it is younger than staleTime', async () => {
|
|
76
|
+
const snap = createPersistedSnapshot<Layout>({ key: 'test:layout', version: 1 })
|
|
77
|
+
snap.write('org-a', { order: ['cached'] }, { ts: Date.now() - 1000 })
|
|
78
|
+
const queryFn = vi.fn(async () => ({ order: ['changed-elsewhere'] }))
|
|
79
|
+
const { result } = renderHook(
|
|
80
|
+
() =>
|
|
81
|
+
usePersistedQuery({
|
|
82
|
+
queryKey: ['layout'],
|
|
83
|
+
queryFn,
|
|
84
|
+
staleTime: 60_000,
|
|
85
|
+
persist: { snapshot: snap, scope: 'org-a' },
|
|
86
|
+
}),
|
|
87
|
+
{ wrapper: wrapperFor(newClient()) },
|
|
88
|
+
)
|
|
89
|
+
expect(result.current.data).toEqual({ order: ['cached'] })
|
|
90
|
+
await waitFor(() => expect(result.current.data).toEqual({ order: ['changed-elsewhere'] }))
|
|
91
|
+
expect(queryFn).toHaveBeenCalledTimes(1)
|
|
92
|
+
expect(snap.read('org-a')?.data).toEqual({ order: ['changed-elsewhere'] })
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('persists the raw payload, not the selected shape, and setQueryData writes back', async () => {
|
|
96
|
+
const snap = createPersistedSnapshot<Layout>({ key: 'test:layout', version: 1 })
|
|
97
|
+
const qc = newClient()
|
|
98
|
+
const { result } = renderHook(
|
|
99
|
+
() =>
|
|
100
|
+
usePersistedQuery({
|
|
101
|
+
queryKey: ['layout'],
|
|
102
|
+
queryFn: async () => ({ order: ['x', 'y'] }),
|
|
103
|
+
select: (d: Layout) => d.order.length,
|
|
104
|
+
persist: { snapshot: snap, scope: 'org-a' },
|
|
105
|
+
}),
|
|
106
|
+
{ wrapper: wrapperFor(qc) },
|
|
107
|
+
)
|
|
108
|
+
await waitFor(() => expect(result.current.data).toBe(2))
|
|
109
|
+
await waitFor(() => expect(snap.read('org-a')?.data).toEqual({ order: ['x', 'y'] }))
|
|
110
|
+
act(() => {
|
|
111
|
+
qc.setQueryData<Layout>(['layout'], { order: ['z'] })
|
|
112
|
+
})
|
|
113
|
+
await waitFor(() => expect(snap.read('org-a')?.data).toEqual({ order: ['z'] }))
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('does not read or write without a scope', async () => {
|
|
117
|
+
const snap = createPersistedSnapshot<Layout>({ key: 'test:layout', version: 1 })
|
|
118
|
+
snap.write('org-a', { order: ['cached'] })
|
|
119
|
+
const { result } = renderHook(
|
|
120
|
+
() =>
|
|
121
|
+
usePersistedQuery({
|
|
122
|
+
queryKey: ['layout'],
|
|
123
|
+
queryFn: async () => ({ order: ['fresh'] }),
|
|
124
|
+
persist: { snapshot: snap, scope: null },
|
|
125
|
+
}),
|
|
126
|
+
{ wrapper: wrapperFor(newClient()) },
|
|
127
|
+
)
|
|
128
|
+
expect(result.current.data).toBeUndefined()
|
|
129
|
+
await waitFor(() => expect(result.current.data).toEqual({ order: ['fresh'] }))
|
|
130
|
+
expect(snap.read('org-a')?.data).toEqual({ order: ['cached'] })
|
|
131
|
+
})
|
|
132
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -135,6 +135,14 @@ export {
|
|
|
135
135
|
type UseOptimisticMutationResult,
|
|
136
136
|
} from './use-optimistic-mutation'
|
|
137
137
|
export { useFlipAnimation, type UseFlipAnimationOptions } from './use-flip-animation'
|
|
138
|
+
export {
|
|
139
|
+
usePersistedQuery,
|
|
140
|
+
createPersistedSnapshot,
|
|
141
|
+
type UsePersistedQueryOptions,
|
|
142
|
+
type PersistedSnapshot,
|
|
143
|
+
type PersistedSnapshotOptions,
|
|
144
|
+
type PersistedEntry,
|
|
145
|
+
} from './use-persisted-query'
|
|
138
146
|
export {
|
|
139
147
|
motionDuration,
|
|
140
148
|
motionEasing,
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { useEffect, useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
useQuery,
|
|
4
|
+
useQueryClient,
|
|
5
|
+
type QueryKey,
|
|
6
|
+
type UseQueryOptions,
|
|
7
|
+
type UseQueryResult,
|
|
8
|
+
} from '@tanstack/react-query'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A versioned, scoped copy of a value in localStorage. Shell data that decides
|
|
12
|
+
* the first paint (navigation, the org's menu layout, installed presets,
|
|
13
|
+
* permissions) is read from here synchronously, so a reload paints the last
|
|
14
|
+
* known state instead of a default that reorders when the network answers.
|
|
15
|
+
*
|
|
16
|
+
* The entry lives under `<key>:v<version>:<scope>`. Bump `version` when the
|
|
17
|
+
* stored shape changes; old entries are simply never read again. `scope` keeps
|
|
18
|
+
* one org or user from seeing another's copy on a shared browser.
|
|
19
|
+
*/
|
|
20
|
+
export interface PersistedSnapshotOptions {
|
|
21
|
+
key: string
|
|
22
|
+
version: number
|
|
23
|
+
/** Entries older than this are ignored (default: 30 days). */
|
|
24
|
+
maxAgeMs?: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface PersistedEntry<T> {
|
|
28
|
+
data: T
|
|
29
|
+
/** When the data was fetched (ms epoch). */
|
|
30
|
+
ts: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface PersistedSnapshot<T> {
|
|
34
|
+
read(scope: string): PersistedEntry<T> | undefined
|
|
35
|
+
write(scope: string, data: T, meta?: { ts?: number }): void
|
|
36
|
+
clear(scope: string): void
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000
|
|
40
|
+
|
|
41
|
+
function storage(): Storage | null {
|
|
42
|
+
try {
|
|
43
|
+
return typeof localStorage === 'undefined' ? null : localStorage
|
|
44
|
+
} catch {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function createPersistedSnapshot<T>({
|
|
50
|
+
key,
|
|
51
|
+
version,
|
|
52
|
+
maxAgeMs = DEFAULT_MAX_AGE_MS,
|
|
53
|
+
}: PersistedSnapshotOptions): PersistedSnapshot<T> {
|
|
54
|
+
const slot = (scope: string) => `${key}:v${version}:${scope}`
|
|
55
|
+
return {
|
|
56
|
+
read(scope) {
|
|
57
|
+
const s = storage()
|
|
58
|
+
if (!s) return undefined
|
|
59
|
+
try {
|
|
60
|
+
const raw = s.getItem(slot(scope))
|
|
61
|
+
if (!raw) return undefined
|
|
62
|
+
const parsed = JSON.parse(raw) as Partial<PersistedEntry<T>>
|
|
63
|
+
if (typeof parsed?.ts !== 'number' || !('data' in parsed)) return undefined
|
|
64
|
+
if (Date.now() - parsed.ts > maxAgeMs) return undefined
|
|
65
|
+
return { data: parsed.data as T, ts: parsed.ts }
|
|
66
|
+
} catch {
|
|
67
|
+
return undefined
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
write(scope, data, { ts = Date.now() } = {}) {
|
|
71
|
+
try {
|
|
72
|
+
storage()?.setItem(slot(scope), JSON.stringify({ data, ts }))
|
|
73
|
+
} catch {
|
|
74
|
+
// quota / private mode: the snapshot is an optimization, never fatal
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
clear(scope) {
|
|
78
|
+
try {
|
|
79
|
+
storage()?.removeItem(slot(scope))
|
|
80
|
+
} catch {
|
|
81
|
+
/* ignore */
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type UsePersistedQueryOptions<TQueryFnData, TData, TQueryKey extends QueryKey> = UseQueryOptions<
|
|
88
|
+
TQueryFnData,
|
|
89
|
+
Error,
|
|
90
|
+
TData,
|
|
91
|
+
TQueryKey
|
|
92
|
+
> & {
|
|
93
|
+
persist: {
|
|
94
|
+
snapshot: PersistedSnapshot<TQueryFnData>
|
|
95
|
+
/**
|
|
96
|
+
* Org/user the data belongs to. Without a scope nothing is read or
|
|
97
|
+
* written (e.g. before sign-in).
|
|
98
|
+
*/
|
|
99
|
+
scope: string | null | undefined
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* `useQuery` seeded from a {@link PersistedSnapshot}: the first render already
|
|
105
|
+
* has the last fetched value (stale-while-revalidate), and every later value —
|
|
106
|
+
* a refetch, or a `setQueryData` from a mutation — is written back. The seed is
|
|
107
|
+
* stale from the start: every page load revalidates it once in the background,
|
|
108
|
+
* so a change made elsewhere (a plantilla applied, an addon installed,
|
|
109
|
+
* permissions edited) shows on the next load even inside `staleTime`.
|
|
110
|
+
*
|
|
111
|
+
* Persist the raw server payload and derive UI shapes with `select`; the
|
|
112
|
+
* snapshot must be JSON.
|
|
113
|
+
*/
|
|
114
|
+
export function usePersistedQuery<
|
|
115
|
+
TQueryFnData,
|
|
116
|
+
TData = TQueryFnData,
|
|
117
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
118
|
+
>(
|
|
119
|
+
options: UsePersistedQueryOptions<TQueryFnData, TData, TQueryKey>,
|
|
120
|
+
): UseQueryResult<TData, Error> {
|
|
121
|
+
const { persist, ...queryOptions } = options
|
|
122
|
+
const { snapshot, scope } = persist
|
|
123
|
+
const seed = useMemo(
|
|
124
|
+
() => (scope ? snapshot.read(scope) : undefined),
|
|
125
|
+
[snapshot, scope],
|
|
126
|
+
)
|
|
127
|
+
const query = useQuery<TQueryFnData, Error, TData, TQueryKey>({
|
|
128
|
+
...queryOptions,
|
|
129
|
+
...(seed && queryOptions.initialData === undefined
|
|
130
|
+
? { initialData: seed.data, initialDataUpdatedAt: 0 }
|
|
131
|
+
: {}),
|
|
132
|
+
} as UseQueryOptions<TQueryFnData, Error, TData, TQueryKey>)
|
|
133
|
+
|
|
134
|
+
const queryClient = useQueryClient()
|
|
135
|
+
const { dataUpdatedAt, status, isPlaceholderData } = query
|
|
136
|
+
const queryKey = queryOptions.queryKey
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
if (!scope || status !== 'success' || isPlaceholderData) return
|
|
139
|
+
// Still the seed: nothing new to store.
|
|
140
|
+
if (dataUpdatedAt === 0) return
|
|
141
|
+
// `query.data` is the selected shape; persist the raw cache value.
|
|
142
|
+
const raw = queryClient.getQueryData<TQueryFnData>(queryKey)
|
|
143
|
+
if (raw === undefined) return
|
|
144
|
+
snapshot.write(scope, raw, { ts: dataUpdatedAt })
|
|
145
|
+
// queryKey is compared by react-query's hash, not identity: a new array
|
|
146
|
+
// each render must not rewrite the snapshot.
|
|
147
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
148
|
+
}, [queryClient, scope, snapshot, seed, status, isPlaceholderData, dataUpdatedAt])
|
|
149
|
+
|
|
150
|
+
return query
|
|
151
|
+
}
|
|
152
|
+
|