@ethisyscore/vite-plugin 1.67.1 → 1.68.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/dist/index.d.cts CHANGED
@@ -773,8 +773,23 @@ interface PlatformReactPageSource {
773
773
  }
774
774
  /** Input to {@link computePlatformReactPages} (already-read filesystem inputs). */
775
775
  interface ComputePlatformReactPagesInput {
776
- /** `useView` module key (matched in each page's source). */
776
+ /**
777
+ * The plugin's own `useView` module key. This does NOT control which calls the scan
778
+ * matches: every `useView(<anyKey>, <Name>)` is matched and then classified against
779
+ * {@link moduleKeys}. Its only role here is being the default single entry of that set.
780
+ */
777
781
  module: string;
782
+ /**
783
+ * Every module key the plugin's page definer actually registers a page's flat `views`
784
+ * map under. Defaults to `[module]`, which is what `createPluginPageDefiner` produces.
785
+ * Must not be empty: an empty set would classify every call as unregistered.
786
+ * Supply the full set for a hand-rolled multi-key definer (registering the same map
787
+ * under several keys to serve cross-module `useView` calls).
788
+ *
789
+ * A `useView` call naming a key OUTSIDE this set can never resolve at runtime, so it is
790
+ * reported in {@link ComputePlatformReactPagesResult.unregisteredViews}.
791
+ */
792
+ moduleKeys?: string[];
778
793
  /** Extension slug for the `/extensions/<slug>/` route prefix. */
779
794
  slug: string;
780
795
  routeMeta: RouteMetaEntry[];
@@ -790,6 +805,13 @@ interface ComputePlatformReactPagesResult {
790
805
  entries: PlatformReactPageEntry[];
791
806
  /** `<file>: view "<name>" has no adapter file` diagnostics. */
792
807
  missingViews: string[];
808
+ /**
809
+ * `useView` calls naming a module key the definer does not register, which therefore
810
+ * render the SDK's `MissingViewFallback` ("View not available") at runtime behind a
811
+ * green build. Previously invisible: the scan was built from the plugin's own module
812
+ * key, so such a call matched nothing and produced no binding AND no diagnostic.
813
+ */
814
+ unregisteredViews: string[];
793
815
  }
794
816
  /**
795
817
  * Pure core: derive the `platformReactPages[]` entries from already-read inputs (no
@@ -852,6 +874,25 @@ interface GeneratePlatformReactManifestConfig {
852
874
  pageOverrides?: Record<string, PlatformReactPageOverride>;
853
875
  /** Path overrides (relative to `root` unless absolute). See {@link PlatformReactManifestPaths}. */
854
876
  paths?: PlatformReactManifestPaths;
877
+ /**
878
+ * Every module key the plugin's definer registers page `views` under. Defaults to
879
+ * `[module]`. See {@link ComputePlatformReactPagesInput.moduleKeys}.
880
+ */
881
+ moduleKeys?: string[];
882
+ /**
883
+ * Throw when any `useView` call cannot be satisfied (default `true`).
884
+ *
885
+ * `useView` is a name-to-component lookup against the static manifest slice the
886
+ * generated entry registers, not an import, so an unsatisfiable call is NOT a build
887
+ * error: the surface renders the SDK's `MissingViewFallback` ("View not available") at
888
+ * runtime behind a green build. Failing the generator is what turns that into a
889
+ * build-time error.
890
+ *
891
+ * Both manifests are still written before the throw, so the emitted files stay in sync
892
+ * with the page tree; the exception, not a stale file, is the gate. Set `false` only to
893
+ * unblock a migration mid-flight, and read the returned diagnostics instead.
894
+ */
895
+ strict?: boolean;
855
896
  }
856
897
  /** What {@link generatePlatformReactManifest} produced. */
857
898
  interface GeneratePlatformReactManifestResult {
@@ -860,6 +901,8 @@ interface GeneratePlatformReactManifestResult {
860
901
  pagesWithoutView: string[];
861
902
  /** `<file>: view "<name>" has no adapter file` diagnostics. */
862
903
  missingViews: string[];
904
+ /** `useView` calls naming an unregistered module key. See {@link ComputePlatformReactPagesResult.unregisteredViews}. */
905
+ unregisteredViews: string[];
863
906
  featureManifestPath: string;
864
907
  overlayPath: string;
865
908
  }
package/dist/index.d.ts CHANGED
@@ -773,8 +773,23 @@ interface PlatformReactPageSource {
773
773
  }
774
774
  /** Input to {@link computePlatformReactPages} (already-read filesystem inputs). */
775
775
  interface ComputePlatformReactPagesInput {
776
- /** `useView` module key (matched in each page's source). */
776
+ /**
777
+ * The plugin's own `useView` module key. This does NOT control which calls the scan
778
+ * matches: every `useView(<anyKey>, <Name>)` is matched and then classified against
779
+ * {@link moduleKeys}. Its only role here is being the default single entry of that set.
780
+ */
777
781
  module: string;
782
+ /**
783
+ * Every module key the plugin's page definer actually registers a page's flat `views`
784
+ * map under. Defaults to `[module]`, which is what `createPluginPageDefiner` produces.
785
+ * Must not be empty: an empty set would classify every call as unregistered.
786
+ * Supply the full set for a hand-rolled multi-key definer (registering the same map
787
+ * under several keys to serve cross-module `useView` calls).
788
+ *
789
+ * A `useView` call naming a key OUTSIDE this set can never resolve at runtime, so it is
790
+ * reported in {@link ComputePlatformReactPagesResult.unregisteredViews}.
791
+ */
792
+ moduleKeys?: string[];
778
793
  /** Extension slug for the `/extensions/<slug>/` route prefix. */
779
794
  slug: string;
780
795
  routeMeta: RouteMetaEntry[];
@@ -790,6 +805,13 @@ interface ComputePlatformReactPagesResult {
790
805
  entries: PlatformReactPageEntry[];
791
806
  /** `<file>: view "<name>" has no adapter file` diagnostics. */
792
807
  missingViews: string[];
808
+ /**
809
+ * `useView` calls naming a module key the definer does not register, which therefore
810
+ * render the SDK's `MissingViewFallback` ("View not available") at runtime behind a
811
+ * green build. Previously invisible: the scan was built from the plugin's own module
812
+ * key, so such a call matched nothing and produced no binding AND no diagnostic.
813
+ */
814
+ unregisteredViews: string[];
793
815
  }
794
816
  /**
795
817
  * Pure core: derive the `platformReactPages[]` entries from already-read inputs (no
@@ -852,6 +874,25 @@ interface GeneratePlatformReactManifestConfig {
852
874
  pageOverrides?: Record<string, PlatformReactPageOverride>;
853
875
  /** Path overrides (relative to `root` unless absolute). See {@link PlatformReactManifestPaths}. */
854
876
  paths?: PlatformReactManifestPaths;
877
+ /**
878
+ * Every module key the plugin's definer registers page `views` under. Defaults to
879
+ * `[module]`. See {@link ComputePlatformReactPagesInput.moduleKeys}.
880
+ */
881
+ moduleKeys?: string[];
882
+ /**
883
+ * Throw when any `useView` call cannot be satisfied (default `true`).
884
+ *
885
+ * `useView` is a name-to-component lookup against the static manifest slice the
886
+ * generated entry registers, not an import, so an unsatisfiable call is NOT a build
887
+ * error: the surface renders the SDK's `MissingViewFallback` ("View not available") at
888
+ * runtime behind a green build. Failing the generator is what turns that into a
889
+ * build-time error.
890
+ *
891
+ * Both manifests are still written before the throw, so the emitted files stay in sync
892
+ * with the page tree; the exception, not a stale file, is the gate. Set `false` only to
893
+ * unblock a migration mid-flight, and read the returned diagnostics instead.
894
+ */
895
+ strict?: boolean;
855
896
  }
856
897
  /** What {@link generatePlatformReactManifest} produced. */
857
898
  interface GeneratePlatformReactManifestResult {
@@ -860,6 +901,8 @@ interface GeneratePlatformReactManifestResult {
860
901
  pagesWithoutView: string[];
861
902
  /** `<file>: view "<name>" has no adapter file` diagnostics. */
862
903
  missingViews: string[];
904
+ /** `useView` calls naming an unregistered module key. See {@link ComputePlatformReactPagesResult.unregisteredViews}. */
905
+ unregisteredViews: string[];
863
906
  featureManifestPath: string;
864
907
  overlayPath: string;
865
908
  }
package/dist/index.js CHANGED
@@ -1555,12 +1555,16 @@ function computePlatformReactPages(input) {
1555
1555
  const pageRouteById = Object.fromEntries(
1556
1556
  input.routeMeta.filter((e) => e.pageId && (e.pattern.startsWith(routePrefix) || e.pattern === routeRoot)).map((e) => [e.pageId, e.pattern === routeRoot ? "" : e.pattern.slice(routePrefix.length)])
1557
1557
  );
1558
- const useViewRe = new RegExp(
1559
- `useView\\(\\s*["']${escapeRegExp(input.module)}["']\\s*,\\s*["']([A-Za-z0-9_]+)["']\\s*\\)`,
1560
- "g"
1561
- );
1558
+ const useViewRe = /useView\(\s*["']([\w-]+)["']\s*,\s*["']([A-Za-z0-9_]+)["']\s*,?\s*\)/g;
1559
+ if (input.moduleKeys !== void 0 && input.moduleKeys.length === 0) {
1560
+ throw new Error(
1561
+ "generate-manifest: moduleKeys was supplied but empty. Omit it to default to [module], or list every module key the page definer registers views under."
1562
+ );
1563
+ }
1564
+ const registeredKeys = new Set(input.moduleKeys ?? [input.module]);
1562
1565
  const entries = [];
1563
1566
  const missingViews = [];
1567
+ const unregisteredViews = [];
1564
1568
  for (const { file, content, moduleSpecifier } of input.pages) {
1565
1569
  const name = basename(file, ".tsx");
1566
1570
  const override = input.pageOverrides?.[file] ?? {};
@@ -1568,7 +1572,13 @@ function computePlatformReactPages(input) {
1568
1572
  useViewRe.lastIndex = 0;
1569
1573
  let m;
1570
1574
  while ((m = useViewRe.exec(content)) !== null) {
1571
- const v = m[1];
1575
+ const [, moduleKey, v] = m;
1576
+ if (!registeredKeys.has(moduleKey)) {
1577
+ unregisteredViews.push(
1578
+ `${file}: useView("${moduleKey}", "${v}") names a module key the definer does not register (registered: ${[...registeredKeys].map((k) => `"${k}"`).join(", ")}), so the lookup renders "View not available" at runtime`
1579
+ );
1580
+ continue;
1581
+ }
1572
1582
  if (input.viewFiles[v] !== void 0) {
1573
1583
  views[v] = input.viewFiles[v];
1574
1584
  } else {
@@ -1586,7 +1596,7 @@ function computePlatformReactPages(input) {
1586
1596
  views
1587
1597
  });
1588
1598
  }
1589
- return { entries, missingViews };
1599
+ return { entries, missingViews, unregisteredViews };
1590
1600
  }
1591
1601
  function walk2(dir) {
1592
1602
  const out = [];
@@ -1643,8 +1653,9 @@ function generatePlatformReactManifest(config) {
1643
1653
  });
1644
1654
  }
1645
1655
  }
1646
- const { entries, missingViews } = computePlatformReactPages({
1656
+ const { entries, missingViews, unregisteredViews } = computePlatformReactPages({
1647
1657
  module,
1658
+ moduleKeys: config.moduleKeys,
1648
1659
  slug,
1649
1660
  routeMeta,
1650
1661
  pages,
@@ -1689,13 +1700,21 @@ function generatePlatformReactManifest(config) {
1689
1700
  const overlayPath = resolve(root, overlayRel);
1690
1701
  writeFileSync(overlayPath, JSON.stringify(overlay, null, 2) + "\n");
1691
1702
  const pagesWithoutView = entries.filter((e) => Object.keys(e.views).length === 0).map((e) => e.id);
1692
- return {
1703
+ const result = {
1693
1704
  pageCount: entries.length,
1694
1705
  pagesWithoutView,
1695
1706
  missingViews,
1707
+ unregisteredViews,
1696
1708
  featureManifestPath,
1697
1709
  overlayPath
1698
1710
  };
1711
+ if ((config.strict ?? true) && (missingViews.length > 0 || unregisteredViews.length > 0)) {
1712
+ throw new Error(
1713
+ `generate-manifest: ${missingViews.length + unregisteredViews.length} unresolvable useView call(s). Each renders "View not available" at runtime behind a green build:
1714
+ ` + [...unregisteredViews, ...missingViews].map((d) => ` - ${d}`).join("\n")
1715
+ );
1716
+ }
1717
+ return result;
1699
1718
  }
1700
1719
  var DEFAULT_MANIFEST = "feature.manifest.json";
1701
1720
  var DEFAULT_OUTPUT_DIR = "dist/iframe-sandbox";