@sjcx/vorma 0.0.0-pre.2 → 0.0.0-pre.3

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 (135) hide show
  1. package/dist/build/assemble-artifacts.d.ts +1 -1
  2. package/dist/build/bundle-client.d.ts +1 -1
  3. package/dist/build/cli.js +27 -37
  4. package/dist/build/compile-application.d.ts +2 -2
  5. package/dist/build/development-artifacts.d.ts +1 -1
  6. package/dist/build/development-build.d.ts +3 -6
  7. package/dist/build/development-work.d.ts +2 -3
  8. package/dist/build/generate-application.d.ts +2 -2
  9. package/dist/build/index.d.ts +2 -3
  10. package/dist/build/index.js +1 -1
  11. package/dist/build/inspect-projects.d.ts +3 -3
  12. package/dist/build/load-config.d.ts +0 -2
  13. package/dist/build/publish-artifacts.d.ts +1 -4
  14. package/dist/build/render-client-transport.d.ts +1 -1
  15. package/dist/build/render-server-generated.d.ts +1 -12
  16. package/dist/build/render-types.d.ts +1 -1
  17. package/dist/build/resolve-config.d.ts +2 -4
  18. package/dist/build/source-layout.d.ts +1 -1
  19. package/dist/{build-DcP5_DUV.js → build-sHSh5zaX.js} +67 -282
  20. package/package.json +5 -36
  21. package/dist/build/compile-server.d.ts +0 -42
  22. package/dist/client/assembly.d.ts +0 -40
  23. package/dist/client/browser-http-client.d.ts +0 -10
  24. package/dist/client/client-loaders.d.ts +0 -93
  25. package/dist/client/commit.d.ts +0 -41
  26. package/dist/client/contracts.d.ts +0 -192
  27. package/dist/client/core.d.ts +0 -45
  28. package/dist/client/development.d.ts +0 -16
  29. package/dist/client/document-recovery.d.ts +0 -4
  30. package/dist/client/endpoints.d.ts +0 -54
  31. package/dist/client/errors.d.ts +0 -87
  32. package/dist/client/freshness.d.ts +0 -51
  33. package/dist/client/head.d.ts +0 -14
  34. package/dist/client/history.d.ts +0 -25
  35. package/dist/client/index.d.ts +0 -80
  36. package/dist/client/index.js +0 -150
  37. package/dist/client/links.d.ts +0 -48
  38. package/dist/client/materialize.d.ts +0 -21
  39. package/dist/client/modules.d.ts +0 -2
  40. package/dist/client/navigation.d.ts +0 -47
  41. package/dist/client/payload.d.ts +0 -54
  42. package/dist/client/prefetch.d.ts +0 -28
  43. package/dist/client/prepare.d.ts +0 -47
  44. package/dist/client/projections.d.ts +0 -26
  45. package/dist/client/queries.d.ts +0 -33
  46. package/dist/client/react/application.d.ts +0 -87
  47. package/dist/client/react/hooks.d.ts +0 -36
  48. package/dist/client/react/index.d.ts +0 -5
  49. package/dist/client/react/index.js +0 -3237
  50. package/dist/client/react/link.d.ts +0 -27
  51. package/dist/client/react/view.d.ts +0 -86
  52. package/dist/client/request.d.ts +0 -16
  53. package/dist/client/route-context.d.ts +0 -31
  54. package/dist/client/route-matching.d.ts +0 -22
  55. package/dist/client/route-synchronization.d.ts +0 -30
  56. package/dist/client/route-url.d.ts +0 -5
  57. package/dist/client/runtime.d.ts +0 -82
  58. package/dist/client/scroll.d.ts +0 -16
  59. package/dist/client/services.d.ts +0 -34
  60. package/dist/client/state.d.ts +0 -102
  61. package/dist/client/static-assets.d.ts +0 -3
  62. package/dist/client/stylesheets.d.ts +0 -7
  63. package/dist/client/transport-type-entries.d.ts +0 -2
  64. package/dist/client/types.d.ts +0 -152
  65. package/dist/client/view-definition.d.ts +0 -24
  66. package/dist/client/work-indicator.d.ts +0 -18
  67. package/dist/compile-Me8EOyMK.js +0 -870
  68. package/dist/development-B_rxuwY7.js +0 -128
  69. package/dist/hash-set-BPx3iXec.js +0 -141
  70. package/dist/href-Cqyax8Y0.js +0 -357
  71. package/dist/materialize-DZ7VSLFk.js +0 -739
  72. package/dist/metadata-BoPKo-G2.js +0 -32
  73. package/dist/primitives/tasks/index.d.ts +0 -1
  74. package/dist/primitives/tasks/index.js +0 -1
  75. package/dist/route-context-CtY_9U_W.js +0 -559
  76. package/dist/route-matching-D_uSG2P9.js +0 -33
  77. package/dist/search-parse-0f7oqVsG.js +0 -375
  78. package/dist/server/config/index.d.ts +0 -36
  79. package/dist/server/config/index.js +0 -30
  80. package/dist/server/development/metadata.d.ts +0 -11
  81. package/dist/server/document.d.ts +0 -37
  82. package/dist/server/form-data.d.ts +0 -21
  83. package/dist/server/graph/compile.d.ts +0 -118
  84. package/dist/server/graph/declarations.d.ts +0 -117
  85. package/dist/server/graph/literal-error-tag.d.ts +0 -14
  86. package/dist/server/graph/pattern-conflicts.d.ts +0 -36
  87. package/dist/server/graph/search-schema.d.ts +0 -13
  88. package/dist/server/graph/transport-schema.d.ts +0 -11
  89. package/dist/server/index.d.ts +0 -310
  90. package/dist/server/index.js +0 -2311
  91. package/dist/server/public-assets.d.ts +0 -18
  92. package/dist/server/runtime/application.d.ts +0 -15
  93. package/dist/server/runtime/assets.d.ts +0 -15
  94. package/dist/server/runtime/context.d.ts +0 -96
  95. package/dist/server/runtime/domain-errors.d.ts +0 -11
  96. package/dist/server/runtime/effects.d.ts +0 -83
  97. package/dist/server/runtime/execute.d.ts +0 -13
  98. package/dist/server/runtime/finalize.d.ts +0 -44
  99. package/dist/server/runtime/handler.d.ts +0 -106
  100. package/dist/server/runtime/head.d.ts +0 -22
  101. package/dist/server/runtime/payload.d.ts +0 -50
  102. package/dist/server/runtime/pipeline.d.ts +0 -27
  103. package/dist/server/runtime/plan.d.ts +0 -98
  104. package/dist/server/runtime/render-document.d.ts +0 -16
  105. package/dist/server/runtime/startup-error.d.ts +0 -11
  106. package/dist/server/runtime/transport-type-entries.d.ts +0 -2
  107. package/dist/server/runtime/vercel-deployment.d.ts +0 -2
  108. package/dist/server/url-pathname.d.ts +0 -13
  109. package/dist/static-assets-BrH3O0M8.js +0 -199
  110. package/dist/universal/generated-types.d.ts +0 -9
  111. package/dist/universal/href.d.ts +0 -17
  112. package/dist/universal/http-method.d.ts +0 -4
  113. package/dist/universal/json-transport.d.ts +0 -14
  114. package/dist/universal/null-prototype-record.d.ts +0 -7
  115. package/dist/universal/path-wire.d.ts +0 -71
  116. package/dist/universal/pattern-language.d.ts +0 -4
  117. package/dist/universal/protocol-schemas.d.ts +0 -99
  118. package/dist/universal/protocol.d.ts +0 -162
  119. package/dist/universal/search-grammar.d.ts +0 -7
  120. package/dist/universal/search-parse.d.ts +0 -22
  121. package/dist/universal/search-serialize.d.ts +0 -16
  122. package/dist/universal/search-shape.d.ts +0 -32
  123. package/dist/universal/static-assets.d.ts +0 -2
  124. package/dist/universal/transport-types/big-decimal.d.ts +0 -13
  125. package/dist/universal/transport-types/chunk.d.ts +0 -8
  126. package/dist/universal/transport-types/date-time-utc.d.ts +0 -13
  127. package/dist/universal/transport-types/date-time-zoned.d.ts +0 -13
  128. package/dist/universal/transport-types/duration.d.ts +0 -13
  129. package/dist/universal/transport-types/hash-map.d.ts +0 -8
  130. package/dist/universal/transport-types/hash-set.d.ts +0 -8
  131. package/dist/universal/transport-types/option.d.ts +0 -10
  132. package/dist/universal/transport-types/redacted.d.ts +0 -9
  133. package/dist/universal/value-transport.d.ts +0 -117
  134. package/dist/value-transport-Bst4Hk-n.js +0 -864
  135. /package/dist/{universal → build}/content-digest.d.ts +0 -0
@@ -1,739 +0,0 @@
1
- import { _ as DOCUMENT_PROTOCOL, h as BROWSER_STATE_PROTOCOL } from "./value-transport-Bst4Hk-n.js";
2
- import { B as RevalidationError, D as projectRouteState, L as NavigationError } from "./route-context-CtY_9U_W.js";
3
- import { Cause, Deferred, Effect, Exit, Option, Result, Scope } from "effect";
4
- import { AsyncResult } from "effect/unstable/reactivity";
5
- //#region src/client/head.ts
6
- const comments = DOCUMENT_PROTOCOL.headComments;
7
- const REGIONS = [
8
- {
9
- selectFn: (s) => s.title === void 0 ? [] : [s.title],
10
- start: comments.title,
11
- end: comments.meta
12
- },
13
- {
14
- selectFn: (s) => s.meta,
15
- start: comments.meta,
16
- end: comments.rest
17
- },
18
- {
19
- selectFn: (s) => s.rest,
20
- start: comments.rest,
21
- end: comments.assets
22
- }
23
- ];
24
- function applyHead(sections) {
25
- for (const region of REGIONS) {
26
- const applied = reconcileRegion(region.selectFn(sections), region);
27
- if (Result.isFailure(applied)) return applied;
28
- }
29
- return Result.succeed(void 0);
30
- }
31
- /** Reads the server-rendered head state from the three managed regions. */
32
- function readDocumentHead() {
33
- const sections = [];
34
- for (const region of REGIONS) {
35
- const boundary = findBoundary({
36
- startMarker: region.start,
37
- endMarker: region.end
38
- });
39
- if (boundary === null) return failHeadReconciliation(`Missing head boundary comments ${region.start}`);
40
- const elements = [];
41
- for (let node = boundary.start.nextSibling; node !== null && node !== boundary.end; node = node.nextSibling) if (node.nodeType === Node.ELEMENT_NODE) elements.push(readHeadElement(node));
42
- sections.push(elements);
43
- }
44
- const title = sections[0] ?? [];
45
- if (title.length > 1) return failHeadReconciliation("The managed title region contains more than one element");
46
- return Result.succeed({
47
- title: title[0],
48
- meta: sections[1] ?? [],
49
- rest: sections[2] ?? []
50
- });
51
- }
52
- function failHeadReconciliation(message) {
53
- return Result.fail({
54
- _tag: "HeadReconciliationError",
55
- message
56
- });
57
- }
58
- function findBoundary(input) {
59
- let opening;
60
- for (const node of document.head.childNodes) {
61
- if (node.nodeType !== Node.COMMENT_NODE) continue;
62
- const value = node.nodeValue?.trim();
63
- if (value === input.startMarker) opening = node;
64
- else if (value === input.endMarker && opening !== void 0) return {
65
- start: opening,
66
- end: node
67
- };
68
- }
69
- return null;
70
- }
71
- function createHeadElement(wire) {
72
- const element = document.createElement(wire.tag);
73
- if (wire.attrs !== void 0) for (const [name, value] of Object.entries(wire.attrs)) element.setAttribute(name, value === true ? "" : value);
74
- if (wire.html !== void 0) element.innerHTML = wire.html;
75
- return element;
76
- }
77
- function readHeadElement(element) {
78
- const attributes = Object.fromEntries([...element.attributes].map((attribute) => {
79
- return [attribute.name, attribute.value];
80
- }));
81
- return {
82
- tag: element.localName,
83
- ...Object.keys(attributes).length === 0 ? {} : { attrs: attributes },
84
- ...element.innerHTML === "" ? {} : { html: element.innerHTML }
85
- };
86
- }
87
- function computeFingerprint(element) {
88
- const attributes = [];
89
- for (const attribute of element.attributes) attributes.push([attribute.name, attribute.value]);
90
- attributes.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
91
- return JSON.stringify([
92
- element.tagName.toUpperCase(),
93
- attributes,
94
- element.innerHTML
95
- ]);
96
- }
97
- function reconcileRegion(elements, region) {
98
- const boundary = findBoundary({
99
- startMarker: region.start,
100
- endMarker: region.end
101
- });
102
- if (boundary === null) return elements.length === 0 ? Result.succeed(void 0) : failHeadReconciliation(`Missing head boundary comments ${region.start}`);
103
- const parent = boundary.end.parentNode;
104
- if (parent === null) return failHeadReconciliation(`Detached head boundary ${region.start}`);
105
- return Result.try({
106
- try: () => {
107
- const current = [];
108
- for (let node = boundary.start.nextSibling; node !== null && node !== boundary.end; node = node.nextSibling) if (node.nodeType === Node.ELEMENT_NODE) current.push(node);
109
- const currentByFingerprint = /* @__PURE__ */ new Map();
110
- for (const element of current) {
111
- const key = computeFingerprint(element);
112
- const list = currentByFingerprint.get(key);
113
- if (list === void 0) currentByFingerprint.set(key, [element]);
114
- else list.push(element);
115
- }
116
- const desired = /* @__PURE__ */ new Map();
117
- for (const wire of elements) {
118
- const element = createHeadElement(wire);
119
- const key = computeFingerprint(element);
120
- desired.delete(key);
121
- desired.set(key, element);
122
- }
123
- const used = /* @__PURE__ */ new Set();
124
- const final = [];
125
- for (const [key, fresh] of desired) {
126
- const match = currentByFingerprint.get(key)?.find((element) => !used.has(element));
127
- if (match === void 0) final.push(fresh);
128
- else {
129
- used.add(match);
130
- final.push(match);
131
- }
132
- }
133
- for (let node = boundary.start.nextSibling; node !== null && node !== boundary.end;) {
134
- const next = node.nextSibling;
135
- if (node.nodeType !== Node.ELEMENT_NODE || !used.has(node)) parent.removeChild(node);
136
- node = next;
137
- }
138
- let cursor = boundary.start;
139
- for (const element of final) {
140
- if (cursor.nextSibling !== element) parent.insertBefore(element, cursor.nextSibling);
141
- cursor = element;
142
- }
143
- },
144
- catch: (error) => {
145
- return {
146
- _tag: "HeadReconciliationError",
147
- message: error instanceof Error ? error.message : String(error)
148
- };
149
- }
150
- });
151
- }
152
- //#endregion
153
- //#region src/client/history.ts
154
- const USER_STATE_FIELD = BROWSER_STATE_PROTOCOL.historyStateFields.userState;
155
- const ENTRY_KEY_FIELD = BROWSER_STATE_PROTOCOL.historyStateFields.entryKey;
156
- const SCROLL_STORAGE_KEY = BROWSER_STATE_PROTOCOL.scrollStorageKey;
157
- /** The history state as a record of fields; a state that is not an object holds no fields. */
158
- function readStateRecord(value) {
159
- return typeof value === "object" && value !== null ? value : {};
160
- }
161
- function createEntryKey() {
162
- return Math.random().toString(36).slice(2);
163
- }
164
- /** Reads native user state and Vorma's entry key without imposing a user-data codec. */
165
- function readBrowserPosition() {
166
- return Result.try({
167
- try: () => {
168
- const state = readStateRecord(window.history.state);
169
- const key = state[ENTRY_KEY_FIELD];
170
- return {
171
- href: window.location.href,
172
- userState: state[USER_STATE_FIELD],
173
- key: typeof key === "string" ? key : void 0
174
- };
175
- },
176
- catch: (cause) => {
177
- return {
178
- _tag: "HistoryStateError",
179
- message: "The browser refused the history read",
180
- cause
181
- };
182
- }
183
- });
184
- }
185
- /** Writes a new or replaced history entry and returns the position it produced. */
186
- function writeBrowserPosition(input) {
187
- const next = {
188
- [USER_STATE_FIELD]: input.userState,
189
- [ENTRY_KEY_FIELD]: input.key
190
- };
191
- return Result.flatMap(Result.try({
192
- try: () => {
193
- if (input.replace) window.history.replaceState({
194
- ...readStateRecord(window.history.state),
195
- ...next
196
- }, "", input.href);
197
- else window.history.pushState(next, "", input.href);
198
- },
199
- catch: (cause) => {
200
- return {
201
- _tag: "HistoryStateError",
202
- message: "The browser refused the history write",
203
- cause
204
- };
205
- }
206
- }), readBrowserPosition);
207
- }
208
- /** One remembered position when the stored entry has that shape. */
209
- function readRememberedEntry(entry) {
210
- if (!Array.isArray(entry)) return [];
211
- const key = entry[0];
212
- const position = entry[1];
213
- if (typeof key !== "string" || typeof position !== "object" || position === null || !("x" in position) || !("y" in position) || typeof position.x !== "number" || typeof position.y !== "number" || !Number.isFinite(position.x) || !Number.isFinite(position.y)) return [];
214
- return [[key, {
215
- x: position.x,
216
- y: position.y
217
- }]];
218
- }
219
- /** The remembered positions; storage that is absent, unreadable, or not in this shape remembers nothing. */
220
- function readRemembered() {
221
- const stored = Result.try(() => sessionStorage.getItem(SCROLL_STORAGE_KEY));
222
- if (Result.isFailure(stored) || stored.success === null) return [];
223
- const text = stored.success;
224
- const parsed = Result.try(() => JSON.parse(text));
225
- if (Result.isFailure(parsed) || !Array.isArray(parsed.success)) return [];
226
- return parsed.success.flatMap(readRememberedEntry);
227
- }
228
- /** Remembers the scroll position of the entry `key` names. */
229
- function rememberScroll(key, scroll) {
230
- const entries = readRemembered().filter(([other]) => other !== key);
231
- entries.push([key, scroll]);
232
- Result.try(() => {
233
- sessionStorage.setItem(SCROLL_STORAGE_KEY, JSON.stringify(entries.slice(-50)));
234
- });
235
- }
236
- function recallScroll(key) {
237
- return readRemembered().find(([other]) => other === key)?.[1];
238
- }
239
- //#endregion
240
- //#region src/client/freshness.ts
241
- const IDLE_ATTEMPT = {
242
- coveredSequence: null,
243
- phase: "idle",
244
- skipWorkIndicator: false,
245
- waiters: [],
246
- latest: AsyncResult.initial()
247
- };
248
- function settleWaiters(waiters, outcome) {
249
- return waiters.map((waiter) => {
250
- return () => Deferred.doneUnsafe(waiter, outcome);
251
- });
252
- }
253
- /**
254
- * Registers a demand after `sequence` from an authorized trigger; merges into
255
- * an outstanding demand. The epoch advances with it, and every query
256
- * computation that evaluates for the new epoch expects itself through
257
- * `expectQueries`; expectations from before the merge are dropped, because a
258
- * retained query that no consumer holds does not evaluate and cannot answer.
259
- */
260
- function registerDemand(facts, input) {
261
- const running = facts.attempt.phase === "running";
262
- const previous = facts.demand === null ? {
263
- skipWorkIndicator: input.skipWorkIndicator,
264
- waiters: []
265
- } : facts.demand;
266
- return {
267
- facts: {
268
- demand: {
269
- afterSequence: input.sequence,
270
- skipWorkIndicator: previous.skipWorkIndicator && input.skipWorkIndicator,
271
- renewed: running,
272
- expectedQueries: /* @__PURE__ */ new Set(),
273
- acknowledgedQueries: /* @__PURE__ */ new Map(),
274
- routeReadSequence: null,
275
- waiters: input.waiter === void 0 ? previous.waiters : [...previous.waiters, input.waiter]
276
- },
277
- epoch: facts.epoch + 1,
278
- attempt: running ? facts.attempt : {
279
- ...facts.attempt,
280
- phase: "idle",
281
- latest: AsyncResult.waiting(facts.attempt.latest)
282
- }
283
- },
284
- complete: [],
285
- startAttempt: !running
286
- };
287
- }
288
- /** An attempt starts for the outstanding demand, recording the sequence it covers and taking the demand's waiters. */
289
- function startAttempt(facts) {
290
- const demand = facts.demand;
291
- if (demand === null) return facts;
292
- return {
293
- ...facts,
294
- demand: {
295
- ...demand,
296
- waiters: [],
297
- renewed: false
298
- },
299
- attempt: {
300
- coveredSequence: demand.afterSequence,
301
- phase: "running",
302
- skipWorkIndicator: demand.skipWorkIndicator,
303
- waiters: [...facts.attempt.waiters, ...demand.waiters],
304
- latest: AsyncResult.waiting(facts.attempt.latest)
305
- }
306
- };
307
- }
308
- /** The running attempt failed and the application's schedule will run another; its waiters wait on. */
309
- function holdAttemptForRetry(facts, error) {
310
- return {
311
- facts: {
312
- ...facts,
313
- attempt: {
314
- ...facts.attempt,
315
- phase: "retrying",
316
- latest: AsyncResult.fail(error)
317
- }
318
- },
319
- complete: [],
320
- startAttempt: false
321
- };
322
- }
323
- /**
324
- * Resolves the demand once its route read committed and every expected
325
- * query has acknowledged. A query leaves the expected set when its
326
- * computation is released without a successor, so a query that unmounted is
327
- * not waited for.
328
- */
329
- function completeIfSatisfied(facts, demand) {
330
- const outstanding = [...demand.expectedQueries].some((id) => {
331
- const acknowledged = demand.acknowledgedQueries.get(id);
332
- return !(acknowledged !== void 0 && acknowledged > demand.afterSequence);
333
- });
334
- if (demand.routeReadSequence === null || outstanding) return {
335
- facts: {
336
- ...facts,
337
- demand
338
- },
339
- complete: [],
340
- startAttempt: false
341
- };
342
- const result = { _tag: "Refreshed" };
343
- return {
344
- facts: {
345
- ...facts,
346
- demand: null,
347
- attempt: {
348
- ...IDLE_ATTEMPT,
349
- latest: AsyncResult.success(result)
350
- }
351
- },
352
- complete: settleWaiters([...facts.attempt.waiters, ...demand.waiters], Effect.succeed(result)),
353
- startAttempt: false
354
- };
355
- }
356
- /** A read with `sequence` committed without a route error. */
357
- function satisfyDemand(facts, input) {
358
- const demand = facts.demand;
359
- const latest = facts.attempt.latest;
360
- if (demand === null) return {
361
- facts: {
362
- ...facts,
363
- attempt: {
364
- ...IDLE_ATTEMPT,
365
- latest
366
- }
367
- },
368
- complete: [],
369
- startAttempt: false
370
- };
371
- if (input.sequence <= demand.afterSequence) return {
372
- facts: {
373
- ...facts,
374
- demand: {
375
- ...demand,
376
- waiters: [...facts.attempt.waiters, ...demand.waiters]
377
- },
378
- attempt: {
379
- ...IDLE_ATTEMPT,
380
- latest
381
- }
382
- },
383
- complete: [],
384
- startAttempt: true
385
- };
386
- return completeIfSatisfied(facts, {
387
- ...demand,
388
- routeReadSequence: input.sequence
389
- });
390
- }
391
- /** An expected query read settled: a qualifying success acknowledges; a failure of a qualifying read fails the attempt. */
392
- function acknowledgeQuery(facts, input) {
393
- const demand = facts.demand;
394
- if (demand === null || !demand.expectedQueries.has(input.id) || input.sequence !== void 0 && input.sequence <= demand.afterSequence) return {
395
- facts,
396
- complete: [],
397
- startAttempt: false
398
- };
399
- if (!input.success || input.sequence === void 0) return failAttempt(facts, makeRevalidationError("query", `Query ${input.id} failed to read`));
400
- return completeIfSatisfied(facts, {
401
- ...demand,
402
- acknowledgedQueries: new Map([...demand.acknowledgedQueries, [input.id, input.sequence]])
403
- });
404
- }
405
- /** Query computations evaluated for the outstanding demand's epoch; each must acknowledge or be released. */
406
- function expectQueries(facts, ids) {
407
- const demand = facts.demand;
408
- if (demand === null || ids.size === 0) return {
409
- facts,
410
- complete: [],
411
- startAttempt: false
412
- };
413
- return {
414
- facts: {
415
- ...facts,
416
- demand: {
417
- ...demand,
418
- expectedQueries: /* @__PURE__ */ new Set([...demand.expectedQueries, ...ids])
419
- }
420
- },
421
- complete: [],
422
- startAttempt: false
423
- };
424
- }
425
- /** A query's computation was released with no successor; a demand waiting only on it completes. */
426
- function releaseQuery(facts, id) {
427
- const demand = facts.demand;
428
- if (demand === null || !demand.expectedQueries.has(id)) return {
429
- facts,
430
- complete: [],
431
- startAttempt: false
432
- };
433
- const expectedQueries = new Set(demand.expectedQueries);
434
- expectedQueries.delete(id);
435
- return completeIfSatisfied(facts, {
436
- ...demand,
437
- expectedQueries
438
- });
439
- }
440
- /** The running attempt failed. Its captured batch fails; a newer demand starts another attempt. */
441
- function failAttempt(facts, error) {
442
- const { demand, attempt } = facts;
443
- const again = demand !== null && (demand.renewed || attempt.coveredSequence !== null && demand.afterSequence > attempt.coveredSequence);
444
- return {
445
- facts: {
446
- ...facts,
447
- demand,
448
- attempt: {
449
- ...attempt,
450
- phase: demand === null || again ? "idle" : "failed",
451
- waiters: [],
452
- latest: AsyncResult.fail(error)
453
- }
454
- },
455
- complete: settleWaiters(attempt.waiters, Effect.fail(error)),
456
- startAttempt: again
457
- };
458
- }
459
- /** The navigation that was running the attempt ended without settling it; the attempt's waiters return to the demand. */
460
- function abandonAttempt(facts) {
461
- const { demand, attempt } = facts;
462
- return {
463
- facts: {
464
- ...facts,
465
- demand: demand === null ? null : {
466
- ...demand,
467
- waiters: [...attempt.waiters, ...demand.waiters]
468
- },
469
- attempt: {
470
- ...attempt,
471
- phase: "idle",
472
- waiters: []
473
- }
474
- },
475
- complete: [],
476
- startAttempt: demand !== null
477
- };
478
- }
479
- /** Whether a new attempt may start: a demand exists, no attempt is running, and no failed attempt already covered the demand's sequence. */
480
- function canStartAttempt(facts) {
481
- const { demand, attempt } = facts;
482
- if (demand === null || attempt.phase === "running") return false;
483
- return !(attempt.phase === "failed" && attempt.coveredSequence !== null && demand.afterSequence <= attempt.coveredSequence);
484
- }
485
- /** Retires the demand and settles every waiter with the given error. */
486
- function retireDemand(facts, error) {
487
- return {
488
- facts: {
489
- ...facts,
490
- demand: null,
491
- attempt: {
492
- ...IDLE_ATTEMPT,
493
- latest: AsyncResult.fail(error)
494
- }
495
- },
496
- complete: settleWaiters([...facts.attempt.waiters, ...facts.demand === null ? [] : facts.demand.waiters], Effect.fail(error)),
497
- startAttempt: false
498
- };
499
- }
500
- function makeRevalidationError(reason, cause) {
501
- return new RevalidationError({
502
- reason,
503
- cause: Cause.isCause(cause) ? cause : Cause.fail(cause)
504
- });
505
- }
506
- //#endregion
507
- //#region src/client/document-recovery.ts
508
- /** Loads the browser's current URL as a document after client navigation cannot complete. */
509
- function reloadDocument(core, cause) {
510
- const refresh = retireDemand(core.getState().freshness, makeRevalidationError("route", cause));
511
- core.updateState((state) => {
512
- return {
513
- ...state,
514
- freshness: refresh.facts
515
- };
516
- });
517
- for (const complete of refresh.complete) complete();
518
- core.publishEvent({
519
- _tag: "FailureReported",
520
- source: "navigation",
521
- cause
522
- });
523
- window.location.reload();
524
- }
525
- //#endregion
526
- //#region src/client/stylesheets.ts
527
- const BUNDLE_ATTRIBUTE = DOCUMENT_PROTOCOL.attributes.cssBundle;
528
- const PRELOAD_ATTRIBUTE = DOCUMENT_PROTOCOL.attributes.cssPreload;
529
- const preparations = /* @__PURE__ */ new WeakMap();
530
- function findLink(input) {
531
- for (const link of document.head.querySelectorAll("link")) if (link.getAttribute(input.attribute) === input.value) return link;
532
- return null;
533
- }
534
- /** Reads the stylesheet bundles that the initial document applied. */
535
- function readDocumentStylesheets() {
536
- return [...document.head.querySelectorAll("link")].flatMap((link) => {
537
- const bundle = link.getAttribute(BUNDLE_ATTRIBUTE);
538
- return bundle === null ? [] : [bundle];
539
- });
540
- }
541
- /** Starts managed CSS preloads and waits for every load or error without applying destination styles. */
542
- function prepareStylesheets(bundles) {
543
- return Effect.forEach(new Set(bundles), (path) => {
544
- return Effect.gen(function* () {
545
- const preparation = yield* acquireStylesheet(path);
546
- if (preparation !== void 0) yield* Deferred.await(preparation.settled);
547
- });
548
- }, {
549
- concurrency: "unbounded",
550
- discard: true
551
- });
552
- }
553
- function acquireStylesheet(path) {
554
- return Effect.acquireRelease(Effect.sync(() => {
555
- if (findLink({
556
- attribute: BUNDLE_ATTRIBUTE,
557
- value: path
558
- }) !== null) return;
559
- const existing = findLink({
560
- attribute: PRELOAD_ATTRIBUTE,
561
- value: path
562
- });
563
- const previous = existing === null ? void 0 : preparations.get(existing);
564
- if (previous !== void 0) {
565
- previous.owners += 1;
566
- return previous;
567
- }
568
- existing?.remove();
569
- const link = document.createElement("link");
570
- link.rel = "preload";
571
- link.as = "style";
572
- link.href = path;
573
- link.setAttribute(PRELOAD_ATTRIBUTE, path);
574
- function dispose() {
575
- link.removeEventListener("load", settle);
576
- link.removeEventListener("error", settle);
577
- }
578
- const preparation = {
579
- link,
580
- settled: Deferred.makeUnsafe(),
581
- owners: 1,
582
- dispose
583
- };
584
- preparations.set(link, preparation);
585
- function settle() {
586
- dispose();
587
- Deferred.doneUnsafe(preparation.settled, Effect.void);
588
- }
589
- link.addEventListener("load", settle);
590
- link.addEventListener("error", settle);
591
- document.head.append(link);
592
- return preparation;
593
- }), (preparation) => {
594
- return Effect.sync(() => {
595
- if (preparation === void 0) return;
596
- preparation.owners -= 1;
597
- if (preparation.owners === 0 && !preparation.link.hasAttribute(BUNDLE_ATTRIBUTE)) {
598
- preparation.dispose();
599
- preparation.link.remove();
600
- }
601
- });
602
- });
603
- }
604
- /** Publishes managed styles after their preload attempts have settled. */
605
- function applyStylesheets(bundles) {
606
- for (const path of new Set(bundles)) {
607
- const prepared = findLink({
608
- attribute: PRELOAD_ATTRIBUTE,
609
- value: path
610
- });
611
- if (prepared === null) continue;
612
- prepared.removeAttribute(PRELOAD_ATTRIBUTE);
613
- prepared.setAttribute(BUNDLE_ATTRIBUTE, path);
614
- prepared.removeAttribute("as");
615
- document.head.append(prepared);
616
- prepared.rel = "stylesheet";
617
- }
618
- }
619
- //#endregion
620
- //#region src/client/commit.ts
621
- /** Accepts a prepared route as the committed frame. Callers hold the uninterruptible region. */
622
- function commitFrame(core, input) {
623
- const position = input.position.kind === "adopt" ? Result.succeed(input.position.position) : writeBrowserPosition(input.position);
624
- if (Result.isFailure(position)) return Result.fail(new NavigationError({
625
- stage: "transition",
626
- cause: Cause.fail(position.failure)
627
- }));
628
- if (input.documentUpdate === "apply") {
629
- const applied = Result.flatMap(applyHead(input.head), () => {
630
- return Result.try(() => applyStylesheets(input.cssBundles));
631
- });
632
- if (Result.isFailure(applied)) {
633
- const cause = Cause.fail(applied.failure);
634
- reloadDocument(core, cause);
635
- return Result.fail(new NavigationError({
636
- stage: "publication",
637
- cause
638
- }));
639
- }
640
- }
641
- const previous = core.getState().frame;
642
- const frame = {
643
- href: position.success.href,
644
- historyState: position.success.userState,
645
- key: position.success.key,
646
- clientBuildId: core.getClientBuildId(),
647
- entries: input.entries,
648
- error: input.error,
649
- head: input.head,
650
- cssBundles: input.cssBundles,
651
- scope: input.scope,
652
- revision: previous === null ? 1 : previous.revision + 1,
653
- committedAt: input.committedAt === void 0 ? Date.now() : input.committedAt,
654
- scrollIntent: input.scrollIntent
655
- };
656
- core.updateState((state) => {
657
- return {
658
- ...state,
659
- frame
660
- };
661
- });
662
- if (previous !== null && previous.scope !== frame.scope) core.forkFiber(Scope.close(previous.scope, Exit.void));
663
- core.publishEvent({
664
- _tag: "RouteCommitted",
665
- previous: previous === null ? Option.none() : Option.some(projectRouteState(previous)),
666
- current: projectRouteState(frame),
667
- reason: input.reason
668
- });
669
- return Result.succeed(frame);
670
- }
671
- //#endregion
672
- //#region src/client/materialize.ts
673
- let developmentModules;
674
- /** Native imports cache production modules; development retains accepted replacement namespaces. */
675
- function enableDevelopmentModules() {
676
- const modules = /* @__PURE__ */ new Map();
677
- const replacements = /* @__PURE__ */ new Map();
678
- developmentModules = modules;
679
- return {
680
- replaceFn(input) {
681
- const url = new URL(input.url, window.location.href);
682
- url.searchParams.delete("t");
683
- const previous = modules.get(url.href);
684
- modules.set(url.href, input.module);
685
- for (const [name, value] of Object.entries(previous ?? {})) {
686
- for (const [old, replacement] of replacements) if (replacement === value) replacements.set(old, input.module[name]);
687
- replacements.set(value, input.module[name]);
688
- }
689
- return replacements;
690
- },
691
- closeFn() {
692
- if (developmentModules === modules) developmentModules = void 0;
693
- }
694
- };
695
- }
696
- function loadModule(url) {
697
- return Effect.tryPromise({
698
- try: async () => {
699
- const key = developmentModules === void 0 ? url : new URL(url, window.location.href).href;
700
- const existing = developmentModules?.get(key);
701
- if (existing !== void 0) return existing;
702
- const module = await import(
703
- /* @vite-ignore */
704
- url
705
- );
706
- if (developmentModules !== void 0 && !developmentModules.has(key)) developmentModules.set(key, module);
707
- return developmentModules?.get(key) ?? module;
708
- },
709
- catch: (cause) => {
710
- return {
711
- _tag: "ModuleLoadError",
712
- url,
713
- cause
714
- };
715
- }
716
- });
717
- }
718
- /** Loads one position independently, retaining its decoded facts and selected view. */
719
- function materializeRoute(route) {
720
- const reference = route.moduleReference;
721
- return reference === null ? Effect.succeed({
722
- ...route,
723
- definition: void 0
724
- }) : Effect.flatMap(loadModule(reference.url), (module) => {
725
- const firstName = reference.exportNames[0];
726
- const definition = firstName === void 0 ? void 0 : module[firstName];
727
- if (definition === void 0 || reference.exportNames.some((name) => module[name] !== definition)) return Effect.fail({
728
- _tag: "ModuleLoadError",
729
- url: reference.url,
730
- cause: "A route must select one view declaration value; aliases must reference that same value"
731
- });
732
- return Effect.succeed({
733
- ...route,
734
- definition
735
- });
736
- });
737
- }
738
- //#endregion
739
- export { readDocumentHead as C, rememberScroll as S, satisfyDemand as _, readDocumentStylesheets as a, readBrowserPosition as b, acknowledgeQuery as c, failAttempt as d, holdAttemptForRetry as f, retireDemand as g, releaseQuery as h, prepareStylesheets as i, canStartAttempt as l, registerDemand as m, materializeRoute as n, reloadDocument as o, makeRevalidationError as p, commitFrame as r, abandonAttempt as s, enableDevelopmentModules as t, expectQueries as u, startAttempt as v, recallScroll as x, createEntryKey as y };