@asteby/metacore-runtime-react 39.2.2 → 39.2.3

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,11 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 39.2.3
4
+
5
+ ### Patch Changes
6
+
7
+ - caf2015: Always revalidate `/metadata/table` on DynamicCRUDPage cache hit and replace the catalog on `prefetchAll`, so addon toolbar actions cannot stick after HotRegister while zustand localStorage still holds the pre-upgrade snapshot.
8
+
3
9
  ## 39.2.2
4
10
 
5
11
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-crud-page.d.ts","sourceRoot":"","sources":["../src/dynamic-crud-page.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAKN,MAAM,OAAO,CAAA;AAad,MAAM,WAAW,sBAAsB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;mDAC+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AASD,MAAM,WAAW,sBAAsB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,oBAAoB;IACjC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,sBAAsB,CAAA;IAC7B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,8DAA8D;IAC9D,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC/B,sDAAsD;IACtD,OAAO,CAAC,EAAE,sBAAsB,CAAA;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,qBAmM1D"}
1
+ {"version":3,"file":"dynamic-crud-page.d.ts","sourceRoot":"","sources":["../src/dynamic-crud-page.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAKN,MAAM,OAAO,CAAA;AAad,MAAM,WAAW,sBAAsB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;mDAC+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AASD,MAAM,WAAW,sBAAsB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,oBAAoB;IACjC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,sBAAsB,CAAA;IAC7B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,8DAA8D;IAC9D,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC/B,sDAAsD;IACtD,OAAO,CAAC,EAAE,sBAAsB,CAAA;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,qBAuM1D"}
@@ -58,9 +58,13 @@ export function DynamicCRUDPage(props) {
58
58
  const [openExport, setOpenExport] = useState(false);
59
59
  const [openImport, setOpenImport] = useState(false);
60
60
  useEffect(() => {
61
+ // Stale-while-revalidate: paint from the persisted cache immediately,
62
+ // then ALWAYS fetch /metadata/table/:model. Returning early on a cache
63
+ // hit left hosts stranded on pre-upgrade actions (missing toolbar
64
+ // buttons after an addon HotRegister) because hard refresh does not
65
+ // clear zustand localStorage.
61
66
  if (cachedMeta) {
62
67
  setMetadata(cachedMeta);
63
- return;
64
68
  }
65
69
  let cancelled = false;
66
70
  api
@@ -72,7 +76,7 @@ export function DynamicCRUDPage(props) {
72
76
  setMetadata(meta ?? null);
73
77
  })
74
78
  .catch(() => {
75
- if (!cancelled)
79
+ if (!cancelled && !cachedMeta)
76
80
  setMetadata(null);
77
81
  });
78
82
  return () => {
@@ -1 +1 @@
1
- {"version":3,"file":"metadata-cache.d.ts","sourceRoot":"","sources":["../src/metadata-cache.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAC9B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;CAC7D;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;AAE7E;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQlF;AAED,UAAU,kBAAkB;IACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACzC,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAA;IACvD,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAA;IAC5D,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;IAC3D,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;IAChE,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IACrC,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IAC1C,WAAW,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD;;;;;;;;;;;;;OAaG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAA;IACxE;;;OAGG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;EAwH5B,CAAA"}
1
+ {"version":3,"file":"metadata-cache.d.ts","sourceRoot":"","sources":["../src/metadata-cache.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAC9B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;CAC7D;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;AAE7E;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQlF;AAED,UAAU,kBAAkB;IACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACzC,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAA;IACvD,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAA;IAC5D,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;IAC3D,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;IAChE,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IACrC,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IAC1C,WAAW,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD;;;;;;;;;;;;;OAaG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAA;IACxE;;;OAGG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;EA4H5B,CAAA"}
@@ -3,6 +3,16 @@
3
3
  // metadata-cache store so the runtime-react package no longer depends on
4
4
  // a host-specific alias.
5
5
  //
6
+ // Contract (stale-while-revalidate):
7
+ // - Cache entries are a FIRST PAINT hint only.
8
+ // - Every consumer (DynamicTable, DynamicCRUDPage, ModelActionToolbar hosts)
9
+ // MUST still GET /metadata/table/:model and apply the live payload —
10
+ // including `actions[]`. Skipping the live fetch on a cache hit is how
11
+ // cross-addon toolbar actions disappear after an addon upgrade while
12
+ // localStorage still holds the pre-upgrade catalog.
13
+ // - `prefetchAll` replaces the catalog from `/metadata/all` and advances
14
+ // `metadataVersion`; a version change wipes the prior cache.
15
+ //
6
16
  // The prefetchAll() method needs an `api` client (axios-like); we keep that
7
17
  // as an injectable parameter so the store stays host-agnostic. If a caller
8
18
  // never invokes prefetchAll, the `api` dep is not required.
@@ -90,9 +100,12 @@ export const useMetadataCache = create()(persist((set, get) => ({
90
100
  const { tables, modals, version } = res.data.data;
91
101
  const serverVersion = version || '';
92
102
  const localVersion = get().metadataVersion;
93
- const versionChanged = serverVersion !== localVersion && localVersion !== '';
94
- const newCache = versionChanged ? {} : { ...get().cache };
95
- const newModalCache = versionChanged ? {} : { ...get().modalCache };
103
+ // Always rebuild from the server catalog. Merging into a
104
+ // persisted cache left hosts with pre-upgrade actions /
105
+ // columns after an addon HotRegister while the tab (or
106
+ // localStorage) stayed open.
107
+ const newCache = {};
108
+ const newModalCache = {};
96
109
  if (tables) {
97
110
  for (const [key, meta] of Object.entries(tables)) {
98
111
  newCache[key] = meta;
@@ -106,7 +119,7 @@ export const useMetadataCache = create()(persist((set, get) => ({
106
119
  set({
107
120
  cache: newCache,
108
121
  modalCache: newModalCache,
109
- metadataVersion: serverVersion,
122
+ metadataVersion: serverVersion || localVersion || String(Date.now()),
110
123
  prefetched: true,
111
124
  });
112
125
  }
@@ -118,7 +131,8 @@ export const useMetadataCache = create()(persist((set, get) => ({
118
131
  }), {
119
132
  name: 'metacore-metadata-cache',
120
133
  // Bump when display hints (e.g. image_stack) must wipe stale cache.
121
- version: 4,
134
+ // v5: always replace catalog on prefetchAll (no merge-with-stale).
135
+ version: 5,
122
136
  migrate: () => ({
123
137
  cache: {},
124
138
  modalCache: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "39.2.2",
3
+ "version": "39.2.3",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -127,9 +127,13 @@ export function DynamicCRUDPage(props: DynamicCRUDPageProps) {
127
127
  const [openImport, setOpenImport] = useState(false)
128
128
 
129
129
  useEffect(() => {
130
+ // Stale-while-revalidate: paint from the persisted cache immediately,
131
+ // then ALWAYS fetch /metadata/table/:model. Returning early on a cache
132
+ // hit left hosts stranded on pre-upgrade actions (missing toolbar
133
+ // buttons after an addon HotRegister) because hard refresh does not
134
+ // clear zustand localStorage.
130
135
  if (cachedMeta) {
131
136
  setMetadata(cachedMeta)
132
- return
133
137
  }
134
138
  let cancelled = false
135
139
  api
@@ -140,7 +144,7 @@ export function DynamicCRUDPage(props: DynamicCRUDPageProps) {
140
144
  setMetadata(meta ?? null)
141
145
  })
142
146
  .catch(() => {
143
- if (!cancelled) setMetadata(null)
147
+ if (!cancelled && !cachedMeta) setMetadata(null)
144
148
  })
145
149
  return () => {
146
150
  cancelled = true
@@ -3,6 +3,16 @@
3
3
  // metadata-cache store so the runtime-react package no longer depends on
4
4
  // a host-specific alias.
5
5
  //
6
+ // Contract (stale-while-revalidate):
7
+ // - Cache entries are a FIRST PAINT hint only.
8
+ // - Every consumer (DynamicTable, DynamicCRUDPage, ModelActionToolbar hosts)
9
+ // MUST still GET /metadata/table/:model and apply the live payload —
10
+ // including `actions[]`. Skipping the live fetch on a cache hit is how
11
+ // cross-addon toolbar actions disappear after an addon upgrade while
12
+ // localStorage still holds the pre-upgrade catalog.
13
+ // - `prefetchAll` replaces the catalog from `/metadata/all` and advances
14
+ // `metadataVersion`; a version change wipes the prior cache.
15
+ //
6
16
  // The prefetchAll() method needs an `api` client (axios-like); we keep that
7
17
  // as an injectable parameter so the store stays host-agnostic. If a caller
8
18
  // never invokes prefetchAll, the `api` dep is not required.
@@ -148,10 +158,13 @@ export const useMetadataCache = create<MetadataCacheState>()(
148
158
 
149
159
  const serverVersion = version || ''
150
160
  const localVersion = get().metadataVersion
151
- const versionChanged = serverVersion !== localVersion && localVersion !== ''
152
161
 
153
- const newCache: Record<string, TableMetadata> = versionChanged ? {} : { ...get().cache }
154
- const newModalCache: Record<string, TableMetadata> = versionChanged ? {} : { ...get().modalCache }
162
+ // Always rebuild from the server catalog. Merging into a
163
+ // persisted cache left hosts with pre-upgrade actions /
164
+ // columns after an addon HotRegister while the tab (or
165
+ // localStorage) stayed open.
166
+ const newCache: Record<string, TableMetadata> = {}
167
+ const newModalCache: Record<string, TableMetadata> = {}
155
168
 
156
169
  if (tables) {
157
170
  for (const [key, meta] of Object.entries(tables)) {
@@ -167,7 +180,7 @@ export const useMetadataCache = create<MetadataCacheState>()(
167
180
  set({
168
181
  cache: newCache,
169
182
  modalCache: newModalCache,
170
- metadataVersion: serverVersion,
183
+ metadataVersion: serverVersion || localVersion || String(Date.now()),
171
184
  prefetched: true,
172
185
  })
173
186
  } catch {
@@ -179,7 +192,8 @@ export const useMetadataCache = create<MetadataCacheState>()(
179
192
  {
180
193
  name: 'metacore-metadata-cache',
181
194
  // Bump when display hints (e.g. image_stack) must wipe stale cache.
182
- version: 4,
195
+ // v5: always replace catalog on prefetchAll (no merge-with-stale).
196
+ version: 5,
183
197
  migrate: () => ({
184
198
  cache: {},
185
199
  modalCache: {},