@ethisyscore/vite-plugin 1.37.0 → 1.39.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
@@ -609,6 +609,12 @@ interface PlatformReactPageSource {
609
609
  file: string;
610
610
  /** The page's source content (scanned for `useView(<module>, …)` calls). */
611
611
  content: string;
612
+ /**
613
+ * Root-relative module specifier for this page (e.g. `src/pages/admin/Foo.tsx`).
614
+ * When pages come from multiple directories each source carries its own specifier,
615
+ * derived from the directory it was read from.
616
+ */
617
+ moduleSpecifier: string;
612
618
  }
613
619
  /** Input to {@link computePlatformReactPages} (already-read filesystem inputs). */
614
620
  interface ComputePlatformReactPagesInput {
@@ -617,12 +623,10 @@ interface ComputePlatformReactPagesInput {
617
623
  /** Extension slug for the `/extensions/<slug>/` route prefix. */
618
624
  slug: string;
619
625
  routeMeta: RouteMetaEntry[];
620
- /** Each page file's basename (with `.tsx`) + its source content. */
626
+ /** Each page file's basename (with `.tsx`) + its source content + its root-relative module specifier. */
621
627
  pages: PlatformReactPageSource[];
622
628
  /** View name → src-relative module path (e.g. `src/adapter/<module>/XView.tsx`). */
623
629
  viewFiles: Record<string, string>;
624
- /** Root-relative pages dir for the `moduleSpecifier` (e.g. `src/pages/<module>`). */
625
- pagesDirRel: string;
626
630
  /** Per-file id/title/route overrides for non-filename-derived plugins. */
627
631
  pageOverrides?: Record<string, PlatformReactPageOverride>;
628
632
  }
@@ -648,8 +652,17 @@ declare function computePlatformReactPages(input: ComputePlatformReactPagesInput
648
652
  interface PlatformReactManifestPaths {
649
653
  /** Source root; default `"src"`. */
650
654
  src?: string;
651
- /** Pages dir; default `src/pages/<module>`. */
652
- pages?: string;
655
+ /**
656
+ * Pages dir(s); default `src/pages/<module>`. Accepts a single string (backward-compat)
657
+ * or an array of directories to scan together. Each `.tsx` file's `moduleSpecifier` is
658
+ * derived from the directory it was read from. A duplicate basename across dirs throws a
659
+ * clear error (fail-fast) — there is no per-dir escape hatch. `pageExclude` removes a
660
+ * filename from ALL scanned dirs, so it cannot preserve one dir's copy while dropping
661
+ * another's; to ship two pages with the same filename, rename one of them.
662
+ */
663
+ pages?: string | string[];
664
+ /** Page filenames (incl. `.tsx`) to skip — e.g. dialogs that live in a pages dir. */
665
+ pageExclude?: string[];
653
666
  /** Adapter (views) dir; default `src/adapter/<module>`. */
654
667
  adapter?: string;
655
668
  /** routeMeta file; default `src/config/routeMeta.json`. */
package/dist/index.d.ts CHANGED
@@ -609,6 +609,12 @@ interface PlatformReactPageSource {
609
609
  file: string;
610
610
  /** The page's source content (scanned for `useView(<module>, …)` calls). */
611
611
  content: string;
612
+ /**
613
+ * Root-relative module specifier for this page (e.g. `src/pages/admin/Foo.tsx`).
614
+ * When pages come from multiple directories each source carries its own specifier,
615
+ * derived from the directory it was read from.
616
+ */
617
+ moduleSpecifier: string;
612
618
  }
613
619
  /** Input to {@link computePlatformReactPages} (already-read filesystem inputs). */
614
620
  interface ComputePlatformReactPagesInput {
@@ -617,12 +623,10 @@ interface ComputePlatformReactPagesInput {
617
623
  /** Extension slug for the `/extensions/<slug>/` route prefix. */
618
624
  slug: string;
619
625
  routeMeta: RouteMetaEntry[];
620
- /** Each page file's basename (with `.tsx`) + its source content. */
626
+ /** Each page file's basename (with `.tsx`) + its source content + its root-relative module specifier. */
621
627
  pages: PlatformReactPageSource[];
622
628
  /** View name → src-relative module path (e.g. `src/adapter/<module>/XView.tsx`). */
623
629
  viewFiles: Record<string, string>;
624
- /** Root-relative pages dir for the `moduleSpecifier` (e.g. `src/pages/<module>`). */
625
- pagesDirRel: string;
626
630
  /** Per-file id/title/route overrides for non-filename-derived plugins. */
627
631
  pageOverrides?: Record<string, PlatformReactPageOverride>;
628
632
  }
@@ -648,8 +652,17 @@ declare function computePlatformReactPages(input: ComputePlatformReactPagesInput
648
652
  interface PlatformReactManifestPaths {
649
653
  /** Source root; default `"src"`. */
650
654
  src?: string;
651
- /** Pages dir; default `src/pages/<module>`. */
652
- pages?: string;
655
+ /**
656
+ * Pages dir(s); default `src/pages/<module>`. Accepts a single string (backward-compat)
657
+ * or an array of directories to scan together. Each `.tsx` file's `moduleSpecifier` is
658
+ * derived from the directory it was read from. A duplicate basename across dirs throws a
659
+ * clear error (fail-fast) — there is no per-dir escape hatch. `pageExclude` removes a
660
+ * filename from ALL scanned dirs, so it cannot preserve one dir's copy while dropping
661
+ * another's; to ship two pages with the same filename, rename one of them.
662
+ */
663
+ pages?: string | string[];
664
+ /** Page filenames (incl. `.tsx`) to skip — e.g. dialogs that live in a pages dir. */
665
+ pageExclude?: string[];
653
666
  /** Adapter (views) dir; default `src/adapter/<module>`. */
654
667
  adapter?: string;
655
668
  /** routeMeta file; default `src/config/routeMeta.json`. */
package/dist/index.js CHANGED
@@ -1227,7 +1227,7 @@ function computePlatformReactPages(input) {
1227
1227
  );
1228
1228
  const entries = [];
1229
1229
  const missingViews = [];
1230
- for (const { file, content } of input.pages) {
1230
+ for (const { file, content, moduleSpecifier } of input.pages) {
1231
1231
  const name = basename(file, ".tsx");
1232
1232
  const override = input.pageOverrides?.[file] ?? {};
1233
1233
  const views = {};
@@ -1245,7 +1245,7 @@ function computePlatformReactPages(input) {
1245
1245
  const route = override.route ?? pageRouteById[id];
1246
1246
  entries.push({
1247
1247
  id,
1248
- moduleSpecifier: `${input.pagesDirRel}/${file}`,
1248
+ moduleSpecifier,
1249
1249
  exportName: "default",
1250
1250
  ...route !== void 0 ? { route } : {},
1251
1251
  title: override.title ?? titleCase(name),
@@ -1270,13 +1270,14 @@ function generatePlatformReactManifest(config) {
1270
1270
  const { root, module } = config;
1271
1271
  const slug = config.slug ?? module;
1272
1272
  const src = config.paths?.src ?? "src";
1273
- const pagesDir = resolve(root, config.paths?.pages ?? `${src}/pages/${module}`);
1274
1273
  const adapterDir = resolve(root, config.paths?.adapter ?? `${src}/adapter/${module}`);
1275
1274
  const routeMetaPath = resolve(root, config.paths?.routeMeta ?? `${src}/config/routeMeta.json`);
1276
1275
  const featureManifestRel = config.paths?.featureManifest ?? "feature.manifest.json";
1277
1276
  const overlayRel = config.paths?.overlay ?? "../extension.manifest.json";
1278
1277
  const routeMeta = existsSync(routeMetaPath) ? JSON.parse(readFileSync(routeMetaPath, "utf8")) : [];
1279
- const pagesDirRel = slash2(relative(root, pagesDir));
1278
+ const pagesCfg = config.paths?.pages ?? `${src}/pages/${module}`;
1279
+ const pageDirs = (Array.isArray(pagesCfg) ? pagesCfg : [pagesCfg]).map((p) => resolve(root, p));
1280
+ const exclude = new Set(config.paths?.pageExclude ?? []);
1280
1281
  const viewFiles = {};
1281
1282
  if (existsSync(adapterDir)) {
1282
1283
  for (const f of walk(adapterDir)) {
@@ -1285,18 +1286,35 @@ function generatePlatformReactManifest(config) {
1285
1286
  }
1286
1287
  }
1287
1288
  }
1288
- const pageFiles = readdirSync(pagesDir).filter((f) => f.endsWith(".tsx")).sort();
1289
- const pages = pageFiles.map((file) => ({
1290
- file,
1291
- content: readFileSync(resolve(pagesDir, file), "utf8")
1292
- }));
1289
+ const seen = /* @__PURE__ */ new Map();
1290
+ const pages = [];
1291
+ for (const dir of pageDirs) {
1292
+ if (!existsSync(dir)) {
1293
+ throw new Error(`generate-manifest: pages dir not found: ${dir}`);
1294
+ }
1295
+ for (const file of readdirSync(dir).filter((f) => f.endsWith(".tsx")).sort()) {
1296
+ if (exclude.has(file)) continue;
1297
+ if (seen.has(file)) {
1298
+ throw new Error(
1299
+ `generate-manifest: duplicate page filename "${file}" in both ${seen.get(file)} and ${dir}`
1300
+ );
1301
+ }
1302
+ seen.set(file, dir);
1303
+ const relDir = slash2(relative(root, dir));
1304
+ const moduleSpecifier = relDir ? `${relDir}/${file}` : file;
1305
+ pages.push({
1306
+ file,
1307
+ content: readFileSync(resolve(dir, file), "utf8"),
1308
+ moduleSpecifier
1309
+ });
1310
+ }
1311
+ }
1293
1312
  const { entries, missingViews } = computePlatformReactPages({
1294
1313
  module,
1295
1314
  slug,
1296
1315
  routeMeta,
1297
1316
  pages,
1298
1317
  viewFiles,
1299
- pagesDirRel,
1300
1318
  pageOverrides: config.pageOverrides
1301
1319
  });
1302
1320
  const schema = config.manifest.schema ?? DEFAULT_SCHEMA;