@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 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';
@@ -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": "41.0.0",
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.8.0",
30
- "@asteby/metacore-ui": "^2.21.0",
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.8.0",
54
- "@asteby/metacore-ui": "2.21.0",
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
+