@kumwe/studio-preview 0.1.0-alpha.10
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 +21 -0
- package/README.md +83 -0
- package/THIRD_PARTY_NOTICES.md +9 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/preview-client.d.ts +96 -0
- package/dist/preview-client.d.ts.map +1 -0
- package/dist/preview-client.js +638 -0
- package/dist/preview-client.js.map +1 -0
- package/dist/preview-host.d.ts +68 -0
- package/dist/preview-host.d.ts.map +1 -0
- package/dist/preview-host.js +486 -0
- package/dist/preview-host.js.map +1 -0
- package/dist/preview-identity.d.ts +29 -0
- package/dist/preview-identity.d.ts.map +1 -0
- package/dist/preview-identity.js +61 -0
- package/dist/preview-identity.js.map +1 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kumwe Studio contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# `@kumwe/studio-preview`
|
|
2
|
+
|
|
3
|
+
Status: pre-Gate-A foundation alpha. The channel is an executable contract spike, not a qualified adapter.
|
|
4
|
+
|
|
5
|
+
An exact-origin, typed request channel between Studio and a host-rendered preview surface. A host can
|
|
6
|
+
render Twig, Liquid, JSX, or another server template without teaching the canvas to reproduce its
|
|
7
|
+
markup. Wildcard target origins are rejected.
|
|
8
|
+
|
|
9
|
+
The channel handles correlation, timeouts, abort signals, protocol filtering, and disposal. The host
|
|
10
|
+
still owns authentication, authorization, CSP, sandboxing, and rendering.
|
|
11
|
+
|
|
12
|
+
## Host responder and handshake
|
|
13
|
+
|
|
14
|
+
`PreviewClient` is the Studio half of the channel; `PreviewHost` is the preview-surface half. Both
|
|
15
|
+
pin an exact target origin and drop any inbound message whose source window, origin, schema, channel
|
|
16
|
+
ID, session generation, or sequence does not match; each direction stamps its own monotonic sequence
|
|
17
|
+
counter. Outbound client messages cross the same canonical guard before posting, and the draft.2
|
|
18
|
+
message vocabulary is closed.
|
|
19
|
+
|
|
20
|
+
The handshake and request flow is announce → ready → render → rendered:
|
|
21
|
+
|
|
22
|
+
1. The host constructs a `PreviewHost` with its renderer id, viewport inventory, and a render
|
|
23
|
+
callback, then calls `announce()` to post `studio.preview/ready`.
|
|
24
|
+
2. Studio awaits `client.ready()`, which resolves with the announced payload — immediately when the
|
|
25
|
+
announcement already arrived — and rejects on timeout, abort, or disposal.
|
|
26
|
+
3. Studio requests `studio.preview/render` via `client.render()` with a session-unique `requestId`.
|
|
27
|
+
The host invokes its render callback with an `AbortSignal` and replies with
|
|
28
|
+
`studio.preview/rendered` carrying the same request ID and draft digest. A newer request aborts and
|
|
29
|
+
generation-invalidates in-flight work on both sides, so a stale result is never posted or resolved
|
|
30
|
+
even when a retry uses the same digest at another viewport.
|
|
31
|
+
4. A failed render is answered with `studio.preview/error` (code `studio.preview/render-failed`, the
|
|
32
|
+
request ID as `correlationId`, `retryable: true`) and a generic message — renderer failure
|
|
33
|
+
details never cross the channel.
|
|
34
|
+
5. `client.select()` forwards `studio.preview/select` to the host's `onSelect` listeners.
|
|
35
|
+
|
|
36
|
+
## Portable draft identity and markers
|
|
37
|
+
|
|
38
|
+
`canonicalPreviewDraftBytes(draft)` returns exactly the canonical UTF-8 bytes of a complete Studio
|
|
39
|
+
artifact. `computePreviewDraftDigest(draft)` hashes those bytes as lowercase hexadecimal SHA-256; it
|
|
40
|
+
does not add an envelope, prefix, viewport, BOM, or newline. The host still validates and authorizes
|
|
41
|
+
the staged draft, recomputes its digest, and compares it before rendering — the digest is never a
|
|
42
|
+
credential.
|
|
43
|
+
|
|
44
|
+
`createPreviewMarker(digest, ordinal)` implements the canonical
|
|
45
|
+
`studio.preview/node/<digest>/<ordinal>` grammar. `createPreviewMarkerInventory(blueprint, digest)`
|
|
46
|
+
enumerates roots, each node before descendants, sorted slot names, then child arrays. Every rendered
|
|
47
|
+
response requires an exact one-to-one `markerMap`; the generic responder refuses a mismatched digest,
|
|
48
|
+
grammar, contiguous order, duplicate, or incomplete map. Because the channel does not hold the draft,
|
|
49
|
+
the authoritative renderer additionally compares node mapping with `createPreviewMarkerInventory`;
|
|
50
|
+
the standalone reference renderer does so. `announceActivation()` accepts only a marker from the
|
|
51
|
+
currently accepted inventory, and the client independently drops invented or revoked activation
|
|
52
|
+
traffic.
|
|
53
|
+
|
|
54
|
+
These semantics require wire protocol `0.1.0-draft.2`. A `.1` peer is incompatible rather than
|
|
55
|
+
silently accepted. Portable implementations replay `@kumwe/studio-testkit/vectors/preview/` against
|
|
56
|
+
their own canonicalizer and traversal.
|
|
57
|
+
|
|
58
|
+
## Marker geometry
|
|
59
|
+
|
|
60
|
+
`client.measure()` posts `studio.preview/measure` with a non-empty bounded marker list and resolves with the
|
|
61
|
+
`studio.preview/measurements` answer: per marker, one or more CSS-pixel rectangles relative to the
|
|
62
|
+
preview viewport origin (inline content fragments across lines), plus viewport metrics. Markers the
|
|
63
|
+
renderer cannot place are returned in a distinct `unknown` list, never thrown. A marker outside the
|
|
64
|
+
latest digest-bound inventory is rejected locally with `PreviewChannelError` code
|
|
65
|
+
`studio.preview/measure-stale-marker`; the host independently rejects raw stale traffic without
|
|
66
|
+
invoking the measurer.
|
|
67
|
+
|
|
68
|
+
The host never reads the DOM. The embedding renderer passes a `measure` callback in
|
|
69
|
+
`PreviewHostOptions`; without one, measure requests are answered with the qualified
|
|
70
|
+
`studio.preview/measure-unavailable` error, and a throwing measurer is answered with
|
|
71
|
+
`studio.preview/measure-failed` — measurer failure details never cross the channel.
|
|
72
|
+
|
|
73
|
+
Geometry is volatile, not document state: each response is stamped with the digest of the render it
|
|
74
|
+
was measured against. The host captures that digest and a private generation before invoking the
|
|
75
|
+
callback. A same-digest rerender, newer measurement, disposal, reload or teardown aborts and
|
|
76
|
+
invalidates the prior measurement. A viewport instruction also rejects the client's pending
|
|
77
|
+
measurement with `PreviewChannelError` code `studio.preview/measure-viewport-changed` and aborts the
|
|
78
|
+
host callback before viewport listeners run, so pre-resize geometry cannot settle late. Measured and
|
|
79
|
+
unknown entries must exactly partition the requested markers.
|
|
80
|
+
|
|
81
|
+
Version negotiation currently requires the exact draft wire version on both sides: schema filtering
|
|
82
|
+
accepts only `STUDIO_WIRE_PROTOCOL_VERSION`, so a ready announcement from a host speaking any other
|
|
83
|
+
version is discarded and `ready()` times out instead of resolving against an incompatible host.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
<!-- Generated by scripts/generate-third-party-notices.mjs. Do not edit by hand. -->
|
|
4
|
+
|
|
5
|
+
Package: `@kumwe/studio-preview`
|
|
6
|
+
|
|
7
|
+
Production closure SHA-256: `4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945`
|
|
8
|
+
|
|
9
|
+
This package has no third-party runtime dependencies.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { PreviewClient, PreviewChannelError, type PreviewClientOptions, type PreviewMeasureOptions, type PreviewMeasureOutcome, type PreviewMessageEvent, type PreviewMessageListener, type PreviewMessageSource, type PreviewMessageTarget, type PreviewProtocolListener, type PreviewReadyOptions, type PreviewRenderOptions, } from './preview-client.js';
|
|
2
|
+
export { PreviewHost, type PreviewHostOptions, type PreviewMeasureCallback, type PreviewMeasurement, type PreviewRenderCallback, type PreviewSelectListener, } from './preview-host.js';
|
|
3
|
+
export { canonicalPreviewDraftBytes, computePreviewDraftDigest, createPreviewMarker, createPreviewMarkerInventory, type PreviewDigestOptions, type PreviewMarkerInventory, } from './preview-identity.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,4BAA4B,EAC5B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { PreviewClient, PreviewChannelError, } from './preview-client.js';
|
|
2
|
+
export { PreviewHost, } from './preview-host.js';
|
|
3
|
+
export { canonicalPreviewDraftBytes, computePreviewDraftDigest, createPreviewMarker, createPreviewMarkerInventory, } from './preview-identity.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,mBAAmB,GAWpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,WAAW,GAMZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,4BAA4B,GAG7B,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type PreviewMeasurePayload, type PreviewMeasurementsPayload, type PreviewMessage, type PreviewReadyPayload, type PreviewRenderedPayload, type PreviewRenderPayload, type PreviewActivatedPayload, type PreviewDisposePayload, type PreviewSelectPayload, type PreviewViewportPayload, type PreviewTeardownPayload, type QualifiedName } from '@kumwe/studio-protocol';
|
|
2
|
+
/** Stable client-side and wire failure surfaced by the preview channel. */
|
|
3
|
+
export declare class PreviewChannelError extends Error {
|
|
4
|
+
readonly code: QualifiedName;
|
|
5
|
+
readonly retryable: boolean;
|
|
6
|
+
constructor(code: QualifiedName, message: string, retryable?: boolean);
|
|
7
|
+
}
|
|
8
|
+
export interface PreviewMessageEvent {
|
|
9
|
+
data: unknown;
|
|
10
|
+
origin: string;
|
|
11
|
+
source: unknown;
|
|
12
|
+
}
|
|
13
|
+
export type PreviewMessageListener = (event: PreviewMessageEvent) => void;
|
|
14
|
+
export interface PreviewMessageSource {
|
|
15
|
+
addEventListener(type: 'message', listener: PreviewMessageListener): void;
|
|
16
|
+
removeEventListener(type: 'message', listener: PreviewMessageListener): void;
|
|
17
|
+
}
|
|
18
|
+
export interface PreviewMessageTarget {
|
|
19
|
+
postMessage(message: unknown, targetOrigin: string): void;
|
|
20
|
+
}
|
|
21
|
+
export interface PreviewClientOptions {
|
|
22
|
+
channelId: string;
|
|
23
|
+
sessionGeneration: string;
|
|
24
|
+
source: PreviewMessageSource;
|
|
25
|
+
target: PreviewMessageTarget;
|
|
26
|
+
targetOrigin: string;
|
|
27
|
+
timeoutMilliseconds?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface PreviewReadyOptions {
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}
|
|
32
|
+
export interface PreviewRenderOptions {
|
|
33
|
+
signal?: AbortSignal;
|
|
34
|
+
}
|
|
35
|
+
export interface PreviewMeasureOptions {
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Result of a `measure()` call. Geometry whose render digest no longer matches the
|
|
40
|
+
* client's latest rendered digest is discarded and surfaced as a `stale` outcome —
|
|
41
|
+
* a typed signal to re-measure, not an error.
|
|
42
|
+
*/
|
|
43
|
+
export type PreviewMeasureOutcome = {
|
|
44
|
+
geometry: PreviewMeasurementsPayload;
|
|
45
|
+
status: 'measured';
|
|
46
|
+
} | {
|
|
47
|
+
measuredDigest: string;
|
|
48
|
+
status: 'stale';
|
|
49
|
+
};
|
|
50
|
+
export type PreviewProtocolListener = (message: PreviewMessage) => void;
|
|
51
|
+
export type PreviewActivationListener = (payload: PreviewActivatedPayload) => void;
|
|
52
|
+
export declare class PreviewClient {
|
|
53
|
+
#private;
|
|
54
|
+
constructor(options: PreviewClientOptions);
|
|
55
|
+
dispose(): void;
|
|
56
|
+
onMessage(listener: PreviewProtocolListener): () => void;
|
|
57
|
+
/**
|
|
58
|
+
* Resolves once the host announces `studio.preview/ready` on this channel. If the
|
|
59
|
+
* announcement was already received, the cached payload resolves immediately.
|
|
60
|
+
*
|
|
61
|
+
* `isPreviewMessage` accepts only ready payloads carrying the exact draft wire protocol
|
|
62
|
+
* version, so an announcement from an incompatible host is filtered out and never resolves
|
|
63
|
+
* this promise — the wait times out instead. The promise also rejects on abort or when the
|
|
64
|
+
* client is disposed.
|
|
65
|
+
*/
|
|
66
|
+
ready(options?: PreviewReadyOptions): Promise<PreviewReadyPayload>;
|
|
67
|
+
render(payload: PreviewRenderPayload, options?: PreviewRenderOptions): Promise<PreviewRenderedPayload>;
|
|
68
|
+
/**
|
|
69
|
+
* Requests the on-screen geometry of render markers from the responder. Resolves with a
|
|
70
|
+
* `measured` outcome carrying viewport-relative CSS-pixel rectangles, or a `stale`
|
|
71
|
+
* outcome when the response was measured against a render this client no longer
|
|
72
|
+
* considers latest. Rejects on teardown, reload, supersession, abort, timeout, and
|
|
73
|
+
* disposal exactly like `render()` does. Requires a completed render: geometry is a
|
|
74
|
+
* volatile measurement of a specific render digest, never document state.
|
|
75
|
+
*/
|
|
76
|
+
measure(payload: PreviewMeasurePayload, options?: PreviewMeasureOptions): Promise<PreviewMeasureOutcome>;
|
|
77
|
+
/**
|
|
78
|
+
* Drive the preview surface to a semantic viewport role or to bounded
|
|
79
|
+
* explicit dimensions. The two are alternatives, so a payload carrying both
|
|
80
|
+
* is refused before it reaches the channel.
|
|
81
|
+
*/
|
|
82
|
+
setViewport(payload: PreviewViewportPayload): void;
|
|
83
|
+
/**
|
|
84
|
+
* Instruct the renderer to revoke the resources it holds for a superseded
|
|
85
|
+
* draft while the channel stays open. This is not teardown: teardown ends
|
|
86
|
+
* the session, dispose frees a render's resources within it.
|
|
87
|
+
*/
|
|
88
|
+
disposeDraft(payload: PreviewDisposePayload): void;
|
|
89
|
+
/** Observe trusted marker interactions the renderer reports. */
|
|
90
|
+
onActivated(listener: PreviewActivationListener): () => void;
|
|
91
|
+
select(payload: PreviewSelectPayload): void;
|
|
92
|
+
/** Announce channel closure to the host, then dispose this client. */
|
|
93
|
+
teardown(reason: PreviewTeardownPayload['reason']): void;
|
|
94
|
+
}
|
|
95
|
+
export declare function normalizeOrigin(input: string): string;
|
|
96
|
+
//# sourceMappingURL=preview-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-client.d.ts","sourceRoot":"","sources":["../src/preview-client.ts"],"names":[],"mappings":"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"}
|