@ethisyscore/vite-plugin 1.23.0 → 1.25.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
@@ -515,6 +515,152 @@ declare function virtualPageEntry(page: PlatformReactPageInput, config: {
515
515
  */
516
516
  declare function buildPlatformReactPages(options?: BuildPlatformReactPagesOptions): Promise<PlatformReactBuildSummary>;
517
517
 
518
+ /**
519
+ * Build-time codegen for a PlatformReact plugin's `feature.manifest.json` +
520
+ * project-root `extension.manifest.json` overlay, from the plugin's `routeMeta.json`
521
+ * and its lifted page/adapter trees. Promoted from the per-plugin `gen-manifest.mjs`
522
+ * so every migrated plugin shares one generator instead of copying the routeMeta →
523
+ * `platformReactPages` derivation (including the nested-URL `route` emission and the
524
+ * dashboard-at-root empty-string route).
525
+ *
526
+ * NOT a Vite plugin — a plain build-step helper a plugin's `gen-manifest.mjs` calls
527
+ * before `build-pages`. It reads the filesystem and writes both manifests.
528
+ */
529
+ /** One entry of the migrated `routeMeta.json` (a faithful shift of the monolith's `routeMeta.ts`). */
530
+ interface RouteMetaEntry {
531
+ /** Full path pattern, re-rooted under `/extensions/<slug>/` (`:seg` = param). */
532
+ pattern: string;
533
+ label: string;
534
+ /** Parent route's `pattern`; omit for a top-level route. */
535
+ parent?: string;
536
+ /** Platform-react page id this pattern maps to (the manifest link; breadcrumbs ignore it). */
537
+ pageId?: string;
538
+ }
539
+ /** Manifest metadata written into `feature.manifest.json`. */
540
+ interface PlatformReactManifestMeta {
541
+ id: string;
542
+ name: string;
543
+ version: string;
544
+ /** Defaults to `"platform-react"`. */
545
+ renderMode?: string;
546
+ /** `$schema` value; defaults to the feature-manifest schema URL. */
547
+ schema?: string;
548
+ }
549
+ /** A generated `ui.platformReactPages[]` entry (feature-manifest form, incl. the build-only `views`). */
550
+ interface PlatformReactPageEntry {
551
+ id: string;
552
+ moduleSpecifier: string;
553
+ exportName: string;
554
+ /** Sub-path under `/extensions/<slug>/`; `""` = the extension-root (dashboard) surface. Absent → host id-match. */
555
+ route?: string;
556
+ title: string;
557
+ /** View name → src-relative module path, read by the page's `useView(<module>, name)`. */
558
+ views: Record<string, string>;
559
+ }
560
+ /**
561
+ * Per-page override, keyed by page filename (incl. `.tsx`). For plugins whose page
562
+ * ids/titles are NOT derived from the filename (e.g. `Timesheets.tsx` → id
563
+ * `"dashboard"` / title `"Dashboard"`). Any field omitted falls back to the derived
564
+ * default (`id` = kebab, `title` = title-case) or the routeMeta lookup (`route`).
565
+ */
566
+ interface PlatformReactPageOverride {
567
+ id?: string;
568
+ title?: string;
569
+ route?: string;
570
+ }
571
+ /** One page file read for {@link computePlatformReactPages}. */
572
+ interface PlatformReactPageSource {
573
+ /** Page filename incl. `.tsx`. */
574
+ file: string;
575
+ /** The page's source content (scanned for `useView(<module>, …)` calls). */
576
+ content: string;
577
+ }
578
+ /** Input to {@link computePlatformReactPages} (already-read filesystem inputs). */
579
+ interface ComputePlatformReactPagesInput {
580
+ /** `useView` module key (matched in each page's source). */
581
+ module: string;
582
+ /** Extension slug for the `/extensions/<slug>/` route prefix. */
583
+ slug: string;
584
+ routeMeta: RouteMetaEntry[];
585
+ /** Each page file's basename (with `.tsx`) + its source content. */
586
+ pages: PlatformReactPageSource[];
587
+ /** View name → src-relative module path (e.g. `src/adapter/<module>/XView.tsx`). */
588
+ viewFiles: Record<string, string>;
589
+ /** Root-relative pages dir for the `moduleSpecifier` (e.g. `src/pages/<module>`). */
590
+ pagesDirRel: string;
591
+ /** Per-file id/title/route overrides for non-filename-derived plugins. */
592
+ pageOverrides?: Record<string, PlatformReactPageOverride>;
593
+ }
594
+ /** Result of {@link computePlatformReactPages}. */
595
+ interface ComputePlatformReactPagesResult {
596
+ entries: PlatformReactPageEntry[];
597
+ /** `<file>: view "<name>" has no adapter file` diagnostics. */
598
+ missingViews: string[];
599
+ }
600
+ /**
601
+ * Pure core: derive the `platformReactPages[]` entries from already-read inputs (no
602
+ * filesystem). Per page: `id` = `pageOverrides[file].id` ?? kebab(filename), `title`
603
+ * = `pageOverrides[file].title` ?? title-case(filename), and `route` =
604
+ * `pageOverrides[file].route` ?? the routeMeta lookup — the routeMeta pattern minus
605
+ * the `/extensions/<slug>/` prefix, keyed by the RESOLVED id (the root pattern
606
+ * `/extensions/<slug>` → the empty-string route, making that page the extension-root
607
+ * / dashboard surface). Empty-string routes are emitted (presence, not truthiness);
608
+ * a page with neither an override route nor a routeMeta entry gets no `route` and
609
+ * falls back to the host's id match.
610
+ */
611
+ declare function computePlatformReactPages(input: ComputePlatformReactPagesInput): ComputePlatformReactPagesResult;
612
+ /** Path overrides for {@link generatePlatformReactManifest} (relative to `root` unless absolute). */
613
+ interface PlatformReactManifestPaths {
614
+ /** Source root; default `"src"`. */
615
+ src?: string;
616
+ /** Pages dir; default `src/pages/<module>`. */
617
+ pages?: string;
618
+ /** Adapter (views) dir; default `src/adapter/<module>`. */
619
+ adapter?: string;
620
+ /** routeMeta file; default `src/config/routeMeta.json`. */
621
+ routeMeta?: string;
622
+ /** feature manifest output; default `"feature.manifest.json"`. */
623
+ featureManifest?: string;
624
+ /** project-root overlay output; default `"../extension.manifest.json"`. */
625
+ overlay?: string;
626
+ }
627
+ /** Author-facing config for {@link generatePlatformReactManifest}. */
628
+ interface GeneratePlatformReactManifestConfig {
629
+ /** Absolute path to the plugin's `ui/` root (holds `src/` + the emitted manifests). */
630
+ root: string;
631
+ /** `useView` module key AND the default `pages/adapter` sub-dir name (e.g. `"finance"`). */
632
+ module: string;
633
+ /** Extension slug for the `/extensions/<slug>/` route prefix; defaults to `module`. */
634
+ slug?: string;
635
+ /** Metadata written into `feature.manifest.json`. */
636
+ manifest: PlatformReactManifestMeta;
637
+ /**
638
+ * Per-page id/title/route overrides, keyed by page filename (incl. `.tsx`). Only
639
+ * needed for plugins whose ids/titles aren't the filename-derived defaults; omit
640
+ * for the filename convention. See {@link PlatformReactPageOverride}.
641
+ */
642
+ pageOverrides?: Record<string, PlatformReactPageOverride>;
643
+ /** Path overrides (relative to `root` unless absolute). See {@link PlatformReactManifestPaths}. */
644
+ paths?: PlatformReactManifestPaths;
645
+ }
646
+ /** What {@link generatePlatformReactManifest} produced. */
647
+ interface GeneratePlatformReactManifestResult {
648
+ pageCount: number;
649
+ /** Page ids whose source resolved zero views. */
650
+ pagesWithoutView: string[];
651
+ /** `<file>: view "<name>" has no adapter file` diagnostics. */
652
+ missingViews: string[];
653
+ featureManifestPath: string;
654
+ overlayPath: string;
655
+ }
656
+ /**
657
+ * Read the plugin's `routeMeta.json` + page/adapter trees and write both
658
+ * `feature.manifest.json` (with the build-only `views` map) and the project-root
659
+ * `extension.manifest.json` overlay (pages WITHOUT `views` — what `cc package` reads
660
+ * for the host's install-time nav-path validation). Returns a summary for logging.
661
+ */
662
+ declare function generatePlatformReactManifest(config: GeneratePlatformReactManifestConfig): GeneratePlatformReactManifestResult;
663
+
518
664
  /** One emitted artifact from a per-page Vite sub-build. */
519
665
  type IframeBuildOutputItem = {
520
666
  type: "chunk";
@@ -606,4 +752,4 @@ interface EthisysPluginOptions {
606
752
  */
607
753
  declare function ethisysManifestPlugin(options?: EthisysPluginOptions): Plugin;
608
754
 
609
- export { type BuildPlatformReactPagesOptions, CONTRACT_B_IMPORT_MAP_ALLOWLIST, CONTRACT_B_RUNTIME_IMPORTS, CONTRACT_B_SEMANTIC_PRIMITIVES, type ContractAManifest, type ContractAPluginOptions, type ContractBManifest, type ContractBPluginOptions, type EthisysPluginOptions, type IframeBuildContext, type IframeBuildOutputItem, type IframeBuildResult, type IframeSandboxBuildSummary, type IframeSandboxPluginOptions, type IframeViteBuild, type ManifestReactiveRuleRef, type ManifestResourceRef, PLATFORM_REACT_DEDUPE, PLATFORM_REACT_EXTERNALS, type ParsePlatformReactPagesOptions, type PlatformReactAlias, type PlatformReactBuildContext, type PlatformReactBuildSummary, type PlatformReactManifest, type PlatformReactPageDeclaration, type PlatformReactPageInput, type PlatformReactPluginOptions, type PlatformReactViteBuild, type ResolvedPlatformReactPage, type ValidationFailure, type ValidationResult, type ViteBuildFn, buildIframeSandboxPages, buildPlatformReactPages, ethisysContractAPlugin, ethisysContractBPlugin, ethisysIframeSandboxPlugin, ethisysManifestPlugin, ethisysPlatformReactPlugin, parsePlatformReactPages, rewriteAliasedExternalImports, validateDeclarativeResource, validateReactiveRule, virtualPageEntry };
755
+ export { type BuildPlatformReactPagesOptions, CONTRACT_B_IMPORT_MAP_ALLOWLIST, CONTRACT_B_RUNTIME_IMPORTS, CONTRACT_B_SEMANTIC_PRIMITIVES, type ComputePlatformReactPagesInput, type ComputePlatformReactPagesResult, type ContractAManifest, type ContractAPluginOptions, type ContractBManifest, type ContractBPluginOptions, type EthisysPluginOptions, type GeneratePlatformReactManifestConfig, type GeneratePlatformReactManifestResult, type IframeBuildContext, type IframeBuildOutputItem, type IframeBuildResult, type IframeSandboxBuildSummary, type IframeSandboxPluginOptions, type IframeViteBuild, type ManifestReactiveRuleRef, type ManifestResourceRef, PLATFORM_REACT_DEDUPE, PLATFORM_REACT_EXTERNALS, type ParsePlatformReactPagesOptions, type PlatformReactAlias, type PlatformReactBuildContext, type PlatformReactBuildSummary, type PlatformReactManifest, type PlatformReactManifestMeta, type PlatformReactManifestPaths, type PlatformReactPageDeclaration, type PlatformReactPageEntry, type PlatformReactPageInput, type PlatformReactPageOverride, type PlatformReactPageSource, type PlatformReactPluginOptions, type PlatformReactViteBuild, type ResolvedPlatformReactPage, type RouteMetaEntry, type ValidationFailure, type ValidationResult, type ViteBuildFn, buildIframeSandboxPages, buildPlatformReactPages, computePlatformReactPages, ethisysContractAPlugin, ethisysContractBPlugin, ethisysIframeSandboxPlugin, ethisysManifestPlugin, ethisysPlatformReactPlugin, generatePlatformReactManifest, parsePlatformReactPages, rewriteAliasedExternalImports, validateDeclarativeResource, validateReactiveRule, virtualPageEntry };
package/dist/index.d.ts CHANGED
@@ -515,6 +515,152 @@ declare function virtualPageEntry(page: PlatformReactPageInput, config: {
515
515
  */
516
516
  declare function buildPlatformReactPages(options?: BuildPlatformReactPagesOptions): Promise<PlatformReactBuildSummary>;
517
517
 
518
+ /**
519
+ * Build-time codegen for a PlatformReact plugin's `feature.manifest.json` +
520
+ * project-root `extension.manifest.json` overlay, from the plugin's `routeMeta.json`
521
+ * and its lifted page/adapter trees. Promoted from the per-plugin `gen-manifest.mjs`
522
+ * so every migrated plugin shares one generator instead of copying the routeMeta →
523
+ * `platformReactPages` derivation (including the nested-URL `route` emission and the
524
+ * dashboard-at-root empty-string route).
525
+ *
526
+ * NOT a Vite plugin — a plain build-step helper a plugin's `gen-manifest.mjs` calls
527
+ * before `build-pages`. It reads the filesystem and writes both manifests.
528
+ */
529
+ /** One entry of the migrated `routeMeta.json` (a faithful shift of the monolith's `routeMeta.ts`). */
530
+ interface RouteMetaEntry {
531
+ /** Full path pattern, re-rooted under `/extensions/<slug>/` (`:seg` = param). */
532
+ pattern: string;
533
+ label: string;
534
+ /** Parent route's `pattern`; omit for a top-level route. */
535
+ parent?: string;
536
+ /** Platform-react page id this pattern maps to (the manifest link; breadcrumbs ignore it). */
537
+ pageId?: string;
538
+ }
539
+ /** Manifest metadata written into `feature.manifest.json`. */
540
+ interface PlatformReactManifestMeta {
541
+ id: string;
542
+ name: string;
543
+ version: string;
544
+ /** Defaults to `"platform-react"`. */
545
+ renderMode?: string;
546
+ /** `$schema` value; defaults to the feature-manifest schema URL. */
547
+ schema?: string;
548
+ }
549
+ /** A generated `ui.platformReactPages[]` entry (feature-manifest form, incl. the build-only `views`). */
550
+ interface PlatformReactPageEntry {
551
+ id: string;
552
+ moduleSpecifier: string;
553
+ exportName: string;
554
+ /** Sub-path under `/extensions/<slug>/`; `""` = the extension-root (dashboard) surface. Absent → host id-match. */
555
+ route?: string;
556
+ title: string;
557
+ /** View name → src-relative module path, read by the page's `useView(<module>, name)`. */
558
+ views: Record<string, string>;
559
+ }
560
+ /**
561
+ * Per-page override, keyed by page filename (incl. `.tsx`). For plugins whose page
562
+ * ids/titles are NOT derived from the filename (e.g. `Timesheets.tsx` → id
563
+ * `"dashboard"` / title `"Dashboard"`). Any field omitted falls back to the derived
564
+ * default (`id` = kebab, `title` = title-case) or the routeMeta lookup (`route`).
565
+ */
566
+ interface PlatformReactPageOverride {
567
+ id?: string;
568
+ title?: string;
569
+ route?: string;
570
+ }
571
+ /** One page file read for {@link computePlatformReactPages}. */
572
+ interface PlatformReactPageSource {
573
+ /** Page filename incl. `.tsx`. */
574
+ file: string;
575
+ /** The page's source content (scanned for `useView(<module>, …)` calls). */
576
+ content: string;
577
+ }
578
+ /** Input to {@link computePlatformReactPages} (already-read filesystem inputs). */
579
+ interface ComputePlatformReactPagesInput {
580
+ /** `useView` module key (matched in each page's source). */
581
+ module: string;
582
+ /** Extension slug for the `/extensions/<slug>/` route prefix. */
583
+ slug: string;
584
+ routeMeta: RouteMetaEntry[];
585
+ /** Each page file's basename (with `.tsx`) + its source content. */
586
+ pages: PlatformReactPageSource[];
587
+ /** View name → src-relative module path (e.g. `src/adapter/<module>/XView.tsx`). */
588
+ viewFiles: Record<string, string>;
589
+ /** Root-relative pages dir for the `moduleSpecifier` (e.g. `src/pages/<module>`). */
590
+ pagesDirRel: string;
591
+ /** Per-file id/title/route overrides for non-filename-derived plugins. */
592
+ pageOverrides?: Record<string, PlatformReactPageOverride>;
593
+ }
594
+ /** Result of {@link computePlatformReactPages}. */
595
+ interface ComputePlatformReactPagesResult {
596
+ entries: PlatformReactPageEntry[];
597
+ /** `<file>: view "<name>" has no adapter file` diagnostics. */
598
+ missingViews: string[];
599
+ }
600
+ /**
601
+ * Pure core: derive the `platformReactPages[]` entries from already-read inputs (no
602
+ * filesystem). Per page: `id` = `pageOverrides[file].id` ?? kebab(filename), `title`
603
+ * = `pageOverrides[file].title` ?? title-case(filename), and `route` =
604
+ * `pageOverrides[file].route` ?? the routeMeta lookup — the routeMeta pattern minus
605
+ * the `/extensions/<slug>/` prefix, keyed by the RESOLVED id (the root pattern
606
+ * `/extensions/<slug>` → the empty-string route, making that page the extension-root
607
+ * / dashboard surface). Empty-string routes are emitted (presence, not truthiness);
608
+ * a page with neither an override route nor a routeMeta entry gets no `route` and
609
+ * falls back to the host's id match.
610
+ */
611
+ declare function computePlatformReactPages(input: ComputePlatformReactPagesInput): ComputePlatformReactPagesResult;
612
+ /** Path overrides for {@link generatePlatformReactManifest} (relative to `root` unless absolute). */
613
+ interface PlatformReactManifestPaths {
614
+ /** Source root; default `"src"`. */
615
+ src?: string;
616
+ /** Pages dir; default `src/pages/<module>`. */
617
+ pages?: string;
618
+ /** Adapter (views) dir; default `src/adapter/<module>`. */
619
+ adapter?: string;
620
+ /** routeMeta file; default `src/config/routeMeta.json`. */
621
+ routeMeta?: string;
622
+ /** feature manifest output; default `"feature.manifest.json"`. */
623
+ featureManifest?: string;
624
+ /** project-root overlay output; default `"../extension.manifest.json"`. */
625
+ overlay?: string;
626
+ }
627
+ /** Author-facing config for {@link generatePlatformReactManifest}. */
628
+ interface GeneratePlatformReactManifestConfig {
629
+ /** Absolute path to the plugin's `ui/` root (holds `src/` + the emitted manifests). */
630
+ root: string;
631
+ /** `useView` module key AND the default `pages/adapter` sub-dir name (e.g. `"finance"`). */
632
+ module: string;
633
+ /** Extension slug for the `/extensions/<slug>/` route prefix; defaults to `module`. */
634
+ slug?: string;
635
+ /** Metadata written into `feature.manifest.json`. */
636
+ manifest: PlatformReactManifestMeta;
637
+ /**
638
+ * Per-page id/title/route overrides, keyed by page filename (incl. `.tsx`). Only
639
+ * needed for plugins whose ids/titles aren't the filename-derived defaults; omit
640
+ * for the filename convention. See {@link PlatformReactPageOverride}.
641
+ */
642
+ pageOverrides?: Record<string, PlatformReactPageOverride>;
643
+ /** Path overrides (relative to `root` unless absolute). See {@link PlatformReactManifestPaths}. */
644
+ paths?: PlatformReactManifestPaths;
645
+ }
646
+ /** What {@link generatePlatformReactManifest} produced. */
647
+ interface GeneratePlatformReactManifestResult {
648
+ pageCount: number;
649
+ /** Page ids whose source resolved zero views. */
650
+ pagesWithoutView: string[];
651
+ /** `<file>: view "<name>" has no adapter file` diagnostics. */
652
+ missingViews: string[];
653
+ featureManifestPath: string;
654
+ overlayPath: string;
655
+ }
656
+ /**
657
+ * Read the plugin's `routeMeta.json` + page/adapter trees and write both
658
+ * `feature.manifest.json` (with the build-only `views` map) and the project-root
659
+ * `extension.manifest.json` overlay (pages WITHOUT `views` — what `cc package` reads
660
+ * for the host's install-time nav-path validation). Returns a summary for logging.
661
+ */
662
+ declare function generatePlatformReactManifest(config: GeneratePlatformReactManifestConfig): GeneratePlatformReactManifestResult;
663
+
518
664
  /** One emitted artifact from a per-page Vite sub-build. */
519
665
  type IframeBuildOutputItem = {
520
666
  type: "chunk";
@@ -606,4 +752,4 @@ interface EthisysPluginOptions {
606
752
  */
607
753
  declare function ethisysManifestPlugin(options?: EthisysPluginOptions): Plugin;
608
754
 
609
- export { type BuildPlatformReactPagesOptions, CONTRACT_B_IMPORT_MAP_ALLOWLIST, CONTRACT_B_RUNTIME_IMPORTS, CONTRACT_B_SEMANTIC_PRIMITIVES, type ContractAManifest, type ContractAPluginOptions, type ContractBManifest, type ContractBPluginOptions, type EthisysPluginOptions, type IframeBuildContext, type IframeBuildOutputItem, type IframeBuildResult, type IframeSandboxBuildSummary, type IframeSandboxPluginOptions, type IframeViteBuild, type ManifestReactiveRuleRef, type ManifestResourceRef, PLATFORM_REACT_DEDUPE, PLATFORM_REACT_EXTERNALS, type ParsePlatformReactPagesOptions, type PlatformReactAlias, type PlatformReactBuildContext, type PlatformReactBuildSummary, type PlatformReactManifest, type PlatformReactPageDeclaration, type PlatformReactPageInput, type PlatformReactPluginOptions, type PlatformReactViteBuild, type ResolvedPlatformReactPage, type ValidationFailure, type ValidationResult, type ViteBuildFn, buildIframeSandboxPages, buildPlatformReactPages, ethisysContractAPlugin, ethisysContractBPlugin, ethisysIframeSandboxPlugin, ethisysManifestPlugin, ethisysPlatformReactPlugin, parsePlatformReactPages, rewriteAliasedExternalImports, validateDeclarativeResource, validateReactiveRule, virtualPageEntry };
755
+ export { type BuildPlatformReactPagesOptions, CONTRACT_B_IMPORT_MAP_ALLOWLIST, CONTRACT_B_RUNTIME_IMPORTS, CONTRACT_B_SEMANTIC_PRIMITIVES, type ComputePlatformReactPagesInput, type ComputePlatformReactPagesResult, type ContractAManifest, type ContractAPluginOptions, type ContractBManifest, type ContractBPluginOptions, type EthisysPluginOptions, type GeneratePlatformReactManifestConfig, type GeneratePlatformReactManifestResult, type IframeBuildContext, type IframeBuildOutputItem, type IframeBuildResult, type IframeSandboxBuildSummary, type IframeSandboxPluginOptions, type IframeViteBuild, type ManifestReactiveRuleRef, type ManifestResourceRef, PLATFORM_REACT_DEDUPE, PLATFORM_REACT_EXTERNALS, type ParsePlatformReactPagesOptions, type PlatformReactAlias, type PlatformReactBuildContext, type PlatformReactBuildSummary, type PlatformReactManifest, type PlatformReactManifestMeta, type PlatformReactManifestPaths, type PlatformReactPageDeclaration, type PlatformReactPageEntry, type PlatformReactPageInput, type PlatformReactPageOverride, type PlatformReactPageSource, type PlatformReactPluginOptions, type PlatformReactViteBuild, type ResolvedPlatformReactPage, type RouteMetaEntry, type ValidationFailure, type ValidationResult, type ViteBuildFn, buildIframeSandboxPages, buildPlatformReactPages, computePlatformReactPages, ethisysContractAPlugin, ethisysContractBPlugin, ethisysIframeSandboxPlugin, ethisysManifestPlugin, ethisysPlatformReactPlugin, generatePlatformReactManifest, parsePlatformReactPages, rewriteAliasedExternalImports, validateDeclarativeResource, validateReactiveRule, virtualPageEntry };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { existsSync, readFileSync, rmSync, mkdirSync, writeFileSync } from 'fs';
2
- import { isAbsolute, resolve, sep, normalize, dirname } from 'path';
1
+ import { existsSync, readFileSync, rmSync, mkdirSync, readdirSync, writeFileSync, statSync } from 'fs';
2
+ import { isAbsolute, resolve, basename, relative, sep, normalize, dirname } from 'path';
3
3
  import { KNOWN_PRIMITIVES, KNOWN_OPERATORS, KNOWN_RULE_KINDS, SduiNode, ReactiveRule, IframeSandboxPageDeclaration, AssetDigest } from '@ethisyscore/protocol';
4
4
  import { createHash } from 'crypto';
5
5
 
@@ -591,6 +591,22 @@ function ethisysContractBPlugin(options = {}) {
591
591
  }
592
592
  };
593
593
  }
594
+
595
+ // src/utils/strings.ts
596
+ function slash2(p) {
597
+ return p.replace(/\\/g, "/");
598
+ }
599
+ function kebab(s) {
600
+ return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/_/g, "-").toLowerCase();
601
+ }
602
+ function titleCase(s) {
603
+ return s.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
604
+ }
605
+ function escapeRegExp(s) {
606
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
607
+ }
608
+
609
+ // src/platform-react/page-bundles.ts
594
610
  var ID_REGEX = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/i;
595
611
  function assertHostOriginRelativePath2(value, label) {
596
612
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) {
@@ -615,9 +631,6 @@ function assertHostOriginRelativePath2(value, label) {
615
631
  );
616
632
  }
617
633
  }
618
- function slash2(p) {
619
- return sep === "\\" ? p.replace(/\\/g, "/") : p;
620
- }
621
634
  function ethisysPlatformReactPlugin(options = {}) {
622
635
  const explicitRoot = options.root;
623
636
  const manifestRel = options.manifestPath ?? "feature.manifest.json";
@@ -988,9 +1001,6 @@ function defaultWriteFile(path, contents) {
988
1001
  mkdirSync(dirname(path), { recursive: true });
989
1002
  writeFileSync(path, contents);
990
1003
  }
991
- function escapeRegExp(s) {
992
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
993
- }
994
1004
  function readManifest(options, root) {
995
1005
  if (options.manifest !== void 0) {
996
1006
  return options.manifest;
@@ -1132,6 +1142,126 @@ async function buildPlatformReactPages(options = {}) {
1132
1142
  );
1133
1143
  return { pages: summaryPages, digests, summaryPath, digestMapPath };
1134
1144
  }
1145
+ var DEFAULT_SCHEMA = "https://ethisys.dev/schemas/feature-manifest.json";
1146
+ function computePlatformReactPages(input) {
1147
+ const routePrefix = `/extensions/${input.slug}/`;
1148
+ const routeRoot = `/extensions/${input.slug}`;
1149
+ const pageRouteById = Object.fromEntries(
1150
+ 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)])
1151
+ );
1152
+ const useViewRe = new RegExp(
1153
+ `useView\\(\\s*["']${escapeRegExp(input.module)}["']\\s*,\\s*["']([A-Za-z0-9_]+)["']\\s*\\)`,
1154
+ "g"
1155
+ );
1156
+ const entries = [];
1157
+ const missingViews = [];
1158
+ for (const { file, content } of input.pages) {
1159
+ const name = basename(file, ".tsx");
1160
+ const override = input.pageOverrides?.[file] ?? {};
1161
+ const views = {};
1162
+ useViewRe.lastIndex = 0;
1163
+ let m;
1164
+ while ((m = useViewRe.exec(content)) !== null) {
1165
+ const v = m[1];
1166
+ if (input.viewFiles[v] !== void 0) {
1167
+ views[v] = input.viewFiles[v];
1168
+ } else {
1169
+ missingViews.push(`${file}: view "${v}" has no adapter file`);
1170
+ }
1171
+ }
1172
+ const id = override.id ?? kebab(name);
1173
+ const route = override.route ?? pageRouteById[id];
1174
+ entries.push({
1175
+ id,
1176
+ moduleSpecifier: `${input.pagesDirRel}/${file}`,
1177
+ exportName: "default",
1178
+ ...route !== void 0 ? { route } : {},
1179
+ title: override.title ?? titleCase(name),
1180
+ views
1181
+ });
1182
+ }
1183
+ return { entries, missingViews };
1184
+ }
1185
+ function walk(dir) {
1186
+ const out = [];
1187
+ for (const n of readdirSync(dir)) {
1188
+ const p = resolve(dir, n);
1189
+ if (statSync(p).isDirectory()) {
1190
+ out.push(...walk(p));
1191
+ } else {
1192
+ out.push(p);
1193
+ }
1194
+ }
1195
+ return out;
1196
+ }
1197
+ function generatePlatformReactManifest(config) {
1198
+ const { root, module } = config;
1199
+ const slug = config.slug ?? module;
1200
+ const src = config.paths?.src ?? "src";
1201
+ const pagesDir = resolve(root, config.paths?.pages ?? `${src}/pages/${module}`);
1202
+ const adapterDir = resolve(root, config.paths?.adapter ?? `${src}/adapter/${module}`);
1203
+ const routeMetaPath = resolve(root, config.paths?.routeMeta ?? `${src}/config/routeMeta.json`);
1204
+ const featureManifestRel = config.paths?.featureManifest ?? "feature.manifest.json";
1205
+ const overlayRel = config.paths?.overlay ?? "../extension.manifest.json";
1206
+ const routeMeta = existsSync(routeMetaPath) ? JSON.parse(readFileSync(routeMetaPath, "utf8")) : [];
1207
+ const pagesDirRel = slash2(relative(root, pagesDir));
1208
+ const viewFiles = {};
1209
+ if (existsSync(adapterDir)) {
1210
+ for (const f of walk(adapterDir)) {
1211
+ if (f.endsWith(".tsx")) {
1212
+ viewFiles[basename(f, ".tsx")] = slash2(relative(root, f));
1213
+ }
1214
+ }
1215
+ }
1216
+ const pageFiles = readdirSync(pagesDir).filter((f) => f.endsWith(".tsx")).sort();
1217
+ const pages = pageFiles.map((file) => ({
1218
+ file,
1219
+ content: readFileSync(resolve(pagesDir, file), "utf8")
1220
+ }));
1221
+ const { entries, missingViews } = computePlatformReactPages({
1222
+ module,
1223
+ slug,
1224
+ routeMeta,
1225
+ pages,
1226
+ viewFiles,
1227
+ pagesDirRel,
1228
+ pageOverrides: config.pageOverrides
1229
+ });
1230
+ const schema = config.manifest.schema ?? DEFAULT_SCHEMA;
1231
+ const renderMode = config.manifest.renderMode ?? "platform-react";
1232
+ const featureManifest = {
1233
+ $schema: schema,
1234
+ id: config.manifest.id,
1235
+ name: config.manifest.name,
1236
+ version: config.manifest.version,
1237
+ renderMode,
1238
+ ui: { platformReactPages: entries }
1239
+ };
1240
+ const featureManifestPath = resolve(root, featureManifestRel);
1241
+ writeFileSync(featureManifestPath, JSON.stringify(featureManifest, null, 2) + "\n");
1242
+ const overlay = {
1243
+ $schema: schema,
1244
+ ui: {
1245
+ platformReactPages: entries.map(({ id, moduleSpecifier, exportName, route, title }) => ({
1246
+ id,
1247
+ moduleSpecifier,
1248
+ exportName,
1249
+ ...route !== void 0 ? { route } : {},
1250
+ title
1251
+ }))
1252
+ }
1253
+ };
1254
+ const overlayPath = resolve(root, overlayRel);
1255
+ writeFileSync(overlayPath, JSON.stringify(overlay, null, 2) + "\n");
1256
+ const pagesWithoutView = entries.filter((e) => Object.keys(e.views).length === 0).map((e) => e.id);
1257
+ return {
1258
+ pageCount: entries.length,
1259
+ pagesWithoutView,
1260
+ missingViews,
1261
+ featureManifestPath,
1262
+ overlayPath
1263
+ };
1264
+ }
1135
1265
  var DEFAULT_MANIFEST = "feature.manifest.json";
1136
1266
  var DEFAULT_OUTPUT_DIR = "dist/iframe-sandbox";
1137
1267
  var DIGEST_MAP_FILENAME2 = "iframe-sandbox-digest-map.json";
@@ -1470,6 +1600,6 @@ function ethisysManifestPlugin(options = {}) {
1470
1600
  };
1471
1601
  }
1472
1602
 
1473
- export { CONTRACT_B_IMPORT_MAP_ALLOWLIST, CONTRACT_B_RUNTIME_IMPORTS, CONTRACT_B_SEMANTIC_PRIMITIVES, PLATFORM_REACT_DEDUPE, PLATFORM_REACT_EXTERNALS, buildIframeSandboxPages, buildPlatformReactPages, ethisysContractAPlugin, ethisysContractBPlugin, ethisysIframeSandboxPlugin, ethisysManifestPlugin, ethisysPlatformReactPlugin, parsePlatformReactPages, rewriteAliasedExternalImports, validateDeclarativeResource, validateReactiveRule, virtualPageEntry };
1603
+ export { CONTRACT_B_IMPORT_MAP_ALLOWLIST, CONTRACT_B_RUNTIME_IMPORTS, CONTRACT_B_SEMANTIC_PRIMITIVES, PLATFORM_REACT_DEDUPE, PLATFORM_REACT_EXTERNALS, buildIframeSandboxPages, buildPlatformReactPages, computePlatformReactPages, ethisysContractAPlugin, ethisysContractBPlugin, ethisysIframeSandboxPlugin, ethisysManifestPlugin, ethisysPlatformReactPlugin, generatePlatformReactManifest, parsePlatformReactPages, rewriteAliasedExternalImports, validateDeclarativeResource, validateReactiveRule, virtualPageEntry };
1474
1604
  //# sourceMappingURL=index.js.map
1475
1605
  //# sourceMappingURL=index.js.map