@valbuild/shared 0.150.10 → 0.150.11

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 (51) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/client/dist/valbuild-shared-client.cjs.dev.js +16 -2
  3. package/client/dist/valbuild-shared-client.cjs.prod.js +16 -2
  4. package/client/dist/valbuild-shared-client.esm.js +2 -2
  5. package/dist/{acquireTypes-dd976839.cjs.prod.js → acquireTypes-6250a305.cjs.prod.js} +46 -46
  6. package/dist/{acquireTypes-6e2f7961.esm.js → acquireTypes-c2227b23.esm.js} +2 -2
  7. package/dist/{acquireTypes-84a4077a.cjs.dev.js → acquireTypes-c9e757a1.cjs.dev.js} +46 -46
  8. package/dist/{slicedToArray-22567815.esm.js → createForOfIteratorHelper-9b80f1a2.esm.js} +136 -106
  9. package/dist/{slicedToArray-d99b4e2e.cjs.prod.js → createForOfIteratorHelper-9ca2078d.cjs.prod.js} +142 -111
  10. package/dist/{slicedToArray-c8a29f6b.cjs.dev.js → createForOfIteratorHelper-f2d7ac6d.cjs.dev.js} +142 -111
  11. package/dist/declarations/src/client/index.d.ts +2 -0
  12. package/dist/declarations/src/internal/ApiRoutes.d.ts +1 -0
  13. package/dist/declarations/src/internal/index.d.ts +2 -0
  14. package/dist/declarations/src/internal/pageInspection.d.ts +117 -0
  15. package/dist/declarations/src/internal/quickPreview.d.ts +91 -0
  16. package/dist/declarations/src/internal/valCanvasProtocol.d.ts +53 -0
  17. package/dist/declarations/src/publish/buildProposal.d.ts +16 -1
  18. package/dist/declarations/src/publish/buildQuickPreview.d.ts +46 -0
  19. package/dist/declarations/src/publish/index.d.ts +3 -2
  20. package/dist/declarations/src/publish/runStudioDeploy.d.ts +10 -0
  21. package/dist/getSitemapTree-5354ce90.cjs.prod.js +1421 -0
  22. package/dist/getSitemapTree-97b3166f.esm.js +1381 -0
  23. package/dist/getSitemapTree-d934ff9c.cjs.dev.js +1421 -0
  24. package/dist/{proposalProject-689c24cc.esm.js → proposalProject-5da177d5.esm.js} +1 -2
  25. package/dist/{proposalProject-926f2c68.cjs.dev.js → proposalProject-76caa377.cjs.prod.js} +2 -3
  26. package/dist/{proposalProject-fab0c026.cjs.prod.js → proposalProject-81fee08f.cjs.dev.js} +2 -3
  27. package/dist/{protocol-7ddc1a71.esm.js → protocol-55cfa3cf.esm.js} +1 -1
  28. package/dist/{protocol-4e2a455b.cjs.prod.js → protocol-b1055ef0.cjs.prod.js} +6 -6
  29. package/dist/{protocol-ac1c3ec7.cjs.dev.js → protocol-d0efb8cd.cjs.dev.js} +6 -6
  30. package/dist/wrapNativeSuper-639b12b7.esm.js +107 -0
  31. package/dist/wrapNativeSuper-8673414f.cjs.prod.js +113 -0
  32. package/dist/wrapNativeSuper-933f991e.cjs.dev.js +113 -0
  33. package/internal/dist/valbuild-shared-internal.cjs.dev.js +53 -34
  34. package/internal/dist/valbuild-shared-internal.cjs.prod.js +53 -34
  35. package/internal/dist/valbuild-shared-internal.esm.js +11 -6
  36. package/package.json +1 -1
  37. package/publish/dist/valbuild-shared-publish.cjs.dev.js +589 -237
  38. package/publish/dist/valbuild-shared-publish.cjs.prod.js +589 -237
  39. package/publish/dist/valbuild-shared-publish.esm.js +504 -155
  40. package/typecheck/dist/valbuild-shared-typecheck.cjs.dev.js +34 -34
  41. package/typecheck/dist/valbuild-shared-typecheck.cjs.prod.js +34 -34
  42. package/typecheck/dist/valbuild-shared-typecheck.esm.js +5 -5
  43. package/typecheck/testing/dist/valbuild-shared-typecheck-testing.cjs.dev.js +7 -7
  44. package/typecheck/testing/dist/valbuild-shared-typecheck-testing.cjs.prod.js +7 -7
  45. package/typecheck/testing/dist/valbuild-shared-typecheck-testing.esm.js +3 -3
  46. package/dist/createForOfIteratorHelper-666a6d17.esm.js +0 -137
  47. package/dist/createForOfIteratorHelper-87a33eff.cjs.dev.js +0 -145
  48. package/dist/createForOfIteratorHelper-fef4fa7d.cjs.prod.js +0 -145
  49. package/dist/getSitemapTree-873f7266.cjs.prod.js +0 -743
  50. package/dist/getSitemapTree-b6161fd8.esm.js +0 -717
  51. package/dist/getSitemapTree-be70d9fc.cjs.dev.js +0 -743
@@ -0,0 +1,91 @@
1
+ /**
2
+ * A quick preview: a proposal's page, running the proposal's CLIENT code
3
+ * built in the design tab, without a build being uploaded or served
4
+ * (valbuild/home `docs/design-tab.md`).
5
+ *
6
+ * A full build of a proposal bundles the app for the server and the browser,
7
+ * uploads it, and has the platform render every page before it is served --
8
+ * minutes. Most of what the design tab changes is components and styles,
9
+ * which the browser half alone shows. So the tab bundles the app in its
10
+ * builder worker, and a service worker on the proposal's address hands the
11
+ * page that bundle instead of the served one:
12
+ *
13
+ * 1. The tab sends the files (`/_app/app.js`, its chunks, the stylesheet and
14
+ * assets) to the page in the preview, over the canvas protocol.
15
+ * 2. The page -- the bridge, which is the only thing at that origin the tab
16
+ * can talk to -- registers {@link QUICK_PREVIEW_SERVICE_WORKER_SOURCE}
17
+ * and stores the files in it (Cache Storage, so a worker the browser
18
+ * stopped still has them).
19
+ * 3. The tab opens the page with `?val_quick=<id>`. The worker serves that
20
+ * document's `/_app/` requests from the files, and everything else from
21
+ * the network: the HTML is the last build's, rendered by its server, and
22
+ * the new code takes it over in the browser.
23
+ *
24
+ * What it cannot show, and the tab says so: anything on the server. Server
25
+ * functions, API routes and loaders that run there are the last build's, as
26
+ * is the page's first render and its `head`. A new dependency is not there
27
+ * either. A build is still what decides, before Publish.
28
+ *
29
+ * Only a document opened with the parameter is served from the files, so a
30
+ * visitor to the proposal's address -- even in the same browser -- is never
31
+ * given them.
32
+ */
33
+ /** The parameter a quick preview's page is opened with. */
34
+ export declare const QUICK_PREVIEW_PARAM = "val_quick";
35
+ /** Where Val's API serves the worker: under `/api/val`. */
36
+ export declare const QUICK_PREVIEW_SERVICE_WORKER_PATH = "/quick-preview-sw.js";
37
+ /** What the page sends the worker to store a preview's files. */
38
+ export declare const QUICK_PREVIEW_STORE_MESSAGE = "val-quick-preview-store";
39
+ /**
40
+ * A preview's files, by their path under `/_app/`: `app.js`, `c-<hash>.js`,
41
+ * `app.css`, `a/<hash>.png`. A binary file is base64.
42
+ */
43
+ export type QuickPreviewFiles = Record<string, {
44
+ body: string;
45
+ contentType: string;
46
+ base64?: true;
47
+ }>;
48
+ /**
49
+ * The files of a quick preview: paths under `/_app/` with no way out of it,
50
+ * each a string body and a type.
51
+ */
52
+ export declare function isQuickPreviewFiles(value: unknown): value is QuickPreviewFiles;
53
+ /**
54
+ * The worker, as the source it is served as: plain, and small, because it is
55
+ * served as a file of its own (`demoServiceWorker.ts` is the same).
56
+ */
57
+ export declare const QUICK_PREVIEW_SERVICE_WORKER_SOURCE = "\n\"use strict\";\nconst PARAM = \"val_quick\";\nconst CACHE = \"val-quick-preview\";\nconst PREFIX = \"/__val_quick/\";\nconst INDEX = PREFIX + \"index\";\nconst KEEP = 4;\n\nself.addEventListener(\"install\", () => self.skipWaiting());\nself.addEventListener(\"activate\", (event) => {\n event.waitUntil(self.clients.claim());\n});\n\nself.addEventListener(\"message\", (event) => {\n const data = event.data;\n if (!data || data.type !== \"val-quick-preview-store\") return;\n const port = event.ports && event.ports[0];\n event.waitUntil(\n store(data.id, data.files).then(\n () => port && port.postMessage({ ok: true }),\n (error) =>\n port &&\n port.postMessage({\n ok: false,\n message: String((error && error.message) || error),\n }),\n ),\n );\n});\n\nfunction keyOf(id, path) {\n return PREFIX + id + \"/\" + path;\n}\n\nasync function store(id, files) {\n const cache = await caches.open(CACHE);\n for (const path of Object.keys(files)) {\n const file = files[path];\n const body = file.base64\n ? Uint8Array.from(atob(file.body), (c) => c.charCodeAt(0))\n : file.body;\n await cache.put(\n keyOf(id, path),\n new Response(body, {\n headers: { \"Content-Type\": file.contentType, \"Cache-Control\": \"no-store\" },\n }),\n );\n }\n // The newest few previews are kept; older ones are deleted.\n const index = await cache.match(INDEX);\n const ids = [id].concat(\n (index ? await index.json() : []).filter((other) => other !== id),\n );\n const dropped = ids.slice(KEEP);\n if (dropped.length > 0) {\n for (const request of await cache.keys()) {\n const path = new URL(request.url).pathname;\n if (dropped.some((old) => path.startsWith(PREFIX + old + \"/\"))) {\n await cache.delete(request);\n }\n }\n }\n await cache.put(INDEX, new Response(JSON.stringify(ids.slice(0, KEEP))));\n}\n\n/** Which preview a document is: by its id, or by the address it was opened at. */\nconst byClient = new Map();\nasync function previewOf(clientId) {\n if (!clientId) return null;\n if (byClient.has(clientId)) return byClient.get(clientId);\n const client = await self.clients.get(clientId);\n const id = client ? new URL(client.url).searchParams.get(PARAM) : null;\n byClient.set(clientId, id);\n return id;\n}\n\nself.addEventListener(\"fetch\", (event) => {\n const url = new URL(event.request.url);\n if (url.origin !== self.location.origin) return;\n if (event.request.mode === \"navigate\") {\n if (event.resultingClientId) {\n byClient.set(event.resultingClientId, url.searchParams.get(PARAM));\n }\n return;\n }\n if (!url.pathname.startsWith(\"/_app/\")) return;\n event.respondWith(serve(event, url));\n});\n\nasync function serve(event, url) {\n const id = await previewOf(event.clientId);\n if (id) {\n const hit = await caches.match(keyOf(id, url.pathname.slice(6)), {\n cacheName: CACHE,\n });\n if (hit) return hit;\n }\n return fetch(event.request);\n}\n";
58
+ /**
59
+ * Store a preview's files in the worker, registering it first: what the
60
+ * bridge does when the tab sends `quickPreview`. `swUrl` is the worker's
61
+ * address on this origin (`/api/val` + {@link QUICK_PREVIEW_SERVICE_WORKER_PATH}).
62
+ */
63
+ export declare function storeQuickPreview(id: string, files: QuickPreviewFiles, options: {
64
+ swUrl: string;
65
+ container?: ServiceWorkerContainer;
66
+ }): Promise<void>;
67
+ /** The address of a page as a quick preview `id`. */
68
+ export declare function withQuickPreviewParam(url: string, id: string): string;
69
+ /**
70
+ * The one origin allowed to send this page a quick preview: the site's, where
71
+ * the design tab is, as this page's own Val server says it (the proposals
72
+ * list's `siteUrl`). `null` when it does not say.
73
+ *
74
+ * A quick preview is code that runs on this address, so the bridge takes one
75
+ * only from its parent, and only when that parent is the site: a page that
76
+ * framed this one could otherwise post a script into the worker and open
77
+ * the frame on it.
78
+ */
79
+ export declare function quickPreviewSiteOrigin(api: string, fetchImpl?: typeof fetch): Promise<string | null>;
80
+ /**
81
+ * Whether `origin` may ask this page for what only the design tab should
82
+ * have -- what is on it (`readPage`), or code to run (`quickPreview`): this
83
+ * page's own origin (the Studio's canvas), or the site's, where the design
84
+ * tab is ({@link quickPreviewSiteOrigin}). Asked of the server once, and
85
+ * again only while it has not said.
86
+ */
87
+ export declare function isDesignTabOrigin(origin: string, options: {
88
+ api: string;
89
+ own: string;
90
+ fetchImpl?: typeof fetch;
91
+ }): Promise<boolean>;
@@ -21,6 +21,8 @@
21
21
  */
22
22
  import type { ModuleFilePath, SourcePath } from "@valbuild/core";
23
23
  import type { PickedElement, PickModifier } from "./elementPicker.js";
24
+ import type { PageLocation, PageSnapshot } from "./pageInspection.js";
25
+ import { type QuickPreviewFiles } from "./quickPreview.js";
24
26
  /** Marks a page load as the studio's canvas frame. */
25
27
  export declare const VAL_CANVAS_PARAM = "val_canvas";
26
28
  /**
@@ -188,6 +190,30 @@ export type ValCanvasPageMessage = {
188
190
  */
189
191
  val: typeof VAL_CANVAS_MESSAGE;
190
192
  type: "elementPickingStopped";
193
+ } | ({
194
+ /**
195
+ * Where the page is: its path and scroll, as it moves. The design tab
196
+ * opens a new build there (`scrollTo`), so a new version replaces the
197
+ * page in place rather than starting over at the top of the front page.
198
+ */
199
+ val: typeof VAL_CANVAS_MESSAGE;
200
+ type: "location";
201
+ } & PageLocation) | {
202
+ /** What `readPage` asked for, or why it could not be read. */
203
+ val: typeof VAL_CANVAS_MESSAGE;
204
+ type: "pageRead";
205
+ requestId: string;
206
+ snapshot: PageSnapshot | null;
207
+ error?: string;
208
+ } | {
209
+ /**
210
+ * A quick preview's files are stored in the page's worker, and a page
211
+ * opened with its id is served them (`quickPreview.ts`) -- or why not.
212
+ */
213
+ val: typeof VAL_CANVAS_MESSAGE;
214
+ type: "quickPreviewStored";
215
+ id: string;
216
+ error?: string;
191
217
  };
192
218
  /** What the studio tells the page. */
193
219
  export type ValCanvasStudioMessage = {
@@ -291,6 +317,33 @@ export type ValCanvasStudioMessage = {
291
317
  modifier: PickModifier;
292
318
  /** Whether the studio still holds the last pick: false takes its outline down. */
293
319
  keepPicked: boolean;
320
+ } | {
321
+ /** Scroll to where the page before this one was (`location`). */
322
+ val: typeof VAL_CANVAS_MESSAGE;
323
+ type: "scrollTo";
324
+ x: number;
325
+ y: number;
326
+ } | {
327
+ /**
328
+ * Read what is on the page (`readPageSnapshot`): the assistant's
329
+ * `read_page`. Answered with `pageRead` and the same `requestId`. A
330
+ * bridge that predates it never answers, and the tab says so.
331
+ */
332
+ val: typeof VAL_CANVAS_MESSAGE;
333
+ type: "readPage";
334
+ requestId: string;
335
+ selector?: string;
336
+ maxItems?: number;
337
+ } | {
338
+ /**
339
+ * Store a quick preview's files in this origin's worker
340
+ * (`storeQuickPreview`): the tab cannot, being another origin.
341
+ * Answered with `quickPreviewStored`.
342
+ */
343
+ val: typeof VAL_CANVAS_MESSAGE;
344
+ type: "quickPreview";
345
+ id: string;
346
+ files: QuickPreviewFiles;
294
347
  };
295
348
  /** Narrow an unknown `event.data` to a message from the page. */
296
349
  export declare function isValCanvasPageMessage(data: unknown): data is ValCanvasPageMessage;
@@ -45,7 +45,14 @@ export type ProposalBuildOutcome<P> = {
45
45
  } | {
46
46
  status: "failed";
47
47
  message: string;
48
+ /**
49
+ * Stopped by whoever started it (`signal`), not by anything wrong with
50
+ * the build: nothing to fix, and nothing to show as an error.
51
+ */
52
+ cancelled?: true;
48
53
  };
54
+ /** What a cancelled build answers. */
55
+ export declare const BUILD_CANCELLED_MESSAGE = "The build was cancelled.";
49
56
  /**
50
57
  * Where a build of the proposal is, around the deploy: the deploy's own steps
51
58
  * are the Studio's deploy state (`useStudioDeployState`), and these are the
@@ -93,13 +100,21 @@ export declare function buildProposal<P extends BuiltProposal>(deps: {
93
100
  * on the layer content had built for it; `undefined` builds on the site's,
94
101
  * as every build of a proposal did before.
95
102
  */
96
- deploy: (files: Record<string, string | null>, target: BuildTargetResponse | undefined) => Promise<StudioDeployResult>;
103
+ deploy: (files: Record<string, string | null>, target: BuildTargetResponse | undefined, signal: AbortSignal | undefined) => Promise<StudioDeployResult>;
97
104
  /**
98
105
  * Whether this document can build at all (`canBuildHere`): Safari cannot,
99
106
  * and a proposal's build has no builder tab to hand off to yet.
100
107
  */
101
108
  canBuildHere: () => boolean;
102
109
  onStep?: (step: ProposalBuildStep) => void;
110
+ /**
111
+ * Stops the build: Cancel, or a watchdog that saw it stall. Answered at
112
+ * once, whatever the build was waiting on, and nothing after it is done --
113
+ * a build stopped while it uploads is never served. Aborted with an `Error`
114
+ * of its own, the build fails with that error's message; otherwise it is
115
+ * `cancelled`.
116
+ */
117
+ signal?: AbortSignal;
103
118
  /** For tests: the clock, and waiting on it. */
104
119
  now?: () => number;
105
120
  sleep?: (ms: number) => Promise<void>;
@@ -0,0 +1,46 @@
1
+ import type { BuildOutput } from "@valbuild/tanstack-build";
2
+ import type { BuildTargetResponse } from "../internal/index.js";
3
+ import type { QuickPreviewFiles } from "../internal/quickPreview.js";
4
+ import type { StudioBuilder } from "./builder.js";
5
+ export type QuickPreviewOutcome = {
6
+ status: "built";
7
+ files: QuickPreviewFiles;
8
+ /** What the proposal's files were staged as: the build is of these. */
9
+ inputs: string | null;
10
+ } | {
11
+ status: "failed";
12
+ message: string;
13
+ };
14
+ export declare function buildQuickPreview(deps: {
15
+ name: string;
16
+ /** The proposal's files, and what they build on. */
17
+ proposals: {
18
+ files(name: string): Promise<{
19
+ files: Record<string, string | null>;
20
+ staged: {
21
+ inputs: string | null;
22
+ };
23
+ }>;
24
+ buildTarget(name: string): Promise<{
25
+ target: BuildTargetResponse;
26
+ layer: "site" | "own";
27
+ }>;
28
+ };
29
+ /** The site's source, which the proposal's files are laid over. */
30
+ siteSource: () => Promise<Record<string, string> | null>;
31
+ /** The site's build target: what the proposal's address serves. */
32
+ siteTarget: () => Promise<BuildTargetResponse>;
33
+ loadBuilder: () => Promise<StudioBuilder>;
34
+ /** Generates `src/routeTree.gen.ts`: see `runStudioDeploy`. */
35
+ generateRouteTree?: (files: Record<string, string>) => Promise<Record<string, string>>;
36
+ /** Each step as it begins: for the tab's progress and timings. */
37
+ onStep?: (label: string) => void;
38
+ signal?: AbortSignal;
39
+ }): Promise<QuickPreviewOutcome>;
40
+ /**
41
+ * The browser half of a build, as the worker serves it under `/_app/`. The
42
+ * stylesheet only when the tab compiled one: an empty one is the case where a
43
+ * build ships the site's live stylesheet (`liveStylesheet` on
44
+ * `runStudioDeploy`), and the page already has that.
45
+ */
46
+ export declare function clientFilesOf(build: BuildOutput): QuickPreviewFiles;
@@ -15,9 +15,10 @@ export type { StudioBuilder } from "./builder.js";
15
15
  export { StudioPublishError, callJson, isTransientPublishError, onPublishRefusal, } from "./callJson.js";
16
16
  export { StudioUploadError, createStudioPublishClient, isExpiredSlot, publishApiOf, type CarriedArtifact, type LivePublicFiles, type PublishApiAt, type StudioPublishClient, } from "./publishClient.js";
17
17
  export { runStudioPublish, type PublishPhase, type StudioPublishResult, } from "./runStudioPublish.js";
18
- export { carriedInto, runStudioDeploy, splitBinaryFiles, withCommittedFiles, type CommittedBinaryFiles, type DeployPhase, type StudioDeployOptions, type StudioDeployResult, } from "./runStudioDeploy.js";
18
+ export { DEPLOY_STOPPED_MESSAGE, carriedInto, runStudioDeploy, splitBinaryFiles, withCommittedFiles, type CommittedBinaryFiles, type DeployPhase, type StudioDeployOptions, type StudioDeployResult, } from "./runStudioDeploy.js";
19
19
  export { STUDIO_OUT_OF_DATE, STUDIO_OUT_OF_DATE_MESSAGE, layerMoved, loadedLayer, markStudioOutOfDate, readLiveLayer, rememberLoadedLayer, resetLoadedLayerForTests, siteMovedSinceLoad, studioOutOfDateRefusals, subscribeStudioOutOfDate, type LayerReading, } from "./loadedLayer.js";
20
20
  export { MergePrepareAnswer, createStudioJobClient, isMergeChange, type PreparedJob, type StudioJobClient, } from "./jobClient.js";
21
21
  export { RENEW_EVERY_MS, runJobToEnd, runStudioJob, type JobPhase, type StudioJobResult, } from "./runStudioJob.js";
22
- export { SERVE_POLL_MS, SERVE_WAIT_MS, buildProposal, withoutLockfiles, type BuiltProposal, type ProposalBuildClient, type ProposalBuildOutcome, type ProposalBuildStep, } from "./buildProposal.js";
22
+ export { BUILD_CANCELLED_MESSAGE, SERVE_POLL_MS, SERVE_WAIT_MS, buildProposal, withoutLockfiles, type BuiltProposal, type ProposalBuildClient, type ProposalBuildOutcome, type ProposalBuildStep, } from "./buildProposal.js";
23
23
  export { proposalProject } from "./proposalProject.js";
24
+ export { buildQuickPreview, clientFilesOf, type QuickPreviewOutcome, } from "./buildQuickPreview.js";
@@ -211,6 +211,14 @@ export interface StudioDeployOptions {
211
211
  */
212
212
  generateRouteTree?: (files: Record<string, string>) => Promise<Record<string, string>>;
213
213
  onPhase: (phase: DeployPhase) => void;
214
+ /**
215
+ * Stops the deploy between its steps: a cancelled proposal build. What is
216
+ * in flight is the caller's to stop -- the requests, through the client's
217
+ * `fetchImpl`; the builder, by stopping its worker -- and nothing after the
218
+ * step it was on is started, so a build stopped before its upload is never
219
+ * declared.
220
+ */
221
+ signal?: AbortSignal;
214
222
  }
215
223
  export declare function runStudioDeploy(options: StudioDeployOptions): Promise<StudioDeployResult>;
216
224
  /**
@@ -242,3 +250,5 @@ export declare function splitBinaryFiles(files: Record<string, string>): {
242
250
  export declare function carriedInto(built: ReadonlyArray<{
243
251
  key: string;
244
252
  }>, carried: ReadonlyArray<CarriedArtifact>, committed: Record<string, string | null> | null): CarriedArtifact[];
253
+ /** What a deploy stopped by its `signal` answers. */
254
+ export declare const DEPLOY_STOPPED_MESSAGE = "The build was stopped.";