@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,161 @@
|
|
|
1
|
+
import type { PreviewProvenanceCarrierPlan, ProvenanceId } from './types.js';
|
|
2
|
+
export type PreviewTransformedOutputStatus = 'guaranteed' | 'derived-single' | 'derived-composite' | 'attribute-carrier-needed' | 'compiler-needed' | 'intervention-needed' | 'unsupported/absent';
|
|
3
|
+
export type PreviewExpressionCaptureModality = 'text' | 'attr' | 'scope';
|
|
4
|
+
export type PreviewExpressionSourceSetKind = 'single' | 'derived-single' | 'derived-composite' | 'unknown';
|
|
5
|
+
export type PreviewExpressionTransformKind = 'identity' | 'uppercase' | 'concat' | 'truncate' | 'date-format' | 'number-format' | 'url-or-slug' | 'custom' | 'precomputed';
|
|
6
|
+
export interface PreviewExpressionSourceRead extends ProvenanceId {
|
|
7
|
+
readonly readKey: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PreviewExpressionCaptureRecord {
|
|
10
|
+
readonly contractVersion: 1;
|
|
11
|
+
readonly sourceReads: readonly PreviewExpressionSourceRead[];
|
|
12
|
+
readonly renderedPrimitive: string | number | boolean | null;
|
|
13
|
+
readonly modality: PreviewExpressionCaptureModality;
|
|
14
|
+
readonly sourceSetKind: PreviewExpressionSourceSetKind;
|
|
15
|
+
readonly transformKind: PreviewExpressionTransformKind;
|
|
16
|
+
readonly debugReason?: string;
|
|
17
|
+
readonly carrierPlan: PreviewProvenanceCarrierPlan | null;
|
|
18
|
+
}
|
|
19
|
+
export interface PreviewTransformedOutputCase {
|
|
20
|
+
readonly id: 'direct-text' | 'uppercase' | 'concat' | 'truncate' | 'date-formatting' | 'number-formatting' | 'url-slug' | 'href' | 'alt' | 'rich-text-split-across-marks' | 'duplicate-strings' | 'precomputed-view-model';
|
|
21
|
+
readonly status: PreviewTransformedOutputStatus;
|
|
22
|
+
readonly modality: PreviewExpressionCaptureModality;
|
|
23
|
+
readonly sourceSetKind: PreviewExpressionSourceSetKind;
|
|
24
|
+
readonly sourceProof: 'direct' | 'captured' | 'not-captured';
|
|
25
|
+
readonly carrierPlan: PreviewProvenanceCarrierPlan | null;
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const PREVIEW_TRANSFORMED_OUTPUT_GATE_MATRIX: readonly [{
|
|
29
|
+
readonly id: "direct-text";
|
|
30
|
+
readonly status: "guaranteed";
|
|
31
|
+
readonly modality: "text";
|
|
32
|
+
readonly sourceSetKind: "single";
|
|
33
|
+
readonly sourceProof: "direct";
|
|
34
|
+
readonly carrierPlan: PreviewProvenanceCarrierPlan;
|
|
35
|
+
readonly reason: "Direct editorial text can use data-ss-p or coded text as a carrier after owner-map validation.";
|
|
36
|
+
}, {
|
|
37
|
+
readonly id: "uppercase";
|
|
38
|
+
readonly status: "derived-single";
|
|
39
|
+
readonly modality: "text";
|
|
40
|
+
readonly sourceSetKind: "derived-single";
|
|
41
|
+
readonly sourceProof: "captured";
|
|
42
|
+
readonly carrierPlan: PreviewProvenanceCarrierPlan;
|
|
43
|
+
readonly reason: "A single-source transform is safe only when Expression Capture proves the source read.";
|
|
44
|
+
}, {
|
|
45
|
+
readonly id: "concat";
|
|
46
|
+
readonly status: "derived-composite";
|
|
47
|
+
readonly modality: "scope";
|
|
48
|
+
readonly sourceSetKind: "derived-composite";
|
|
49
|
+
readonly sourceProof: "captured";
|
|
50
|
+
readonly carrierPlan: {
|
|
51
|
+
readonly kind: "future-scope";
|
|
52
|
+
readonly carrier: "scope-carrier";
|
|
53
|
+
readonly modality: "scope";
|
|
54
|
+
readonly anchorKind: "scope";
|
|
55
|
+
readonly status: "planned";
|
|
56
|
+
readonly previewOnly: true;
|
|
57
|
+
readonly markerPayload: "opaque-marker-id";
|
|
58
|
+
readonly reason: "Composite or structural outputs need group/scope ownership.";
|
|
59
|
+
};
|
|
60
|
+
readonly reason: "Multiple source reads must become composite/group/scope ownership, never a fake single-field overlay.";
|
|
61
|
+
}, {
|
|
62
|
+
readonly id: "truncate";
|
|
63
|
+
readonly status: "compiler-needed";
|
|
64
|
+
readonly modality: "text";
|
|
65
|
+
readonly sourceSetKind: "unknown";
|
|
66
|
+
readonly sourceProof: "not-captured";
|
|
67
|
+
readonly carrierPlan: null;
|
|
68
|
+
readonly reason: "Destructive transforms can cut or move hidden markers and need captured expression causality.";
|
|
69
|
+
}, {
|
|
70
|
+
readonly id: "date-formatting";
|
|
71
|
+
readonly status: "compiler-needed";
|
|
72
|
+
readonly modality: "text";
|
|
73
|
+
readonly sourceSetKind: "unknown";
|
|
74
|
+
readonly sourceProof: "not-captured";
|
|
75
|
+
readonly carrierPlan: null;
|
|
76
|
+
readonly reason: "Formatted dates are derived view output; coded text must not be written into date values.";
|
|
77
|
+
}, {
|
|
78
|
+
readonly id: "number-formatting";
|
|
79
|
+
readonly status: "compiler-needed";
|
|
80
|
+
readonly modality: "text";
|
|
81
|
+
readonly sourceSetKind: "unknown";
|
|
82
|
+
readonly sourceProof: "not-captured";
|
|
83
|
+
readonly carrierPlan: null;
|
|
84
|
+
readonly reason: "Formatted numbers are derived view output and are not proven by marker survival.";
|
|
85
|
+
}, {
|
|
86
|
+
readonly id: "url-slug";
|
|
87
|
+
readonly status: "unsupported/absent";
|
|
88
|
+
readonly modality: "attr";
|
|
89
|
+
readonly sourceSetKind: "unknown";
|
|
90
|
+
readonly sourceProof: "not-captured";
|
|
91
|
+
readonly carrierPlan: null;
|
|
92
|
+
readonly reason: "URLs, slugs, and pathnames must never receive coded text carriers.";
|
|
93
|
+
}, {
|
|
94
|
+
readonly id: "href";
|
|
95
|
+
readonly status: "attribute-carrier-needed";
|
|
96
|
+
readonly modality: "attr";
|
|
97
|
+
readonly sourceSetKind: "derived-single";
|
|
98
|
+
readonly sourceProof: "captured";
|
|
99
|
+
readonly carrierPlan: {
|
|
100
|
+
readonly kind: "future-attribute";
|
|
101
|
+
readonly carrier: "attribute-output-carrier";
|
|
102
|
+
readonly modality: "attr:href";
|
|
103
|
+
readonly anchorKind: "attribute";
|
|
104
|
+
readonly status: "planned";
|
|
105
|
+
readonly previewOnly: true;
|
|
106
|
+
readonly markerPayload: "opaque-marker-id";
|
|
107
|
+
readonly reason: "URL and technical attributes need explicit attribute capture, not coded text.";
|
|
108
|
+
};
|
|
109
|
+
readonly reason: "href needs explicit attribute capture/carrier; Unicode text in the URL is forbidden.";
|
|
110
|
+
}, {
|
|
111
|
+
readonly id: "alt";
|
|
112
|
+
readonly status: "attribute-carrier-needed";
|
|
113
|
+
readonly modality: "attr";
|
|
114
|
+
readonly sourceSetKind: "single";
|
|
115
|
+
readonly sourceProof: "captured";
|
|
116
|
+
readonly carrierPlan: PreviewProvenanceCarrierPlan;
|
|
117
|
+
readonly reason: "alt can be editorial, but it is still an attribute surface and needs an attribute carrier.";
|
|
118
|
+
}, {
|
|
119
|
+
readonly id: "rich-text-split-across-marks";
|
|
120
|
+
readonly status: "guaranteed";
|
|
121
|
+
readonly modality: "text";
|
|
122
|
+
readonly sourceSetKind: "single";
|
|
123
|
+
readonly sourceProof: "direct";
|
|
124
|
+
readonly carrierPlan: PreviewProvenanceCarrierPlan;
|
|
125
|
+
readonly reason: "Rich text is supported at individual text-node granularity, not as a wrapper around the full JSON field.";
|
|
126
|
+
}, {
|
|
127
|
+
readonly id: "duplicate-strings";
|
|
128
|
+
readonly status: "intervention-needed";
|
|
129
|
+
readonly modality: "scope";
|
|
130
|
+
readonly sourceSetKind: "unknown";
|
|
131
|
+
readonly sourceProof: "not-captured";
|
|
132
|
+
readonly carrierPlan: {
|
|
133
|
+
readonly kind: "future-scope";
|
|
134
|
+
readonly carrier: "scope-carrier";
|
|
135
|
+
readonly modality: "scope";
|
|
136
|
+
readonly anchorKind: "scope";
|
|
137
|
+
readonly status: "planned";
|
|
138
|
+
readonly previewOnly: true;
|
|
139
|
+
readonly markerPayload: "opaque-marker-id";
|
|
140
|
+
readonly reason: "Composite or structural outputs need group/scope ownership.";
|
|
141
|
+
};
|
|
142
|
+
readonly reason: "Equal rendered strings cannot be routed by value matching; they need explicit source identity or scope grouping.";
|
|
143
|
+
}, {
|
|
144
|
+
readonly id: "precomputed-view-model";
|
|
145
|
+
readonly status: "unsupported/absent";
|
|
146
|
+
readonly modality: "text";
|
|
147
|
+
readonly sourceSetKind: "unknown";
|
|
148
|
+
readonly sourceProof: "not-captured";
|
|
149
|
+
readonly carrierPlan: null;
|
|
150
|
+
readonly reason: "A precomputed primitive without captured reads has no reliable source truth at render time.";
|
|
151
|
+
}];
|
|
152
|
+
export declare function transformedOutputCanProduceSingleFieldOverlay(output: Pick<PreviewTransformedOutputCase, 'status' | 'sourceSetKind' | 'sourceProof'>): boolean;
|
|
153
|
+
export declare function classifyPreviewExpressionCapture(input: {
|
|
154
|
+
readonly sourceReads: readonly PreviewExpressionSourceRead[];
|
|
155
|
+
readonly renderedPrimitive: PreviewExpressionCaptureRecord['renderedPrimitive'];
|
|
156
|
+
readonly modality: PreviewExpressionCaptureModality;
|
|
157
|
+
readonly transformKind: PreviewExpressionTransformKind;
|
|
158
|
+
readonly carrierPlan?: PreviewProvenanceCarrierPlan | null;
|
|
159
|
+
readonly debugReason?: string;
|
|
160
|
+
}): PreviewExpressionCaptureRecord;
|
|
161
|
+
export declare function statusForExpressionCapture(capture: PreviewExpressionCaptureRecord): PreviewTransformedOutputStatus;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conserved deliberately: this matrix is the executable specification for
|
|
3
|
+
* the annotation seam (guaranteed vs carrier/compiler/intervention needed),
|
|
4
|
+
* not residue from DOM inference.
|
|
5
|
+
*/
|
|
6
|
+
import { createPreviewProvenanceAttributeCarrierPlan, createPreviewProvenanceCodedTextCarrierPlan, previewProvenanceFutureCarrierPlans, } from './carrier-plan.js';
|
|
7
|
+
const directTextCarrierPlan = createPreviewProvenanceCodedTextCarrierPlan({
|
|
8
|
+
surface: 'direct-editorial-text',
|
|
9
|
+
});
|
|
10
|
+
const richTextCarrierPlan = createPreviewProvenanceCodedTextCarrierPlan({
|
|
11
|
+
surface: 'rich-text-text-node',
|
|
12
|
+
});
|
|
13
|
+
const altCarrierPlan = createPreviewProvenanceAttributeCarrierPlan({
|
|
14
|
+
modality: 'attr:alt',
|
|
15
|
+
anchorKind: 'attribute',
|
|
16
|
+
});
|
|
17
|
+
const hrefFutureCarrierPlan = previewProvenanceFutureCarrierPlans.find((plan) => plan.kind === 'future-attribute');
|
|
18
|
+
const scopeFutureCarrierPlan = previewProvenanceFutureCarrierPlans.find((plan) => plan.kind === 'future-scope');
|
|
19
|
+
export const PREVIEW_TRANSFORMED_OUTPUT_GATE_MATRIX = [
|
|
20
|
+
{
|
|
21
|
+
id: 'direct-text',
|
|
22
|
+
status: 'guaranteed',
|
|
23
|
+
modality: 'text',
|
|
24
|
+
sourceSetKind: 'single',
|
|
25
|
+
sourceProof: 'direct',
|
|
26
|
+
carrierPlan: directTextCarrierPlan,
|
|
27
|
+
reason: 'Direct editorial text can use data-ss-p or coded text as a carrier after owner-map validation.',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'uppercase',
|
|
31
|
+
status: 'derived-single',
|
|
32
|
+
modality: 'text',
|
|
33
|
+
sourceSetKind: 'derived-single',
|
|
34
|
+
sourceProof: 'captured',
|
|
35
|
+
carrierPlan: directTextCarrierPlan,
|
|
36
|
+
reason: 'A single-source transform is safe only when Expression Capture proves the source read.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'concat',
|
|
40
|
+
status: 'derived-composite',
|
|
41
|
+
modality: 'scope',
|
|
42
|
+
sourceSetKind: 'derived-composite',
|
|
43
|
+
sourceProof: 'captured',
|
|
44
|
+
carrierPlan: scopeFutureCarrierPlan,
|
|
45
|
+
reason: 'Multiple source reads must become composite/group/scope ownership, never a fake single-field overlay.',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'truncate',
|
|
49
|
+
status: 'compiler-needed',
|
|
50
|
+
modality: 'text',
|
|
51
|
+
sourceSetKind: 'unknown',
|
|
52
|
+
sourceProof: 'not-captured',
|
|
53
|
+
carrierPlan: null,
|
|
54
|
+
reason: 'Destructive transforms can cut or move hidden markers and need captured expression causality.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'date-formatting',
|
|
58
|
+
status: 'compiler-needed',
|
|
59
|
+
modality: 'text',
|
|
60
|
+
sourceSetKind: 'unknown',
|
|
61
|
+
sourceProof: 'not-captured',
|
|
62
|
+
carrierPlan: null,
|
|
63
|
+
reason: 'Formatted dates are derived view output; coded text must not be written into date values.',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 'number-formatting',
|
|
67
|
+
status: 'compiler-needed',
|
|
68
|
+
modality: 'text',
|
|
69
|
+
sourceSetKind: 'unknown',
|
|
70
|
+
sourceProof: 'not-captured',
|
|
71
|
+
carrierPlan: null,
|
|
72
|
+
reason: 'Formatted numbers are derived view output and are not proven by marker survival.',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: 'url-slug',
|
|
76
|
+
status: 'unsupported/absent',
|
|
77
|
+
modality: 'attr',
|
|
78
|
+
sourceSetKind: 'unknown',
|
|
79
|
+
sourceProof: 'not-captured',
|
|
80
|
+
carrierPlan: null,
|
|
81
|
+
reason: 'URLs, slugs, and pathnames must never receive coded text carriers.',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 'href',
|
|
85
|
+
status: 'attribute-carrier-needed',
|
|
86
|
+
modality: 'attr',
|
|
87
|
+
sourceSetKind: 'derived-single',
|
|
88
|
+
sourceProof: 'captured',
|
|
89
|
+
carrierPlan: hrefFutureCarrierPlan,
|
|
90
|
+
reason: 'href needs explicit attribute capture/carrier; Unicode text in the URL is forbidden.',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: 'alt',
|
|
94
|
+
status: 'attribute-carrier-needed',
|
|
95
|
+
modality: 'attr',
|
|
96
|
+
sourceSetKind: 'single',
|
|
97
|
+
sourceProof: 'captured',
|
|
98
|
+
carrierPlan: altCarrierPlan,
|
|
99
|
+
reason: 'alt can be editorial, but it is still an attribute surface and needs an attribute carrier.',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'rich-text-split-across-marks',
|
|
103
|
+
status: 'guaranteed',
|
|
104
|
+
modality: 'text',
|
|
105
|
+
sourceSetKind: 'single',
|
|
106
|
+
sourceProof: 'direct',
|
|
107
|
+
carrierPlan: richTextCarrierPlan,
|
|
108
|
+
reason: 'Rich text is supported at individual text-node granularity, not as a wrapper around the full JSON field.',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: 'duplicate-strings',
|
|
112
|
+
status: 'intervention-needed',
|
|
113
|
+
modality: 'scope',
|
|
114
|
+
sourceSetKind: 'unknown',
|
|
115
|
+
sourceProof: 'not-captured',
|
|
116
|
+
carrierPlan: scopeFutureCarrierPlan,
|
|
117
|
+
reason: 'Equal rendered strings cannot be routed by value matching; they need explicit source identity or scope grouping.',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'precomputed-view-model',
|
|
121
|
+
status: 'unsupported/absent',
|
|
122
|
+
modality: 'text',
|
|
123
|
+
sourceSetKind: 'unknown',
|
|
124
|
+
sourceProof: 'not-captured',
|
|
125
|
+
carrierPlan: null,
|
|
126
|
+
reason: 'A precomputed primitive without captured reads has no reliable source truth at render time.',
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
export function transformedOutputCanProduceSingleFieldOverlay(output) {
|
|
130
|
+
if (output.sourceProof === 'not-captured')
|
|
131
|
+
return false;
|
|
132
|
+
return (output.status === 'guaranteed' ||
|
|
133
|
+
output.status === 'derived-single') && (output.sourceSetKind === 'single' ||
|
|
134
|
+
output.sourceSetKind === 'derived-single');
|
|
135
|
+
}
|
|
136
|
+
export function classifyPreviewExpressionCapture(input) {
|
|
137
|
+
const sourceSetKind = classifyExpressionSourceSetKind(input);
|
|
138
|
+
return {
|
|
139
|
+
contractVersion: 1,
|
|
140
|
+
sourceReads: input.sourceReads,
|
|
141
|
+
renderedPrimitive: input.renderedPrimitive,
|
|
142
|
+
modality: input.modality,
|
|
143
|
+
sourceSetKind,
|
|
144
|
+
transformKind: input.transformKind,
|
|
145
|
+
...(input.debugReason ? { debugReason: input.debugReason } : {}),
|
|
146
|
+
carrierPlan: input.carrierPlan ?? null,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
export function statusForExpressionCapture(capture) {
|
|
150
|
+
if (capture.sourceSetKind === 'unknown') {
|
|
151
|
+
return capture.transformKind === 'precomputed'
|
|
152
|
+
? 'unsupported/absent'
|
|
153
|
+
: 'compiler-needed';
|
|
154
|
+
}
|
|
155
|
+
if (capture.modality === 'attr' &&
|
|
156
|
+
(capture.carrierPlan === null || capture.carrierPlan.status !== 'emitted')) {
|
|
157
|
+
return 'attribute-carrier-needed';
|
|
158
|
+
}
|
|
159
|
+
if (capture.sourceSetKind === 'single')
|
|
160
|
+
return 'guaranteed';
|
|
161
|
+
if (capture.sourceSetKind === 'derived-single')
|
|
162
|
+
return 'derived-single';
|
|
163
|
+
return 'derived-composite';
|
|
164
|
+
}
|
|
165
|
+
function classifyExpressionSourceSetKind(input) {
|
|
166
|
+
if (input.sourceReads.length === 0)
|
|
167
|
+
return 'unknown';
|
|
168
|
+
if (input.sourceReads.length > 1)
|
|
169
|
+
return 'derived-composite';
|
|
170
|
+
return input.transformKind === 'identity' ? 'single' : 'derived-single';
|
|
171
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { type PreviewReadScopeEcho } from '@storystick/client/internal';
|
|
2
|
+
import type { PreviewReadContext } from '@storystick/types/preview-query-targeting';
|
|
3
|
+
export interface PathAnchor {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly key: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ProvenanceId {
|
|
8
|
+
readonly documentId: string;
|
|
9
|
+
readonly variantId?: string;
|
|
10
|
+
readonly canonicalPath: string;
|
|
11
|
+
readonly pathAnchors: readonly PathAnchor[];
|
|
12
|
+
readonly navigationPath?: string;
|
|
13
|
+
readonly navigationAnchors?: readonly PathAnchor[];
|
|
14
|
+
/** Scope of the concrete read that produced this source, when attested. */
|
|
15
|
+
readonly readScope?: PreviewReadScopeEcho;
|
|
16
|
+
/**
|
|
17
|
+
* Private rich-text leaf metadata. Present only for richtext source ids
|
|
18
|
+
* emitted per rendered text node inside one editable rich text field.
|
|
19
|
+
*/
|
|
20
|
+
readonly textNodeIndex?: number;
|
|
21
|
+
readonly sourceKind: 'stored' | 'binding' | 'model' | 'computed' | 'richtext' | 'embed' | 'emptyFallback' | 'unknown';
|
|
22
|
+
}
|
|
23
|
+
export interface SourceSet {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly kind: 'single' | 'composite' | 'derived' | 'unknown';
|
|
26
|
+
readonly sources: readonly ProvenanceId[];
|
|
27
|
+
readonly primary?: ProvenanceId;
|
|
28
|
+
readonly derivation?: 'identity' | 'binding' | 'model' | 'concat' | 'truncate' | 'format' | 'richtext-flatten' | 'custom';
|
|
29
|
+
readonly editable: 'single-field' | 'multi-field' | 'not-editable';
|
|
30
|
+
}
|
|
31
|
+
export type ProvenanceMarkerModality = 'text' | 'attr:href' | 'attr:src' | 'attr:alt' | 'attr:title' | 'attr:aria-label';
|
|
32
|
+
export type ProvenanceAnchorKind = 'element' | 'attribute' | 'text-range' | 'scope';
|
|
33
|
+
export type PreviewProvenanceCarrierPlan = {
|
|
34
|
+
readonly kind: 'attribute';
|
|
35
|
+
readonly carrier: 'data-ss-p' | 'data-ss-e';
|
|
36
|
+
readonly modality: ProvenanceMarkerModality;
|
|
37
|
+
readonly anchorKind: ProvenanceAnchorKind;
|
|
38
|
+
readonly status: 'emitted';
|
|
39
|
+
readonly previewOnly: true;
|
|
40
|
+
readonly markerPayload: 'opaque-marker-id';
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: 'text';
|
|
43
|
+
readonly carrier: 'coded-text-unicode-tags';
|
|
44
|
+
readonly modality: 'text';
|
|
45
|
+
readonly anchorKind: 'element';
|
|
46
|
+
readonly status: 'emitted';
|
|
47
|
+
readonly previewOnly: true;
|
|
48
|
+
readonly markerPayload: 'opaque-marker-id';
|
|
49
|
+
readonly surface: 'direct-editorial-text' | 'rich-text-text-node' | 'fallback-text-carrier';
|
|
50
|
+
} | {
|
|
51
|
+
readonly kind: 'text-range';
|
|
52
|
+
readonly carrier: 'coded-text-unicode-tags';
|
|
53
|
+
readonly modality: 'text';
|
|
54
|
+
readonly anchorKind: 'text-range';
|
|
55
|
+
readonly status: 'emitted';
|
|
56
|
+
readonly previewOnly: true;
|
|
57
|
+
readonly markerPayload: 'opaque-marker-id';
|
|
58
|
+
readonly surface: 'non-promoted-text-range';
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: 'future-attribute' | 'future-media' | 'future-scope';
|
|
61
|
+
readonly carrier: 'attribute-output-carrier' | 'media-carrier' | 'scope-carrier';
|
|
62
|
+
readonly modality: ProvenanceMarkerModality | 'media' | 'scope';
|
|
63
|
+
readonly anchorKind: ProvenanceAnchorKind;
|
|
64
|
+
readonly status: 'planned';
|
|
65
|
+
readonly previewOnly: true;
|
|
66
|
+
readonly markerPayload: 'opaque-marker-id';
|
|
67
|
+
readonly reason: string;
|
|
68
|
+
};
|
|
69
|
+
export interface MarkerRecord {
|
|
70
|
+
readonly markerId: string;
|
|
71
|
+
readonly sourceSetId: string;
|
|
72
|
+
readonly modality: ProvenanceMarkerModality;
|
|
73
|
+
readonly anchorKind: ProvenanceAnchorKind;
|
|
74
|
+
readonly carrierPlans?: readonly PreviewProvenanceCarrierPlan[];
|
|
75
|
+
readonly anchorMultiplicity?: 'single' | 'multi';
|
|
76
|
+
/** `expected` is a non-fatal public diagnostic state for missing anchors. */
|
|
77
|
+
readonly presence?: 'required' | 'optional' | 'expected';
|
|
78
|
+
readonly renderedTextFingerprint?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface ProvenanceFrame {
|
|
81
|
+
readonly type: 'storystick.preview.provenance-frame';
|
|
82
|
+
readonly version: 1;
|
|
83
|
+
readonly sessionId?: string;
|
|
84
|
+
readonly readContext?: PreviewReadContext;
|
|
85
|
+
readonly routeHash: string;
|
|
86
|
+
readonly codeVersion: string;
|
|
87
|
+
readonly variantId?: string;
|
|
88
|
+
/** Gateway requested-vs-applied scope observed by this render. */
|
|
89
|
+
readonly previewScope?: PreviewReadScopeEcho;
|
|
90
|
+
readonly renderId: string;
|
|
91
|
+
readonly generation: number;
|
|
92
|
+
readonly renderNonce?: string;
|
|
93
|
+
readonly emissionRevision?: number;
|
|
94
|
+
readonly sourceSets: readonly SourceSet[];
|
|
95
|
+
readonly markers: readonly MarkerRecord[];
|
|
96
|
+
}
|
|
97
|
+
export interface AuthoritativeSet {
|
|
98
|
+
readonly documentIds: ReadonlySet<string>;
|
|
99
|
+
readonly routeHash: string;
|
|
100
|
+
readonly codeVersion: string;
|
|
101
|
+
readonly variantId?: string | null;
|
|
102
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared timing constants retained for adapter scheduling. Preview browser
|
|
3
|
+
* grants themselves are coordinated by `grant-coordinator.ts`; this module has
|
|
4
|
+
* no postMessage or parent-window dependency.
|
|
5
|
+
*/
|
|
6
|
+
export declare const REFRESH_OFFSET_MS = 240000;
|
|
7
|
+
export declare const REFRESH_JITTER_MS = 5000;
|
|
8
|
+
export declare const REFRESH_TIMEOUT_MS = 5000;
|
|
9
|
+
export declare const REFRESH_RETRY_COUNT = 2;
|
|
10
|
+
export declare const REFRESH_BACKOFF_MS: readonly number[];
|
|
11
|
+
export declare function computeRefreshAt(issuedAt: number, random?: () => number): number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared timing constants retained for adapter scheduling. Preview browser
|
|
3
|
+
* grants themselves are coordinated by `grant-coordinator.ts`; this module has
|
|
4
|
+
* no postMessage or parent-window dependency.
|
|
5
|
+
*/
|
|
6
|
+
export const REFRESH_OFFSET_MS = 240_000;
|
|
7
|
+
export const REFRESH_JITTER_MS = 5_000;
|
|
8
|
+
export const REFRESH_TIMEOUT_MS = 5_000;
|
|
9
|
+
export const REFRESH_RETRY_COUNT = 2;
|
|
10
|
+
export const REFRESH_BACKOFF_MS = [1_000, 3_000];
|
|
11
|
+
export function computeRefreshAt(issuedAt, random = Math.random) {
|
|
12
|
+
const jitter = (random() * 2 - 1) * REFRESH_JITTER_MS;
|
|
13
|
+
return issuedAt + REFRESH_OFFSET_MS + jitter;
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Geometry of an explicitly resolved preview target, independent of its
|
|
2
|
+
* provenance, transport and overlay renderer. Hidden content is not opened. */
|
|
3
|
+
export declare function isPreviewTargetRendered(element: Element): boolean;
|
|
4
|
+
/** Native nearest alignment handles nested scroll owners without taking focus.
|
|
5
|
+
* The optional completion callback lets reveal paint outlive a long smooth
|
|
6
|
+
* scroll. It observes only the explicit target, including nested scroll motion;
|
|
7
|
+
* cleanup cancels the observation, not a newer browser scroll. */
|
|
8
|
+
export declare function scrollPreviewTargetIntoView(element: Element, onSettled?: () => void): () => void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Geometry of an explicitly resolved preview target, independent of its
|
|
2
|
+
* provenance, transport and overlay renderer. Hidden content is not opened. */
|
|
3
|
+
export function isPreviewTargetRendered(element) {
|
|
4
|
+
const win = element.ownerDocument.defaultView;
|
|
5
|
+
if (!win)
|
|
6
|
+
return false;
|
|
7
|
+
const style = win.getComputedStyle(element);
|
|
8
|
+
if (style.display === "none" || style.visibility === "hidden")
|
|
9
|
+
return false;
|
|
10
|
+
return Array.from(element.getClientRects()).some((rect) => rect.width > 0 && rect.height > 0);
|
|
11
|
+
}
|
|
12
|
+
/** Native nearest alignment handles nested scroll owners without taking focus.
|
|
13
|
+
* The optional completion callback lets reveal paint outlive a long smooth
|
|
14
|
+
* scroll. It observes only the explicit target, including nested scroll motion;
|
|
15
|
+
* cleanup cancels the observation, not a newer browser scroll. */
|
|
16
|
+
export function scrollPreviewTargetIntoView(element, onSettled) {
|
|
17
|
+
const win = element.ownerDocument.defaultView;
|
|
18
|
+
const reducedMotion = win?.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
19
|
+
element.scrollIntoView({
|
|
20
|
+
block: "nearest",
|
|
21
|
+
inline: "nearest",
|
|
22
|
+
behavior: reducedMotion ? "instant" : "smooth",
|
|
23
|
+
});
|
|
24
|
+
if (!onSettled || !win || reducedMotion) {
|
|
25
|
+
onSettled?.();
|
|
26
|
+
return () => { };
|
|
27
|
+
}
|
|
28
|
+
let previous = element.getBoundingClientRect();
|
|
29
|
+
let stableFrames = 0;
|
|
30
|
+
const startedAt = win.performance.now();
|
|
31
|
+
let frame = win.requestAnimationFrame(observe);
|
|
32
|
+
function observe(now) {
|
|
33
|
+
const current = element.getBoundingClientRect();
|
|
34
|
+
stableFrames = current.top === previous.top && current.left === previous.left
|
|
35
|
+
? stableFrames + 1
|
|
36
|
+
: 0;
|
|
37
|
+
previous = current;
|
|
38
|
+
// Three still frames also cover an already-visible target (no scrollend
|
|
39
|
+
// event). Bound observation if the target itself continuously animates.
|
|
40
|
+
if (!element.isConnected || stableFrames >= 3 || now - startedAt >= 5_000) {
|
|
41
|
+
onSettled();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
frame = win.requestAnimationFrame(observe);
|
|
45
|
+
}
|
|
46
|
+
return () => win.cancelAnimationFrame(frame);
|
|
47
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const STORYSTICK_ROUTE_BASE_PATH = "/api/storystick";
|
|
2
|
+
export declare const STORYSTICK_PREVIEW_ROUTE_PATH = "/api/storystick/preview";
|
|
3
|
+
export declare const STORYSTICK_PREVIEW_TOKEN_ROUTE_PATH = "/api/storystick/preview/token";
|
|
4
|
+
export declare const STORYSTICK_PREVIEW_CONTEXT_ROUTE_PATH = "/api/storystick/preview/context";
|
|
5
|
+
export declare const STORYSTICK_PREVIEW_DISABLE_ROUTE_PATH = "/api/storystick/preview/disable";
|
|
6
|
+
export declare const STORYSTICK_PREVIEW_AUTHORING_ROUTE_PATH = "/api/storystick/preview/authoring";
|
|
7
|
+
export declare const STORYSTICK_HEALTH_ROUTE_PATH = "/api/storystick/health";
|
|
8
|
+
export declare const STORYSTICK_MIGRATION_READBACK_ROUTE_PATH = "/api/storystick/migration-readback";
|
|
9
|
+
export declare const STORYSTICK_REVALIDATE_ROUTE_PATH = "/api/storystick/revalidate";
|
|
10
|
+
export declare const STORYSTICK_PREVIEW_PROVENANCE_RUNTIME_ROUTE_PATH = "/api/storystick/provenance-runtime";
|
|
11
|
+
export declare function storystickRouteForBasePath(basePath: string, routePath: string): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const STORYSTICK_ROUTE_BASE_PATH = '/api/storystick';
|
|
2
|
+
export const STORYSTICK_PREVIEW_ROUTE_PATH = `${STORYSTICK_ROUTE_BASE_PATH}/preview`;
|
|
3
|
+
export const STORYSTICK_PREVIEW_TOKEN_ROUTE_PATH = `${STORYSTICK_PREVIEW_ROUTE_PATH}/token`;
|
|
4
|
+
export const STORYSTICK_PREVIEW_CONTEXT_ROUTE_PATH = `${STORYSTICK_PREVIEW_ROUTE_PATH}/context`;
|
|
5
|
+
export const STORYSTICK_PREVIEW_DISABLE_ROUTE_PATH = `${STORYSTICK_PREVIEW_ROUTE_PATH}/disable`;
|
|
6
|
+
export const STORYSTICK_PREVIEW_AUTHORING_ROUTE_PATH = `${STORYSTICK_PREVIEW_ROUTE_PATH}/authoring`;
|
|
7
|
+
export const STORYSTICK_HEALTH_ROUTE_PATH = `${STORYSTICK_ROUTE_BASE_PATH}/health`;
|
|
8
|
+
export const STORYSTICK_MIGRATION_READBACK_ROUTE_PATH = `${STORYSTICK_ROUTE_BASE_PATH}/migration-readback`;
|
|
9
|
+
export const STORYSTICK_REVALIDATE_ROUTE_PATH = `${STORYSTICK_ROUTE_BASE_PATH}/revalidate`;
|
|
10
|
+
export const STORYSTICK_PREVIEW_PROVENANCE_RUNTIME_ROUTE_PATH = `${STORYSTICK_ROUTE_BASE_PATH}/provenance-runtime`;
|
|
11
|
+
export function storystickRouteForBasePath(basePath, routePath) {
|
|
12
|
+
const normalized = basePath.trim().replace(/^\/+|\/+$/g, '');
|
|
13
|
+
return normalized.length === 0 ? routePath : `/${normalized}${routePath}`;
|
|
14
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { PreviewRoutePresentation } from '@storystick/transport-allowlist';
|
|
2
|
+
export type { PreviewServerRenderReceipt, PreviewRoutePresentation } from '@storystick/transport-allowlist';
|
|
3
|
+
/**
|
|
4
|
+
* Iframe→Studio router-transition subscriber (ADR-108 D6).
|
|
5
|
+
*
|
|
6
|
+
* Framework-agnostic contract used by adapters (`@storystick/next/
|
|
7
|
+
* preview-nav` for Next, future Astro/Vue/Svelte adapters) to report
|
|
8
|
+
* router transitions to the preview orchestrator inside `activate()`.
|
|
9
|
+
* The orchestrator then emits a `storystick.preview.location` envelope
|
|
10
|
+
* to the parent Studio.
|
|
11
|
+
*
|
|
12
|
+
* Mirror of `nav-handler.ts` (default no-op + register/get/clear), but
|
|
13
|
+
* direction-inverted:
|
|
14
|
+
*
|
|
15
|
+
* - `setRouterSubscriber(handler)` — adapter registers a callback the
|
|
16
|
+
* SDK invokes when the customer's router transitions. The adapter
|
|
17
|
+
* is responsible for the framework-specific wiring (Next App: rAF-
|
|
18
|
+
* coalesced `usePathname` + `useSearchParams`; Next Pages:
|
|
19
|
+
* `router.events.on('routeChangeComplete')`; etc.) — this module
|
|
20
|
+
* stays free of framework imports.
|
|
21
|
+
*
|
|
22
|
+
* - `getRouterSubscriber()` — internal getter used by `activate()`'s
|
|
23
|
+
* router-transition handler (it stores the function so consumers
|
|
24
|
+
* can call into it as transitions happen). Returns `null` before
|
|
25
|
+
* any adapter has registered. **Currently unused by `activate()`
|
|
26
|
+
* directly** — the activate orchestrator stores the handler it
|
|
27
|
+
* wants to invoke and ignores the registered subscriber; the
|
|
28
|
+
* getter exists for tests + future plug-points (overlay click
|
|
29
|
+
* handler, navigateToField wiring) that want to read the
|
|
30
|
+
* subscriber from outside the orchestrator's closure.
|
|
31
|
+
*
|
|
32
|
+
* The "subscriber" wording emphasises that the SDK consumes the
|
|
33
|
+
* adapter's signal (one-way callback); the adapter is the producer of
|
|
34
|
+
* the transition events.
|
|
35
|
+
*
|
|
36
|
+
* Cleanup discipline (StrictMode safety): adapters MUST call
|
|
37
|
+
* `setRouterSubscriber(null)` on unmount. Without it a StrictMode
|
|
38
|
+
* double-mount would leave a stale subscriber registered after the
|
|
39
|
+
* first mount unmounts. The cleanup also lets a fresh adapter mount
|
|
40
|
+
* (overlay react remount on route change) register cleanly.
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* Adapter-reported router transition tuple. Browser form throughout —
|
|
44
|
+
* pathname starts with `/`, search has no leading `?`, hash includes
|
|
45
|
+
* the `#`. Empty strings for `search` / `hash` mean "no query" / "no
|
|
46
|
+
* fragment" respectively.
|
|
47
|
+
*/
|
|
48
|
+
export interface RouterTransition {
|
|
49
|
+
/** Explicit adapter confirmation after a commanded render, including same-URL refresh. */
|
|
50
|
+
commandId?: string;
|
|
51
|
+
presentation?: PreviewRoutePresentation;
|
|
52
|
+
/** Browser pathname for this commit, before the adapter removes its basePath. */
|
|
53
|
+
browserPathname?: string;
|
|
54
|
+
pathname: string;
|
|
55
|
+
search: string;
|
|
56
|
+
hash: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Subscriber callback shape. The adapter invokes the registered
|
|
60
|
+
* handler with the post-transition tuple (after the customer's
|
|
61
|
+
* router has updated its internal state and the browser URL has
|
|
62
|
+
* already settled at the new value).
|
|
63
|
+
*/
|
|
64
|
+
export type RouterSubscriber = (transition: RouterTransition) => void;
|
|
65
|
+
interface PreviewRouterSubscriberCell {
|
|
66
|
+
subscriber: RouterSubscriber | null;
|
|
67
|
+
}
|
|
68
|
+
declare global {
|
|
69
|
+
var __storystick_preview_router_subscriber__: PreviewRouterSubscriberCell | undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Register the router subscriber. Replaces any previously registered
|
|
73
|
+
* subscriber. Pass `null` to reset to the default no-op.
|
|
74
|
+
*/
|
|
75
|
+
export declare function setRouterSubscriber(fn: RouterSubscriber | null): void;
|
|
76
|
+
/**
|
|
77
|
+
* Read the currently-registered subscriber. Returns `null` before any
|
|
78
|
+
* adapter has called `setRouterSubscriber`. Consumers gate their
|
|
79
|
+
* invocation on the non-null return.
|
|
80
|
+
*/
|
|
81
|
+
export declare function getRouterSubscriber(): RouterSubscriber | null;
|
|
82
|
+
/**
|
|
83
|
+
* Convenience for `activate()`'s router-transition path: invoke the
|
|
84
|
+
* currently-registered subscriber if any, no-op otherwise. Centralises
|
|
85
|
+
* the null-check so callers don't repeat it.
|
|
86
|
+
*/
|
|
87
|
+
export declare function notifyRouterTransition(transition: RouterTransition): void;
|
|
88
|
+
/**
|
|
89
|
+
* Test-only reset. Vitest isolates modules per file but multiple
|
|
90
|
+
* cases inside one file would otherwise share state.
|
|
91
|
+
*/
|
|
92
|
+
export declare function _resetRouterSubscriberForTests(): void;
|