@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.
Files changed (245) hide show
  1. package/LICENSE +112 -0
  2. package/PUBLIC-API.md +55 -0
  3. package/README.md +42 -2
  4. package/dist/.source-hash +1 -0
  5. package/dist/authoring/runtime-contract.d.ts +89 -0
  6. package/dist/authoring/runtime-contract.js +28 -0
  7. package/dist/channel-taxonomy.d.ts +17 -0
  8. package/dist/channel-taxonomy.js +46 -0
  9. package/dist/context-command.d.ts +18 -0
  10. package/dist/context-command.js +38 -0
  11. package/dist/dev/suspicious-codeword-detector.d.ts +15 -0
  12. package/dist/dev/suspicious-codeword-detector.js +220 -0
  13. package/dist/dev/suspicious-codeword-detector.noop.d.ts +3 -0
  14. package/dist/dev/suspicious-codeword-detector.noop.js +4 -0
  15. package/dist/framework/browser-context.d.ts +2 -0
  16. package/dist/framework/browser-context.js +2 -0
  17. package/dist/framework/generation-refresh.d.ts +23 -0
  18. package/dist/framework/generation-refresh.js +82 -0
  19. package/dist/framework/generation-signal.d.ts +8 -0
  20. package/dist/framework/generation-signal.js +17 -0
  21. package/dist/framework/projection-generation-watch.d.ts +5 -0
  22. package/dist/framework/projection-generation-watch.js +53 -0
  23. package/dist/framework/render-receipt.d.ts +8 -0
  24. package/dist/framework/render-receipt.js +10 -0
  25. package/dist/framework/runtime-adapter-store.d.ts +30 -0
  26. package/dist/framework/runtime-adapter-store.js +81 -0
  27. package/dist/grant-coordinator.d.ts +53 -0
  28. package/dist/grant-coordinator.js +329 -0
  29. package/dist/grant-lifecycle.d.ts +52 -0
  30. package/dist/grant-lifecycle.js +74 -0
  31. package/dist/identity/__test-adapter.d.ts +34 -0
  32. package/dist/identity/__test-adapter.js +59 -0
  33. package/dist/identity/browser-context-gate.d.ts +4 -0
  34. package/dist/identity/browser-context-gate.js +22 -0
  35. package/dist/identity/browser-context.d.ts +13 -0
  36. package/dist/identity/browser-context.js +22 -0
  37. package/dist/identity/carriers/postmessage.d.ts +84 -0
  38. package/dist/identity/carriers/postmessage.js +177 -0
  39. package/dist/identity/carriers/storage-state.d.ts +41 -0
  40. package/dist/identity/carriers/storage-state.js +99 -0
  41. package/dist/identity/carriers/storage.d.ts +39 -0
  42. package/dist/identity/carriers/storage.js +182 -0
  43. package/dist/identity/carriers/url.d.ts +19 -0
  44. package/dist/identity/carriers/url.js +38 -0
  45. package/dist/identity/identity-state-machine.d.ts +70 -0
  46. package/dist/identity/identity-state-machine.js +244 -0
  47. package/dist/identity/identity-types.d.ts +192 -0
  48. package/dist/identity/identity-types.js +22 -0
  49. package/dist/identity/index.d.ts +18 -0
  50. package/dist/identity/index.js +16 -0
  51. package/dist/identity/preview-cookie.d.ts +9 -0
  52. package/dist/identity/preview-cookie.js +12 -0
  53. package/dist/identity/preview-draft.d.ts +6 -0
  54. package/dist/identity/preview-draft.js +25 -0
  55. package/dist/identity/preview-identity.d.ts +28 -0
  56. package/dist/identity/preview-identity.js +84 -0
  57. package/dist/identity/preview-scope.d.ts +28 -0
  58. package/dist/identity/preview-scope.js +47 -0
  59. package/dist/identity/resolver.d.ts +110 -0
  60. package/dist/identity/resolver.js +334 -0
  61. package/dist/identity/session-query.d.ts +4 -0
  62. package/dist/identity/session-query.js +19 -0
  63. package/dist/index.d.ts +90 -0
  64. package/dist/index.js +788 -0
  65. package/dist/interaction-mode.d.ts +58 -0
  66. package/dist/interaction-mode.js +93 -0
  67. package/dist/nav-handler.d.ts +95 -0
  68. package/dist/nav-handler.js +84 -0
  69. package/dist/overlay-label.d.ts +79 -0
  70. package/dist/overlay-label.js +73 -0
  71. package/dist/provenance/anchor-map.d.ts +95 -0
  72. package/dist/provenance/anchor-map.js +177 -0
  73. package/dist/provenance/carrier-plan.d.ts +51 -0
  74. package/dist/provenance/carrier-plan.js +90 -0
  75. package/dist/provenance/coded-text.d.ts +20 -0
  76. package/dist/provenance/coded-text.js +302 -0
  77. package/dist/provenance/direct-edit-locator.d.ts +29 -0
  78. package/dist/provenance/direct-edit-locator.js +218 -0
  79. package/dist/provenance/editable-leaf.d.ts +134 -0
  80. package/dist/provenance/editable-leaf.js +483 -0
  81. package/dist/provenance/editor-target.d.ts +29 -0
  82. package/dist/provenance/editor-target.js +46 -0
  83. package/dist/provenance/field-leaf-walker.d.ts +21 -0
  84. package/dist/provenance/field-leaf-walker.js +98 -0
  85. package/dist/provenance/frame-dependencies.d.ts +212 -0
  86. package/dist/provenance/frame-dependencies.js +550 -0
  87. package/dist/provenance/index.d.ts +26 -0
  88. package/dist/provenance/index.js +26 -0
  89. package/dist/provenance/local-events.d.ts +1 -0
  90. package/dist/provenance/local-events.js +1 -0
  91. package/dist/provenance/markers.d.ts +21 -0
  92. package/dist/provenance/markers.js +70 -0
  93. package/dist/provenance/multi-frame-anchor-map.d.ts +54 -0
  94. package/dist/provenance/multi-frame-anchor-map.js +109 -0
  95. package/dist/provenance/normalize.d.ts +2 -0
  96. package/dist/provenance/normalize.js +19 -0
  97. package/dist/provenance/overlay-focus-echo.d.ts +17 -0
  98. package/dist/provenance/overlay-focus-echo.js +16 -0
  99. package/dist/provenance/overlay-projection.d.ts +65 -0
  100. package/dist/provenance/overlay-projection.js +201 -0
  101. package/dist/provenance/owner-map.d.ts +55 -0
  102. package/dist/provenance/owner-map.js +239 -0
  103. package/dist/provenance/read-carrier.d.ts +22 -0
  104. package/dist/provenance/read-carrier.js +92 -0
  105. package/dist/provenance/recorder.d.ts +38 -0
  106. package/dist/provenance/recorder.js +82 -0
  107. package/dist/provenance/render-context.d.ts +106 -0
  108. package/dist/provenance/render-context.js +338 -0
  109. package/dist/provenance/reveal-contract.d.ts +44 -0
  110. package/dist/provenance/reveal-contract.js +1 -0
  111. package/dist/provenance/richtext-slice-embed-address.d.ts +20 -0
  112. package/dist/provenance/richtext-slice-embed-address.js +35 -0
  113. package/dist/provenance/runtime-script.d.ts +1 -0
  114. package/dist/provenance/runtime-script.js +2217 -0
  115. package/dist/provenance/sidecar-store.d.ts +63 -0
  116. package/dist/provenance/sidecar-store.js +151 -0
  117. package/dist/provenance/sidecar.d.ts +34 -0
  118. package/dist/provenance/sidecar.js +227 -0
  119. package/dist/provenance/slice-model.d.ts +28 -0
  120. package/dist/provenance/slice-model.js +86 -0
  121. package/dist/provenance/source-identity.d.ts +3 -0
  122. package/dist/provenance/source-identity.js +7 -0
  123. package/dist/provenance/source-map-materializer.d.ts +76 -0
  124. package/dist/provenance/source-map-materializer.js +286 -0
  125. package/dist/provenance/source-registry.d.ts +103 -0
  126. package/dist/provenance/source-registry.js +562 -0
  127. package/dist/provenance/transformed-output-gate.d.ts +161 -0
  128. package/dist/provenance/transformed-output-gate.js +171 -0
  129. package/dist/provenance/types.d.ts +102 -0
  130. package/dist/provenance/types.js +1 -0
  131. package/dist/refresh-policy.d.ts +11 -0
  132. package/dist/refresh-policy.js +14 -0
  133. package/dist/reveal-target.d.ts +8 -0
  134. package/dist/reveal-target.js +47 -0
  135. package/dist/route-paths.d.ts +11 -0
  136. package/dist/route-paths.js +14 -0
  137. package/dist/router-subscriber.d.ts +92 -0
  138. package/dist/router-subscriber.js +44 -0
  139. package/dist/runtime/anchor-types.d.ts +5 -0
  140. package/dist/runtime/anchor-types.js +1 -0
  141. package/dist/runtime/authority-store.d.ts +31 -0
  142. package/dist/runtime/authority-store.js +56 -0
  143. package/dist/runtime/boot.d.ts +52 -0
  144. package/dist/runtime/boot.js +379 -0
  145. package/dist/runtime/content-refresh.d.ts +30 -0
  146. package/dist/runtime/content-refresh.js +68 -0
  147. package/dist/runtime/emit-runtime-error.d.ts +51 -0
  148. package/dist/runtime/emit-runtime-error.js +64 -0
  149. package/dist/runtime/field-proxy.d.ts +112 -0
  150. package/dist/runtime/field-proxy.js +471 -0
  151. package/dist/runtime/form-contract-reporter.d.ts +99 -0
  152. package/dist/runtime/form-contract-reporter.js +391 -0
  153. package/dist/runtime/invalidation-adapter.d.ts +17 -0
  154. package/dist/runtime/invalidation-adapter.js +42 -0
  155. package/dist/runtime/live-query-overlay.d.ts +39 -0
  156. package/dist/runtime/live-query-overlay.js +345 -0
  157. package/dist/runtime/momentary-navigate.d.ts +16 -0
  158. package/dist/runtime/momentary-navigate.js +106 -0
  159. package/dist/runtime/observation-scheduler.d.ts +15 -0
  160. package/dist/runtime/observation-scheduler.js +42 -0
  161. package/dist/runtime/perf-metrics.d.ts +28 -0
  162. package/dist/runtime/perf-metrics.js +90 -0
  163. package/dist/runtime/preview-interaction-policy.d.ts +1 -0
  164. package/dist/runtime/preview-interaction-policy.js +103 -0
  165. package/dist/runtime/preview-overlay-painter.d.ts +27 -0
  166. package/dist/runtime/preview-overlay-painter.js +1732 -0
  167. package/dist/runtime/preview-overlay-sidecar.d.ts +26 -0
  168. package/dist/runtime/preview-overlay-sidecar.js +45 -0
  169. package/dist/runtime/preview-perspective-alignment.d.ts +15 -0
  170. package/dist/runtime/preview-perspective-alignment.js +40 -0
  171. package/dist/runtime/preview-perspective-intent-state.d.ts +23 -0
  172. package/dist/runtime/preview-perspective-intent-state.js +5 -0
  173. package/dist/runtime/preview-transition-state.d.ts +142 -0
  174. package/dist/runtime/preview-transition-state.js +257 -0
  175. package/dist/runtime/render-mode-state.d.ts +51 -0
  176. package/dist/runtime/render-mode-state.js +76 -0
  177. package/dist/runtime/request-id.d.ts +4 -0
  178. package/dist/runtime/request-id.js +8 -0
  179. package/dist/runtime/resolve-schema-field.d.ts +99 -0
  180. package/dist/runtime/resolve-schema-field.js +356 -0
  181. package/dist/runtime/runtime-error-dispatch.d.ts +23 -0
  182. package/dist/runtime/runtime-error-dispatch.js +75 -0
  183. package/dist/runtime/schema-store.d.ts +121 -0
  184. package/dist/runtime/schema-store.js +667 -0
  185. package/dist/runtime/snapshot-assembly.d.ts +104 -0
  186. package/dist/runtime/snapshot-assembly.js +553 -0
  187. package/dist/runtime/snapshot-reporter.d.ts +55 -0
  188. package/dist/runtime/snapshot-reporter.js +375 -0
  189. package/dist/runtime/standalone-overlay-controller.d.ts +33 -0
  190. package/dist/runtime/standalone-overlay-controller.js +281 -0
  191. package/dist/runtime/store.d.ts +307 -0
  192. package/dist/runtime/store.js +1026 -0
  193. package/dist/runtime/windowed-minimap-projection.d.ts +28 -0
  194. package/dist/runtime/windowed-minimap-projection.js +189 -0
  195. package/dist/runtime/workspace-shortcuts.d.ts +30 -0
  196. package/dist/runtime/workspace-shortcuts.js +188 -0
  197. package/dist/sdk-error-copy.d.ts +48 -0
  198. package/dist/sdk-error-copy.js +182 -0
  199. package/dist/select-cursor.d.ts +2 -0
  200. package/dist/select-cursor.js +23 -0
  201. package/dist/server/admission-cookie.d.ts +38 -0
  202. package/dist/server/admission-cookie.js +122 -0
  203. package/dist/server/control-client.d.ts +29 -0
  204. package/dist/server/control-client.js +22 -0
  205. package/dist/server/control-errors.d.ts +22 -0
  206. package/dist/server/control-errors.js +165 -0
  207. package/dist/server/draft-route.d.ts +12 -0
  208. package/dist/server/draft-route.js +45 -0
  209. package/dist/server/extract-token.d.ts +30 -0
  210. package/dist/server/extract-token.js +98 -0
  211. package/dist/server/grant.d.ts +128 -0
  212. package/dist/server/grant.js +395 -0
  213. package/dist/server/ordinary-read-provenance.d.ts +11 -0
  214. package/dist/server/ordinary-read-provenance.js +124 -0
  215. package/dist/server/preview-read-metadata.d.ts +10 -0
  216. package/dist/server/preview-read-metadata.js +27 -0
  217. package/dist/server/provenance-frame-builder.d.ts +53 -0
  218. package/dist/server/provenance-frame-builder.js +102 -0
  219. package/dist/server/provenance-runtime.d.ts +70 -0
  220. package/dist/server/provenance-runtime.js +46 -0
  221. package/dist/server/read-context-command.d.ts +11 -0
  222. package/dist/server/read-context-command.js +53 -0
  223. package/dist/server/read-identity.d.ts +3 -0
  224. package/dist/server/read-identity.js +63 -0
  225. package/dist/server/read-lifecycle.d.ts +17 -0
  226. package/dist/server/read-lifecycle.js +52 -0
  227. package/dist/server/render-frame-provenance.d.ts +133 -0
  228. package/dist/server/render-frame-provenance.js +676 -0
  229. package/dist/server/render-id.d.ts +15 -0
  230. package/dist/server/render-id.js +22 -0
  231. package/dist/server/route-document-provenance.d.ts +77 -0
  232. package/dist/server/route-document-provenance.js +1327 -0
  233. package/dist/server/route-session-cookie.d.ts +33 -0
  234. package/dist/server/route-session-cookie.js +54 -0
  235. package/dist/session-projections.d.ts +33 -0
  236. package/dist/session-projections.js +43 -0
  237. package/dist/session-subscriber.d.ts +124 -0
  238. package/dist/session-subscriber.js +79 -0
  239. package/dist/sha256-fallback.d.ts +30 -0
  240. package/dist/sha256-fallback.js +126 -0
  241. package/dist/types.d.ts +446 -0
  242. package/dist/types.js +85 -0
  243. package/dist/validators.d.ts +61 -0
  244. package/dist/validators.js +110 -0
  245. package/package.json +206 -3
@@ -0,0 +1,76 @@
1
+ import { type PreviewReadScopeEcho } from '@storystick/client/internal';
2
+ import { type PreviewProvenanceEditableLeaf, type PreviewProvenanceEditableTextLeafContext, type PreviewProvenanceEditableTextPathManifest, type PreviewProvenancePathPart } from './editable-leaf.js';
3
+ import type { PathAnchor, ProvenanceId, SourceSet } from './types.js';
4
+ export interface PreviewProvenanceQueryResultLike {
5
+ readonly documentId: string;
6
+ readonly storyType?: string;
7
+ readonly fields?: unknown;
8
+ readonly _previewScope?: PreviewReadScopeEcho;
9
+ readonly _locale?: {
10
+ readonly variantId?: string | null;
11
+ };
12
+ readonly _variant?: {
13
+ readonly variantId?: string | null;
14
+ };
15
+ }
16
+ export interface PreviewProvenanceSourceMapEntry {
17
+ readonly resultPath: readonly PreviewProvenancePathPart[];
18
+ readonly documentId: string;
19
+ readonly variantId?: string;
20
+ readonly readScope?: PreviewReadScopeEcho;
21
+ readonly storyType: string;
22
+ readonly canonicalPath: string;
23
+ readonly pathAnchors: readonly PathAnchor[];
24
+ readonly sourceKind: PreviewProvenanceEditableTextLeafContext['sourceKind'];
25
+ readonly outputKind?: PreviewProvenanceEditableTextLeafContext['outputKind'];
26
+ readonly renderedText?: string;
27
+ readonly derivation?: SourceSet['derivation'];
28
+ readonly textNodeIndex?: number;
29
+ }
30
+ export interface PreviewProvenanceQueryResultSourceMap {
31
+ readonly documentId: string;
32
+ readonly storyType: string;
33
+ readonly entries: readonly PreviewProvenanceSourceMapEntry[];
34
+ }
35
+ export interface MaterializePreviewProvenanceSourceMapInput {
36
+ readonly queryResult: PreviewProvenanceQueryResultLike;
37
+ readonly manifest: PreviewProvenanceEditableTextPathManifest;
38
+ readonly keyPrefix: string;
39
+ readonly sourceSetPrefix: string;
40
+ readonly keyForEntry?: (entry: PreviewProvenanceSourceMapEntry, defaultKey: string) => string;
41
+ readonly presence?: PreviewProvenanceEditableLeaf['presence'];
42
+ readonly anchorMultiplicity?: PreviewProvenanceEditableLeaf['anchorMultiplicity'];
43
+ }
44
+ export interface MaterializedPreviewProvenanceSourceMap {
45
+ readonly sourceMapEntries: number;
46
+ readonly leaves: readonly PreviewProvenanceEditableLeaf[];
47
+ readonly skipped: PreviewProvenanceSourceMapSkipSummary;
48
+ }
49
+ export interface PreviewProvenanceSourceMapSkipSummary {
50
+ readonly manifestIneligible: number;
51
+ readonly nonIdentityDerivation: number;
52
+ }
53
+ export declare function attachPreviewProvenanceSourceMap<T extends object>(value: T, sourceMap: PreviewProvenanceQueryResultSourceMap): T;
54
+ export declare function getPreviewProvenanceSourceMap(value: unknown): PreviewProvenanceQueryResultSourceMap | null;
55
+ export declare function ensurePreviewProvenanceSourceMap<T extends PreviewProvenanceQueryResultLike>(queryResult: T): PreviewProvenanceQueryResultSourceMap;
56
+ export declare function createPreviewProvenanceQueryResultSourceMap(queryResult: PreviewProvenanceQueryResultLike): PreviewProvenanceQueryResultSourceMap;
57
+ export declare function collectPreviewProvenanceSourceMappedQueryResults(root: unknown): readonly PreviewProvenanceQueryResultLike[];
58
+ export declare function materializePreviewProvenanceSourceMap(input: MaterializePreviewProvenanceSourceMapInput): MaterializedPreviewProvenanceSourceMap;
59
+ /** Identity of an editorial source supplied by this read, including bindings. */
60
+ export declare function previewProvenanceSourceIdentityFromQueryResult(queryResult: PreviewProvenanceQueryResultLike): Pick<ProvenanceId, 'documentId' | 'variantId' | 'readScope'>;
61
+ /**
62
+ * Read the gateway's explicit applied-scope echo.
63
+ *
64
+ * `undefined` means the payload predates the echo and callers may use their
65
+ * legacy identity fallback. `null` is authoritative: the gateway explicitly
66
+ * says living content was applied, so an expected variant must not mask it.
67
+ */
68
+ export declare function appliedPreviewVariantIdFromQueryResult(queryResult: PreviewProvenanceQueryResultLike): string | null | undefined;
69
+ /**
70
+ * Read the requested scope echo even when the concrete document is outside
71
+ * that scope. A host frame can retain the session lifecycle identity while
72
+ * only an applicable target payload is allowed to prove a mismatch.
73
+ */
74
+ export declare function requestedPreviewVariantIdFromQueryResult(queryResult: PreviewProvenanceQueryResultLike): string | null | undefined;
75
+ /** Return the complete gateway-owned scope echo for runtime reporting. */
76
+ export declare function previewReadScopeEchoFromQueryResult(queryResult: PreviewProvenanceQueryResultLike): PreviewReadScopeEcho | undefined;
@@ -0,0 +1,286 @@
1
+ import { getPreviewReadSourceMap, setPreviewReadSourceMap } from '@storystick/types';
2
+ import { createPreviewProvenanceEditableLeaf, formatPreviewProvenanceCanonicalPath, matchingPreviewProvenanceEditablePathPattern, } from './editable-leaf.js';
3
+ import { walkPreviewProvenanceFieldLeaves } from './field-leaf-walker.js';
4
+ import { normalizePreviewVariantId } from '../identity/preview-identity.js';
5
+ export function attachPreviewProvenanceSourceMap(value, sourceMap) {
6
+ setPreviewReadSourceMap(value, sourceMap);
7
+ return value;
8
+ }
9
+ export function getPreviewProvenanceSourceMap(value) {
10
+ if (!isObject(value))
11
+ return null;
12
+ const sourceMap = getPreviewReadSourceMap(value);
13
+ return isPreviewProvenanceSourceMap(sourceMap) ? sourceMap : null;
14
+ }
15
+ export function ensurePreviewProvenanceSourceMap(queryResult) {
16
+ const existing = getPreviewProvenanceSourceMap(queryResult);
17
+ if (existing !== null)
18
+ return existing;
19
+ const sourceMap = createPreviewProvenanceQueryResultSourceMap(queryResult);
20
+ attachPreviewProvenanceSourceMap(queryResult, sourceMap);
21
+ return sourceMap;
22
+ }
23
+ export function createPreviewProvenanceQueryResultSourceMap(queryResult) {
24
+ const storyType = typeof queryResult.storyType === 'string' && queryResult.storyType.length > 0
25
+ ? queryResult.storyType
26
+ : 'unknown';
27
+ const entries = [];
28
+ const sourceIdentity = previewProvenanceSourceIdentityFromQueryResult(queryResult);
29
+ walkPreviewProvenanceFieldLeaves({
30
+ root: queryResult.fields,
31
+ onLeaf: (walked) => {
32
+ entries.push({
33
+ resultPath: walked.path,
34
+ ...sourceIdentity,
35
+ storyType,
36
+ canonicalPath: formatPreviewProvenanceCanonicalPath(walked.path),
37
+ pathAnchors: walked.pathAnchors,
38
+ sourceKind: walked.sourceKind,
39
+ outputKind: walked.outputKind,
40
+ renderedText: walked.renderedText,
41
+ derivation: 'identity',
42
+ ...(walked.textNodeIndex === undefined
43
+ ? {}
44
+ : { textNodeIndex: walked.textNodeIndex }),
45
+ });
46
+ },
47
+ });
48
+ return {
49
+ documentId: queryResult.documentId,
50
+ storyType,
51
+ entries,
52
+ };
53
+ }
54
+ export function collectPreviewProvenanceSourceMappedQueryResults(root) {
55
+ const out = new Map();
56
+ const seen = new WeakSet();
57
+ const visit = (value) => {
58
+ if (!isObject(value))
59
+ return;
60
+ if (seen.has(value))
61
+ return;
62
+ seen.add(value);
63
+ if (isQueryResultLike(value)) {
64
+ // The first occurrence is the canonical render carrier. Delivery
65
+ // documents expose referenced QueryResult-like entries twice (`byId`
66
+ // and `byRef`); letting the later alias replace the first would encode a
67
+ // different clone from the one SDK readers return.
68
+ if (!out.has(value.documentId))
69
+ out.set(value.documentId, value);
70
+ visit(value.resolved);
71
+ const referenced = value._referencedDocs;
72
+ if (isObject(referenced)) {
73
+ // JSON object order is not a contract. Readers use `byId` as their
74
+ // canonical convenience carrier, so always visit it before aliases.
75
+ visit(referenced.byId);
76
+ visit(referenced.byRef);
77
+ }
78
+ else {
79
+ visit(referenced);
80
+ }
81
+ return;
82
+ }
83
+ if (Array.isArray(value)) {
84
+ for (const item of value)
85
+ visit(item);
86
+ return;
87
+ }
88
+ for (const [key, child] of Object.entries(value)) {
89
+ if (key === '__ssPreviewProvenance')
90
+ continue;
91
+ visit(child);
92
+ }
93
+ };
94
+ visit(root);
95
+ return [...out.values()];
96
+ }
97
+ export function materializePreviewProvenanceSourceMap(input) {
98
+ const sourceMap = ensurePreviewProvenanceSourceMap(input.queryResult);
99
+ const leaves = [];
100
+ let manifestIneligible = 0;
101
+ let nonIdentityDerivation = 0;
102
+ for (const entry of sourceMap.entries) {
103
+ const outputKind = entry.outputKind ?? 'text';
104
+ const value = outputKind === 'element'
105
+ ? valueAtPath(input.queryResult.fields, entry.resultPath)
106
+ : entry.renderedText;
107
+ const context = {
108
+ path: entry.resultPath,
109
+ fieldName: leafFieldName(entry.resultPath),
110
+ value,
111
+ sourceKind: entry.sourceKind,
112
+ outputKind,
113
+ textNodeIndex: entry.textNodeIndex,
114
+ };
115
+ const pattern = matchingPreviewProvenanceSourceMapEntryPattern(context, sourceMap.storyType, input.manifest);
116
+ if (pattern === null) {
117
+ manifestIneligible++;
118
+ continue;
119
+ }
120
+ const hasNonIdentityDerivation = entry.derivation !== undefined && entry.derivation !== 'identity';
121
+ if (hasNonIdentityDerivation)
122
+ nonIdentityDerivation++;
123
+ const slug = pathSlug(entry.resultPath, entry.pathAnchors);
124
+ const documentSlug = safeSlugPart(entry.documentId);
125
+ const defaultKey = `${input.keyPrefix}:${slug}${entry.textNodeIndex === undefined ? '' : `:richtext:${entry.textNodeIndex}`}`;
126
+ const source = sourceForSourceMapEntry(entry);
127
+ leaves.push(createPreviewProvenanceEditableLeaf({
128
+ key: input.keyForEntry?.(entry, defaultKey) ?? defaultKey,
129
+ documentId: entry.documentId,
130
+ variantId: entry.variantId,
131
+ readScope: entry.readScope,
132
+ leafPath: entry.resultPath,
133
+ pathAnchors: entry.pathAnchors,
134
+ sourceKind: entry.sourceKind,
135
+ sourceSetId: `${input.sourceSetPrefix}_${documentSlug}_${slug}${entry.textNodeIndex === undefined ? '' : `_richtext_${entry.textNodeIndex}`}`,
136
+ outputKind,
137
+ modality: pattern.modality ?? 'text',
138
+ anchorKind: pattern.anchorKind ?? 'element',
139
+ renderedText: entry.renderedText,
140
+ ...(hasNonIdentityDerivation
141
+ ? {
142
+ sourceSet: {
143
+ kind: 'derived',
144
+ sources: [source],
145
+ primary: source,
146
+ derivation: entry.derivation,
147
+ editable: 'not-editable',
148
+ },
149
+ }
150
+ : {}),
151
+ codedText: outputKind === 'text' &&
152
+ !hasNonIdentityDerivation &&
153
+ entry.sourceKind === 'stored'
154
+ ? true
155
+ : undefined,
156
+ codedRichTextTextNodeIndex: outputKind === 'text' &&
157
+ !hasNonIdentityDerivation &&
158
+ entry.sourceKind === 'richtext'
159
+ ? entry.textNodeIndex
160
+ : undefined,
161
+ // Image attribute carriers retain their established repeatable contract.
162
+ // C3 re-arms text-field duplication diagnostics without changing the
163
+ // SDK image surface or its anchoring grammar.
164
+ anchorMultiplicity: input.anchorMultiplicity ??
165
+ (pattern.modality === 'attr:src' && pattern.anchorKind === 'attribute'
166
+ ? 'multi'
167
+ : undefined),
168
+ // Element carriers follow the caller's declared presence, like text.
169
+ presence: input.presence,
170
+ }));
171
+ }
172
+ return {
173
+ sourceMapEntries: sourceMap.entries.length,
174
+ leaves,
175
+ skipped: {
176
+ manifestIneligible,
177
+ nonIdentityDerivation,
178
+ },
179
+ };
180
+ }
181
+ function sourceForSourceMapEntry(entry) {
182
+ return {
183
+ documentId: entry.documentId,
184
+ ...(entry.variantId !== undefined ? { variantId: entry.variantId } : {}),
185
+ ...(entry.readScope !== undefined ? { readScope: entry.readScope } : {}),
186
+ canonicalPath: entry.canonicalPath,
187
+ pathAnchors: entry.pathAnchors,
188
+ sourceKind: entry.sourceKind,
189
+ ...(entry.textNodeIndex !== undefined
190
+ ? { textNodeIndex: entry.textNodeIndex }
191
+ : {}),
192
+ };
193
+ }
194
+ function valueAtPath(root, path) {
195
+ let current = root;
196
+ for (const part of path) {
197
+ if (current === null || typeof current !== 'object')
198
+ return undefined;
199
+ current = current[part];
200
+ }
201
+ return current;
202
+ }
203
+ function matchingPreviewProvenanceSourceMapEntryPattern(context, storyType, manifest) {
204
+ return matchingPreviewProvenanceEditablePathPattern(context, manifest[storyType] ?? []);
205
+ }
206
+ /** Identity of an editorial source supplied by this read, including bindings. */
207
+ export function previewProvenanceSourceIdentityFromQueryResult(queryResult) {
208
+ const variantId = queryResultVariantId(queryResult);
209
+ const readScope = previewReadScopeEchoFromQueryResult(queryResult);
210
+ return {
211
+ documentId: queryResult.documentId,
212
+ ...(variantId !== null ? { variantId } : {}),
213
+ ...(readScope !== undefined ? { readScope } : {}),
214
+ };
215
+ }
216
+ function queryResultVariantId(queryResult) {
217
+ const echoedAppliedVariantId = appliedPreviewVariantIdFromQueryResult(queryResult);
218
+ if (echoedAppliedVariantId !== undefined)
219
+ return echoedAppliedVariantId;
220
+ return (normalizePreviewVariantId(queryResult._locale?.variantId) ??
221
+ normalizePreviewVariantId(queryResult._variant?.variantId));
222
+ }
223
+ /**
224
+ * Read the gateway's explicit applied-scope echo.
225
+ *
226
+ * `undefined` means the payload predates the echo and callers may use their
227
+ * legacy identity fallback. `null` is authoritative: the gateway explicitly
228
+ * says living content was applied, so an expected variant must not mask it.
229
+ */
230
+ export function appliedPreviewVariantIdFromQueryResult(queryResult) {
231
+ const scope = queryResult._previewScope;
232
+ if (scope === undefined ||
233
+ scope.appliesToDocument === false ||
234
+ !Object.prototype.hasOwnProperty.call(scope, 'appliedVariantId')) {
235
+ return undefined;
236
+ }
237
+ return normalizePreviewVariantId(scope.appliedVariantId);
238
+ }
239
+ /**
240
+ * Read the requested scope echo even when the concrete document is outside
241
+ * that scope. A host frame can retain the session lifecycle identity while
242
+ * only an applicable target payload is allowed to prove a mismatch.
243
+ */
244
+ export function requestedPreviewVariantIdFromQueryResult(queryResult) {
245
+ const scope = queryResult._previewScope;
246
+ if (scope === undefined ||
247
+ !Object.prototype.hasOwnProperty.call(scope, 'requestedVariantId')) {
248
+ return undefined;
249
+ }
250
+ return normalizePreviewVariantId(scope.requestedVariantId);
251
+ }
252
+ /** Return the complete gateway-owned scope echo for runtime reporting. */
253
+ export function previewReadScopeEchoFromQueryResult(queryResult) {
254
+ return queryResult._previewScope;
255
+ }
256
+ function isPreviewProvenanceSourceMap(value) {
257
+ return (isObject(value) &&
258
+ typeof value.documentId === 'string' &&
259
+ typeof value.storyType === 'string' &&
260
+ Array.isArray(value.entries));
261
+ }
262
+ function isQueryResultLike(value) {
263
+ return (isObject(value) &&
264
+ typeof value.documentId === 'string' &&
265
+ isObject(value.fields));
266
+ }
267
+ function leafFieldName(path) {
268
+ const leaf = path[path.length - 1];
269
+ return typeof leaf === 'string' ? leaf : null;
270
+ }
271
+ function pathSlug(path, pathAnchors) {
272
+ const keyByArrayPath = new Map(pathAnchors.map((anchor) => [anchor.path, anchor.key]));
273
+ return path.map((part, index) => {
274
+ if (typeof part === 'number') {
275
+ const arrayPath = formatPreviewProvenanceCanonicalPath(path.slice(0, index));
276
+ return safeSlugPart(keyByArrayPath.get(arrayPath) ?? String(part));
277
+ }
278
+ return safeSlugPart(part);
279
+ }).join('_');
280
+ }
281
+ function safeSlugPart(value) {
282
+ return value.replace(/[^A-Za-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'field';
283
+ }
284
+ function isObject(value) {
285
+ return typeof value === 'object' && value !== null;
286
+ }
@@ -0,0 +1,103 @@
1
+ import { type MultiFrameAnchorMaps } from "./multi-frame-anchor-map.js";
2
+ import { type PreviewPaintRenderIdentity } from "./anchor-map.js";
3
+ import type { ProvenanceOwnerMap, ResolvedProvenanceOwner } from "./owner-map.js";
4
+ import { type PreviewOverlayClickTarget } from "./overlay-projection.js";
5
+ import type { PreviewOverlayClickPayload, PreviewV2RevealResultStatus, PreviewV2RevealSourcePayload, PreviewV2RevealTargetToken } from "@storystick/transport-allowlist";
6
+ import type { PreviewV2RevealSliceRequest, PreviewV2SourceIdentity, PreviewV2SourceIdentityRequest } from "./reveal-contract.js";
7
+ export interface PreviewPresentationFrameIdentity {
8
+ documentId: string | null;
9
+ pathname: string;
10
+ sessionId?: string | null;
11
+ routeHash?: string | null;
12
+ renderId?: string | null;
13
+ codeVersion?: string | null;
14
+ }
15
+ export interface ActivePreviewOverlayClickTargets {
16
+ generation: number;
17
+ /** Authority used to revalidate a paint before interaction routing. */
18
+ interactionAuthority: "live-direct-locator" | "legacy-snapshot";
19
+ presentationFrameIdentity: PreviewPresentationFrameIdentity;
20
+ renderIdentity: PreviewPaintRenderIdentity;
21
+ targets: ReadonlyMap<string, PreviewOverlayClickTarget>;
22
+ }
23
+ export interface PreviewV2SourceRegistryInput {
24
+ sessionId: string | null;
25
+ anchorMap: MultiFrameAnchorMaps | null;
26
+ ownerMap: ProvenanceOwnerMap | null;
27
+ sourceMapBytes: number | null;
28
+ activeOverlayTargets?: ActivePreviewOverlayClickTargets | null;
29
+ sourceIdentitySnapshot?: PreviewV2SourceIdentitySnapshot | null;
30
+ /** Read transient iframe scroll state without rebuilding the registry. */
31
+ currentViewport?: () => MultiFrameAnchorMaps["viewport"];
32
+ activePaintFor?: (documentId: string, sourceSetId: string) => PreviewV2ActivePaint | null;
33
+ }
34
+ export interface PreviewV2ActivePaint {
35
+ readonly sourceSetId: string;
36
+ readonly markerId: string;
37
+ readonly paintId: string;
38
+ readonly renderIdentity: PreviewPaintRenderIdentity;
39
+ }
40
+ export type PreviewV2RevealTargetSelection = {
41
+ readonly kind: "active-paint";
42
+ readonly paintId: string;
43
+ } | {
44
+ readonly kind: "nearest-viewport-fallback";
45
+ readonly paintId: string;
46
+ } | {
47
+ readonly kind: "first-document-fallback";
48
+ readonly paintId: string;
49
+ };
50
+ export type PreviewV2RevealPayloadResolution = {
51
+ ok: true;
52
+ payload: PreviewV2RevealSourcePayload;
53
+ expectedStatus: PreviewV2RevealResultStatus;
54
+ selection: PreviewV2RevealTargetSelection;
55
+ } | {
56
+ ok: false;
57
+ sourceKey: string | null;
58
+ status: Extract<PreviewV2RevealResultStatus, "unknownSource" | "notMounted" | "routeMissing">;
59
+ };
60
+ export interface PreviewV2RevealBehavior {
61
+ scroll: boolean;
62
+ flash: boolean;
63
+ durationMs: number;
64
+ }
65
+ interface CachedPreviewV2SourceIdentity {
66
+ sourceKey: string;
67
+ sourceKind: ResolvedProvenanceOwner["sourceKind"];
68
+ frameId: string;
69
+ routeHash: string;
70
+ variantId: string | null;
71
+ codeVersion: string;
72
+ renderId: string;
73
+ sourceMapBytes: number | null;
74
+ }
75
+ export interface PreviewV2SourceIdentitySnapshot {
76
+ renderIdentity: PreviewPaintRenderIdentity;
77
+ entries: ReadonlyMap<string, CachedPreviewV2SourceIdentity>;
78
+ markerIdsBySourceKey: ReadonlyMap<string, readonly string[]>;
79
+ }
80
+ export declare function createPreviewV2SourceIdentitySnapshot(input: {
81
+ sessionId: string | null;
82
+ anchorMap: MultiFrameAnchorMaps | null;
83
+ ownerMap: ProvenanceOwnerMap | null;
84
+ sourceMapBytes: number | null;
85
+ }): PreviewV2SourceIdentitySnapshot | null;
86
+ export declare function createPreviewV2SourceRegistry(input: PreviewV2SourceRegistryInput): {
87
+ resolveSourceIdentity: (request: PreviewV2SourceIdentityRequest) => Omit<PreviewV2SourceIdentity, "sourceMapLookupMs"> | null;
88
+ resolveActiveRenderTargets: (sourceKey: string) => PreviewV2RevealTargetToken[];
89
+ resolveRevealPayloadForStudioTarget: (args: {
90
+ request: PreviewV2SourceIdentityRequest;
91
+ requestId: string;
92
+ behavior: PreviewV2RevealBehavior;
93
+ }) => PreviewV2RevealPayloadResolution;
94
+ resolveRevealPayloadForStudioSlice: (args: {
95
+ request: PreviewV2RevealSliceRequest;
96
+ requestId: string;
97
+ behavior: PreviewV2RevealBehavior;
98
+ }) => PreviewV2RevealPayloadResolution;
99
+ resolveEditableTargetFromOverlayClick: (payload: PreviewOverlayClickPayload, options?: {
100
+ expectedPresentationDocumentId?: string | null;
101
+ }) => PreviewOverlayClickTarget | null;
102
+ };
103
+ export {};