@graview/guest 0.1.9 → 0.1.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.
Files changed (173) hide show
  1. package/README.md +301 -2
  2. package/client.js +2 -0
  3. package/dist/channel.d.ts +11 -3
  4. package/dist/channel.d.ts.map +1 -1
  5. package/dist/channel.js +5 -1
  6. package/dist/channel.js.map +1 -1
  7. package/dist/cli.d.ts +16 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +75 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/client-script.d.ts +3 -0
  12. package/dist/client-script.d.ts.map +1 -0
  13. package/dist/client-script.js +21 -0
  14. package/dist/client-script.js.map +1 -0
  15. package/dist/client.d.ts +2 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.generated.d.ts +4 -0
  18. package/dist/client.generated.d.ts.map +1 -0
  19. package/dist/client.generated.js +9 -0
  20. package/dist/client.generated.js.map +1 -0
  21. package/dist/client.js +12 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/headless/describe.d.ts +19 -0
  24. package/dist/headless/describe.d.ts.map +1 -0
  25. package/dist/headless/describe.js +255 -0
  26. package/dist/headless/describe.js.map +1 -0
  27. package/dist/headless/draw.d.ts +17 -0
  28. package/dist/headless/draw.d.ts.map +1 -0
  29. package/dist/headless/draw.js +25 -0
  30. package/dist/headless/draw.js.map +1 -0
  31. package/dist/headless/index.d.ts +99 -0
  32. package/dist/headless/index.d.ts.map +1 -0
  33. package/dist/headless/index.js +143 -0
  34. package/dist/headless/index.js.map +1 -0
  35. package/dist/headless/judge.d.ts +16 -0
  36. package/dist/headless/judge.d.ts.map +1 -0
  37. package/dist/headless/judge.js +52 -0
  38. package/dist/headless/judge.js.map +1 -0
  39. package/dist/headless/node.d.ts +8 -0
  40. package/dist/headless/node.d.ts.map +1 -0
  41. package/dist/headless/node.js +80 -0
  42. package/dist/headless/node.js.map +1 -0
  43. package/dist/headless/protocol.d.ts +71 -0
  44. package/dist/headless/protocol.d.ts.map +1 -0
  45. package/dist/headless/protocol.js +14 -0
  46. package/dist/headless/protocol.js.map +1 -0
  47. package/dist/headless/runtime.d.ts +2 -0
  48. package/dist/headless/runtime.d.ts.map +1 -0
  49. package/dist/headless/runtime.generated.d.ts +2 -0
  50. package/dist/headless/runtime.generated.d.ts.map +1 -0
  51. package/dist/headless/runtime.generated.js +8 -0
  52. package/dist/headless/runtime.generated.js.map +1 -0
  53. package/dist/headless/runtime.js +171 -0
  54. package/dist/headless/runtime.js.map +1 -0
  55. package/dist/headless/tree.d.ts +54 -0
  56. package/dist/headless/tree.d.ts.map +1 -0
  57. package/dist/headless/tree.js +128 -0
  58. package/dist/headless/tree.js.map +1 -0
  59. package/dist/host/css.d.ts +118 -0
  60. package/dist/host/css.d.ts.map +1 -0
  61. package/dist/host/css.js +963 -0
  62. package/dist/host/css.js.map +1 -0
  63. package/dist/host/draw-budget.d.ts +10 -0
  64. package/dist/host/draw-budget.d.ts.map +1 -0
  65. package/dist/host/draw-budget.js +29 -0
  66. package/dist/host/draw-budget.js.map +1 -0
  67. package/dist/host/frame.d.ts +19 -1
  68. package/dist/host/frame.d.ts.map +1 -1
  69. package/dist/host/frame.js +21 -2
  70. package/dist/host/frame.js.map +1 -1
  71. package/dist/host/index.d.ts +4 -3
  72. package/dist/host/index.d.ts.map +1 -1
  73. package/dist/host/index.js +7 -1
  74. package/dist/host/index.js.map +1 -1
  75. package/dist/host/kit.d.ts +6 -2
  76. package/dist/host/kit.d.ts.map +1 -1
  77. package/dist/host/kit.js +12 -5
  78. package/dist/host/kit.js.map +1 -1
  79. package/dist/host/links.d.ts +24 -0
  80. package/dist/host/links.d.ts.map +1 -0
  81. package/dist/host/links.js +35 -0
  82. package/dist/host/links.js.map +1 -0
  83. package/dist/host/manifest.d.ts +50 -0
  84. package/dist/host/manifest.d.ts.map +1 -0
  85. package/dist/host/manifest.js +103 -0
  86. package/dist/host/manifest.js.map +1 -0
  87. package/dist/host/open-draw.d.ts +44 -0
  88. package/dist/host/open-draw.d.ts.map +1 -0
  89. package/dist/host/open-draw.js +108 -0
  90. package/dist/host/open-draw.js.map +1 -0
  91. package/dist/host/open-judge.d.ts +53 -0
  92. package/dist/host/open-judge.d.ts.map +1 -0
  93. package/dist/host/open-judge.js +95 -0
  94. package/dist/host/open-judge.js.map +1 -0
  95. package/dist/host/open-render.d.ts +32 -0
  96. package/dist/host/open-render.d.ts.map +1 -0
  97. package/dist/host/open-render.js +262 -0
  98. package/dist/host/open-render.js.map +1 -0
  99. package/dist/host/press.d.ts +15 -0
  100. package/dist/host/press.d.ts.map +1 -0
  101. package/dist/host/press.js +156 -0
  102. package/dist/host/press.js.map +1 -0
  103. package/dist/host/react.d.ts +15 -2
  104. package/dist/host/react.d.ts.map +1 -1
  105. package/dist/host/react.js +13 -5
  106. package/dist/host/react.js.map +1 -1
  107. package/dist/host/session.d.ts +94 -1
  108. package/dist/host/session.d.ts.map +1 -1
  109. package/dist/host/session.js +103 -14
  110. package/dist/host/session.js.map +1 -1
  111. package/dist/host/theme.d.ts +14 -0
  112. package/dist/host/theme.d.ts.map +1 -0
  113. package/dist/host/theme.js +51 -0
  114. package/dist/host/theme.js.map +1 -0
  115. package/dist/host/view-runtime.generated.d.ts +2 -0
  116. package/dist/host/view-runtime.generated.d.ts.map +1 -0
  117. package/dist/host/view-runtime.generated.js +7 -0
  118. package/dist/host/view-runtime.generated.js.map +1 -0
  119. package/dist/host/view-source.d.ts +5 -0
  120. package/dist/host/view-source.d.ts.map +1 -0
  121. package/dist/host/view-source.js +39 -0
  122. package/dist/host/view-source.js.map +1 -0
  123. package/dist/host/view.d.ts +134 -0
  124. package/dist/host/view.d.ts.map +1 -0
  125. package/dist/host/view.js +381 -0
  126. package/dist/host/view.js.map +1 -0
  127. package/dist/host/views.d.ts +10 -0
  128. package/dist/host/views.d.ts.map +1 -0
  129. package/dist/host/views.js +15 -0
  130. package/dist/host/views.js.map +1 -0
  131. package/dist/host/worker-react.d.ts +51 -0
  132. package/dist/host/worker-react.d.ts.map +1 -0
  133. package/dist/host/worker-react.js +123 -0
  134. package/dist/host/worker-react.js.map +1 -0
  135. package/dist/host/worker-start.d.ts +49 -0
  136. package/dist/host/worker-start.d.ts.map +1 -0
  137. package/dist/host/worker-start.js +122 -0
  138. package/dist/host/worker-start.js.map +1 -0
  139. package/dist/host/worker.d.ts +17 -12
  140. package/dist/host/worker.d.ts.map +1 -1
  141. package/dist/host/worker.js +58 -117
  142. package/dist/host/worker.js.map +1 -1
  143. package/dist/host/writes.d.ts +49 -0
  144. package/dist/host/writes.d.ts.map +1 -0
  145. package/dist/host/writes.js +76 -0
  146. package/dist/host/writes.js.map +1 -0
  147. package/dist/index.d.ts +1 -1
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/open-kit.d.ts +148 -0
  150. package/dist/open-kit.d.ts.map +1 -0
  151. package/dist/open-kit.js +321 -0
  152. package/dist/open-kit.js.map +1 -0
  153. package/dist/protocol.d.ts +109 -3
  154. package/dist/protocol.d.ts.map +1 -1
  155. package/dist/protocol.js +13 -0
  156. package/dist/protocol.js.map +1 -1
  157. package/dist/worker/harden.d.ts +13 -2
  158. package/dist/worker/harden.d.ts.map +1 -1
  159. package/dist/worker/harden.js +10 -4
  160. package/dist/worker/harden.js.map +1 -1
  161. package/dist/worker/natives.d.ts +1 -0
  162. package/dist/worker/natives.d.ts.map +1 -1
  163. package/dist/worker/natives.js +4 -0
  164. package/dist/worker/natives.js.map +1 -1
  165. package/dist/worker/view-global.d.ts +70 -0
  166. package/dist/worker/view-global.d.ts.map +1 -0
  167. package/dist/worker/view-global.js +264 -0
  168. package/dist/worker/view-global.js.map +1 -0
  169. package/dist/worker/view.d.ts +14 -0
  170. package/dist/worker/view.d.ts.map +1 -0
  171. package/dist/worker/view.js +64 -0
  172. package/dist/worker/view.js.map +1 -0
  173. package/package.json +30 -4
package/README.md CHANGED
@@ -57,7 +57,67 @@ entries import nothing of the framework, so a guest bundle carries none of it.
57
57
  `GuestProps` is the plain-data half of `ViewProps` — `node`, `nodes`, the
58
58
  `edges` among them, `label`, `fidelity`, `cardinality`, `mode`, `selected`,
59
59
  `implicated`, `flagged` — and `acts`, the acts the viewer may run. A record
60
- the viewer may not see is in none of them.
60
+ the viewer may not see is in none of them. Every record's `label` is
61
+ filled as the host labels it, and `theme` and `places` are the app's.
62
+
63
+ ### What a frame guest reads, its look, and its place
64
+
65
+ ```ts
66
+ views.register("package", { cardinality: "many", fidelity: "full" },
67
+ guestView({ url, name: "prices", title: "The price sheet", reads: { kinds: ["offer"], edges: ["includes"] } }),
68
+ { title: "The price sheet" });
69
+ views.home(guestView({ url: frontUrl, name: "front", reads: { kinds: ["package"] } }));
70
+ ```
71
+
72
+ A guest is handed what it is drawn over and the edges among those records.
73
+ With `reads` it is also handed every record of the kinds it reads and
74
+ every edge of the edges it reads between the records it holds, as the
75
+ viewer sees them (`readAcross`, the rule a worker view's manifest uses
76
+ too). A guest over packages that reads `offer` and `includes` gets each
77
+ package's offers, and an offer the viewer may not see is in none of it.
78
+ Drawn as the home (`views.home`), a guest is drawn over nothing and sees
79
+ what it reads: it is the routed home's body, and the landing over the scene.
80
+
81
+ Its props carry `theme`, a `GuestTheme`: the scheme, the accent, ground,
82
+ panel, ink, muted ink and edge colours, and the body and mono fonts, read
83
+ off the element the frame is drawn in. The scheme is the app's own (the
84
+ embed's `data-graview-scheme`), not the system's, and the host pushes
85
+ again when the app's toggle changes it. `mountGuestView` takes `reads`,
86
+ `theme` and `places` too.
87
+
88
+ `title` names the frame for assistive technology. Registered with the same
89
+ title, the guest is a place on both faces: listed by `placesOf`, at
90
+ `/places/the-price-sheet` on the routed face and `#view=the-price-sheet` in
91
+ the scene. `props.places` lists the app's places, and
92
+ `guest.navigate({ place: "the-packages" })` goes to one.
93
+
94
+ ### One client, served or inlined
95
+
96
+ `@graview/guest/client.js` is the frame guest's client as one prebuilt
97
+ classic script (2.4 kB). It leaves one global, `GraviewGuest`, and
98
+ `GraviewGuest.connect()` is `connectGuest()`. A host serves it at a path of
99
+ its own, or inlines its text where a frame's policy allows inline script
100
+ alone, as Graview Cloud serves an uploaded view (`script-src
101
+ 'unsafe-inline'`). `GUEST_CLIENT` from `@graview/guest/client` is that
102
+ text, and `GUEST_CLIENT_SHA256` its hash for a policy that names it.
103
+
104
+ ```html
105
+ <main id="app"></main>
106
+ <script>/* GUEST_CLIENT */</script>
107
+ <script>
108
+ const guest = GraviewGuest.connect();
109
+ guest.subscribe((props) => {
110
+ document.body.style.background = props.theme.panel;
111
+ app.replaceChildren(...props.nodes.map((node) => Object.assign(document.createElement("p"), { textContent: node.label })));
112
+ guest.size(document.documentElement.scrollHeight);
113
+ });
114
+ </script>
115
+ ```
116
+
117
+ How to write one, with a worked example, is the `graview-embed` skill.
118
+ `guest-sandbox --transport=client` serves a guest of a few lines under that
119
+ policy and finds it renders, acts, navigates, resizes and follows the
120
+ app's toggle in Chromium, WebKit and Firefox.
61
121
 
62
122
  ## In a worker
63
123
 
@@ -84,7 +144,11 @@ limits. A second ready from the same worker is dropped. Once it is ready,
84
144
  the host sends a heartbeat over the port and the worker's runtime answers
85
145
  it; a worker that goes `limits.silentMs` (5 000 by default) without an
86
146
  answer — a guest spinning in `while (true)` — is terminated, and
87
- the host is told `silent`. A guest that is busy but yields is kept. What the guest draws
147
+ the host is told `silent`. A guest that is busy but yields is kept. The
148
+ host also counts its own time drawing what the guest sends. Over any one
149
+ second it spends at most `limits.drawMs` (100 by default). Past it, the
150
+ rest of the batch is left undrawn, the worker is terminated, and the host
151
+ is told `slow`. What the guest draws
88
152
  comes over the port as Remote DOM mutation records, and the host draws only
89
153
  the kit (`GUEST_KIT`), with `createKitRenderer`. Both are
90
154
  `@graview/guest/host/worker`, apart from the frame's host, so a page that
@@ -144,3 +208,238 @@ runs guests it did not build checks them, or better, builds them itself.
144
208
 
145
209
  The worker entry carries Remote DOM (`@remote-dom/core` and its polyfill,
146
210
  MIT, pinned); the frame guest and the host do not.
211
+
212
+ ## A worker view on the open kit
213
+
214
+ A view that needs more than the kit's components — a card grid, a chart,
215
+ an animated ring — draws plain HTML, SVG and one stylesheet instead. What
216
+ keeps it safe is what it can reach, not what it can draw: it runs in the
217
+ same hardened classic worker, and the host draws what it says into a
218
+ shadow root inside a region of the host's own — `contain: layout paint
219
+ style`, `isolation: isolate`, `overflow: clip` — keeping only what the open
220
+ kit allows. The view is one plain script with no imports and no build;
221
+ the host puts the view's runtime in front of it.
222
+
223
+ ```ts
224
+ import { mountWorkerView } from "@graview/guest/host/worker";
225
+
226
+ const view = mountWorkerView(element, { manifest, worker: { source }, store, principal,
227
+ onFailure: (reason, detail) => showTheTierOneFace(reason, detail) });
228
+ ```
229
+
230
+ In the worker, the view has one global, `graview`:
231
+
232
+ ```js
233
+ graview.style(`.grid { display: grid; gap: 12px } .card { background: var(--graview-panel) }`);
234
+ graview.onProps((props) => graview.render(graview.html`
235
+ <section class="grid">${props.nodes.map((n) => graview.html`<article class="card"><h3>${n.label}</h3></article>`)}</section>`));
236
+ graview.on("click", ".card", (event) => { /* … */ });
237
+ ```
238
+
239
+ What may be drawn is one declaration, read by both sides: most of HTML's
240
+ sectioning, text, lists, tables, `details`, buttons, fields and `img`;
241
+ SVG's shapes, paths, text, gradients, clip paths, masks, markers and `use`
242
+ of `#id`; and CSS for layout, grid, flex, colour, type, transitions,
243
+ keyframes, media and container queries, with the app's theme tokens
244
+ (`--graview-*`) inherited, light or dark as the app is. The stylesheet,
245
+ every `style` attribute and every SVG paint are read with the CSS Syntax
246
+ tokenizer and parser — escapes decoded, comments gone — and written afresh
247
+ from what was kept: `url()` only as `url(#id)` on a paint, no `@import`,
248
+ `@font-face` or other at-rule but `@media`, `@supports`, `@container` and
249
+ `@keyframes`, only the functions on the list (no `image-set()`, `attr()`,
250
+ `cross-fade()`, `element()` …), `position` only static, relative or
251
+ absolute, and no selector that reaches out of the shadow tree (`:host`,
252
+ `::slotted`). An image is a `data:` image or a `blob:` of the page's own;
253
+ an SVG image in an `img` runs no script and loads nothing. No `<script>`,
254
+ `<iframe>`, `<object>`, `<embed>`, `<link>`, `<meta>`, `<base>`, `<style>`,
255
+ `<form>`, SVG `<image>` or `<foreignObject>`, no `src`, `href`, `srcset`,
256
+ `formaction` or `on*` attribute is drawn; what is not drawn is in
257
+ `refused`, with why. A view never speaks as the app's chrome. `<nav>`,
258
+ `<header>`, `<footer>`, `<aside>` and `<search>` are drawn as `<div>`, and
259
+ `<output>` as `<span>`. Each holds what it held and is marked
260
+ `data-graview-as`, and the view's selectors for those names are read as
261
+ that attribute. A `<section>` is never named, and `role` takes no landmark
262
+ or notice's role. `guest-sandbox --transport=open` serves a page with no
263
+ content security policy, tries every way out, and finds no request leaving
264
+ it in Chromium, WebKit or Firefox.
265
+
266
+ ### A worker view is a place
267
+
268
+ A worker view says what it is and what it may touch in a manifest the host
269
+ enforces:
270
+
271
+ ```ts
272
+ import { registerWorkerView, workerHome } from "@graview/guest/host/views";
273
+
274
+ const packages = {
275
+ manifest: { name: "packages", title: "The packages", attach: "package", cardinality: "many",
276
+ reads: { kinds: ["offer"], edges: ["includes"] }, acts: ["set-standing"] },
277
+ worker: { source },
278
+ author: "Made by Claude for Nick",
279
+ };
280
+ views: (schema, registry) => registerWorkerView(registry, packages), // the embed's views
281
+ pages.surface("home", workerHome(frontPage)); // a view of the home
282
+ ```
283
+
284
+ It is handed the viewer's sight and nothing more, cut to the kind it
285
+ attaches to (the members the face hands it, or every one the viewer sees)
286
+ and the kinds and edges it reads: a record the viewer may not see is in
287
+ none of it, and a kind it did not ask to read is not handed to it however
288
+ visible. Every record's `label` is filled as the host labels it — for a
289
+ frame guest too. A titled view is a named place on the Graview face and
290
+ the pages face, by its title; whatever the registry drew for that kind
291
+ before is drawn if the view fails. With `attach: "home"`,
292
+ `registerWorkerView` makes it the home's own view (FR-81). That is the
293
+ routed home's body and the landing over the scene when it is at home, in
294
+ place of the home the app declared, which is drawn if the view fails.
295
+ `workerHome` makes it the routed face's whole home surface instead. Its props carry the app's look as a
296
+ `GuestTheme` — the scheme, the accent, ground, panel, ink, muted ink and
297
+ edge colours, and the body and mono fonts — read off the region it is
298
+ drawn in, and the host
299
+ pushes again when the app's own toggle changes the scheme, whatever the
300
+ system prefers. `checkManifest` says what in a manifest names a kind, an
301
+ edge or an act the app does not declare, and the host refuses to start
302
+ such a view (`onFailure` hears `manifest`).
303
+
304
+ ### Writes that cannot leak
305
+
306
+ A view runs for every member with that member's sight, and its author is
307
+ not the member, so the danger is a view reading what this viewer may see
308
+ and writing it where somebody else may. An act must be named in the
309
+ manifest. Where the app's sight is total — no sight is declared, or every
310
+ kind is seen whole by everybody (`sightIsTotal`) — an act the view asks for
311
+ from its code applies with its arguments as given. Otherwise it applies
312
+ only from a press the host itself saw:
313
+
314
+ ```html
315
+ <fieldset>
316
+ <input name="summary" placeholder="What it is">
317
+ <button data-act="set-summary" data-record="package:start">Say it</button>
318
+ </fieldset>
319
+ ```
320
+
321
+ A trusted click on an element with `data-act` is judged and applied in the
322
+ click's own handler, before the view hears of it (it hears `pressed`). Its
323
+ arguments come only from the record the element is bound to (`data-record`,
324
+ one the view was shown), the manifest's constants for the act (`{ act,
325
+ as, constants }`), and the fields in the press's `fieldset` the host read
326
+ itself — each one the viewer's: its last change a trusted `input`, and
327
+ nothing the view wrote in it since. A field the view filled is the view's
328
+ until the viewer empties it; a `change` a browser raises when such a field
329
+ loses focus is not typing; a view that says back what a field shows, or
330
+ empties it, takes nothing away. Either way an act is applied as the viewer,
331
+ `via: "view:<name>"`, within the view's allowance, and undoable.
332
+
333
+ ### Links stay in the app
334
+
335
+ A worker view links to a record or a named place of this app, and nowhere
336
+ else. The open kit draws no `href`, so `<a href="https://…">` is text;
337
+ `<a data-record="offer:coaching">` and `<a data-place="the-packages">` are
338
+ made links by the host — focusable, a link to assistive technology — and
339
+ followed by it on a press or Enter, to a record the viewer may see or a
340
+ place the app has. `graview.navigate("offer:coaching")` and
341
+ `graview.navigate({ place: "the-packages" })` are held to the same. The
342
+ props list the app's places (`places`, each with its slug and title). On
343
+ the Graview face a record is focused and chosen and a place is drawn; on
344
+ the pages face each goes to its own address — through `useGoTo` in
345
+ `@graview/react`, which the routed face provides. The kit's `gv-link`
346
+ keeps `links.origins`: it is the kit's one deliberate way out, to the
347
+ origins a host lists, and an open-kit view has none.
348
+
349
+ ### Limits, and what is drawn in a view's place
350
+
351
+ The host caps a view's code (`maxSourceBytes`, 256 000 by default), the
352
+ nodes it draws (`maxNodes`, 5 000), the messages it sends (`messages` in
353
+ `messageWindowMs`, 120 a second) and the time it takes over each push of
354
+ what it is shown (`pushMs`, 1 000 ms: the view's listeners as its runtime
355
+ times them, and the wait for the runtime to say it drew, as the host times
356
+ it), beside the heartbeat's `silentMs`, and the page's own time drawing
357
+ what the view sends (`drawMs`, 100 ms of any second). Past any of them the worker is
358
+ terminated, the plain face of what the view was shown — its title and each
359
+ record by its label, drawn by the host — is drawn in the region, and
360
+ `onFailure` hears why: `source`, `nodes`, `flood`, `slow`, `silent`,
361
+ `error` (it threw before it drew), `refused` or `manifest`, with a sentence
362
+ saying it. A host draws its own in its place with `fallback`; the React
363
+ registrations draw whatever the registry drew for the kind before.
364
+
365
+ What is left: work a view schedules with timers between pushes is not
366
+ timed per push. A view that busies its own worker for just under
367
+ `silentMs`, answers the heartbeat, and does it again can hold a core of the
368
+ reader's machine for as long as it is shown. That is the worker's thread,
369
+ not the page's; the page stays responsive.
370
+
371
+ ### A view with no build
372
+
373
+ A view is handed over as its plain source, `{ source }`: one script
374
+ against the `graview` global, with no imports, no bundler and no copy of
375
+ the protocol. The host puts the view's runtime in front of it — Remote
376
+ DOM's polyfill, the hardening, the channel and the global, which the host
377
+ holds as one classic script and fetches only when it first starts a view —
378
+ and runs both as one strict classic worker. A module worker is not an
379
+ option: a `blob:` one is refused in an opaque origin. The hardened worker
380
+ has no `eval`, no function constructor and no `importScripts`, so the one
381
+ way left to load code is `import()`, which is syntax: a source whose text
382
+ says `import` anywhere, even in a string or a comment, is refused before it
383
+ runs (`checkViewSource` says why), and so is one that exports. `{ script }`
384
+ still takes a whole worker script built against `@graview/guest/worker/view`.
385
+ How to write one — the manifest, what may be drawn, the theme's tokens, the
386
+ write rules, links and limits, with a list lens and a home worked through —
387
+ is the `graview-worker-view` skill (`graview skills install`).
388
+
389
+ ### Run a view headless, and say what it drew
390
+
391
+ Before a view is applied, a host can run it once with no network and no
392
+ DOM, against one member's sight, and be told what it drew in the words
393
+ `describePlace` says a place in (`@graview/core/describe`): its headings,
394
+ text, figures and fields, and its lists with each record's title and what
395
+ its row or card says. Or it is told why the view will not do.
396
+
397
+ ```ts
398
+ import { runWorkerViewHeadless } from "@graview/guest/headless";
399
+
400
+ const result = await runWorkerViewHeadless({ manifest, source, store, principal, run });
401
+ if (result.ok) say(result.description.text); // "The packages (/places/the-packages) — as partner …"
402
+ else say(result.reason, result.detail); // "act": It asks for the act "buy", which its manifest does not name.
403
+ ```
404
+
405
+ The reasons are the page's (`source`, `manifest`, `error`, `nodes`,
406
+ `flood`, `slow`, `refused`) and two of a headless run's own: `act`, an act
407
+ asked for from the view's code or bound to a press (`data-act`) that its
408
+ manifest does not name, and `isolate`, the host's isolate could not run it.
409
+ Nothing is applied: an act the view asks for is written down in the
410
+ transcript and answered with a refusal.
411
+
412
+ A view never runs in the host's own context. The host supplies the
413
+ isolate: `run` is handed one script and one JSON string (`HeadlessPayload`),
414
+ loads the script into an isolate of its choosing, calls the global it
415
+ leaves (`graviewHeadless`) with the string, and hands back the string it
416
+ resolves with. Nothing but text crosses. There is no default, and without
417
+ a `run` the helper throws. The script is the headless runtime, then the
418
+ view. It makes the isolate a worker's before the view is read: the same
419
+ `graview` global over a transcript, a console that writes to it, timers
420
+ that never fire, and everything outside the worker's allowlist taken from
421
+ the global. Then the view's top line runs and it is pushed what it is
422
+ shown, once. What it sent is judged again in the host's context, from the
423
+ transcript alone, by the open kit's own renderer drawing into a tree of
424
+ plain objects (`drawTranscript`, `describeDrawing`), so the isolate's word
425
+ is not taken for what the view drew.
426
+
427
+ `nodeIsolate` from `@graview/guest/headless/node` is a `run` for Node: a
428
+ worker thread with a heap ceiling and a context made from nothing (no
429
+ `process`, `require`, `fetch` or timers; no code from strings), with a
430
+ deadline that covers the microtasks the view queues. In workerd, the
431
+ script is one module of a worker of its own with no outbound network, and
432
+ the host's module, loaded first, keeps `Response` to answer with:
433
+
434
+ ```js
435
+ // before.js
436
+ const Made = Response; export const answer = (text) => new Made(text);
437
+ // host.js
438
+ import { answer } from "./before.js"; import "./view.js"; // view.js is payload.script
439
+ const run = globalThis.graviewHeadless;
440
+ export default { async fetch(request) { return answer(await run(await request.text())); } };
441
+ ```
442
+
443
+ `graview view check view.js --app app.js --manifest manifest.json --seed
444
+ seed.json --roles partner` does the same from a terminal, with
445
+ `nodeIsolate`.
package/client.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! @graview/guest/client.js — a frame guest's client (GraviewGuest.connect). Generated from src/client-script.ts. Elastic License 2.0. */
2
+ "use strict";var GraviewGuest=(()=>{var f=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var k=(o,t)=>{for(var r in t)f(o,r,{get:t[r],enumerable:!0})},M=(o,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of O(t))!H.call(o,a)&&a!==r&&f(o,a,{get:()=>t[a],enumerable:!(i=R(t,a))||i.enumerable});return o};var P=o=>M(f({},"__esModule",{value:!0}),o);var T={};k(T,{connect:()=>w,protocol:()=>y});var y=1;function G(o){let t=o;return typeof o=="object"&&o!==null&&t.graview==="host-hello"&&typeof t.nonce=="string"}function b(o,t={}){let r,i="",a,h=0,u=new Set,g=new Map,m=[],d=n=>{r?r.postMessage({...n,nonce:i}):m.push(n)},x=n=>{let e=n.data;if(!(!e||typeof e!="object")){if(e.type==="props"){a=e.props;for(let s of u)s(e.props)}else e.type==="answer"?(g.get(e.id)?.(e),g.delete(e.id)):e.type==="event"&&typeof e.listener=="number"?t.onEvent?.(e):e.type==="heartbeat"&&typeof e.beat=="number"&&d({type:"heartbeat",beat:e.beat});t.onMessage?.(e)}},p=()=>{},E=n=>{if(r||!o.fromHost(n)||!G(n.data)||n.data.protocol!==1)return;let e=n.ports[0];if(e){r=e,i=n.data.nonce,r.onmessage=x,r.start?.(),p();for(let s of m.splice(0))d(s)}};p=o.listen(E),o.ready({graview:"guest-ready",protocol:1});let c,v={get props(){return a},subscribe(n){return u.add(n),()=>u.delete(n)},act(n,e={}){let s=h+=1;return new Promise(l=>{g.set(s,l),d({type:"act",id:s,name:n,args:e})})},navigate(n){typeof n=="string"?d({type:"navigate",to:n}):n&&typeof n.place=="string"&&d({type:"navigate",place:n.place})},size(n){d({type:"size",height:n})},autoSize(n){let e=n??globalThis.document?.documentElement,s=globalThis.ResizeObserver;if(!e||!s||typeof e.getBoundingClientRect!="function")return()=>{};c?.disconnect();let l=new s(()=>v.size(Math.ceil(e.getBoundingClientRect().height)));return l.observe(e),c=l,()=>l.disconnect()},close(){c?.disconnect(),p(),r?.close(),u.clear()}};return{guest:v,send:d}}function w(o={}){let t=o.window??globalThis;return b({listen(r){return t.addEventListener("message",r),()=>t.removeEventListener("message",r)},fromHost:r=>r.source===t.parent&&(o.hostOrigin===void 0||r.origin===o.hostOrigin),ready:r=>t.parent?.postMessage(r,"*")}).guest}return P(T);})();
package/dist/channel.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type GuestAnswer, type GuestEvent, type GuestProps, type GuestRequest } from "./protocol.js";
1
+ import { type GuestAnswer, type GuestEvent, type GuestProps, type GuestRequest, type HostMessage } from "./protocol.js";
2
2
  /**
3
3
  * A GUEST'S ONE CHANNEL to the host that started it. It can read what the
4
4
  * host pushed and ask; it cannot reach the store, and an act it asks for
@@ -11,8 +11,14 @@ export interface Guest {
11
11
  subscribe(listener: (props: GuestProps) => void): () => void;
12
12
  /** Ask for an act by name. Resolves with the host's answer; never rejects for a refusal. */
13
13
  act(name: string, args?: Readonly<Record<string, unknown>>): Promise<GuestAnswer>;
14
- /** Ask the host to go to a record. A record the viewer may not see goes nowhere. */
15
- navigate(to: string): void;
14
+ /**
15
+ * Ask the host to go to a record, by its id, or to one of the app's named
16
+ * places (`{ place: slug }`, one `props.places` lists). A record the viewer
17
+ * may not see, and a place the app does not have, go nowhere.
18
+ */
19
+ navigate(to: string | {
20
+ readonly place: string;
21
+ }): void;
16
22
  /** Ask for a height, in CSS pixels. */
17
23
  size(height: number): void;
18
24
  /** Ask for the height of an element whenever it changes. Returns the stop. In a worker, where nothing is laid out, it does nothing. */
@@ -44,6 +50,8 @@ export interface GuestLink {
44
50
  */
45
51
  export declare function openGuest(link: GuestLink, hooks?: {
46
52
  readonly onEvent?: (event: GuestEvent) => void;
53
+ /** Every message from the host, once the channel's own handling of it is done: a runtime's way to hear what is its own (FR-90). */
54
+ readonly onMessage?: (message: HostMessage) => void;
47
55
  }): {
48
56
  readonly guest: Guest;
49
57
  send(request: Unsent): void;
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,MAAM,WAAW,KAAK;IACpB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAAC;IACvC,uDAAuD;IACvD,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC7D,4FAA4F;IAC5F,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClF,oFAAoF;IACpF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uCAAuC;IACvC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uIAAuI;IACvI,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC;IACxC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,+CAA+C;AAC/C,MAAM,MAAM,MAAM,GAAG,YAAY,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,YAAY,GAAG,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEhH;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,wEAAwE;IACxE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACzD,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;IACvC,iBAAiB;IACjB,KAAK,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACtF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,GAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CAAO,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAwFjK"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,MAAM,WAAW,KAAK;IACpB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAAC;IACvC,uDAAuD;IACvD,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC7D,4FAA4F;IAC5F,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClF;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACxD,uCAAuC;IACvC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uIAAuI;IACvI,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC;IACxC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,+CAA+C;AAC/C,MAAM,MAAM,MAAM,GAAG,YAAY,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,YAAY,GAAG,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEhH;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,wEAAwE;IACxE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACzD,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;IACvC,iBAAiB;IACjB,KAAK,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACtF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,EACf,KAAK,GAAE;IACL,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/C,mIAAmI;IACnI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAChD,GACL;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CA0FxD"}
package/dist/channel.js CHANGED
@@ -38,6 +38,7 @@ export function openGuest(link, hooks = {}) {
38
38
  /* The runtime answers, so only a blocked event loop goes quiet. */
39
39
  send({ type: "heartbeat", beat: message.beat });
40
40
  }
41
+ hooks.onMessage?.(message);
41
42
  };
42
43
  let stop = () => { };
43
44
  const hello = (event) => {
@@ -77,7 +78,10 @@ export function openGuest(link, hooks = {}) {
77
78
  });
78
79
  },
79
80
  navigate(to) {
80
- send({ type: "navigate", to });
81
+ if (typeof to === "string")
82
+ send({ type: "navigate", to });
83
+ else if (to && typeof to.place === "string")
84
+ send({ type: "navigate", place: to.place });
81
85
  },
82
86
  size(height) {
83
87
  send({ type: "size", height });
@@ -1 +1 @@
1
- {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `graview view check` — run a worker view once, headless, and say what it
3
+ * drew (FR-95).
4
+ *
5
+ * The view's source, its manifest, the app it is for and, given one, a seed
6
+ * to run it over, seated as one member: it runs in a worker thread's fresh
7
+ * context with no network (`@graview/guest/headless/node`) and the command
8
+ * prints what it drew in the words `graview describe` says a place in, or
9
+ * why it will not do. Exit 0 when it drew, 1 when it will not do.
10
+ *
11
+ * Reached through the `graview` command line, which dispatches here; this
12
+ * package ships no bin of its own.
13
+ */
14
+ export declare const VIEW_USAGE = " graview view check <view.js> --app <app> --manifest <manifest.json>\n [--seed <file>] [--as <id>] [--roles a,b] [--width <px>] [--json]\n run a worker view once, headless, with no network, seated as one\n member (the system, unless --as or --roles say who), and say what it\n drew, or why it will not do\n";
15
+ export declare function view(argv: readonly string[]): Promise<number>;
16
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,UAAU,2VAKtB,CAAC;AASF,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA2CnE"}
package/dist/cli.js ADDED
@@ -0,0 +1,75 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { Store } from "@graview/core";
4
+ import { loadApp } from "@graview/core/cli";
5
+ import { runWorkerViewHeadless } from "./headless/index.js";
6
+ import { nodeIsolate } from "./headless/node.js";
7
+ /**
8
+ * `graview view check` — run a worker view once, headless, and say what it
9
+ * drew (FR-95).
10
+ *
11
+ * The view's source, its manifest, the app it is for and, given one, a seed
12
+ * to run it over, seated as one member: it runs in a worker thread's fresh
13
+ * context with no network (`@graview/guest/headless/node`) and the command
14
+ * prints what it drew in the words `graview describe` says a place in, or
15
+ * why it will not do. Exit 0 when it drew, 1 when it will not do.
16
+ *
17
+ * Reached through the `graview` command line, which dispatches here; this
18
+ * package ships no bin of its own.
19
+ */
20
+ export const VIEW_USAGE = ` graview view check <view.js> --app <app> --manifest <manifest.json>
21
+ [--seed <file>] [--as <id>] [--roles a,b] [--width <px>] [--json]
22
+ run a worker view once, headless, with no network, seated as one
23
+ member (the system, unless --as or --roles say who), and say what it
24
+ drew, or why it will not do
25
+ `;
26
+ function flag(argv, name) {
27
+ const at = argv.indexOf(name);
28
+ return at === -1 ? undefined : argv[at + 1];
29
+ }
30
+ const readJson = (file) => JSON.parse(readFileSync(resolve(process.cwd(), file), "utf8"));
31
+ export async function view(argv) {
32
+ const [command, file] = argv;
33
+ if (command !== "check" || !file || file.startsWith("--")) {
34
+ process.stdout.write(`graview view — a worker view, run where it can reach nothing\n\n${VIEW_USAGE}`);
35
+ return command === undefined || command === "help" || command === "--help" ? 0 : 1;
36
+ }
37
+ const appAt = flag(argv, "--app");
38
+ const manifestAt = flag(argv, "--manifest");
39
+ if (!appAt || !manifestAt) {
40
+ process.stderr.write(`graview view check needs --app and --manifest.\n\n${VIEW_USAGE}`);
41
+ return 1;
42
+ }
43
+ const app = await loadApp(appAt);
44
+ const seedAt = flag(argv, "--seed");
45
+ const store = new Store({
46
+ schema: app.schema,
47
+ mutations: (app.mutations ?? []),
48
+ ...(app.policy ? { policy: app.policy } : {}),
49
+ ...(seedAt ? { snapshot: readJson(seedAt) } : {}),
50
+ });
51
+ const roles = (flag(argv, "--roles") ?? "").split(",").map((role) => role.trim()).filter(Boolean);
52
+ const as = flag(argv, "--as");
53
+ const principal = as || roles.length > 0 ? { kind: "human", id: as ?? "graview-view-check", ...(roles.length > 0 ? { roles } : {}) } : { kind: "system", id: "graview-view-check" };
54
+ const width = flag(argv, "--width");
55
+ const result = await runWorkerViewHeadless({
56
+ store,
57
+ principal,
58
+ manifest: readJson(manifestAt),
59
+ source: readFileSync(resolve(process.cwd(), file), "utf8"),
60
+ run: nodeIsolate(),
61
+ places: (app.views?.places?.() ?? []).map((place) => ({ as: place.as, title: place.title, kind: place.kind })),
62
+ ...(width ? { width: Number(width) } : {}),
63
+ });
64
+ if (argv.includes("--json")) {
65
+ process.stdout.write(`${JSON.stringify(result.ok ? result.description : { reason: result.reason, detail: result.detail }, null, 2)}\n`);
66
+ return result.ok ? 0 : 1;
67
+ }
68
+ if (!result.ok) {
69
+ process.stdout.write(`${file} will not do (${result.reason}): ${result.detail}\n`);
70
+ return 1;
71
+ }
72
+ process.stdout.write(`${result.description.text}\n`);
73
+ return 0;
74
+ }
75
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { connectGuest as connect } from "./guest.js";
2
+ export { GUEST_PROTOCOL as protocol } from "./protocol.js";
3
+ //# sourceMappingURL=client-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-script.d.ts","sourceRoot":"","sources":["../src/client-script.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,21 @@
1
+ /*
2
+ * THE FRAME GUEST'S CLIENT, AS ONE CLASSIC SCRIPT (FR-88).
3
+ *
4
+ * `connectGuest` is a module, so every frame guest bundled or inlined its
5
+ * own copy. This is the entry `scripts/guest-view-runtime.mjs` bundles into
6
+ * `client.js` at the package's root — `@graview/guest/client.js`, an IIFE
7
+ * that leaves one global, `GraviewGuest`:
8
+ *
9
+ * const guest = GraviewGuest.connect();
10
+ * guest.subscribe((props) => draw(props)); // nodes, edges, acts, theme, places
11
+ * guest.act("add-note", { label: "…" }); // the viewer's act, answered
12
+ * guest.navigate("offer:7"); // or { place: "the-packages" }
13
+ * guest.autoSize(); // or guest.size(px)
14
+ *
15
+ * A host serves it at a fixed path of its own, or inlines its text
16
+ * (`GUEST_CLIENT`, from `@graview/guest/client`) where a frame's policy
17
+ * allows inline script alone.
18
+ */
19
+ export { connectGuest as connect } from "./guest.js";
20
+ export { GUEST_PROTOCOL as protocol } from "./protocol.js";
21
+ //# sourceMappingURL=client-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-script.js","sourceRoot":"","sources":["../src/client-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { GUEST_CLIENT, GUEST_CLIENT_SHA256 } from "./client.generated.js";
2
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const GUEST_CLIENT: string;
2
+ /** For `script-src 'sha256-…'`. */
3
+ export declare const GUEST_CLIENT_SHA256: string;
4
+ //# sourceMappingURL=client.generated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.generated.d.ts","sourceRoot":"","sources":["../src/client.generated.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,EAAE,MAA+5E,CAAC;AAC37E,mCAAmC;AACnC,eAAO,MAAM,mBAAmB,EAAE,MAA8D,CAAC"}
@@ -0,0 +1,9 @@
1
+ /*
2
+ * GENERATED by scripts/guest-view-runtime.mjs from src/client-script.ts — do not edit.
3
+ * The frame guest's client as one classic script (FR-88), as text a host
4
+ * inlines, and its hash for a policy that names it.
5
+ */
6
+ export const GUEST_CLIENT = "/*! @graview/guest/client.js — a frame guest's client (GraviewGuest.connect). Generated from src/client-script.ts. Elastic License 2.0. */\n\"use strict\";var GraviewGuest=(()=>{var f=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var k=(o,t)=>{for(var r in t)f(o,r,{get:t[r],enumerable:!0})},M=(o,t,r,i)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let a of O(t))!H.call(o,a)&&a!==r&&f(o,a,{get:()=>t[a],enumerable:!(i=R(t,a))||i.enumerable});return o};var P=o=>M(f({},\"__esModule\",{value:!0}),o);var T={};k(T,{connect:()=>w,protocol:()=>y});var y=1;function G(o){let t=o;return typeof o==\"object\"&&o!==null&&t.graview===\"host-hello\"&&typeof t.nonce==\"string\"}function b(o,t={}){let r,i=\"\",a,h=0,u=new Set,g=new Map,m=[],d=n=>{r?r.postMessage({...n,nonce:i}):m.push(n)},x=n=>{let e=n.data;if(!(!e||typeof e!=\"object\")){if(e.type===\"props\"){a=e.props;for(let s of u)s(e.props)}else e.type===\"answer\"?(g.get(e.id)?.(e),g.delete(e.id)):e.type===\"event\"&&typeof e.listener==\"number\"?t.onEvent?.(e):e.type===\"heartbeat\"&&typeof e.beat==\"number\"&&d({type:\"heartbeat\",beat:e.beat});t.onMessage?.(e)}},p=()=>{},E=n=>{if(r||!o.fromHost(n)||!G(n.data)||n.data.protocol!==1)return;let e=n.ports[0];if(e){r=e,i=n.data.nonce,r.onmessage=x,r.start?.(),p();for(let s of m.splice(0))d(s)}};p=o.listen(E),o.ready({graview:\"guest-ready\",protocol:1});let c,v={get props(){return a},subscribe(n){return u.add(n),()=>u.delete(n)},act(n,e={}){let s=h+=1;return new Promise(l=>{g.set(s,l),d({type:\"act\",id:s,name:n,args:e})})},navigate(n){typeof n==\"string\"?d({type:\"navigate\",to:n}):n&&typeof n.place==\"string\"&&d({type:\"navigate\",place:n.place})},size(n){d({type:\"size\",height:n})},autoSize(n){let e=n??globalThis.document?.documentElement,s=globalThis.ResizeObserver;if(!e||!s||typeof e.getBoundingClientRect!=\"function\")return()=>{};c?.disconnect();let l=new s(()=>v.size(Math.ceil(e.getBoundingClientRect().height)));return l.observe(e),c=l,()=>l.disconnect()},close(){c?.disconnect(),p(),r?.close(),u.clear()}};return{guest:v,send:d}}function w(o={}){let t=o.window??globalThis;return b({listen(r){return t.addEventListener(\"message\",r),()=>t.removeEventListener(\"message\",r)},fromHost:r=>r.source===t.parent&&(o.hostOrigin===void 0||r.origin===o.hostOrigin),ready:r=>t.parent?.postMessage(r,\"*\")}).guest}return P(T);})();\n";
7
+ /** For `script-src 'sha256-…'`. */
8
+ export const GUEST_CLIENT_SHA256 = "sha256-3FZdxG7Qo/vAIcKcV2ujTNB3AGU+ASH0aHfbjDVzECQ=";
9
+ //# sourceMappingURL=client.generated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.generated.js","sourceRoot":"","sources":["../src/client.generated.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAW,s5EAAs5E,CAAC;AAC37E,mCAAmC;AACnC,MAAM,CAAC,MAAM,mBAAmB,GAAW,qDAAqD,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,12 @@
1
+ /*
2
+ * THE FRAME GUEST'S CLIENT, AS TEXT A HOST CAN INLINE (FR-88):
3
+ * `@graview/guest/client`.
4
+ *
5
+ * `@graview/guest/client.js` is the client as a file, for a host that
6
+ * serves it at a path of its own. Where a frame's policy allows inline
7
+ * script alone (`script-src 'unsafe-inline'`, as Graview Cloud serves an
8
+ * uploaded view), a host puts this text in a `<script>` of the frame's page
9
+ * instead, or names its hash in the policy (`script-src 'sha256-…'`).
10
+ */
11
+ export { GUEST_CLIENT, GUEST_CLIENT_SHA256 } from "./client.generated.js";
12
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { DescribedPart, DescribedProblem } from "@graview/core/describe";
2
+ import type { GuestProps } from "../protocol.js";
3
+ import { TreeElement } from "./tree.js";
4
+ export interface DescribeDrawingContext {
5
+ /** What the view was shown: a record a link or a row names is looked up here, and only here. */
6
+ readonly props: GuestProps;
7
+ /** The app's places, by slug: where a `data-place` may point. */
8
+ readonly places: readonly string[];
9
+ }
10
+ export interface DescribedDrawing {
11
+ readonly parts: readonly DescribedPart[];
12
+ readonly problems: readonly DescribedProblem[];
13
+ /** The acts the drawing binds a press to (`data-act`), each once. */
14
+ readonly acts: readonly string[];
15
+ /** The records it binds or links to (`data-record`), each once. */
16
+ readonly records: readonly string[];
17
+ }
18
+ export declare function describeDrawing(root: TreeElement, context: DescribeDrawingContext): DescribedDrawing;
19
+ //# sourceMappingURL=describe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/headless/describe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAA2B,MAAM,WAAW,CAAC;AAoBjE,MAAM,WAAW,sBAAsB;IACrC,gGAAgG;IAChG,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC/C,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AA8BD,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,GAAG,gBAAgB,CAiNpG"}