@pygmalionjs/pygmalion 0.5.14 → 0.5.15

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.
Files changed (108) hide show
  1. package/dist-lib/types/App.d.ts +5 -0
  2. package/dist-lib/types/canvas/CameraLayer.d.ts +9 -0
  3. package/dist-lib/types/canvas/Canvas.d.ts +19 -0
  4. package/dist-lib/types/canvas/FrameLabelBanner.d.ts +7 -0
  5. package/dist-lib/types/canvas/FrameView.d.ts +9 -0
  6. package/dist-lib/types/canvas/FrozenRoutePreview.d.ts +12 -0
  7. package/dist-lib/types/canvas/InspectOverlay.d.ts +10 -0
  8. package/dist-lib/types/canvas/LightweightCanvas.d.ts +10 -0
  9. package/dist-lib/types/canvas/ObjectControls.d.ts +22 -0
  10. package/dist-lib/types/canvas/Preview.d.ts +3 -0
  11. package/dist-lib/types/canvas/SectionBoxes.d.ts +24 -0
  12. package/dist-lib/types/canvas/ShadowRoutePreview.d.ts +14 -0
  13. package/dist-lib/types/canvas/StoryboardConnections.d.ts +31 -0
  14. package/dist-lib/types/canvas/cameraPlacement.d.ts +45 -0
  15. package/dist-lib/types/canvas/domTags.d.ts +10 -0
  16. package/dist-lib/types/canvas/layoutContext.d.ts +9 -0
  17. package/dist-lib/types/canvas/useFlowSession.d.ts +36 -0
  18. package/dist-lib/types/canvas/useFrameLod.d.ts +35 -0
  19. package/dist-lib/types/editor/adaptiveFrameLayout.d.ts +67 -0
  20. package/dist-lib/types/editor/assetEditing.d.ts +10 -0
  21. package/dist-lib/types/editor/bannerStyle.d.ts +18 -0
  22. package/dist-lib/types/editor/catalog.d.ts +101 -0
  23. package/dist-lib/types/editor/codegen.d.ts +11 -0
  24. package/dist-lib/types/editor/componentConnections.d.ts +63 -0
  25. package/dist-lib/types/editor/componentInstances.d.ts +27 -0
  26. package/dist-lib/types/editor/contentBounds.d.ts +34 -0
  27. package/dist-lib/types/editor/designCompiler.d.ts +100 -0
  28. package/dist-lib/types/editor/designImport.d.ts +448 -0
  29. package/dist-lib/types/editor/documentSync.d.ts +28 -0
  30. package/dist-lib/types/editor/domImport.d.ts +58 -0
  31. package/dist-lib/types/editor/editModePolicy.d.ts +17 -0
  32. package/dist-lib/types/editor/fiberMap.d.ts +16 -0
  33. package/dist-lib/types/editor/flowSessionScheduler.d.ts +97 -0
  34. package/dist-lib/types/editor/flowSessions.d.ts +137 -0
  35. package/dist-lib/types/editor/frameHeight.d.ts +14 -0
  36. package/dist-lib/types/editor/frameIdentity.d.ts +9 -0
  37. package/dist-lib/types/editor/frameLabels.d.ts +124 -0
  38. package/dist-lib/types/editor/frameLanes.d.ts +62 -0
  39. package/dist-lib/types/editor/frameLod.d.ts +123 -0
  40. package/dist-lib/types/editor/frameLodRuntime.d.ts +64 -0
  41. package/dist-lib/types/editor/framePointerHit.d.ts +67 -0
  42. package/dist-lib/types/editor/framePointerIntent.d.ts +53 -0
  43. package/dist-lib/types/editor/framePreviewChannels.d.ts +26 -0
  44. package/dist-lib/types/editor/framePreviewKeys.d.ts +21 -0
  45. package/dist-lib/types/editor/frameWheelRouting.d.ts +16 -0
  46. package/dist-lib/types/editor/frozenImport.d.ts +70 -0
  47. package/dist-lib/types/editor/host.d.ts +114 -0
  48. package/dist-lib/types/editor/inspect.d.ts +225 -0
  49. package/dist-lib/types/editor/interactiveStates.d.ts +103 -0
  50. package/dist-lib/types/editor/livePreviewInstances.d.ts +93 -0
  51. package/dist-lib/types/editor/liveScreens.d.ts +20 -0
  52. package/dist-lib/types/editor/nodeSelector.d.ts +20 -0
  53. package/dist-lib/types/editor/previewBootstrap.d.ts +189 -0
  54. package/dist-lib/types/editor/previewEnvironmentControls.d.ts +33 -0
  55. package/dist-lib/types/editor/previewHydration.d.ts +5 -0
  56. package/dist-lib/types/editor/previewIntent.d.ts +17 -0
  57. package/dist-lib/types/editor/previewSweep.d.ts +129 -0
  58. package/dist-lib/types/editor/previewWarmup.d.ts +77 -0
  59. package/dist-lib/types/editor/projectBootGate.d.ts +45 -0
  60. package/dist-lib/types/editor/projectRuntime.d.ts +138 -0
  61. package/dist-lib/types/editor/registry.d.ts +38 -0
  62. package/dist-lib/types/editor/routePreview.d.ts +285 -0
  63. package/dist-lib/types/editor/routePreviewArtifactV2.d.ts +34 -0
  64. package/dist-lib/types/editor/routePreviewArtifactV3.d.ts +64 -0
  65. package/dist-lib/types/editor/routePreviewPlacement.d.ts +9 -0
  66. package/dist-lib/types/editor/routePreviewStatus.d.ts +48 -0
  67. package/dist-lib/types/editor/scenarioCoverage.d.ts +167 -0
  68. package/dist-lib/types/editor/screenCards.d.ts +101 -0
  69. package/dist-lib/types/editor/screenDimensions.d.ts +63 -0
  70. package/dist-lib/types/editor/screenFlows.d.ts +47 -0
  71. package/dist-lib/types/editor/screenInteractions.d.ts +4 -0
  72. package/dist-lib/types/editor/screenLists.d.ts +40 -0
  73. package/dist-lib/types/editor/screenStateGroups.d.ts +36 -0
  74. package/dist-lib/types/editor/screenshotBitmaps.d.ts +20 -0
  75. package/dist-lib/types/editor/sectionHeaders.d.ts +117 -0
  76. package/dist-lib/types/editor/shadowPreview.d.ts +103 -0
  77. package/dist-lib/types/editor/sharedSource.d.ts +40 -0
  78. package/dist-lib/types/editor/sourceJournal.d.ts +27 -0
  79. package/dist-lib/types/editor/store.d.ts +838 -0
  80. package/dist-lib/types/editor/storyboardComposition.d.ts +116 -0
  81. package/dist-lib/types/editor/storyboardDiscovery.d.ts +105 -0
  82. package/dist-lib/types/editor/storyboardEnvironment.d.ts +22 -0
  83. package/dist-lib/types/editor/storyboardGraph.d.ts +120 -0
  84. package/dist-lib/types/editor/storyboardGraphRuntime.d.ts +12 -0
  85. package/dist-lib/types/editor/storyboardGraphView.d.ts +104 -0
  86. package/dist-lib/types/editor/surfaceDemands.d.ts +138 -0
  87. package/dist-lib/types/editor/tokens.d.ts +26 -0
  88. package/dist-lib/types/editor/useObserved.d.ts +1 -0
  89. package/dist-lib/types/editor/viewportPresets.d.ts +21 -0
  90. package/dist-lib/types/editor/visualQa.d.ts +50 -0
  91. package/dist-lib/types/lib.d.ts +345 -0
  92. package/dist-lib/types/shell/ApplyPanel.d.ts +1 -0
  93. package/dist-lib/types/shell/AssetsPanel.d.ts +3 -0
  94. package/dist-lib/types/shell/CanvasStatusProbe.d.ts +5 -0
  95. package/dist-lib/types/shell/CodePanel.d.ts +1 -0
  96. package/dist-lib/types/shell/ComponentStateControls.d.ts +108 -0
  97. package/dist-lib/types/shell/ContextMenu.d.ts +1 -0
  98. package/dist-lib/types/shell/LayerTree.d.ts +7 -0
  99. package/dist-lib/types/shell/PropsPanel.d.ts +1 -0
  100. package/dist-lib/types/shell/StoryboardGraphPanel.d.ts +23 -0
  101. package/dist-lib/types/shell/ZoomIndicator.d.ts +4 -0
  102. package/dist-lib/types/shell/qaPresentation.d.ts +9 -0
  103. package/dist-lib/types/testing.d.ts +8 -0
  104. package/dist-lib/types/ui/SourceRefControl.d.ts +38 -0
  105. package/dist-lib/types/ui/icons.d.ts +30 -0
  106. package/package.json +7 -8
  107. package/testing.d.ts +0 -26
  108. package/types.d.ts +0 -2675
@@ -0,0 +1,77 @@
1
+ import type { StoryboardEnvironment } from './designImport';
2
+ import { type DesignFrameHeightMode } from './frameHeight';
3
+ import { type LivePreviewInstances } from './livePreviewInstances';
4
+ import type { StoryboardGraph } from './storyboardGraph';
5
+ /** The page facts warmup planning reads; a store PageModel satisfies it. */
6
+ export interface PreviewWarmupPage {
7
+ id: string;
8
+ importPageId?: string;
9
+ session?: string;
10
+ route?: string | null;
11
+ width?: number;
12
+ height?: number;
13
+ heightMode?: DesignFrameHeightMode;
14
+ maxHeight?: number;
15
+ resolvedDocumentHeight?: number;
16
+ environment?: StoryboardEnvironment;
17
+ interactions?: readonly unknown[];
18
+ layersImported?: boolean;
19
+ }
20
+ export interface PreviewWarmupTarget {
21
+ key: string;
22
+ url: string;
23
+ width: number;
24
+ height: number;
25
+ }
26
+ /** How many groups are warmed on open. One on purpose: each warm boot is a full app document (see module comment). */
27
+ export declare const PREVIEW_WARMUP_GROUP_LIMIT = 1;
28
+ /** Below this reported device memory (GB), warming is skipped entirely. */
29
+ export declare const PREVIEW_WARMUP_MIN_DEVICE_MEMORY_GB = 4;
30
+ /**
31
+ * Picks the instance groups worth booting before any frame asks.
32
+ *
33
+ * Pool-eligible pages are grouped by their shared-instance key; groups are
34
+ * ranked by member count because one boot amortizes across every member, and
35
+ * ties keep page order so the plan is deterministic. The key mirrors what
36
+ * FrameView computes for an inactive frame — page environment only — while the
37
+ * boot URL carries the baseline-merged environment, exactly like a lease boot.
38
+ */
39
+ export declare function planLivePreviewWarmup(pages: readonly PreviewWarmupPage[], appOrigin: string, baselineEnvironment?: StoryboardEnvironment, groupLimit?: number): PreviewWarmupTarget[];
40
+ /**
41
+ * Frame ids of the storyboard successors of the active page.
42
+ *
43
+ * A successor node is represented by one frame — its canonical screen when
44
+ * that frame exists, otherwise the first declared alias — and only frames the
45
+ * hover-intent path would accept qualify: a route is present and the layers
46
+ * were not imported.
47
+ */
48
+ export declare function storyboardSuccessorPageIds(graph: StoryboardGraph | null, pages: readonly PreviewWarmupPage[], activePageId: string): string[];
49
+ export interface StartPreviewWarmupOptions {
50
+ /** The observable selection source; only activePageId is tracked. */
51
+ editor: {
52
+ activePageId: string;
53
+ };
54
+ getPages: () => readonly PreviewWarmupPage[];
55
+ appOrigin: string;
56
+ baselineEnvironment?: StoryboardEnvironment;
57
+ /** Test seam — defaults to the shared pool. */
58
+ instances?: Pick<LivePreviewInstances, 'warm'>;
59
+ /** Test seam — defaults to the published storyboard graph. */
60
+ getGraph?: () => StoryboardGraph | null;
61
+ /** Test seam — defaults to navigator.deviceMemory. */
62
+ deviceMemoryGb?: number;
63
+ }
64
+ /**
65
+ * Warms the top instance group once and, from then on, prepares the
66
+ * storyboard successors of whichever screen becomes active.
67
+ *
68
+ * Returns a dispose function that stops the selection reaction. Warm boots
69
+ * already in flight finish on their own; the pool treats them as ordinary
70
+ * instances afterwards.
71
+ *
72
+ * On devices reporting less than PREVIEW_WARMUP_MIN_DEVICE_MEMORY_GB of
73
+ * memory the whole feature is inert: no pool boot and no successor intents,
74
+ * because both end in an offscreen application document the device cannot
75
+ * spare (see the module comment for the measured cost).
76
+ */
77
+ export declare function startPreviewWarmup(options: StartPreviewWarmupOptions): () => void;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * How long the client keeps polling a mirror that answers 'syncing'.
3
+ * Must outlast the server's own worst case: 180s shared-lock wait + 180s
4
+ * capture-lease wait + checkout materialization (git switch, dependency
5
+ * install, preview boot). 420s gives that chain a minute of headroom.
6
+ */
7
+ export declare const MIRROR_SYNC_POLL_TIMEOUT_MS = 420000;
8
+ /** Poll cadence while the mirror reports 'syncing'. */
9
+ export declare const MIRROR_SYNC_POLL_INTERVAL_MS = 500;
10
+ /** First automatic boot-retry delay after a failed refresh. */
11
+ export declare const MIRROR_BOOT_RETRY_BASE_MS = 5000;
12
+ /** Ceiling for the boot-retry backoff. */
13
+ export declare const MIRROR_BOOT_RETRY_MAX_MS = 30000;
14
+ /** Delay before automatic boot retry `attempt` (0-based): 5s, 10s, 20s, then 30s forever. */
15
+ export declare function mirrorBootRetryDelayMs(attempt: number): number;
16
+ /** The slice of the mirror status the gate decides on. */
17
+ export interface MirrorGateStatus {
18
+ state: string;
19
+ }
20
+ export interface SettleMirrorStatusOptions<S extends MirrorGateStatus> {
21
+ /** Status of the initial request; returned as-is when already settled. */
22
+ initial: S;
23
+ /** One GET of the mirror status endpoint. */
24
+ fetchStatus: () => Promise<S>;
25
+ /** One POST to the mirror refresh endpoint; resolves with the post-sync status. */
26
+ requestResync: () => Promise<S>;
27
+ timeoutMs?: number;
28
+ intervalMs?: number;
29
+ /** Test seams. */
30
+ now?: () => number;
31
+ sleep?: (ms: number) => Promise<void>;
32
+ }
33
+ /**
34
+ * Settles the mirror status a boot can act on.
35
+ *
36
+ * 'syncing' is polled through — the server is alive and working, and its own
37
+ * lock waits exceed two minutes, so giving up earlier than MIRROR_SYNC_POLL_-
38
+ * TIMEOUT_MS misreads a busy server as a dead one. 'drifted' asks the server
39
+ * to resync exactly once: drift means another server moved the shared
40
+ * checkout, and one refresh re-materializes the ref this server serves.
41
+ *
42
+ * Returns the first status that is neither, or the last observed status when
43
+ * the window closes. The caller decides whether that status is fatal.
44
+ */
45
+ export declare function settleMirrorStatus<S extends MirrorGateStatus>(options: SettleMirrorStatusOptions<S>): Promise<S>;
@@ -0,0 +1,138 @@
1
+ import type { InspectApplyPayload } from './inspect';
2
+ import type { InspectApplyResult, InspectImpactResult, InspectPreviewResult } from './host';
3
+ export type PygmalionIntegrationState = 'up_to_date' | 'auto_merged' | 'review_required' | 'conflict' | 'offline';
4
+ export interface PygmalionDevMirrorStatus {
5
+ /** 'drifted' means another server moved the shared mirror checkout; a refresh resyncs it. */
6
+ state: 'idle' | 'syncing' | 'ready' | 'error' | 'drifted';
7
+ commit: string | null;
8
+ shortCommit: string | null;
9
+ /** Git ref the mirror is tracking, or null when it follows the source branch. */
10
+ sourceRef: string | null;
11
+ syncedAt: string | null;
12
+ updated: boolean;
13
+ warning: string | null;
14
+ error: string | null;
15
+ appOrigin: string | null;
16
+ }
17
+ /** One revision the mirror can be repointed at. */
18
+ export interface PygmalionSourceRef {
19
+ name: string;
20
+ commit: string;
21
+ fullName: string;
22
+ kind: 'local' | 'remote';
23
+ }
24
+ /** Revisions available to `switchSource`, listed from the mirror repository. */
25
+ export interface PygmalionSourceRefs {
26
+ refs: readonly PygmalionSourceRef[];
27
+ /** Revision followed when none is pinned. */
28
+ defaultRef: string | null;
29
+ /** Ref that renders uncommitted work. */
30
+ worktreeRef: string | null;
31
+ }
32
+ export interface PygmalionVisualOperation {
33
+ id: string;
34
+ revision: number;
35
+ kind: 'visual';
36
+ createdAt: string;
37
+ commitSha: string;
38
+ files: string[];
39
+ integrationState: PygmalionIntegrationState;
40
+ }
41
+ export interface PygmalionVisualRevertOperation {
42
+ id: string;
43
+ revision: number;
44
+ kind: 'visual-revert';
45
+ createdAt: string;
46
+ commitSha: string;
47
+ revertsOperationId: string;
48
+ revertsRevision: number;
49
+ revertsCommitSha: string;
50
+ recordedCommitSha: string;
51
+ files: string[];
52
+ integrationState: PygmalionIntegrationState;
53
+ }
54
+ export type PygmalionSessionOperation = PygmalionVisualOperation | PygmalionVisualRevertOperation;
55
+ export interface PygmalionDesignSessionStatus {
56
+ id: string;
57
+ createdAt: string;
58
+ updatedAt: string;
59
+ createdFromSha: string;
60
+ baseDevSha: string;
61
+ branchName: string | null;
62
+ headSha: string | null;
63
+ revision: number;
64
+ integration: {
65
+ state: PygmalionIntegrationState;
66
+ latestDevSha: string;
67
+ checkedAt: string;
68
+ affectedFiles: string[];
69
+ conflictFiles: string[];
70
+ error?: string;
71
+ };
72
+ lastOperation: PygmalionSessionOperation | null;
73
+ canRevert: boolean;
74
+ lastRevertableOperation: PygmalionVisualOperation | null;
75
+ lastRevert: PygmalionVisualRevertOperation | null;
76
+ appOrigin: string | null;
77
+ previewError: string | null;
78
+ }
79
+ export interface PygmalionRevertResult {
80
+ reverted: true;
81
+ operation: PygmalionVisualRevertOperation;
82
+ session: PygmalionDesignSessionStatus;
83
+ }
84
+ export interface PygmalionProjectEndpoints {
85
+ mirror: string;
86
+ sessions: string;
87
+ inspect: string;
88
+ }
89
+ export interface PygmalionProjectRuntimeOptions {
90
+ endpoints?: Partial<PygmalionProjectEndpoints>;
91
+ sessionId?: string;
92
+ sessionStorageKey?: string;
93
+ autoStart?: boolean;
94
+ fetcher?: typeof fetch;
95
+ formatApplyMessage?: (session: PygmalionDesignSessionStatus, applied: number) => string | undefined;
96
+ /** Compare the canonical impact screen before and after application using the host Playwright capture endpoint. */
97
+ visualQa?: {
98
+ endpoint?: string;
99
+ eligibleFrameIds: readonly string[];
100
+ };
101
+ }
102
+ export interface PygmalionProjectRuntime {
103
+ mirror: PygmalionDevMirrorStatus;
104
+ session: PygmalionDesignSessionStatus | null;
105
+ ready: boolean;
106
+ appOrigin: string | null;
107
+ previewRevision: string;
108
+ /**
109
+ * Source SHA of previewRevision, without the session mutation counter.
110
+ * Artifact bundles are stamped with this, so hosts must build artifact cache
111
+ * namespaces from it instead of parsing previewRevision themselves.
112
+ */
113
+ previewSourceRevision: string;
114
+ refresh(manual?: boolean, sourceRef?: string): Promise<void>;
115
+ /**
116
+ * Repoints the mirror at another git ref without restarting the dev server.
117
+ * Pass PYGMALION_WORKTREE_SOURCE_REF to preview uncommitted work.
118
+ * The artifact cache is keyed by source SHA, so a switch invalidates it.
119
+ */
120
+ switchSource(sourceRef: string, options?: {
121
+ discardEdits?: boolean;
122
+ }): Promise<void>;
123
+ /**
124
+ * Revisions `switchSource` can be given. Empty until listed, so a host can
125
+ * offer a choice instead of asking for a ref string.
126
+ */
127
+ sourceRefs: PygmalionSourceRefs;
128
+ loadSourceRefs(): Promise<PygmalionSourceRefs>;
129
+ previewVisual(payload: InspectApplyPayload): Promise<InspectPreviewResult>;
130
+ inspectImpact(componentFiles: string[]): Promise<InspectImpactResult>;
131
+ applyVisual(payload: InspectApplyPayload): Promise<InspectApplyResult>;
132
+ revertLastVisual(): Promise<PygmalionRevertResult>;
133
+ }
134
+ /**
135
+ * A general-purpose browser runtime that consumes the Vite plugin's dev mirror and design session API.
136
+ * The host only provides the route/fixture catalog and display text, and the Git·preview life cycle is left to this hook.
137
+ */
138
+ export declare function usePygmalionProject(options?: PygmalionProjectRuntimeOptions): PygmalionProjectRuntime;
@@ -0,0 +1,38 @@
1
+ import type { ComponentType } from 'react';
2
+ /** Literal prop values that can be previewed, serialized, and written back safely. */
3
+ export type RegistryPropValue = string | number | boolean;
4
+ export interface RegistryEntry {
5
+ component: ComponentType<any>;
6
+ /** Previewable props. Boolean vocabularies become On/Off controls; other values become selects. */
7
+ props?: Record<string, readonly RegistryPropValue[]>;
8
+ /** Optional human-readable labels for preview controls. */
9
+ propLabels?: Readonly<Record<string, string>>;
10
+ /** Default props on insert. */
11
+ defaultProps?: Record<string, RegistryPropValue>;
12
+ /** Default string children to use when inserting into the component palette. */
13
+ defaultChildren?: string;
14
+ /** 'text' = Edit children as a string (button label) · 'nodes' = Place canvas nodes as children (container components such as Card). */
15
+ children?: 'text' | 'none' | 'nodes';
16
+ /**
17
+ * Whether a captured screen subtree may be REPLACED by this entry when a
18
+ * screen is imported. Only declare it for entries that render the real
19
+ * component from literal props: a catalog demo or a fixture-seeded adapter
20
+ * draws its own sample content, so collapsing into it swaps the captured
21
+ * screen for that sample (five distinct records became five copies of one
22
+ * fixture record). Default false — the captured DOM is kept, and a
23
+ * designer can still adopt a node into an instance on demand.
24
+ */
25
+ collapsible?: boolean;
26
+ /** Path for generating codegen import statements. */
27
+ importPath?: string;
28
+ /** In inspection mode, only actually valid dynamic cases are exposed. */
29
+ casePreview?: {
30
+ /** Whether the text varies in length at runtime, such as user input/API response. */
31
+ text?: boolean;
32
+ /** A preview of what states the component actually supports. */
33
+ states?: readonly ('selected' | 'disabled' | 'loading')[];
34
+ };
35
+ }
36
+ export type ComponentRegistry = Record<string, RegistryEntry>;
37
+ export declare function setComponentRegistry(r: ComponentRegistry): void;
38
+ export declare function getRegistry(): ComponentRegistry;
@@ -0,0 +1,285 @@
1
+ import { type RoutePreviewArtifactBundleV2 } from './routePreviewArtifactV2.js';
2
+ import { type RoutePreviewArtifactBundleV3, type RoutePreviewArtifactV3Diagnostic, type RoutePreviewArtifactV3Status } from './routePreviewArtifactV3.js';
3
+ import type { StoryboardEnvironment } from './designImport';
4
+ import { type InstanceResolver } from './fiberMap';
5
+ type SlotRelease = () => void;
6
+ export interface RoutePreviewRecipe {
7
+ namespace?: string;
8
+ previewRevision?: string;
9
+ route: string;
10
+ width: number;
11
+ height: number;
12
+ environment?: unknown;
13
+ preset?: unknown;
14
+ interactions?: unknown;
15
+ assertions?: unknown;
16
+ }
17
+ export interface RoutePreviewArtifactBundleV1 {
18
+ version: 1;
19
+ namespace: string;
20
+ /** Source SHA at the time of creation. It must match the value before the first ':' of runtime previewRevision. */
21
+ sourceRevision?: string;
22
+ snapshots: Record<string, string>;
23
+ }
24
+ export type RoutePreviewArtifactBundle = RoutePreviewArtifactBundleV1 | RoutePreviewArtifactBundleV2 | RoutePreviewArtifactBundleV3;
25
+ export interface RoutePreviewArtifactOutcome {
26
+ status: RoutePreviewArtifactV3Status;
27
+ diagnostics: readonly RoutePreviewArtifactV3Diagnostic[];
28
+ /** The snapshot is a last-known preview shown while an exact revision is loading. */
29
+ stale?: boolean;
30
+ screenshot: {
31
+ mediaType: 'image/png' | 'image/webp';
32
+ width: number;
33
+ height: number;
34
+ dataUrl: string;
35
+ } | null;
36
+ }
37
+ export interface RoutePreviewShadowArtifact {
38
+ bodyHtml: string;
39
+ bodyAttributes: string;
40
+ htmlAttributes: string;
41
+ sharedStylesheets: readonly {
42
+ key: string;
43
+ cssText: string;
44
+ }[];
45
+ stylesheetLinksHtml: string;
46
+ }
47
+ export interface RoutePreviewArtifactPage {
48
+ canonicalId: string;
49
+ route: string;
50
+ /** What this page's capture must have come from. Compared per frame. */
51
+ fingerprint?: string;
52
+ width?: number;
53
+ height?: number;
54
+ environment?: StoryboardEnvironment;
55
+ preset?: unknown;
56
+ interactions?: unknown;
57
+ assertions?: unknown;
58
+ }
59
+ export interface RoutePreviewArtifactSeedResult {
60
+ accepted: number;
61
+ rejected: number;
62
+ reason?: 'invalid-bundle' | 'namespace-mismatch' | 'revision-mismatch';
63
+ }
64
+ export interface RoutePreviewArtifactFrameIdentity {
65
+ id: string;
66
+ fingerprint?: string;
67
+ }
68
+ /** Lifecycle of resolving one frame against an exact artifact endpoint. */
69
+ export type RoutePreviewArtifactResolution = {
70
+ status: 'idle';
71
+ } | {
72
+ status: 'checking';
73
+ } | {
74
+ status: 'outdated';
75
+ message?: string;
76
+ } | {
77
+ status: 'generating';
78
+ } | {
79
+ status: 'error';
80
+ reason: 'unavailable' | 'rejected';
81
+ message: string;
82
+ } | {
83
+ status: 'exact';
84
+ };
85
+ export type RoutePreviewArtifactFrameRequestResult = {
86
+ status: 'accepted';
87
+ } | {
88
+ status: 'unavailable';
89
+ message?: string;
90
+ } | {
91
+ status: 'rejected';
92
+ message: string;
93
+ };
94
+ export type RoutePreviewState = 'hydrating' | 'live' | 'cached' | 'detailed' | 'placeholder';
95
+ export declare function resolveRoutePreviewState(input: {
96
+ hasRoute: boolean;
97
+ layersImported: boolean;
98
+ cacheHydrated: boolean;
99
+ hasSnapshot: boolean;
100
+ liveGranted: boolean;
101
+ }): RoutePreviewState;
102
+ export declare function routePreviewRetryDelay(failedAttempt: number, options?: {
103
+ maxAttempts?: number;
104
+ baseDelayMs?: number;
105
+ }): number | null;
106
+ export interface RoutePreviewPersistentRecord {
107
+ version: number;
108
+ key: string;
109
+ namespace: string;
110
+ snapshot: string;
111
+ bytes: number;
112
+ lastAccess: number;
113
+ }
114
+ export interface RoutePreviewPersistence {
115
+ read(key: string): Promise<unknown>;
116
+ readMany?(keys: readonly string[]): Promise<Map<string, unknown>>;
117
+ write(record: RoutePreviewPersistentRecord): Promise<void>;
118
+ remove(key: string): Promise<void>;
119
+ clear(namespace?: string): Promise<void>;
120
+ }
121
+ export interface RoutePreviewSlotTicket {
122
+ promise: Promise<SlotRelease>;
123
+ cancel: () => void;
124
+ updatePriority: (priority: number) => void;
125
+ }
126
+ export declare function recommendedRoutePreviewConcurrency(capabilities?: {
127
+ hardwareConcurrency?: number;
128
+ deviceMemory?: number;
129
+ }): number;
130
+ /** Coalesces keyed notifications; nested batches flush once at the outermost end. */
131
+ export declare function beginSnapshotNotificationBatch(): void;
132
+ export declare function endSnapshotNotificationBatch(): void;
133
+ export declare function subscribeRoutePreviewSnapshots(listener: () => void): () => void;
134
+ export declare function getRoutePreviewSnapshotRevision(): number;
135
+ /** Fires for writes, hydration verdicts, and evictions of exactly this key. */
136
+ export declare function subscribeRoutePreviewSnapshotKey(key: string, listener: () => void): () => void;
137
+ /** Changes when this key's channel fires or a whole-store event bumps the epoch. */
138
+ export declare function getRoutePreviewSnapshotKeyVersion(key: string): number;
139
+ export declare function subscribeRoutePreviewArtifactKey(cacheKey: string, listener: () => void): () => void;
140
+ export declare function getRoutePreviewArtifactKeyVersion(cacheKey: string): number;
141
+ /** Artifact resolutions live in the frame-identity key space, not the recipe one. */
142
+ export declare function subscribeRoutePreviewArtifactIdentity(id: string, fingerprint: string | undefined, listener: () => void): () => void;
143
+ export declare function getRoutePreviewArtifactIdentityVersion(id: string, fingerprint?: string): number;
144
+ /** Pairs with getActiveRoutePreviewCount; slot events never reach the snapshot channel. */
145
+ export declare function subscribeRoutePreviewSlotCount(listener: () => void): () => void;
146
+ export declare function getActiveRoutePreviewCount(): number;
147
+ export declare function hasRoutePreviewSnapshot(key: string): boolean;
148
+ /** A last-known stale artifact is drawable, but it is not a current warm hit. */
149
+ export declare function hasExactRoutePreviewSnapshot(key: string): boolean;
150
+ export declare function getRoutePreviewArtifactOutcome(key: string): RoutePreviewArtifactOutcome | null;
151
+ /**
152
+ * Artifact outcomes change only when a bundle is seeded or cleared, so frames
153
+ * subscribe to this instead of the per-snapshot revision. Reading the outcome
154
+ * without it leaves memoized frames on a replaced bundle forever.
155
+ */
156
+ export declare function getRoutePreviewArtifactRevision(): number;
157
+ export declare function subscribeRoutePreviewArtifacts(listener: () => void): () => void;
158
+ export declare function getRoutePreviewArtifactResolution(id: string, fingerprint?: string): RoutePreviewArtifactResolution;
159
+ /** Publishes cache-probe state for one or more exact frame identities. */
160
+ export declare function setRoutePreviewArtifactResolution(frames: readonly RoutePreviewArtifactFrameIdentity[], resolution: RoutePreviewArtifactResolution): void;
161
+ export declare function isRoutePreviewSnapshotHydrated(key: string): boolean;
162
+ /**
163
+ * Persistent cache identity excluding random mirror ports.
164
+ * By normalizing the object key order, the same screen recipe always uses the same key.
165
+ */
166
+ type RoutePreviewFrameRequester = (frames: readonly RoutePreviewArtifactFrameIdentity[]) => RoutePreviewArtifactFrameRequestResult | Promise<RoutePreviewArtifactFrameRequestResult> | void;
167
+ /** Installed by the host adapter, which owns the transport. */
168
+ export declare function setRoutePreviewArtifactFrameRequester(requester: RoutePreviewFrameRequester | null): void;
169
+ /**
170
+ * When an exact artifact endpoint exists, background cache misses stay cheap:
171
+ * only an active or deliberately hovered frame may boot the live application.
172
+ */
173
+ export declare function setRoutePreviewArtifactEndpointConfigured(configured: boolean): void;
174
+ export declare function shouldStartRoutePreviewProducer({ detailActive, previewIntended, }: {
175
+ detailActive: boolean;
176
+ previewIntended: boolean;
177
+ }): boolean;
178
+ /** A persisted exact frozen snapshot already satisfies the active editor frame. */
179
+ export declare function shouldRequestRoutePreviewArtifactFrame({ cacheHydrated, detailActive, hasRoute, layersImported, hasExactArtifact, hasExactSnapshot, hasFingerprint, }: {
180
+ cacheHydrated: boolean;
181
+ detailActive: boolean;
182
+ hasRoute: boolean;
183
+ layersImported: boolean;
184
+ hasExactArtifact: boolean;
185
+ hasExactSnapshot: boolean;
186
+ hasFingerprint: boolean;
187
+ }): boolean;
188
+ /**
189
+ * Asks for one frame's capture, once per identity.
190
+ *
191
+ * Called when a frame becomes visible, which is why the editor no longer needs
192
+ * every screen captured before it can show anything. A changed fingerprint is a
193
+ * new identity, so an edited screen is requested again.
194
+ */
195
+ export declare function requestRoutePreviewArtifactFrame(id: string, fingerprint?: string, options?: {
196
+ retry?: boolean;
197
+ }): Promise<RoutePreviewArtifactResolution> | null;
198
+ /**
199
+ * Asks for many frames' captures in one requester call.
200
+ *
201
+ * The background sweep delegates its interaction screens in chunks, and a
202
+ * chunk must not fan out into one transport round trip per frame. Identities
203
+ * already resolved exactly, already generating, or already failed are skipped
204
+ * (an error is retried only on request); the remaining frames share a single
205
+ * requester call and a single resolution, and each identity joins the same
206
+ * in-flight dedupe map the single-frame request uses.
207
+ */
208
+ export declare function requestRoutePreviewArtifactFrames(frames: readonly RoutePreviewArtifactFrameIdentity[], options?: {
209
+ retry?: boolean;
210
+ }): Promise<RoutePreviewArtifactResolution> | null;
211
+ export declare function createRoutePreviewRecipeKey(recipe: RoutePreviewRecipe): string;
212
+ /**
213
+ * Returns the compact body plus pooled style input without reconstructing a
214
+ * complete HTML snapshot for every frame.
215
+ */
216
+ export declare function getRoutePreviewShadowArtifact(key: string): RoutePreviewShadowArtifact | null;
217
+ /**
218
+ * Extracts the artifact source SHA from a runtime previewRevision.
219
+ * Runtime revisions are `<sourceSha>:<sessionRevision>`, while artifact bundles
220
+ * are stamped with the source SHA alone. Every identity comparison and every
221
+ * artifact request must go through this so both sides agree.
222
+ */
223
+ export declare function routePreviewSourceRevision(previewRevision: string): string;
224
+ /**
225
+ * Synchronously inject build-time snapshots into the memory cache before mounting the app.
226
+ * IndexedDB storage uses the existing setRoutePreviewSnapshot write-through as is.
227
+ */
228
+ export declare function seedRoutePreviewArtifacts(bundle: RoutePreviewArtifactBundle | null | undefined, options: {
229
+ namespace: string;
230
+ previewRevision: string;
231
+ appOrigin: string;
232
+ baselineEnvironment?: StoryboardEnvironment;
233
+ allowStaleIdentity?: boolean;
234
+ /** Endpoint-validated v3 subsets may prove freshness by frame fingerprint. */
235
+ allowMatchingFrameIdentity?: boolean;
236
+ pages: readonly RoutePreviewArtifactPage[];
237
+ }): RoutePreviewArtifactSeedResult;
238
+ export declare function setRoutePreviewCacheNamespace(namespace: string | null | undefined): void;
239
+ export declare function getRoutePreviewCacheNamespace(): string;
240
+ export declare function routePreviewPruneKeys(records: readonly Pick<RoutePreviewPersistentRecord, 'key' | 'bytes' | 'lastAccess'>[]): string[];
241
+ /** Persistence seam for node testing. It is not exposed to public package entrypoint. */
242
+ export declare function setRoutePreviewPersistenceForTests(persistence: RoutePreviewPersistence | null | undefined): void;
243
+ /**
244
+ * Several iframes are prepared in parallel, but computed style → NodeModel conversion is performed in parallel.
245
+ * Limited to 2-lane dedicated to main thread. Requests for the same screen are combined into one.
246
+ */
247
+ export declare function scheduleRouteLayerCapture<T>(key: string, priority: number, task: () => Promise<T>): Promise<T>;
248
+ /** Limits the number of actual app iframes that will boot simultaneously across the entire editor. */
249
+ export declare function acquireRoutePreviewSlot(priority?: number): RoutePreviewSlotTicket;
250
+ export declare function setRoutePreviewConcurrency(value: number): void;
251
+ export declare function getRoutePreviewSnapshot(key: string): string | null;
252
+ /** Immediately records to memory and writes through to IndexedDB. */
253
+ export declare function setRoutePreviewSnapshot(key: string, snapshot: string): boolean;
254
+ /**
255
+ * Raise persistent hits to memory LRU. miss/corrupt does not resolve until judgment is complete
256
+ * It is possible to prevent a race in which the caller acquires the live iframe slot first.
257
+ */
258
+ export declare function hydrateRoutePreviewSnapshot(key: string): Promise<string | null>;
259
+ /** Hydrates multiple screen recipes in parallel to fill the memory cache before the first paint. */
260
+ export declare function prehydrateRoutePreviewSnapshots(keys: readonly string[]): Promise<Map<string, string>>;
261
+ export declare function clearRoutePreviewSnapshots(namespace?: string): void;
262
+ /**
263
+ * Asynchronous operations with the same preview key share one slot and promise.
264
+ * The caller must complete the actual iframe preparation and serialization within the task.
265
+ */
266
+ export declare function scheduleRoutePreviewTask<T>(key: string, priority: number, task: () => Promise<T>): Promise<T>;
267
+ /**
268
+ * High-level scheduling API that uses snapshot cache and in-flight dedupe together.
269
+ * The caller should only express priority as to whether or not it is nearViewport, and the call itself should not be blocked.
270
+ */
271
+ export declare function scheduleRoutePreviewSnapshot(key: string, priority: number, task: () => Promise<string | null>, runtimeKey?: string): Promise<string | null>;
272
+ /** Maps live elements to their source metadata for stamping (docs/perf-contracts.md). */
273
+ export interface RoutePreviewSourceAnnotator {
274
+ /** Resolves the registry component instance rooted at an element. */
275
+ resolveInstance?: InstanceResolver;
276
+ /** Resolves the `file#localName` CSS-module source of an element. */
277
+ resolveStyle?: (el: Element) => string | null;
278
+ }
279
+ export interface SerializeRoutePreviewOptions {
280
+ annotate?: RoutePreviewSourceAnnotator;
281
+ }
282
+ /** Fix the running app document as a script-less srcDoc and terminate the API, timer, and React runtime. */
283
+ export declare function serializeRoutePreview(iframe: HTMLIFrameElement, fallbackUrl: string, options?: SerializeRoutePreviewOptions): string | null;
284
+ export declare function waitForRoutePreviewSettle(ms?: number): Promise<void>;
285
+ export {};
@@ -0,0 +1,34 @@
1
+ export type RoutePreviewArtifactV2Hash = `sha256-${string}`;
2
+ export interface RoutePreviewArtifactV2HeadReference {
3
+ readonly kind: 'head' | 'stylesheet';
4
+ readonly hash: RoutePreviewArtifactV2Hash;
5
+ }
6
+ export interface RoutePreviewArtifactV2Document {
7
+ readonly doctype: string;
8
+ readonly htmlAttributes: string;
9
+ readonly headAttributes: string;
10
+ readonly bodyAttributes: string;
11
+ }
12
+ export interface RoutePreviewArtifactV2Frame {
13
+ readonly document: RoutePreviewArtifactV2Document;
14
+ readonly head: readonly RoutePreviewArtifactV2HeadReference[];
15
+ readonly body: string;
16
+ }
17
+ export interface RoutePreviewArtifactBundleV2 {
18
+ readonly version: 2;
19
+ readonly namespace: string;
20
+ readonly sourceRevision?: string;
21
+ readonly assets: {
22
+ readonly head: Readonly<Record<RoutePreviewArtifactV2Hash, string>>;
23
+ readonly stylesheets: Readonly<Record<RoutePreviewArtifactV2Hash, string>>;
24
+ };
25
+ readonly frames: Readonly<Record<string, RoutePreviewArtifactV2Frame>>;
26
+ }
27
+ export interface RoutePreviewArtifactV2ValidationResult {
28
+ valid: boolean;
29
+ errors: string[];
30
+ bytes: number;
31
+ }
32
+ export declare function isSafeFrozenRoutePreviewSnapshotV2(snapshot: unknown): snapshot is string;
33
+ export declare function validateRoutePreviewArtifactV2Browser(value: unknown): RoutePreviewArtifactV2ValidationResult;
34
+ export declare function reconstructRoutePreviewArtifactSnapshotV2(value: unknown, frameId: string): string | null;