@storystick/preview 0.0.0-stage → 0.2.0-rc.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/LICENSE +112 -0
- package/PUBLIC-API.md +55 -0
- package/README.md +42 -2
- package/dist/.source-hash +1 -0
- package/dist/authoring/runtime-contract.d.ts +89 -0
- package/dist/authoring/runtime-contract.js +28 -0
- package/dist/channel-taxonomy.d.ts +17 -0
- package/dist/channel-taxonomy.js +46 -0
- package/dist/context-command.d.ts +18 -0
- package/dist/context-command.js +38 -0
- package/dist/dev/suspicious-codeword-detector.d.ts +15 -0
- package/dist/dev/suspicious-codeword-detector.js +220 -0
- package/dist/dev/suspicious-codeword-detector.noop.d.ts +3 -0
- package/dist/dev/suspicious-codeword-detector.noop.js +4 -0
- package/dist/framework/browser-context.d.ts +2 -0
- package/dist/framework/browser-context.js +2 -0
- package/dist/framework/generation-refresh.d.ts +23 -0
- package/dist/framework/generation-refresh.js +82 -0
- package/dist/framework/generation-signal.d.ts +8 -0
- package/dist/framework/generation-signal.js +17 -0
- package/dist/framework/projection-generation-watch.d.ts +5 -0
- package/dist/framework/projection-generation-watch.js +53 -0
- package/dist/framework/render-receipt.d.ts +8 -0
- package/dist/framework/render-receipt.js +10 -0
- package/dist/framework/runtime-adapter-store.d.ts +30 -0
- package/dist/framework/runtime-adapter-store.js +81 -0
- package/dist/grant-coordinator.d.ts +53 -0
- package/dist/grant-coordinator.js +329 -0
- package/dist/grant-lifecycle.d.ts +52 -0
- package/dist/grant-lifecycle.js +74 -0
- package/dist/identity/__test-adapter.d.ts +34 -0
- package/dist/identity/__test-adapter.js +59 -0
- package/dist/identity/browser-context-gate.d.ts +4 -0
- package/dist/identity/browser-context-gate.js +22 -0
- package/dist/identity/browser-context.d.ts +13 -0
- package/dist/identity/browser-context.js +22 -0
- package/dist/identity/carriers/postmessage.d.ts +84 -0
- package/dist/identity/carriers/postmessage.js +177 -0
- package/dist/identity/carriers/storage-state.d.ts +41 -0
- package/dist/identity/carriers/storage-state.js +99 -0
- package/dist/identity/carriers/storage.d.ts +39 -0
- package/dist/identity/carriers/storage.js +182 -0
- package/dist/identity/carriers/url.d.ts +19 -0
- package/dist/identity/carriers/url.js +38 -0
- package/dist/identity/identity-state-machine.d.ts +70 -0
- package/dist/identity/identity-state-machine.js +244 -0
- package/dist/identity/identity-types.d.ts +192 -0
- package/dist/identity/identity-types.js +22 -0
- package/dist/identity/index.d.ts +18 -0
- package/dist/identity/index.js +16 -0
- package/dist/identity/preview-cookie.d.ts +9 -0
- package/dist/identity/preview-cookie.js +12 -0
- package/dist/identity/preview-draft.d.ts +6 -0
- package/dist/identity/preview-draft.js +25 -0
- package/dist/identity/preview-identity.d.ts +28 -0
- package/dist/identity/preview-identity.js +84 -0
- package/dist/identity/preview-scope.d.ts +28 -0
- package/dist/identity/preview-scope.js +47 -0
- package/dist/identity/resolver.d.ts +110 -0
- package/dist/identity/resolver.js +334 -0
- package/dist/identity/session-query.d.ts +4 -0
- package/dist/identity/session-query.js +19 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.js +788 -0
- package/dist/interaction-mode.d.ts +58 -0
- package/dist/interaction-mode.js +93 -0
- package/dist/nav-handler.d.ts +95 -0
- package/dist/nav-handler.js +84 -0
- package/dist/overlay-label.d.ts +79 -0
- package/dist/overlay-label.js +73 -0
- package/dist/provenance/anchor-map.d.ts +95 -0
- package/dist/provenance/anchor-map.js +177 -0
- package/dist/provenance/carrier-plan.d.ts +51 -0
- package/dist/provenance/carrier-plan.js +90 -0
- package/dist/provenance/coded-text.d.ts +20 -0
- package/dist/provenance/coded-text.js +302 -0
- package/dist/provenance/direct-edit-locator.d.ts +29 -0
- package/dist/provenance/direct-edit-locator.js +218 -0
- package/dist/provenance/editable-leaf.d.ts +134 -0
- package/dist/provenance/editable-leaf.js +483 -0
- package/dist/provenance/editor-target.d.ts +29 -0
- package/dist/provenance/editor-target.js +46 -0
- package/dist/provenance/field-leaf-walker.d.ts +21 -0
- package/dist/provenance/field-leaf-walker.js +98 -0
- package/dist/provenance/frame-dependencies.d.ts +212 -0
- package/dist/provenance/frame-dependencies.js +550 -0
- package/dist/provenance/index.d.ts +26 -0
- package/dist/provenance/index.js +26 -0
- package/dist/provenance/local-events.d.ts +1 -0
- package/dist/provenance/local-events.js +1 -0
- package/dist/provenance/markers.d.ts +21 -0
- package/dist/provenance/markers.js +70 -0
- package/dist/provenance/multi-frame-anchor-map.d.ts +54 -0
- package/dist/provenance/multi-frame-anchor-map.js +109 -0
- package/dist/provenance/normalize.d.ts +2 -0
- package/dist/provenance/normalize.js +19 -0
- package/dist/provenance/overlay-focus-echo.d.ts +17 -0
- package/dist/provenance/overlay-focus-echo.js +16 -0
- package/dist/provenance/overlay-projection.d.ts +65 -0
- package/dist/provenance/overlay-projection.js +201 -0
- package/dist/provenance/owner-map.d.ts +55 -0
- package/dist/provenance/owner-map.js +239 -0
- package/dist/provenance/read-carrier.d.ts +22 -0
- package/dist/provenance/read-carrier.js +92 -0
- package/dist/provenance/recorder.d.ts +38 -0
- package/dist/provenance/recorder.js +82 -0
- package/dist/provenance/render-context.d.ts +106 -0
- package/dist/provenance/render-context.js +338 -0
- package/dist/provenance/reveal-contract.d.ts +44 -0
- package/dist/provenance/reveal-contract.js +1 -0
- package/dist/provenance/richtext-slice-embed-address.d.ts +20 -0
- package/dist/provenance/richtext-slice-embed-address.js +35 -0
- package/dist/provenance/runtime-script.d.ts +1 -0
- package/dist/provenance/runtime-script.js +2217 -0
- package/dist/provenance/sidecar-store.d.ts +63 -0
- package/dist/provenance/sidecar-store.js +151 -0
- package/dist/provenance/sidecar.d.ts +34 -0
- package/dist/provenance/sidecar.js +227 -0
- package/dist/provenance/slice-model.d.ts +28 -0
- package/dist/provenance/slice-model.js +86 -0
- package/dist/provenance/source-identity.d.ts +3 -0
- package/dist/provenance/source-identity.js +7 -0
- package/dist/provenance/source-map-materializer.d.ts +76 -0
- package/dist/provenance/source-map-materializer.js +286 -0
- package/dist/provenance/source-registry.d.ts +103 -0
- package/dist/provenance/source-registry.js +562 -0
- package/dist/provenance/transformed-output-gate.d.ts +161 -0
- package/dist/provenance/transformed-output-gate.js +171 -0
- package/dist/provenance/types.d.ts +102 -0
- package/dist/provenance/types.js +1 -0
- package/dist/refresh-policy.d.ts +11 -0
- package/dist/refresh-policy.js +14 -0
- package/dist/reveal-target.d.ts +8 -0
- package/dist/reveal-target.js +47 -0
- package/dist/route-paths.d.ts +11 -0
- package/dist/route-paths.js +14 -0
- package/dist/router-subscriber.d.ts +92 -0
- package/dist/router-subscriber.js +44 -0
- package/dist/runtime/anchor-types.d.ts +5 -0
- package/dist/runtime/anchor-types.js +1 -0
- package/dist/runtime/authority-store.d.ts +31 -0
- package/dist/runtime/authority-store.js +56 -0
- package/dist/runtime/boot.d.ts +52 -0
- package/dist/runtime/boot.js +379 -0
- package/dist/runtime/content-refresh.d.ts +30 -0
- package/dist/runtime/content-refresh.js +68 -0
- package/dist/runtime/emit-runtime-error.d.ts +51 -0
- package/dist/runtime/emit-runtime-error.js +64 -0
- package/dist/runtime/field-proxy.d.ts +112 -0
- package/dist/runtime/field-proxy.js +471 -0
- package/dist/runtime/form-contract-reporter.d.ts +99 -0
- package/dist/runtime/form-contract-reporter.js +391 -0
- package/dist/runtime/invalidation-adapter.d.ts +17 -0
- package/dist/runtime/invalidation-adapter.js +42 -0
- package/dist/runtime/live-query-overlay.d.ts +39 -0
- package/dist/runtime/live-query-overlay.js +345 -0
- package/dist/runtime/momentary-navigate.d.ts +16 -0
- package/dist/runtime/momentary-navigate.js +106 -0
- package/dist/runtime/observation-scheduler.d.ts +15 -0
- package/dist/runtime/observation-scheduler.js +42 -0
- package/dist/runtime/perf-metrics.d.ts +28 -0
- package/dist/runtime/perf-metrics.js +90 -0
- package/dist/runtime/preview-interaction-policy.d.ts +1 -0
- package/dist/runtime/preview-interaction-policy.js +103 -0
- package/dist/runtime/preview-overlay-painter.d.ts +27 -0
- package/dist/runtime/preview-overlay-painter.js +1732 -0
- package/dist/runtime/preview-overlay-sidecar.d.ts +26 -0
- package/dist/runtime/preview-overlay-sidecar.js +45 -0
- package/dist/runtime/preview-perspective-alignment.d.ts +15 -0
- package/dist/runtime/preview-perspective-alignment.js +40 -0
- package/dist/runtime/preview-perspective-intent-state.d.ts +23 -0
- package/dist/runtime/preview-perspective-intent-state.js +5 -0
- package/dist/runtime/preview-transition-state.d.ts +142 -0
- package/dist/runtime/preview-transition-state.js +257 -0
- package/dist/runtime/render-mode-state.d.ts +51 -0
- package/dist/runtime/render-mode-state.js +76 -0
- package/dist/runtime/request-id.d.ts +4 -0
- package/dist/runtime/request-id.js +8 -0
- package/dist/runtime/resolve-schema-field.d.ts +99 -0
- package/dist/runtime/resolve-schema-field.js +356 -0
- package/dist/runtime/runtime-error-dispatch.d.ts +23 -0
- package/dist/runtime/runtime-error-dispatch.js +75 -0
- package/dist/runtime/schema-store.d.ts +121 -0
- package/dist/runtime/schema-store.js +667 -0
- package/dist/runtime/snapshot-assembly.d.ts +104 -0
- package/dist/runtime/snapshot-assembly.js +553 -0
- package/dist/runtime/snapshot-reporter.d.ts +55 -0
- package/dist/runtime/snapshot-reporter.js +375 -0
- package/dist/runtime/standalone-overlay-controller.d.ts +33 -0
- package/dist/runtime/standalone-overlay-controller.js +281 -0
- package/dist/runtime/store.d.ts +307 -0
- package/dist/runtime/store.js +1026 -0
- package/dist/runtime/windowed-minimap-projection.d.ts +28 -0
- package/dist/runtime/windowed-minimap-projection.js +189 -0
- package/dist/runtime/workspace-shortcuts.d.ts +30 -0
- package/dist/runtime/workspace-shortcuts.js +188 -0
- package/dist/sdk-error-copy.d.ts +48 -0
- package/dist/sdk-error-copy.js +182 -0
- package/dist/select-cursor.d.ts +2 -0
- package/dist/select-cursor.js +23 -0
- package/dist/server/admission-cookie.d.ts +38 -0
- package/dist/server/admission-cookie.js +122 -0
- package/dist/server/control-client.d.ts +29 -0
- package/dist/server/control-client.js +22 -0
- package/dist/server/control-errors.d.ts +22 -0
- package/dist/server/control-errors.js +165 -0
- package/dist/server/draft-route.d.ts +12 -0
- package/dist/server/draft-route.js +45 -0
- package/dist/server/extract-token.d.ts +30 -0
- package/dist/server/extract-token.js +98 -0
- package/dist/server/grant.d.ts +128 -0
- package/dist/server/grant.js +395 -0
- package/dist/server/ordinary-read-provenance.d.ts +11 -0
- package/dist/server/ordinary-read-provenance.js +124 -0
- package/dist/server/preview-read-metadata.d.ts +10 -0
- package/dist/server/preview-read-metadata.js +27 -0
- package/dist/server/provenance-frame-builder.d.ts +53 -0
- package/dist/server/provenance-frame-builder.js +102 -0
- package/dist/server/provenance-runtime.d.ts +70 -0
- package/dist/server/provenance-runtime.js +46 -0
- package/dist/server/read-context-command.d.ts +11 -0
- package/dist/server/read-context-command.js +53 -0
- package/dist/server/read-identity.d.ts +3 -0
- package/dist/server/read-identity.js +63 -0
- package/dist/server/read-lifecycle.d.ts +17 -0
- package/dist/server/read-lifecycle.js +52 -0
- package/dist/server/render-frame-provenance.d.ts +133 -0
- package/dist/server/render-frame-provenance.js +676 -0
- package/dist/server/render-id.d.ts +15 -0
- package/dist/server/render-id.js +22 -0
- package/dist/server/route-document-provenance.d.ts +77 -0
- package/dist/server/route-document-provenance.js +1327 -0
- package/dist/server/route-session-cookie.d.ts +33 -0
- package/dist/server/route-session-cookie.js +54 -0
- package/dist/session-projections.d.ts +33 -0
- package/dist/session-projections.js +43 -0
- package/dist/session-subscriber.d.ts +124 -0
- package/dist/session-subscriber.js +79 -0
- package/dist/sha256-fallback.d.ts +30 -0
- package/dist/sha256-fallback.js +126 -0
- package/dist/types.d.ts +446 -0
- package/dist/types.js +85 -0
- package/dist/validators.d.ts +61 -0
- package/dist/validators.js +110 -0
- package/package.json +206 -3
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
import { collectPreviewReadObservations } from '@storystick/client/internal';
|
|
2
|
+
import { PREVIEW_PROVENANCE_CODED_TEXT_START, appliedPreviewVariantIdFromQueryResult, previewReadScopeEchoFromQueryResult, requestedPreviewVariantIdFromQueryResult, classifyPreviewProvenanceCodedTextTarget, collectPreviewProvenanceSourceMappedQueryResults, collectPreviewFrameDependencies, createPreviewProvenanceAttributeCarrierPlan, createPreviewProvenanceCodedTextCarrierPlan, createPreviewFrameDependencySet, createPublicSidecar, materializePreviewProvenanceSourceMap, previewProvenanceSourceSetForLeaf, recordPreviewProvenanceEditableLeaves, validateProvenanceFrame, } from '@storystick/preview/provenance';
|
|
3
|
+
import { normalizePreviewVariantId } from '@storystick/preview/identity';
|
|
4
|
+
import { defaultPreviewProvenanceRenderId } from './render-id.js';
|
|
5
|
+
import { resolvePreviewFrameReadMetadataFromObservations, } from './preview-read-metadata.js';
|
|
6
|
+
import { withPreviewProvenanceContext, } from '../provenance/render-context.js';
|
|
7
|
+
import { buildPreviewProvenanceFrameWithRuntime, } from './provenance-frame-builder.js';
|
|
8
|
+
import { createPreviewProvenanceTemporalIdentity, } from './provenance-runtime.js';
|
|
9
|
+
const RENDER_FRAME_SOURCE_SET_CAP = 512;
|
|
10
|
+
const RENDER_FRAME_MARKER_CAP = 2_048;
|
|
11
|
+
const RENDER_FRAME_JSON_BYTES_CAP = 256 * 1024;
|
|
12
|
+
const ESTIMATED_MARKER_ID = `p_${'x'.repeat(22)}`;
|
|
13
|
+
export function unstable_previewRenderFrameRootAttrs(frame) {
|
|
14
|
+
return frame?.sessionId
|
|
15
|
+
? { 'data-preview-message-session-id': frame.sessionId }
|
|
16
|
+
: {};
|
|
17
|
+
}
|
|
18
|
+
export async function unstable_buildPreviewRenderFrameWithRuntime(options, runtime) {
|
|
19
|
+
const enabled = options.enabled ?? runtime.config.isEnabled();
|
|
20
|
+
if (!enabled)
|
|
21
|
+
return null;
|
|
22
|
+
runtime.recorder.markNoStore({ enabled });
|
|
23
|
+
const codeVersion = options.codeVersion ?? runtime.config.resolveCodeVersion();
|
|
24
|
+
const readObservations = collectPreviewReadObservations(options.codedDocument, options.codedContext);
|
|
25
|
+
const readMetadata = typeof options.observationId === 'string' &&
|
|
26
|
+
typeof options.renderWatermark === 'number'
|
|
27
|
+
? {
|
|
28
|
+
readContext: options.readContext,
|
|
29
|
+
receiptIds: options.receiptIds ?? [],
|
|
30
|
+
observationId: options.observationId,
|
|
31
|
+
renderWatermark: options.renderWatermark,
|
|
32
|
+
}
|
|
33
|
+
: resolvePreviewFrameReadMetadataFromObservations(codeVersion, readObservations);
|
|
34
|
+
if (readMetadata === null && readObservations.some((read) => read.readContext))
|
|
35
|
+
return null;
|
|
36
|
+
const input = {
|
|
37
|
+
runtime,
|
|
38
|
+
enabled,
|
|
39
|
+
frameId: options.frameId,
|
|
40
|
+
routeHash: options.routeHash,
|
|
41
|
+
variantId: options.variantId,
|
|
42
|
+
previewScope: options.previewScope,
|
|
43
|
+
fallbackPathname: options.fallbackPathname ?? options.pathname,
|
|
44
|
+
sessionId: options.sessionId,
|
|
45
|
+
codeVersion,
|
|
46
|
+
renderId: options.renderId,
|
|
47
|
+
generation: options.generation,
|
|
48
|
+
renderNonce: options.renderNonce,
|
|
49
|
+
emissionRevision: options.emissionRevision,
|
|
50
|
+
readMetadata,
|
|
51
|
+
authoritativeDocumentIds: options.authoritativeDocumentIds,
|
|
52
|
+
dependencies: [
|
|
53
|
+
...(options.dependencies ?? []),
|
|
54
|
+
...collectPreviewFrameDependencies(options.codedDocument, options.codedContext),
|
|
55
|
+
],
|
|
56
|
+
leaves: options.leaves,
|
|
57
|
+
sourceMapDiagnostics: options.sourceMapDiagnostics ?? defaultSourceMapDiagnostics(options.leaves),
|
|
58
|
+
codedDocument: options.codedDocument,
|
|
59
|
+
codedContext: options.codedContext,
|
|
60
|
+
codedTextRoot: options.codedTextRoot ?? options.codedDocument,
|
|
61
|
+
codedTextRootPrefix: options.codedTextRootPrefix,
|
|
62
|
+
codedTextRootsByDocumentId: options.codedTextRootsByDocumentId,
|
|
63
|
+
fixture: options.fixture,
|
|
64
|
+
projectId: options.projectId,
|
|
65
|
+
endpoint: options.endpoint,
|
|
66
|
+
convexUrl: options.convexUrl,
|
|
67
|
+
};
|
|
68
|
+
const capped = capPreviewProvenanceLeaves(input);
|
|
69
|
+
if (input.fixture?.enabled) {
|
|
70
|
+
return buildFixtureRenderFrame(input, capped);
|
|
71
|
+
}
|
|
72
|
+
const result = await buildPreviewProvenanceFrameWithRuntime({
|
|
73
|
+
enabled: input.enabled,
|
|
74
|
+
frameId: input.frameId,
|
|
75
|
+
sessionId: input.sessionId,
|
|
76
|
+
routeHash: input.routeHash,
|
|
77
|
+
variantId: input.variantId,
|
|
78
|
+
previewScope: input.previewScope,
|
|
79
|
+
fallbackPathname: input.fallbackPathname,
|
|
80
|
+
codeVersion: input.codeVersion,
|
|
81
|
+
renderId: input.renderId,
|
|
82
|
+
generation: input.generation,
|
|
83
|
+
renderNonce: input.renderNonce,
|
|
84
|
+
emissionRevision: input.emissionRevision,
|
|
85
|
+
readContext: input.readMetadata?.readContext,
|
|
86
|
+
receiptIds: input.readMetadata?.receiptIds,
|
|
87
|
+
observationId: input.readMetadata?.observationId,
|
|
88
|
+
renderWatermark: input.readMetadata?.renderWatermark,
|
|
89
|
+
authoritativeDocumentIds: input.authoritativeDocumentIds,
|
|
90
|
+
dependencies: input.dependencies,
|
|
91
|
+
leaves: capped.leaves,
|
|
92
|
+
codedTextRoot: input.codedTextRoot,
|
|
93
|
+
codedTextRootPrefix: input.codedTextRootPrefix,
|
|
94
|
+
codedTextRootsByDocumentId: input.codedTextRootsByDocumentId,
|
|
95
|
+
projectId: input.projectId,
|
|
96
|
+
endpoint: input.endpoint,
|
|
97
|
+
convexUrl: input.convexUrl,
|
|
98
|
+
}, runtime);
|
|
99
|
+
if (result === null)
|
|
100
|
+
return null;
|
|
101
|
+
logPreviewProvenanceCodedTextWriteDebug({
|
|
102
|
+
frameId: input.frameId,
|
|
103
|
+
pathname: input.fallbackPathname,
|
|
104
|
+
cap: capped,
|
|
105
|
+
codedTextWrites: result.codedTextWrites,
|
|
106
|
+
codedDocument: input.codedDocument,
|
|
107
|
+
codedContext: input.codedContext,
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
frameId: input.frameId,
|
|
111
|
+
sessionId: result.sessionId,
|
|
112
|
+
routeHash: result.routeHash,
|
|
113
|
+
variantId: result.variantId,
|
|
114
|
+
attrsByKey: result.attrsByKey,
|
|
115
|
+
codedDocument: attachPreviewProvenanceContext(input.codedDocument, result.attrsByKey),
|
|
116
|
+
codedContext: attachPreviewProvenanceContext(input.codedContext, result.attrsByKey),
|
|
117
|
+
renderFrame: result.renderFrame,
|
|
118
|
+
dependencySet: result.dependencySet,
|
|
119
|
+
publicSidecar: result.publicSidecar,
|
|
120
|
+
validationOk: result.validationOk,
|
|
121
|
+
diagnostics: previewRenderFrameDiagnostics({
|
|
122
|
+
input,
|
|
123
|
+
cap: capped,
|
|
124
|
+
frame: result.renderFrame,
|
|
125
|
+
publicSidecar: result.publicSidecar,
|
|
126
|
+
codedTextWrites: result.codedTextWrites,
|
|
127
|
+
}),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export async function unstable_buildPreviewDocumentRenderFrameFromReadsWithRuntime(options, runtime) {
|
|
131
|
+
const enabled = options.enabled ?? runtime.config.isEnabled();
|
|
132
|
+
if (!enabled)
|
|
133
|
+
return null;
|
|
134
|
+
const codedContext = options.context === undefined ? undefined : cloneJson(options.context);
|
|
135
|
+
const reads = options.documents ?? collectPreviewProvenanceSourceMappedQueryResults(options.context);
|
|
136
|
+
const documents = reads.map(normalizePreviewDocumentRenderFrameRead).filter((entry) => entry.document !== null && entry.document !== undefined);
|
|
137
|
+
const plans = documents.map((entry) => planPreviewDocumentRenderFrameRead({
|
|
138
|
+
frameId: options.frameId,
|
|
139
|
+
manifest: options.manifest,
|
|
140
|
+
read: entry,
|
|
141
|
+
}));
|
|
142
|
+
const sourceMapDiagnostics = summarizeDocumentMarkPlans(plans);
|
|
143
|
+
const codedTextRootsByDocumentId = codedTextRootsForRenderFrameReads({
|
|
144
|
+
reads: documents,
|
|
145
|
+
codedContext,
|
|
146
|
+
});
|
|
147
|
+
const dependencies = [
|
|
148
|
+
...(options.dependencies ?? []),
|
|
149
|
+
...dependenciesForRenderFrameReads(documents),
|
|
150
|
+
...collectPreviewFrameDependencies(options.context, ...documents.map((read) => read.document)),
|
|
151
|
+
];
|
|
152
|
+
const echoedAppliedVariantId = appliedVariantIdFromRenderFrameReads(documents);
|
|
153
|
+
const echoedRequestedVariantId = requestedVariantIdFromRenderFrameReads(documents);
|
|
154
|
+
const previewScope = previewScopeFromRenderFrameReads(documents);
|
|
155
|
+
const variantId = echoedAppliedVariantId !== undefined
|
|
156
|
+
? echoedAppliedVariantId
|
|
157
|
+
: echoedRequestedVariantId !== undefined
|
|
158
|
+
? echoedRequestedVariantId
|
|
159
|
+
: options.variantId === undefined
|
|
160
|
+
? variantIdFromRenderFrameReads(documents)
|
|
161
|
+
: normalizePreviewVariantId(options.variantId);
|
|
162
|
+
const codeVersion = options.codeVersion ?? runtime.config.resolveCodeVersion();
|
|
163
|
+
const readObservations = collectPreviewReadObservations(options.context, ...documents.map((read) => read.document));
|
|
164
|
+
const readMetadata = resolvePreviewFrameReadMetadataFromObservations(codeVersion, readObservations);
|
|
165
|
+
if (readMetadata === null && readObservations.some((read) => read.readContext))
|
|
166
|
+
return null;
|
|
167
|
+
return unstable_buildPreviewRenderFrameWithRuntime({
|
|
168
|
+
enabled,
|
|
169
|
+
frameId: options.frameId,
|
|
170
|
+
routeHash: options.routeHash,
|
|
171
|
+
variantId: options.variantId === undefined ? variantId ?? undefined : variantId,
|
|
172
|
+
previewScope,
|
|
173
|
+
sessionId: options.sessionId,
|
|
174
|
+
codeVersion,
|
|
175
|
+
renderId: options.renderId,
|
|
176
|
+
generation: options.generation,
|
|
177
|
+
renderNonce: options.renderNonce,
|
|
178
|
+
emissionRevision: options.emissionRevision,
|
|
179
|
+
readContext: readMetadata?.readContext,
|
|
180
|
+
receiptIds: readMetadata?.receiptIds,
|
|
181
|
+
observationId: readMetadata?.observationId,
|
|
182
|
+
renderWatermark: readMetadata?.renderWatermark,
|
|
183
|
+
authoritativeDocumentIds: options.authoritativeDocumentIds ?? documents
|
|
184
|
+
.map((entry) => entry.document.documentId)
|
|
185
|
+
.filter((value) => value.length > 0),
|
|
186
|
+
dependencies,
|
|
187
|
+
leaves: plans.flatMap((plan) => plan.marks),
|
|
188
|
+
sourceMapDiagnostics,
|
|
189
|
+
codedContext,
|
|
190
|
+
codedTextRootPrefix: options.codedTextRootPrefix ?? [],
|
|
191
|
+
codedTextRootsByDocumentId,
|
|
192
|
+
fixture: options.fixture,
|
|
193
|
+
projectId: options.projectId,
|
|
194
|
+
endpoint: options.endpoint,
|
|
195
|
+
convexUrl: options.convexUrl,
|
|
196
|
+
}, runtime);
|
|
197
|
+
}
|
|
198
|
+
function normalizePreviewDocumentRenderFrameRead(read) {
|
|
199
|
+
if (isRecord(read) && 'document' in read) {
|
|
200
|
+
return read;
|
|
201
|
+
}
|
|
202
|
+
return { document: read };
|
|
203
|
+
}
|
|
204
|
+
function dependenciesForRenderFrameReads(reads) {
|
|
205
|
+
return reads.flatMap((read) => {
|
|
206
|
+
const storyType = read.storyType ?? storyTypeOf(read.document);
|
|
207
|
+
return [
|
|
208
|
+
{
|
|
209
|
+
kind: 'document',
|
|
210
|
+
documentId: read.document.documentId,
|
|
211
|
+
...(storyType === 'unknown' ? {} : { storyType }),
|
|
212
|
+
reason: 'scope-document',
|
|
213
|
+
},
|
|
214
|
+
...(read.dependencies ?? []),
|
|
215
|
+
];
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function variantIdFromRenderFrameReads(reads) {
|
|
219
|
+
for (const read of reads) {
|
|
220
|
+
const variantId = normalizePreviewVariantId(read.document._locale?.variantId) ??
|
|
221
|
+
normalizePreviewVariantId(read.document._variant?.variantId);
|
|
222
|
+
if (variantId !== null)
|
|
223
|
+
return variantId;
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
function appliedVariantIdFromRenderFrameReads(reads) {
|
|
228
|
+
let sawScopeEcho = false;
|
|
229
|
+
for (const read of reads) {
|
|
230
|
+
const appliedVariantId = appliedPreviewVariantIdFromQueryResult(read.document);
|
|
231
|
+
if (appliedVariantId === undefined)
|
|
232
|
+
continue;
|
|
233
|
+
sawScopeEcho = true;
|
|
234
|
+
if (appliedVariantId !== null)
|
|
235
|
+
return appliedVariantId;
|
|
236
|
+
}
|
|
237
|
+
return sawScopeEcho ? null : undefined;
|
|
238
|
+
}
|
|
239
|
+
function requestedVariantIdFromRenderFrameReads(reads) {
|
|
240
|
+
for (const read of reads) {
|
|
241
|
+
const requestedVariantId = requestedPreviewVariantIdFromQueryResult(read.document);
|
|
242
|
+
if (requestedVariantId !== undefined)
|
|
243
|
+
return requestedVariantId;
|
|
244
|
+
}
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
function previewScopeFromRenderFrameReads(reads) {
|
|
248
|
+
let fallback;
|
|
249
|
+
for (const read of reads) {
|
|
250
|
+
const scope = previewReadScopeEchoFromQueryResult(read.document);
|
|
251
|
+
if (scope === undefined)
|
|
252
|
+
continue;
|
|
253
|
+
fallback ??= scope;
|
|
254
|
+
if (scope.appliesToDocument !== false)
|
|
255
|
+
return scope;
|
|
256
|
+
}
|
|
257
|
+
return fallback;
|
|
258
|
+
}
|
|
259
|
+
function defaultSourceMapDiagnostics(leaves) {
|
|
260
|
+
return {
|
|
261
|
+
entries: leaves.length,
|
|
262
|
+
manifestIneligible: 0,
|
|
263
|
+
nonIdentityDerivation: 0,
|
|
264
|
+
carrierSkipped: 0,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function planPreviewDocumentRenderFrameRead(input) {
|
|
268
|
+
const storyType = input.read.storyType ?? storyTypeOf(input.read.document);
|
|
269
|
+
const fields = input.read.fields ?? input.read.document.fields;
|
|
270
|
+
if (fields === null || fields === undefined) {
|
|
271
|
+
return emptyDocumentMarkPlan();
|
|
272
|
+
}
|
|
273
|
+
const queryResult = input.read.fields === undefined && input.read.storyType === undefined
|
|
274
|
+
? input.read.document
|
|
275
|
+
: {
|
|
276
|
+
documentId: input.read.document.documentId,
|
|
277
|
+
storyType,
|
|
278
|
+
fields,
|
|
279
|
+
};
|
|
280
|
+
const materialized = materializePreviewProvenanceSourceMap({
|
|
281
|
+
queryResult,
|
|
282
|
+
manifest: input.manifest,
|
|
283
|
+
// Keys remain document-scoped here. Source-set document scoping belongs to
|
|
284
|
+
// the materializer so every caller receives it exactly once.
|
|
285
|
+
keyPrefix: input.read.keyPrefix ??
|
|
286
|
+
`${input.frameId}:${storyType}:${input.read.document.documentId}`,
|
|
287
|
+
sourceSetPrefix: input.read.sourceSetPrefix ??
|
|
288
|
+
`${safeSourceSetPart(input.frameId)}_${safeSourceSetPart(storyType)}`,
|
|
289
|
+
presence: 'optional',
|
|
290
|
+
});
|
|
291
|
+
const marks = materialized.leaves.flatMap((leaf) => {
|
|
292
|
+
if (input.read.renderedLeavesPolicy === undefined)
|
|
293
|
+
return [leaf];
|
|
294
|
+
const expected = input.read.renderedLeavesPolicy({
|
|
295
|
+
document: input.read.document,
|
|
296
|
+
storyType,
|
|
297
|
+
fields,
|
|
298
|
+
canonicalPath: leaf.canonicalPath,
|
|
299
|
+
leaf,
|
|
300
|
+
});
|
|
301
|
+
return expected ? [{ ...leaf, presence: 'expected' }] : [];
|
|
302
|
+
});
|
|
303
|
+
return documentMarkPlan(marks, materialized, {
|
|
304
|
+
carrierSkipped: materialized.leaves.length - marks.length,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
function codedTextRootsForRenderFrameReads(input) {
|
|
308
|
+
const roots = new Map();
|
|
309
|
+
const contextDocuments = new Map(collectPreviewProvenanceSourceMappedQueryResults(input.codedContext)
|
|
310
|
+
.map((document) => [document.documentId, document]));
|
|
311
|
+
for (const read of input.reads) {
|
|
312
|
+
if (read.codedTextRootPath) {
|
|
313
|
+
const root = valueAtPath(input.codedContext, read.codedTextRootPath);
|
|
314
|
+
if (root !== undefined)
|
|
315
|
+
roots.set(read.document.documentId, root);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const contextDocument = contextDocuments.get(read.document.documentId);
|
|
319
|
+
if (contextDocument && isRecord(contextDocument.fields)) {
|
|
320
|
+
roots.set(read.document.documentId, contextDocument.fields);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return roots;
|
|
324
|
+
}
|
|
325
|
+
function emptyDocumentMarkPlan() {
|
|
326
|
+
return {
|
|
327
|
+
marks: [],
|
|
328
|
+
sourceMapEntries: 0,
|
|
329
|
+
skipped: {
|
|
330
|
+
manifestIneligible: 0,
|
|
331
|
+
nonIdentityDerivation: 0,
|
|
332
|
+
},
|
|
333
|
+
carrierSkipped: 0,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
function documentMarkPlan(marks, materialized, options = {}) {
|
|
337
|
+
return {
|
|
338
|
+
marks,
|
|
339
|
+
sourceMapEntries: materialized.sourceMapEntries,
|
|
340
|
+
skipped: materialized.skipped,
|
|
341
|
+
carrierSkipped: options.carrierSkipped ?? 0,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function summarizeDocumentMarkPlans(plans) {
|
|
345
|
+
return {
|
|
346
|
+
entries: sum(plans, (plan) => plan.sourceMapEntries),
|
|
347
|
+
manifestIneligible: sum(plans, (plan) => plan.skipped.manifestIneligible),
|
|
348
|
+
nonIdentityDerivation: sum(plans, (plan) => plan.skipped.nonIdentityDerivation),
|
|
349
|
+
carrierSkipped: sum(plans, (plan) => plan.carrierSkipped),
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function capPreviewProvenanceLeaves(input) {
|
|
353
|
+
const leaves = [];
|
|
354
|
+
let capped = false;
|
|
355
|
+
for (const leaf of input.leaves) {
|
|
356
|
+
if (leaves.length >= RENDER_FRAME_SOURCE_SET_CAP ||
|
|
357
|
+
leaves.length >= RENDER_FRAME_MARKER_CAP) {
|
|
358
|
+
capped = true;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
const candidate = [...leaves, leaf];
|
|
362
|
+
if (estimatePreviewProvenanceFrameBytes(input, candidate) >
|
|
363
|
+
RENDER_FRAME_JSON_BYTES_CAP) {
|
|
364
|
+
capped = true;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
leaves.push(leaf);
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
leaves,
|
|
371
|
+
dropped: input.leaves.length - leaves.length,
|
|
372
|
+
capped,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function previewRenderFrameDiagnostics(input) {
|
|
376
|
+
const carrierSkipped = input.input.sourceMapDiagnostics.carrierSkipped +
|
|
377
|
+
input.cap.dropped +
|
|
378
|
+
countSkippedCarrierPlans(input.publicSidecar) +
|
|
379
|
+
input.codedTextWrites.failures.length;
|
|
380
|
+
return {
|
|
381
|
+
sourceMapEntries: input.input.sourceMapDiagnostics.entries,
|
|
382
|
+
carriersWritten: countWrittenCarrierPlans(input.publicSidecar),
|
|
383
|
+
carrierSkipped,
|
|
384
|
+
frameBytes: jsonByteLength(input.frame),
|
|
385
|
+
frameCapped: input.cap.capped,
|
|
386
|
+
skipped: {
|
|
387
|
+
manifestIneligible: input.input.sourceMapDiagnostics.manifestIneligible,
|
|
388
|
+
nonIdentityDerivation: input.input.sourceMapDiagnostics.nonIdentityDerivation,
|
|
389
|
+
cap: input.cap.dropped,
|
|
390
|
+
codedTextWriteFailures: input.codedTextWrites.failures.length,
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function estimatePreviewProvenanceFrameBytes(input, leaves) {
|
|
395
|
+
const routeHash = input.routeHash ?? 'x'.repeat(64);
|
|
396
|
+
const codeVersion = input.codeVersion ?? input.runtime.config.resolveCodeVersion();
|
|
397
|
+
const renderId = input.renderId ??
|
|
398
|
+
defaultPreviewProvenanceRenderId({
|
|
399
|
+
frameId: input.frameId,
|
|
400
|
+
routeHash,
|
|
401
|
+
});
|
|
402
|
+
const frame = {
|
|
403
|
+
type: 'storystick.preview.provenance-frame',
|
|
404
|
+
version: 1,
|
|
405
|
+
sessionId: input.sessionId ?? input.fixture?.sessionId ?? 'preview-session',
|
|
406
|
+
routeHash,
|
|
407
|
+
...(normalizePreviewVariantId(input.variantId) !== null
|
|
408
|
+
? { variantId: normalizePreviewVariantId(input.variantId) }
|
|
409
|
+
: {}),
|
|
410
|
+
codeVersion,
|
|
411
|
+
renderId,
|
|
412
|
+
generation: input.generation ?? 1,
|
|
413
|
+
sourceSets: leaves.map(estimatedSourceSetForLeaf),
|
|
414
|
+
markers: leaves.map((leaf) => ({
|
|
415
|
+
markerId: ESTIMATED_MARKER_ID,
|
|
416
|
+
sourceSetId: leaf.sourceSetId,
|
|
417
|
+
modality: 'text',
|
|
418
|
+
anchorKind: 'element',
|
|
419
|
+
carrierPlans: estimatedCarrierPlansForLeaf(leaf),
|
|
420
|
+
anchorMultiplicity: leaf.anchorMultiplicity,
|
|
421
|
+
presence: leaf.presence,
|
|
422
|
+
renderedTextFingerprint: 'txt:000000:000000',
|
|
423
|
+
})),
|
|
424
|
+
};
|
|
425
|
+
return jsonByteLength(frame);
|
|
426
|
+
}
|
|
427
|
+
function estimatedSourceSetForLeaf(leaf) {
|
|
428
|
+
return previewProvenanceSourceSetForLeaf(leaf);
|
|
429
|
+
}
|
|
430
|
+
function estimatedCarrierPlansForLeaf(leaf) {
|
|
431
|
+
const carrierPlans = [
|
|
432
|
+
createPreviewProvenanceAttributeCarrierPlan({
|
|
433
|
+
modality: 'text',
|
|
434
|
+
anchorKind: 'element',
|
|
435
|
+
}),
|
|
436
|
+
];
|
|
437
|
+
if (leaf.codedRichTextTextNodeIndex !== undefined) {
|
|
438
|
+
carrierPlans.push(createPreviewProvenanceCodedTextCarrierPlan({
|
|
439
|
+
surface: 'rich-text-text-node',
|
|
440
|
+
}));
|
|
441
|
+
}
|
|
442
|
+
else if (leaf.codedText === true || leaf.codedTextPath !== undefined) {
|
|
443
|
+
const policy = classifyPreviewProvenanceCodedTextTarget({
|
|
444
|
+
canonicalPath: leaf.navigationPath ?? leaf.canonicalPath,
|
|
445
|
+
sourceKind: leaf.sourceKind === 'richtext' ? 'richtext' : 'stored',
|
|
446
|
+
});
|
|
447
|
+
if (policy.allowed) {
|
|
448
|
+
carrierPlans.push(createPreviewProvenanceCodedTextCarrierPlan({
|
|
449
|
+
surface: policy.surface,
|
|
450
|
+
}));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return carrierPlans;
|
|
454
|
+
}
|
|
455
|
+
function countWrittenCarrierPlans(sidecar) {
|
|
456
|
+
return sum(sidecar?.markers ?? [], (marker) => (marker.carrierPlans ?? []).filter((plan) => plan.status === 'emitted')
|
|
457
|
+
.length);
|
|
458
|
+
}
|
|
459
|
+
function countSkippedCarrierPlans(sidecar) {
|
|
460
|
+
return sum(sidecar?.markers ?? [], (marker) => (marker.carrierPlans ?? []).filter((plan) => plan.status !== 'emitted')
|
|
461
|
+
.length);
|
|
462
|
+
}
|
|
463
|
+
async function buildFixtureRenderFrame(input, capped) {
|
|
464
|
+
const identity = await resolveFixturePreviewIdentity(input);
|
|
465
|
+
const codeVersion = input.codeVersion ?? input.runtime.config.resolveCodeVersion();
|
|
466
|
+
const renderId = input.renderId ??
|
|
467
|
+
defaultPreviewProvenanceRenderId({
|
|
468
|
+
frameId: input.frameId,
|
|
469
|
+
routeHash: identity.routeHash,
|
|
470
|
+
});
|
|
471
|
+
const generation = input.generation ?? 1;
|
|
472
|
+
const generatedTemporalIdentity = createPreviewProvenanceTemporalIdentity(input.runtime, {
|
|
473
|
+
sessionId: identity.sessionId,
|
|
474
|
+
frameId: input.frameId,
|
|
475
|
+
routeHash: identity.routeHash,
|
|
476
|
+
codeVersion,
|
|
477
|
+
renderId,
|
|
478
|
+
generation,
|
|
479
|
+
});
|
|
480
|
+
const recorded = await recordPreviewProvenanceEditableLeaves({
|
|
481
|
+
sessionId: identity.sessionId,
|
|
482
|
+
routeHash: identity.routeHash,
|
|
483
|
+
variantId: identity.variantId,
|
|
484
|
+
previewScope: input.previewScope,
|
|
485
|
+
codeVersion,
|
|
486
|
+
renderId,
|
|
487
|
+
generation,
|
|
488
|
+
renderNonce: input.renderNonce ?? generatedTemporalIdentity.renderNonce,
|
|
489
|
+
emissionRevision: input.emissionRevision ?? generatedTemporalIdentity.emissionRevision,
|
|
490
|
+
enabled: input.enabled,
|
|
491
|
+
leaves: capped.leaves,
|
|
492
|
+
codedTextRoot: input.codedTextRoot,
|
|
493
|
+
codedTextRootPrefix: input.codedTextRootPrefix,
|
|
494
|
+
codedTextRootsByDocumentId: input.codedTextRootsByDocumentId,
|
|
495
|
+
});
|
|
496
|
+
const dependencySet = createPreviewFrameDependencySet({
|
|
497
|
+
sessionId: identity.sessionId,
|
|
498
|
+
routeHash: identity.routeHash,
|
|
499
|
+
variantId: identity.variantId,
|
|
500
|
+
codeVersion,
|
|
501
|
+
frameId: input.frameId,
|
|
502
|
+
renderId,
|
|
503
|
+
generation,
|
|
504
|
+
observationId: input.readMetadata?.observationId,
|
|
505
|
+
renderWatermark: input.readMetadata?.renderWatermark,
|
|
506
|
+
dependencies: input.dependencies ?? input.authoritativeDocumentIds.map((documentId) => ({
|
|
507
|
+
kind: 'document',
|
|
508
|
+
documentId,
|
|
509
|
+
reason: 'rendered-document',
|
|
510
|
+
})),
|
|
511
|
+
});
|
|
512
|
+
const validation = validateProvenanceFrame(recorded.renderFrame, {
|
|
513
|
+
documentIds: new Set(input.authoritativeDocumentIds),
|
|
514
|
+
routeHash: identity.routeHash,
|
|
515
|
+
variantId: identity.variantId,
|
|
516
|
+
codeVersion,
|
|
517
|
+
});
|
|
518
|
+
const publicSidecar = recorded.publicSidecar === null
|
|
519
|
+
? null
|
|
520
|
+
: createPublicSidecar(recorded.renderFrame, dependencySet);
|
|
521
|
+
return {
|
|
522
|
+
frameId: input.frameId,
|
|
523
|
+
sessionId: identity.sessionId,
|
|
524
|
+
routeHash: identity.routeHash,
|
|
525
|
+
variantId: identity.variantId,
|
|
526
|
+
attrsByKey: recorded.attrsByKey,
|
|
527
|
+
codedDocument: attachPreviewProvenanceContext(input.codedDocument, recorded.attrsByKey),
|
|
528
|
+
codedContext: attachPreviewProvenanceContext(input.codedContext, recorded.attrsByKey),
|
|
529
|
+
renderFrame: recorded.renderFrame,
|
|
530
|
+
dependencySet,
|
|
531
|
+
publicSidecar,
|
|
532
|
+
validationOk: validation.ok,
|
|
533
|
+
diagnostics: previewRenderFrameDiagnostics({
|
|
534
|
+
input,
|
|
535
|
+
cap: capped,
|
|
536
|
+
frame: recorded.renderFrame,
|
|
537
|
+
publicSidecar,
|
|
538
|
+
codedTextWrites: recorded.codedTextWrites,
|
|
539
|
+
}),
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
async function resolveFixturePreviewIdentity(input) {
|
|
543
|
+
const fixture = input.fixture;
|
|
544
|
+
const explicitVariantId = input.variantId === undefined
|
|
545
|
+
? undefined
|
|
546
|
+
: normalizePreviewVariantId(input.variantId);
|
|
547
|
+
const fallbackSessionId = fixture?.sessionId ?? input.sessionId ?? '';
|
|
548
|
+
const liveSessionId = await input.runtime.recorder.readSessionId();
|
|
549
|
+
const sessionId = liveSessionId ?? fallbackSessionId;
|
|
550
|
+
const liveRouteIdentity = liveSessionId !== null && input.variantId === undefined
|
|
551
|
+
? await input.runtime.recorder.resolveRouteIdentity({
|
|
552
|
+
sessionId,
|
|
553
|
+
fallbackPathname: input.fallbackPathname,
|
|
554
|
+
projectId: input.projectId,
|
|
555
|
+
endpoint: input.endpoint,
|
|
556
|
+
convexUrl: input.convexUrl,
|
|
557
|
+
}).catch(() => null)
|
|
558
|
+
: null;
|
|
559
|
+
const fallbackVariantId = explicitVariantId !== undefined
|
|
560
|
+
? explicitVariantId
|
|
561
|
+
: liveRouteIdentity?.variantId ?? normalizePreviewVariantId(fixture?.variantId);
|
|
562
|
+
if (input.routeHash !== undefined) {
|
|
563
|
+
return {
|
|
564
|
+
sessionId,
|
|
565
|
+
routeHash: input.routeHash,
|
|
566
|
+
variantId: fallbackVariantId,
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
if (liveSessionId !== null) {
|
|
570
|
+
const routeIdentity = liveRouteIdentity ??
|
|
571
|
+
await input.runtime.recorder.resolveRouteIdentity({
|
|
572
|
+
sessionId,
|
|
573
|
+
fallbackPathname: input.fallbackPathname,
|
|
574
|
+
projectId: input.projectId,
|
|
575
|
+
endpoint: input.endpoint,
|
|
576
|
+
convexUrl: input.convexUrl,
|
|
577
|
+
}).catch(() => null);
|
|
578
|
+
if (routeIdentity !== null) {
|
|
579
|
+
return {
|
|
580
|
+
sessionId,
|
|
581
|
+
routeHash: routeIdentity.routeHash,
|
|
582
|
+
variantId: fallbackVariantId ?? routeIdentity.variantId,
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
sessionId,
|
|
588
|
+
routeHash: fixture?.routeHash ??
|
|
589
|
+
`route:${input.fallbackPathname || '/'}`,
|
|
590
|
+
variantId: fallbackVariantId,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
function logPreviewProvenanceCodedTextWriteDebug(input) {
|
|
594
|
+
if (process.env.STORYSTICK_PREVIEW_PROVENANCE_DEBUG !== '1')
|
|
595
|
+
return;
|
|
596
|
+
const contextMarkerCounts = {};
|
|
597
|
+
if (isRecord(input.codedContext)) {
|
|
598
|
+
for (const [key, value] of Object.entries(input.codedContext)) {
|
|
599
|
+
const count = countCodedTextMarkers(value);
|
|
600
|
+
if (count > 0)
|
|
601
|
+
contextMarkerCounts[key] = count;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
console.warn('[preview-provenance] coded-text writes', {
|
|
605
|
+
frameId: input.frameId,
|
|
606
|
+
pathname: input.pathname ?? null,
|
|
607
|
+
attempted: input.codedTextWrites.attempted,
|
|
608
|
+
written: input.codedTextWrites.written,
|
|
609
|
+
failures: input.codedTextWrites.failures.length,
|
|
610
|
+
capDropped: input.cap.dropped,
|
|
611
|
+
capApplied: input.cap.capped,
|
|
612
|
+
markersInCodedDocument: countCodedTextMarkers(input.codedDocument),
|
|
613
|
+
markersInCodedContext: countCodedTextMarkers(input.codedContext),
|
|
614
|
+
markersInCodedContextByKey: contextMarkerCounts,
|
|
615
|
+
});
|
|
616
|
+
for (const failure of input.codedTextWrites.failures.slice(0, 48)) {
|
|
617
|
+
console.warn('[preview-provenance] coded-text write failure', failure);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
function countCodedTextMarkers(value) {
|
|
621
|
+
if (value === undefined)
|
|
622
|
+
return 0;
|
|
623
|
+
try {
|
|
624
|
+
const json = JSON.stringify(value);
|
|
625
|
+
if (typeof json !== 'string')
|
|
626
|
+
return 0;
|
|
627
|
+
return json.split(PREVIEW_PROVENANCE_CODED_TEXT_START).length - 1;
|
|
628
|
+
}
|
|
629
|
+
catch {
|
|
630
|
+
return 0;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function attachPreviewProvenanceContext(value, attrsByKey) {
|
|
634
|
+
if (value === undefined)
|
|
635
|
+
return undefined;
|
|
636
|
+
return withPreviewProvenanceContext(value, attrsByKey);
|
|
637
|
+
}
|
|
638
|
+
function jsonByteLength(value) {
|
|
639
|
+
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
640
|
+
}
|
|
641
|
+
function sum(values, valueOf) {
|
|
642
|
+
let total = 0;
|
|
643
|
+
for (const value of values)
|
|
644
|
+
total += valueOf(value);
|
|
645
|
+
return total;
|
|
646
|
+
}
|
|
647
|
+
function cloneJson(value) {
|
|
648
|
+
return JSON.parse(JSON.stringify(value));
|
|
649
|
+
}
|
|
650
|
+
function valueAtPath(root, path) {
|
|
651
|
+
let cursor = root;
|
|
652
|
+
for (const part of path) {
|
|
653
|
+
if (typeof part === 'number') {
|
|
654
|
+
if (!Array.isArray(cursor))
|
|
655
|
+
return undefined;
|
|
656
|
+
cursor = cursor[part];
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
if (!isRecord(cursor))
|
|
660
|
+
return undefined;
|
|
661
|
+
cursor = cursor[part];
|
|
662
|
+
}
|
|
663
|
+
return cursor;
|
|
664
|
+
}
|
|
665
|
+
function isRecord(value) {
|
|
666
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
667
|
+
}
|
|
668
|
+
function storyTypeOf(document) {
|
|
669
|
+
return typeof document.storyType === 'string' && document.storyType.length > 0
|
|
670
|
+
? document.storyType
|
|
671
|
+
: 'unknown';
|
|
672
|
+
}
|
|
673
|
+
function safeSourceSetPart(value) {
|
|
674
|
+
return value.replace(/[^A-Za-z0-9]+/g, '_').replace(/^_+|_+$/g, '') ||
|
|
675
|
+
'field';
|
|
676
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic preview render-id derivation.
|
|
3
|
+
*
|
|
4
|
+
* Marker identity (HMAC) incorporates the renderId, so the stability of
|
|
5
|
+
* every provenance marker across refreshes rests on this derivation
|
|
6
|
+
* having ZERO temporal or random components. Pinned by
|
|
7
|
+
* tests/preview-provenance-render-id.test.ts — do not add Date/random
|
|
8
|
+
* inputs here.
|
|
9
|
+
*/
|
|
10
|
+
export declare function defaultPreviewProvenanceRenderId(input: {
|
|
11
|
+
readonly frameId: string;
|
|
12
|
+
readonly routeHash: string;
|
|
13
|
+
}): string;
|
|
14
|
+
/** Independent mounts of the same document must not replace each other's frame. */
|
|
15
|
+
export declare function createPreviewOccurrenceId(): string;
|