@ethisyscore/vite-plugin 1.142.0 → 1.142.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/dist/index.cjs CHANGED
@@ -1019,8 +1019,8 @@ var PLATFORM_REACT_EXTERNALS = [
1019
1019
  // Externalised, not bundled, and not merely to save weight: bundling it gave
1020
1020
  // every page its OWN `QueryClient`, so a mutation on the detail page
1021
1021
  // invalidated a cache the list page could not see and a deleted row survived
1022
- // until a browser reload. One host-realm module instance is one cache across
1023
- // every plugin surface.
1022
+ // until a browser reload. One host-realm module instance is one React context,
1023
+ // through which the host hands every surface of a plugin the same client.
1024
1024
  //
1025
1025
  // Requires a host whose `hostModuleRegistry` serves this specifier: an external
1026
1026
  // the deployed host does NOT register is an unresolvable bare import, and the
@@ -1029,25 +1029,26 @@ var PLATFORM_REACT_EXTERNALS = [
1029
1029
  // `useSurfaceQueryClient` in plugin-ui) covers the softer case — module served,
1030
1030
  // no client in scope — and cannot cover this one.
1031
1031
  //
1032
- // THE SECOND GATE, and it binds each plugin rather than the estate: one cache
1033
- // means one KEY SPACE, so two owners using the same key now read each other's
1034
- // entry. Measured across the estate before this change: `["currencies"]` is
1035
- // used verbatim by coreconnect-web, bf-hr and bf-legal, from a copied
1036
- // `useCurrencies.ts` — three owners, one key, previously harmless only because
1037
- // each bundle had a cache of its own.
1038
- //
1039
- // A plugin therefore joins the shared cache the moment it is REBUILT on this
1040
- // SDK, and must have owner-namespaced its keys first. That ordering is the
1041
- // enforcement point and it is per plugin: a plugin not yet rebuilt still has
1042
- // its own cache and is unaffected, so this can be rolled out one plugin at a
1043
- // time rather than estate-wide.
1032
+ // The KEY SPACE is per plugin, and the host owns that boundary. A single
1033
+ // client for the whole app put every plugin's keys beside the host's and each
1034
+ // other's, and they collided: `["employees","lookup"]` is cached by hr,
1035
+ // finance and projects in different shapes, and `["currencies"]` by
1036
+ // coreconnect-web, bf-hr and bf-legal from a copied `useCurrencies.ts`. So the
1037
+ // host (coreconnect-web `pluginQueryClients.ts`, PBI 5626) wraps every page
1038
+ // and overlay of one plugin in a client of that plugin's own: its surfaces
1039
+ // share a cache, and no plugin can read, overwrite or invalidate another's.
1040
+ // Plugin keys need no owner prefix. The corollary is that a plugin cannot
1041
+ // refresh another plugin's cache either; cross-plugin freshness comes from
1042
+ // the kernel's push to each plugin's OWN group (`cache.plugin-invalidate`),
1043
+ // which the host forwards only to the plugin it names and the plugin maps to
1044
+ // its own keys through the definers' `cacheSubscriptions`. The host fans no
1045
+ // plugin's change out to another plugin's client.
1044
1046
  //
1045
1047
  // The ORGANISATION axis needs nothing here, and that was checked rather than
1046
- // assumed: coreconnect-web's AuthContext calls `queryClient.clear()` on logout
1047
- // AND on a live org switch between two non-null tenants, then bumps the
1048
- // authority epoch to force a remount. Plugins sharing that client inherit both.
1049
- // Sharing is in fact stricter than the status quo, where a plugin's private
1050
- // cache is unreachable by the host's teardown.
1048
+ // assumed: coreconnect-web clears its own client AND every plugin client on
1049
+ // logout, on a live organisation or identity switch, and when a plugin's
1050
+ // bundle bytes may have changed, then bumps the authority epoch to force a
1051
+ // remount.
1051
1052
  "@tanstack/react-query"
1052
1053
  ];
1053
1054
  var PLATFORM_REACT_DEDUPE = [
@@ -1129,6 +1130,35 @@ Use a STATIC top-level import of the package root instead. A dynamic import of a
1129
1130
  }
1130
1131
  };
1131
1132
  }
1133
+ var RETIRED_HOST_SPECIFIERS = ["@ethisyscore/host-query-client"];
1134
+ function looksImported(code, spec) {
1135
+ const gap = String.raw`\s*(?:/\*[\s\S]*?\*/\s*)*`;
1136
+ const q = escapeRegExp(spec);
1137
+ return new RegExp(`(?:\\bfrom${gap}|\\bimport${gap}\\(?${gap}|\\brequire${gap}\\(${gap})["'\`]${q}["'\`]`).test(code);
1138
+ }
1139
+ function rejectRetiredHostSpecifiers(retired = RETIRED_HOST_SPECIFIERS) {
1140
+ const retiredSet = new Set(retired);
1141
+ const message = (spec, where) => `[build-pages] ${where} imports "${spec}", which the host keeps registered only so old bundles link: it serves no client a plugin should use. A plugin surface runs on the QueryClient the host provides around it; read it with useQueryClient() inside the surface.`;
1142
+ return {
1143
+ name: "reject-retired-host-specifiers",
1144
+ enforce: "pre",
1145
+ resolveId(source, importer) {
1146
+ if (retiredSet.has(source)) {
1147
+ throw new Error(message(source, importer ?? "a module"));
1148
+ }
1149
+ return null;
1150
+ },
1151
+ renderChunk(code, chunk) {
1152
+ const imported = Array.isArray(chunk.imports) ? /* @__PURE__ */ new Set([...chunk.imports, ...chunk.dynamicImports ?? []]) : void 0;
1153
+ for (const spec of retired) {
1154
+ if (imported ? imported.has(spec) : looksImported(code, spec)) {
1155
+ throw new Error(message(spec, chunk.fileName ?? "bundle"));
1156
+ }
1157
+ }
1158
+ return null;
1159
+ }
1160
+ };
1161
+ }
1132
1162
  function virtualPageEntry(page, config) {
1133
1163
  const VIRTUAL_ID = `\0virtual:surface/${page.id}`;
1134
1164
  const views = page.views ?? {};
@@ -1214,6 +1244,8 @@ function makeDefaultBuild(viteBuild) {
1214
1244
  // `enforce: "pre"`, this one declares none. See its doc for why "none" is the
1215
1245
  // only position that sees compiled CSS.
1216
1246
  plugins: [
1247
+ // First, so a retired host specifier fails with its importer's name before anything resolves it.
1248
+ rejectRetiredHostSpecifiers(),
1217
1249
  ctx.surfacePlugin,
1218
1250
  ...ctx.plugins,
1219
1251
  scopePluginCssPlugin(),
@@ -1454,7 +1486,8 @@ function ethisysPlatformReactPlugin(options = {}) {
1454
1486
  return [
1455
1487
  ethisysPlatformReactPagesPlugin(options),
1456
1488
  scopePluginCssPlugin(),
1457
- assertHostResolvableExternals([...PLATFORM_REACT_EXTERNALS, "@ethisyscore/host-ui-externals"])
1489
+ assertHostResolvableExternals([...PLATFORM_REACT_EXTERNALS, "@ethisyscore/host-ui-externals"]),
1490
+ rejectRetiredHostSpecifiers()
1458
1491
  ];
1459
1492
  }
1460
1493
  function ethisysPlatformReactPagesPlugin(options = {}) {