@ogygia/core 0.12.3 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LateIsland.svelte +3 -2
- package/dist/LateIslandAwait.svelte +6 -2
- package/dist/Region.svelte +22 -33
- package/dist/boundary.d.ts +0 -2
- package/dist/boundary.js +8 -6
- package/dist/compiler/debarrel/barrel.d.ts +15 -8
- package/dist/compiler/debarrel/barrel.js +92 -45
- package/dist/compiler/debarrel/plugin.js +41 -17
- package/dist/compiler/dev/dev-hmr.d.ts +3 -0
- package/dist/compiler/dev/dev-hmr.js +3 -0
- package/dist/compiler/driver.js +11 -4
- package/dist/compiler/flags.js +21 -7
- package/dist/compiler/fouc-css.js +5 -1
- package/dist/compiler/kit.js +5 -1
- package/dist/compiler/link/build-output.js +12 -3
- package/dist/compiler/macros/bake.js +18 -4
- package/dist/compiler/macros/dollar.js +6 -1
- package/dist/compiler/macros/source.js +6 -1
- package/dist/compiler/macros/store.js +10 -2
- package/dist/compiler/macros/wire.js +6 -1
- package/dist/compiler/parse/scan.js +10 -3
- package/dist/compiler/region/transform.js +188 -74
- package/dist/context-bridge.js +13 -5
- package/dist/context.d.ts +9 -0
- package/dist/context.js +30 -1
- package/dist/document.d.ts +1 -1
- package/dist/document.js +7 -1
- package/dist/early-holes-head.d.ts +5 -0
- package/dist/early-holes-head.js +20 -0
- package/dist/early-holes.d.ts +34 -0
- package/dist/early-holes.js +51 -0
- package/dist/entry-hydrate.js +9 -12
- package/dist/events/bus.js +7 -2
- package/dist/events/schema.d.ts +2 -2
- package/dist/fn-transport.js +4 -3
- package/dist/hooks.js +94 -163
- package/dist/insights/page-assets.js +11 -3
- package/dist/insights/page-insights.d.ts +0 -2
- package/dist/insights/page-insights.js +14 -10
- package/dist/insights/session-insights.js +2 -2
- package/dist/internal-instruments.d.ts +3 -1
- package/dist/internal-instruments.js +3 -1
- package/dist/internal-server.d.ts +3 -2
- package/dist/internal-server.js +3 -2
- package/dist/internal.d.ts +1 -2
- package/dist/internal.js +1 -2
- package/dist/keep-fallback.d.ts +0 -2
- package/dist/keep-fallback.js +4 -5
- package/dist/live-transport.js +3 -2
- package/dist/messages/build.d.ts +585 -0
- package/dist/messages/build.js +800 -0
- package/dist/messages/core.d.ts +464 -0
- package/dist/messages/core.js +843 -0
- package/dist/messages/define.d.ts +62 -0
- package/dist/messages/define.js +49 -0
- package/dist/messages/index.d.ts +6 -0
- package/dist/messages/index.js +6 -0
- package/dist/messages/island.d.ts +4 -0
- package/dist/messages/island.js +34 -0
- package/dist/messages/lazy.d.ts +3 -0
- package/dist/messages/lazy.js +22 -0
- package/dist/messages/prose.d.ts +15 -0
- package/dist/messages/prose.js +43 -0
- package/dist/messages/server.d.ts +142 -0
- package/dist/messages/server.js +246 -0
- package/dist/nested.d.ts +3 -0
- package/dist/nested.js +8 -1
- package/dist/plugin/css.js +14 -13
- package/dist/plugin/facts.d.ts +2 -0
- package/dist/plugin/facts.js +10 -6
- package/dist/plugin/hooks.d.ts +7 -17
- package/dist/plugin/hooks.js +32 -4
- package/dist/plugin/index.d.ts +9 -2
- package/dist/plugin/request-scope.d.ts +20 -0
- package/dist/plugin/request-scope.js +149 -0
- package/dist/plugin/server.d.ts +20 -2
- package/dist/plugin/server.js +98 -28
- package/dist/plugin/testing.d.ts +6 -0
- package/dist/plugin/testing.js +14 -2
- package/dist/policies.d.ts +21 -0
- package/dist/policies.js +66 -0
- package/dist/preference.js +6 -1
- package/dist/preload.js +6 -9
- package/dist/ref-watch.d.ts +0 -10
- package/dist/ref-watch.js +14 -1
- package/dist/ref.js +17 -5
- package/dist/region-snippet.js +9 -3
- package/dist/region.js +2 -1
- package/dist/report-thrown.d.ts +9 -0
- package/dist/report-thrown.js +15 -0
- package/dist/rules.d.ts +17 -0
- package/dist/rules.js +57 -0
- package/dist/runtime/beacon.d.ts +0 -4
- package/dist/runtime/beacon.js +58 -43
- package/dist/runtime/boot-link.js +19 -2
- package/dist/runtime/client-hooks.js +2 -1
- package/dist/runtime/concurrency.d.ts +16 -5
- package/dist/runtime/concurrency.js +123 -7
- package/dist/runtime/core.d.ts +3 -1
- package/dist/runtime/core.js +718 -384
- package/dist/runtime/devalue-lane.d.ts +13 -0
- package/dist/runtime/devalue-lane.js +49 -0
- package/dist/runtime/disclose-version.d.ts +1 -0
- package/dist/runtime/disclose-version.js +14 -0
- package/dist/runtime/early-holes.d.ts +4 -0
- package/dist/runtime/early-holes.js +40 -0
- package/dist/runtime/entry-locations.js +40 -49
- package/dist/runtime/foreign-props.d.ts +0 -7
- package/dist/runtime/foreign-props.js +2 -1
- package/dist/runtime/form-continuity.d.ts +2 -2
- package/dist/runtime/form-continuity.js +30 -8
- package/dist/runtime/frame-nav.d.ts +7 -1
- package/dist/runtime/frame-nav.js +84 -18
- package/dist/runtime/frame-store.d.ts +25 -16
- package/dist/runtime/frame-store.js +124 -98
- package/dist/runtime/frames.js +8 -4
- package/dist/runtime/hole-facts.js +6 -7
- package/dist/runtime/hole-fetch.d.ts +17 -0
- package/dist/runtime/hole-fetch.js +47 -0
- package/dist/runtime/hydrate-core.d.ts +4 -4
- package/dist/runtime/hydrate-core.js +80 -64
- package/dist/runtime/import-again.d.ts +33 -0
- package/dist/runtime/import-again.js +217 -0
- package/dist/runtime/interaction-replay.d.ts +5 -3
- package/dist/runtime/interaction-replay.js +6 -6
- package/dist/runtime/interaction.d.ts +14 -3
- package/dist/runtime/interaction.js +46 -23
- package/dist/runtime/kit-page-thread.svelte.d.ts +2 -1
- package/dist/runtime/kit-page-thread.svelte.js +44 -20
- package/dist/runtime/lakes.d.ts +1 -1
- package/dist/runtime/lakes.js +18 -5
- package/dist/runtime/live.d.ts +1 -2
- package/dist/runtime/live.js +6 -8
- package/dist/runtime/load-scheduler.d.ts +29 -18
- package/dist/runtime/load-scheduler.js +236 -136
- package/dist/runtime/nav-handle.js +25 -6
- package/dist/runtime/navigation.d.ts +24 -0
- package/dist/runtime/navigation.js +24 -0
- package/dist/runtime/ownership.d.ts +1 -1
- package/dist/runtime/page-defer.js +3 -3
- package/dist/runtime/parse-html.d.ts +15 -4
- package/dist/runtime/parse-html.js +24 -5
- package/dist/runtime/pushable-props.svelte.d.ts +21 -0
- package/dist/runtime/pushable-props.svelte.js +37 -0
- package/dist/runtime/region-endpoint-url.js +4 -6
- package/dist/runtime/region-machines.d.ts +111 -0
- package/dist/runtime/region-machines.js +97 -0
- package/dist/runtime/region-sheets.d.ts +31 -0
- package/dist/runtime/region-sheets.js +49 -0
- package/dist/runtime/restore-report.d.ts +1 -0
- package/dist/runtime/restore-report.js +36 -0
- package/dist/runtime/restore.d.ts +5 -2
- package/dist/runtime/restore.js +33 -14
- package/dist/runtime/router-nav.d.ts +32 -12
- package/dist/runtime/router-nav.js +320 -228
- package/dist/runtime/router.d.ts +83 -19
- package/dist/runtime/router.js +297 -129
- package/dist/runtime/rules.d.ts +35 -0
- package/dist/runtime/rules.js +137 -0
- package/dist/runtime/schedule.d.ts +6 -3
- package/dist/runtime/schedule.js +172 -57
- package/dist/runtime/seeds.d.ts +5 -1
- package/dist/runtime/seeds.js +11 -5
- package/dist/runtime/session.d.ts +46 -7
- package/dist/runtime/session.js +78 -10
- package/dist/runtime/slots.d.ts +53 -20
- package/dist/runtime/slots.js +2 -3
- package/dist/runtime/soft-refresh.d.ts +16 -0
- package/dist/runtime/soft-refresh.js +14 -0
- package/dist/runtime/svelte-warnings.d.ts +4 -10
- package/dist/runtime/svelte-warnings.js +7 -4
- package/dist/runtime/wire-classes.js +21 -8
- package/dist/runtime/wire-format.js +6 -3
- package/dist/script.js +8 -7
- package/dist/seed-ref-reviver.d.ts +0 -9
- package/dist/seed-ref-reviver.js +2 -1
- package/dist/seed-refs.d.ts +46 -36
- package/dist/seed-refs.js +131 -92
- package/dist/server/document-tail.d.ts +6 -0
- package/dist/server/document-tail.js +7 -1
- package/dist/server/early-holes-csp.d.ts +14 -0
- package/dist/server/early-holes-csp.js +73 -0
- package/dist/server/page-facts.d.ts +4 -1
- package/dist/server/page-facts.js +4 -1
- package/dist/server/page-seed.d.ts +2 -2
- package/dist/server/page-seed.js +104 -11
- package/dist/server/page-stream.d.ts +14 -1
- package/dist/server/page-stream.js +119 -2
- package/dist/server/personal-response.d.ts +0 -5
- package/dist/server/personal-response.js +6 -2
- package/dist/server/props-wire.js +5 -1
- package/dist/server/region-endpoint.js +10 -2
- package/dist/server/render-cache.d.ts +24 -20
- package/dist/server/render-cache.js +99 -40
- package/dist/server/render-page.js +46 -15
- package/dist/server/request-stats.d.ts +10 -8
- package/dist/server/request-stats.js +20 -12
- package/dist/server/rules.d.ts +11 -0
- package/dist/server/rules.js +64 -0
- package/dist/server/signing-key.js +31 -18
- package/dist/server/stream-regions.d.ts +14 -1
- package/dist/server/stream-regions.js +38 -2
- package/dist/shared-state.js +5 -1
- package/dist/shims/app-navigation.js +3 -2
- package/dist/shims/page-store.svelte.js +16 -2
- package/dist/source.js +7 -2
- package/dist/store-transport.js +12 -5
- package/dist/transport.js +3 -2
- package/dist/vite/index.js +17 -10
- package/dist/vite/kit-dirs.js +7 -1
- package/dist/vite/options.d.ts +2 -1
- package/dist/vite/options.js +11 -20
- package/dist/vite/package-files.js +13 -3
- package/dist/vite/paths.d.ts +2 -0
- package/dist/vite/paths.js +4 -4
- package/dist/vite/plugin-api.js +42 -14
- package/dist/vite/style-preprocess.js +10 -3
- package/package.json +8 -1
- package/dist/KeepHost.svelte +0 -19
- package/dist/KeepHost.svelte.d.ts +0 -10
- package/dist/LiveHost.svelte +0 -19
- package/dist/LiveHost.svelte.d.ts +0 -10
- package/dist/NestedProvider.svelte +0 -13
- package/dist/NestedProvider.svelte.d.ts +0 -8
- package/dist/runtime/page-cache.d.ts +0 -23
- package/dist/runtime/page-cache.js +0 -74
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Rules } from "../rules.js";
|
|
2
|
+
import { warn } from "../messages/server.js";
|
|
3
|
+
import { observe } from "@ogygia/machine";
|
|
4
|
+
// src/server/rules.ts
|
|
5
|
+
/**
|
|
6
|
+
* THE SERVER'S RULES (#313, ../rules.ts): what is always true of the server, checked a task after
|
|
7
|
+
* each response ends (in dev, and in a build made with `OGYGIA_RULES=1`), printed with its code.
|
|
8
|
+
*
|
|
9
|
+
* - `rule_request_scope_open`: a request's scope (its timers, streams, fetches) is closed once its
|
|
10
|
+
* response has ended.
|
|
11
|
+
* - `rule_flight_kept_failure`: no flight keeps a failure: an answer kept is never an error.
|
|
12
|
+
*
|
|
13
|
+
* Each area tells this module what it holds (`note_response_end`) only when rules are on: every call
|
|
14
|
+
* site folds out of a build without them.
|
|
15
|
+
*/
|
|
16
|
+
/** The server's rules. */
|
|
17
|
+
const server_rules = /* @__PURE__ */ new Rules();
|
|
18
|
+
/** Request scopes whose response has ended, until a check sees them closed. */
|
|
19
|
+
const ended = /* @__PURE__ */ new Set();
|
|
20
|
+
/** A response ended (its body read to the end, cancelled, or none): its request's scope must be
|
|
21
|
+
* closed by the time the next check runs. */
|
|
22
|
+
function note_response_end(owner) {
|
|
23
|
+
if (!installed) return;
|
|
24
|
+
ended.add(owner);
|
|
25
|
+
check_soon();
|
|
26
|
+
}
|
|
27
|
+
function request_scopes_closed() {
|
|
28
|
+
let open = 0;
|
|
29
|
+
for (const owner of ended) if (owner.closed) ended.delete(owner);
|
|
30
|
+
else open++;
|
|
31
|
+
return open === 0 ? null : `${open} request scope(s) still open after their response ended`;
|
|
32
|
+
}
|
|
33
|
+
/** The flights' entries that keep an error as their answer now, each with what it keeps. An entry
|
|
34
|
+
* leaves when it moves on (dropped, or a fresh answer kept): the rule is about what is kept now, so
|
|
35
|
+
* a check (a simulated run, the next response in dev) sees its own breaks, not an earlier one's. */
|
|
36
|
+
const kept_failures = /* @__PURE__ */ new Map();
|
|
37
|
+
function no_kept_failure() {
|
|
38
|
+
if (kept_failures.size === 0) return null;
|
|
39
|
+
return [...kept_failures.values()].slice(0, 10).join("; ");
|
|
40
|
+
}
|
|
41
|
+
let installed = false;
|
|
42
|
+
let pending = false;
|
|
43
|
+
/** Checks every rule a task from now (once, however many responses ask), and says what broke. */
|
|
44
|
+
function check_soon() {
|
|
45
|
+
if (pending) return;
|
|
46
|
+
pending = true;
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
pending = false;
|
|
49
|
+
server_rules.say((code, detail) => warn(code, { detail }));
|
|
50
|
+
}, 0);
|
|
51
|
+
}
|
|
52
|
+
/** Rules on: checked after each response, and what broke is said with its code. */
|
|
53
|
+
function install_server_rules() {
|
|
54
|
+
if (installed) return;
|
|
55
|
+
installed = true;
|
|
56
|
+
server_rules.add("rule_request_scope_open", request_scopes_closed);
|
|
57
|
+
server_rules.add("rule_flight_kept_failure", no_kept_failure);
|
|
58
|
+
observe((name, _from, to, machine) => {
|
|
59
|
+
const answer = to?.kind === "kept" ? to.answer : void 0;
|
|
60
|
+
if (answer instanceof Error) kept_failures.set(machine, `"${name}" kept ${answer.name}: ${answer.message.slice(0, 120)}`);
|
|
61
|
+
else if (kept_failures.size !== 0) kept_failures.delete(machine);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export { install_server_rules, note_response_end, server_rules };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OgygiaError, warn } from "../messages/server.js";
|
|
1
2
|
import { buildHadSecret, buildKey } from "virtual:ogygia/secret";
|
|
2
3
|
import { sign } from "virtual:ogygia/sign";
|
|
3
4
|
import { building } from "$app/env";
|
|
@@ -24,23 +25,27 @@ const SOURCE_NAME = {
|
|
|
24
25
|
env: "OGYGIA_SECRET",
|
|
25
26
|
build: "this build's random key"
|
|
26
27
|
};
|
|
28
|
+
const slots = globalThis;
|
|
27
29
|
function slot() {
|
|
28
|
-
|
|
29
|
-
return g[SLOT] ??= {};
|
|
30
|
+
return slots[SLOT] ?? { kind: "undecided" };
|
|
30
31
|
}
|
|
31
32
|
function signing_key() {
|
|
32
33
|
const s = slot();
|
|
33
|
-
if (s.
|
|
34
|
+
if (s.kind === "decided") return s.key;
|
|
34
35
|
const from_env = typeof process !== "undefined" && process.env?.OGYGIA_SECRET || "";
|
|
35
|
-
const [secret, source] = s.
|
|
36
|
-
|
|
36
|
+
const [secret, source] = s.kind === "secret" ? [s.option, "option"] : from_env ? [from_env, "env"] : [buildKey, "build"];
|
|
37
|
+
const key = {
|
|
37
38
|
secret,
|
|
38
39
|
stable: source !== "build",
|
|
39
40
|
fp: key_fingerprint(secret),
|
|
40
41
|
source
|
|
41
42
|
};
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
slots[SLOT] = {
|
|
44
|
+
kind: "decided",
|
|
45
|
+
key
|
|
46
|
+
};
|
|
47
|
+
if (!key.stable && !import.meta.env.DEV) warn_build_key();
|
|
48
|
+
return key;
|
|
44
49
|
}
|
|
45
50
|
/**
|
|
46
51
|
* Record the app's `handle({ secret })`. A blank one counts as none (an app can pass a value that may
|
|
@@ -50,15 +55,23 @@ function signing_key() {
|
|
|
50
55
|
function configure_signing_secret(secret) {
|
|
51
56
|
if (!secret?.trim()) return;
|
|
52
57
|
const s = slot();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
if (s.kind === "undecided") {
|
|
59
|
+
slots[SLOT] = {
|
|
60
|
+
kind: "secret",
|
|
61
|
+
option: secret
|
|
62
|
+
};
|
|
56
63
|
return;
|
|
57
64
|
}
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
const decided = s.kind === "decided" ? s.key.secret : s.option;
|
|
66
|
+
if (decided === secret) return;
|
|
67
|
+
const from = s.kind === "decided" ? `${SOURCE_NAME[s.key.source]}, decided by an earlier mint or verify` : "another handle({ secret })";
|
|
68
|
+
const error = new OgygiaError("secret_conflict", {
|
|
69
|
+
key: key_fingerprint(secret),
|
|
70
|
+
decided: key_fingerprint(decided),
|
|
71
|
+
from
|
|
72
|
+
});
|
|
73
|
+
if (import.meta.env.DEV) throw error;
|
|
74
|
+
console.error(error);
|
|
62
75
|
}
|
|
63
76
|
function key_fingerprint(secret) {
|
|
64
77
|
return sign(secret, "ogygia:key-fp").slice(0, 8);
|
|
@@ -70,12 +83,12 @@ function warn_build_key() {
|
|
|
70
83
|
const K = Symbol.for("ogygia.build-key-warned");
|
|
71
84
|
if (g[K]) return;
|
|
72
85
|
g[K] = true;
|
|
73
|
-
if (building)
|
|
74
|
-
else if (buildHadSecret) console.error(
|
|
75
|
-
else
|
|
86
|
+
if (building) warn("build_key_prerender");
|
|
87
|
+
else if (buildHadSecret) console.error(new OgygiaError("secret_missing_at_runtime"));
|
|
88
|
+
else warn("secret_missing");
|
|
76
89
|
}
|
|
77
90
|
/** Tests: forget the decided key and the app's secret. */
|
|
78
91
|
function reset_signing_key() {
|
|
79
|
-
delete
|
|
92
|
+
delete slots[SLOT];
|
|
80
93
|
}
|
|
81
94
|
export { configure_signing_secret, key_fingerprint, reset_signing_key, signing_key };
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
import { Scope } from "@ogygia/machine";
|
|
1
2
|
/** Build a parcel `<template data-ogygia-slot="…">…rendered html…</template>` (length-framed when
|
|
2
3
|
* the html carries a `</template` of its own). */
|
|
3
4
|
export declare function build_parcel(slot: string, html: string): string;
|
|
4
5
|
/** The done-sentinel parcel (empty template) the client watches to end the batch. */
|
|
5
|
-
export declare function done_parcel(): string;
|
|
6
|
+
export declare function done_parcel(): string;
|
|
7
|
+
/** One region call's answer in a batch: its slot (the capability signature) and its HTML. Null:
|
|
8
|
+
* the call is left out (the client fetches it on its own). */
|
|
9
|
+
export type BatchAnswer = {
|
|
10
|
+
slot: string;
|
|
11
|
+
html: string;
|
|
12
|
+
} | null;
|
|
13
|
+
/**
|
|
14
|
+
* The batch's frame stream: every call renders at once, and each answer goes out as its parcel the
|
|
15
|
+
* moment it settles, whatever the order; the done sentinel ends it. `render` is handed the batch's
|
|
16
|
+
* signal: it aborts when the stream is cancelled, or when `owner` (the request's) ends first.
|
|
17
|
+
*/
|
|
18
|
+
export declare function batch_stream(calls: readonly string[], render: (endpoint: string, signal: AbortSignal) => Promise<BatchAnswer>, owner?: Scope): ReadableStream<Uint8Array>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { STALE, machine } from "@ogygia/machine";
|
|
1
2
|
// src/server/stream-regions.ts
|
|
2
3
|
/**
|
|
3
4
|
* Region parcels for the batch endpoint (single-flight navigation, a page's first-load holes, OOO).
|
|
@@ -11,7 +12,7 @@
|
|
|
11
12
|
* decoded string counts in — so its content can never close the box or forge a parcel for another
|
|
12
13
|
* slot, and it no longer falls back to a second request.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
+
* No I/O and no Kit (the batch stream is handed its render), so it stays unit-testable.
|
|
15
16
|
*/
|
|
16
17
|
/** Sentinel slot appended once a batch finishes, so waiting regions know it is complete. */
|
|
17
18
|
const STREAM_DONE_SLOT = "__ogygia_done__";
|
|
@@ -33,4 +34,39 @@ function build_parcel(slot, html) {
|
|
|
33
34
|
function done_parcel() {
|
|
34
35
|
return `<template data-ogygia-slot="${STREAM_DONE_SLOT}"></template>`;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
const batch_def = machine()({
|
|
38
|
+
name: "batch stream",
|
|
39
|
+
initial: "streaming",
|
|
40
|
+
steps: {
|
|
41
|
+
streaming: ["ended", "cancelled"],
|
|
42
|
+
ended: [],
|
|
43
|
+
cancelled: []
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* The batch's frame stream: every call renders at once, and each answer goes out as its parcel the
|
|
48
|
+
* moment it settles, whatever the order; the done sentinel ends it. `render` is handed the batch's
|
|
49
|
+
* signal: it aborts when the stream is cancelled, or when `owner` (the request's) ends first.
|
|
50
|
+
*/
|
|
51
|
+
function batch_stream(calls, render, owner) {
|
|
52
|
+
const encoder = new TextEncoder();
|
|
53
|
+
const batch = batch_def.create();
|
|
54
|
+
owner?.defer(() => {
|
|
55
|
+
batch.move("streaming", "cancelled");
|
|
56
|
+
});
|
|
57
|
+
return new ReadableStream({
|
|
58
|
+
async start(controller) {
|
|
59
|
+
const streaming = batch.now;
|
|
60
|
+
if (await batch.scope.task((signal) => Promise.all(calls.map(async (endpoint) => {
|
|
61
|
+
const out = await render(endpoint, signal).catch(() => null);
|
|
62
|
+
if (out && batch.now === streaming) controller.enqueue(encoder.encode(build_parcel(out.slot, out.html)));
|
|
63
|
+
}))) === STALE || !batch.move("streaming", "ended")) return;
|
|
64
|
+
controller.enqueue(encoder.encode(done_parcel()));
|
|
65
|
+
controller.close();
|
|
66
|
+
},
|
|
67
|
+
cancel() {
|
|
68
|
+
batch.move("streaming", "cancelled");
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export { batch_stream, build_parcel, done_parcel };
|
package/dist/shared-state.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OgygiaError } from "./messages/island.js";
|
|
1
2
|
import { parse, stringify } from "devalue";
|
|
2
3
|
import { createSubscriber } from "svelte/reactivity";
|
|
3
4
|
// src/shared-state.ts
|
|
@@ -46,7 +47,10 @@ function snapshot(name, value) {
|
|
|
46
47
|
try {
|
|
47
48
|
return parse(stringify(value));
|
|
48
49
|
} catch (e) {
|
|
49
|
-
throw new
|
|
50
|
+
throw new OgygiaError("shared_state_not_plain", {
|
|
51
|
+
name,
|
|
52
|
+
reason: e instanceof Error ? e.message : String(e)
|
|
53
|
+
});
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
var SharedState = class {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { kit_bridge } from "./kit-bridge.js";
|
|
2
2
|
import { refresh_remote_instances } from "./kit-remote/remote-cache.js";
|
|
3
3
|
import { bind_to_component } from "../runtime/nav-hooks.js";
|
|
4
|
+
import { OgygiaError } from "../messages/island.js";
|
|
4
5
|
// src/shims/app-navigation.ts
|
|
5
6
|
const kit = () => kit_bridge()?.navigation ?? null;
|
|
6
7
|
const og = () => globalThis[Symbol.for("ogygia.nav")] ?? null;
|
|
7
8
|
/** No runtime on this document at all (neither Kit's nor ogygia's): the browser navigates. */
|
|
8
9
|
function browser_goto(url, opts = {}) {
|
|
9
10
|
const target = new URL(url, location.href);
|
|
10
|
-
if (target.protocol !== "http:" && target.protocol !== "https:") throw new
|
|
11
|
-
if (target.origin !== location.origin && !opts.external) throw new
|
|
11
|
+
if (target.protocol !== "http:" && target.protocol !== "https:") throw new OgygiaError("goto_not_http");
|
|
12
|
+
if (target.origin !== location.origin && !opts.external) throw new OgygiaError("goto_cross_origin");
|
|
12
13
|
if (opts.replaceState) location.replace(target.href);
|
|
13
14
|
else location.assign(target.href);
|
|
14
15
|
return Promise.resolve();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { foreign_hydrate } from "../current-region.js";
|
|
2
|
+
import { warn } from "../messages/island.js";
|
|
2
3
|
// src/shims/page-store.svelte.ts
|
|
3
4
|
const FALLBACK = {
|
|
4
5
|
url: typeof location !== "undefined" ? new URL(location.href) : new URL("http://localhost/"),
|
|
@@ -32,7 +33,9 @@ var PageState = class {
|
|
|
32
33
|
this.state = s.state ?? {};
|
|
33
34
|
for (const fn of this.#subscribers) try {
|
|
34
35
|
fn();
|
|
35
|
-
} catch {
|
|
36
|
+
} catch (error) {
|
|
37
|
+
report_thrown(error);
|
|
38
|
+
}
|
|
36
39
|
}
|
|
37
40
|
reset() {
|
|
38
41
|
this.set({
|
|
@@ -51,6 +54,13 @@ var PageState = class {
|
|
|
51
54
|
return () => this.#subscribers.delete(fn);
|
|
52
55
|
}
|
|
53
56
|
};
|
|
57
|
+
/** report-thrown.ts's `report_thrown`, here in full: island-side code never imports a module the
|
|
58
|
+
* runtime's boot imports (runtime-boot-svelte-free.test.ts), and the boot's ref watchers use it. */
|
|
59
|
+
function report_thrown(error) {
|
|
60
|
+
const report = globalThis.reportError;
|
|
61
|
+
if (typeof report === "function") report(error);
|
|
62
|
+
else console.error(error);
|
|
63
|
+
}
|
|
54
64
|
const PAGE_STATE_KEY = Symbol.for("ogygia.page-state");
|
|
55
65
|
const global_scope = globalThis;
|
|
56
66
|
const page_state = global_scope[PAGE_STATE_KEY] ??= new PageState();
|
|
@@ -72,6 +82,10 @@ function warn_foreign_page_read(expr) {
|
|
|
72
82
|
const f = foreign_hydrate();
|
|
73
83
|
if (!f || warned_foreign_entries.has(f.entry)) return;
|
|
74
84
|
warned_foreign_entries.add(f.entry);
|
|
75
|
-
|
|
85
|
+
warn("foreign_page_read", {
|
|
86
|
+
expr,
|
|
87
|
+
entry: f.entry,
|
|
88
|
+
origin: f.origin
|
|
89
|
+
});
|
|
76
90
|
}
|
|
77
91
|
export { PageState, page_state, reset_page, set_page, subscribe_page, warn_foreign_page_read };
|
package/dist/source.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fnv1a } from "./runtime/hash.js";
|
|
2
|
+
import { report_thrown } from "./report-thrown.js";
|
|
2
3
|
// src/source.ts
|
|
3
4
|
/**
|
|
4
5
|
* DATA SOURCES — `import.meta.og.source(fn)`, the RUNTIME half (the compiler rewrites the macro to
|
|
@@ -29,10 +30,14 @@ function set_source_observer(fn) {
|
|
|
29
30
|
function record_source_read(tag) {
|
|
30
31
|
try {
|
|
31
32
|
slots.recorder?.(tag);
|
|
32
|
-
} catch {
|
|
33
|
+
} catch (error) {
|
|
34
|
+
report_thrown(error);
|
|
35
|
+
}
|
|
33
36
|
try {
|
|
34
37
|
slots.observer?.(tag);
|
|
35
|
-
} catch {
|
|
38
|
+
} catch (error) {
|
|
39
|
+
report_thrown(error);
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
42
|
/** The identity stamp — read by `postrender.invalidate(fn, args)`. */
|
|
38
43
|
const SOURCE_ID = Symbol.for("ogygia.source.id");
|
package/dist/store-transport.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { wire } from "./live-transport.js";
|
|
2
2
|
import { mint, register_kind, resolve } from "./ref.js";
|
|
3
|
+
import { OgygiaError, warn } from "./messages/island.js";
|
|
3
4
|
import { derived, get, writable } from "svelte/store";
|
|
4
5
|
// src/store-transport.ts
|
|
5
6
|
/**
|
|
@@ -81,7 +82,7 @@ function mark_store(store, tag) {
|
|
|
81
82
|
enumerable: false
|
|
82
83
|
});
|
|
83
84
|
} catch {
|
|
84
|
-
if (typeof console !== "undefined")
|
|
85
|
+
if (typeof console !== "undefined") warn("store_not_extensible", { tag });
|
|
85
86
|
}
|
|
86
87
|
return store;
|
|
87
88
|
}
|
|
@@ -100,12 +101,15 @@ function register_store_kind() {
|
|
|
100
101
|
const t = ref.t ?? GENERIC_TAG;
|
|
101
102
|
const factory = t === GENERIC_TAG ? void 0 : store_registry().factories.get(t);
|
|
102
103
|
if (t !== GENERIC_TAG && factory === void 0) {
|
|
103
|
-
if (typeof console !== "undefined")
|
|
104
|
+
if (typeof console !== "undefined") warn("store_factory_missing", { tag: t });
|
|
104
105
|
return writable(ref.d);
|
|
105
106
|
}
|
|
106
107
|
const built = factory ? factory(ref.d) : writable(ref.d);
|
|
107
108
|
if (built === null || typeof built !== "object") {
|
|
108
|
-
if (typeof console !== "undefined")
|
|
109
|
+
if (typeof console !== "undefined") warn("store_factory_bad_rebuild", {
|
|
110
|
+
tag: t,
|
|
111
|
+
got: type_of(built)
|
|
112
|
+
});
|
|
109
113
|
return writable(ref.d);
|
|
110
114
|
}
|
|
111
115
|
return built;
|
|
@@ -160,7 +164,10 @@ function __og_store(tag, factory) {
|
|
|
160
164
|
if (product === null || typeof product !== "object") {
|
|
161
165
|
if (!warned_unbranded.has(tag) && typeof console !== "undefined") {
|
|
162
166
|
warned_unbranded.add(tag);
|
|
163
|
-
|
|
167
|
+
warn("store_factory_unbranded", {
|
|
168
|
+
tag,
|
|
169
|
+
got: type_of(product)
|
|
170
|
+
});
|
|
164
171
|
}
|
|
165
172
|
return product;
|
|
166
173
|
}
|
|
@@ -221,7 +228,7 @@ function register_derived_kind() {
|
|
|
221
228
|
},
|
|
222
229
|
decode(ref) {
|
|
223
230
|
const d = ref.d;
|
|
224
|
-
if (typeof d.f !== "function") throw new
|
|
231
|
+
if (typeof d.f !== "function") throw new OgygiaError("og_derived_formula_missing");
|
|
225
232
|
return og_derived(d.single ? d.s[0] : d.s, d.f, d.seed);
|
|
226
233
|
}
|
|
227
234
|
});
|
package/dist/transport.js
CHANGED
|
@@ -6,6 +6,7 @@ import { register_wire_kind } from "./live-transport.js";
|
|
|
6
6
|
import { register_derived_kind, register_store_kind } from "./store-transport.js";
|
|
7
7
|
import { register_snippet_kind } from "./region-snippet.js";
|
|
8
8
|
import { register_fn_kind } from "./fn-transport.js";
|
|
9
|
+
import { OgygiaError } from "./messages/island.js";
|
|
9
10
|
// src/transport.ts
|
|
10
11
|
/**
|
|
11
12
|
* `ogygiaTransport` — the SvelteKit `transport` entry that lets a held region cross the wire.
|
|
@@ -38,7 +39,7 @@ function encode_region(value) {
|
|
|
38
39
|
return pack(f.id, props, sign(f.id, props), f.module, f.hydrate, f.hydrateMargin, f.html);
|
|
39
40
|
}
|
|
40
41
|
if (typeof f.html === "string") return pack("", f.props ?? {}, "", "", void 0, void 0, f.html);
|
|
41
|
-
throw new
|
|
42
|
+
throw new OgygiaError("held_region_plain_import");
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
/** The region DECODE law (single-flight frame write for baked HTML + deferred rebuild),
|
|
@@ -88,7 +89,7 @@ function register_region_kind() {
|
|
|
88
89
|
},
|
|
89
90
|
encode(value) {
|
|
90
91
|
const packed = encode_region(value);
|
|
91
|
-
if (packed === false) throw new
|
|
92
|
+
if (packed === false) throw new OgygiaError("region_kind_mismatch");
|
|
92
93
|
return { d: packed };
|
|
93
94
|
},
|
|
94
95
|
decode(ref) {
|
package/dist/vite/index.js
CHANGED
|
@@ -4,8 +4,8 @@ import { island_sourcemaps_plugin } from "./sourcemaps.js";
|
|
|
4
4
|
import { server_sourcemaps_plugin } from "./server-sourcemaps.js";
|
|
5
5
|
import { install_dev_client_maps, install_dev_maps, install_dev_page_keys } from "./dev-maps.js";
|
|
6
6
|
import { CLIENT_BINDING_STUB, DEFAULT_IMPORT_KEYS, asRegionLocals, import_keys_hint, is_island_path, islandChunkFileName, islandId, islandPublicUrl, normalize_import_keys, wrapperVirtualId } from "../compiler/region/transform.js";
|
|
7
|
-
import { regionId, regionIdentity, strategyKey } from "../compiler/region/identity.js";
|
|
8
7
|
import { rewrite_lake_import_to_placeholder } from "../compiler/region/emit.js";
|
|
8
|
+
import { regionId, regionIdentity, strategyKey } from "../compiler/region/identity.js";
|
|
9
9
|
import { debarrel } from "../compiler/debarrel/plugin.js";
|
|
10
10
|
import { definePlugin, find_plugins, resolve_plugins } from "./plugin-api.js";
|
|
11
11
|
import { assert_no_legacy_options, resolve_options, validate_region_presets } from "./options.js";
|
|
@@ -34,7 +34,8 @@ import { async_twin_redirect, svelte_async_enabled } from "./late-island.js";
|
|
|
34
34
|
import { flags_manifest } from "../compiler/flags.js";
|
|
35
35
|
import { RESOLVED, V_ROUTER_CSS, V_ROUTE_CONFIG, V_ROUTE_CSR, V_SERVER_ISLANDS, V_SERVER_MANIFEST } from "../compiler/ids.js";
|
|
36
36
|
import { OWN_PACKAGE_NAMES, is_own_specifier } from "../own-package.js";
|
|
37
|
-
import { APP_SHIMS, CLIENT_BINDING_STUB_FILE, HMAC_MODULE, KIT_REMOTE_CLIENT, KIT_REMOTE_STATE, OGYGIA_INJECTED_FILES, OGYGIA_INJECTED_IMPORTS, OGYGIA_REGION_MODULES, PKG_ROOT, PKG_ROOT_ID, REGION_ENDPOINT_MODULE, RUNTIME_DIR, RUNTIME_HASH, STUB_CLIENT, STUB_PATHS, STUB_STATE, real_posix, scan_entry_pattern } from "./paths.js";
|
|
37
|
+
import { APP_SHIMS, CLIENT_BINDING_STUB_FILE, HMAC_MODULE, KIT_REMOTE_CLIENT, KIT_REMOTE_STATE, OGYGIA_INJECTED_FILES, OGYGIA_INJECTED_IMPORTS, OGYGIA_REGION_MODULES, OGYGIA_VERSION, PKG_ROOT, PKG_ROOT_ID, REGION_ENDPOINT_MODULE, RUNTIME_DIR, RUNTIME_HASH, STUB_CLIENT, STUB_PATHS, STUB_STATE, real_posix, scan_entry_pattern } from "./paths.js";
|
|
38
|
+
import { OgygiaError, line, warn } from "../messages/build.js";
|
|
38
39
|
import crypto from "node:crypto";
|
|
39
40
|
import fs from "node:fs";
|
|
40
41
|
import path from "node:path";
|
|
@@ -44,6 +45,7 @@ import { loadEnv } from "vite";
|
|
|
44
45
|
const KIT_CLIENT_APP_RE = /\/generated\/(?:build\/|dev\/)?client(-optimized)?\/app\.js$/;
|
|
45
46
|
const ROUTE_HOST_OR_OPTION_RE = /[\\/]\+(page|layout)(\.server)?\.(svelte|js|ts)$/;
|
|
46
47
|
const KIT_PAGE_THREAD = "\nimport { page as __og_kit_page, navigating as __og_kit_nav } from '$app/state';\nimport * as __og_kit_navigation from '$app/navigation';\nglobalThis[Symbol.for('ogygia.kit-page')] = { page: __og_kit_page, navigating: __og_kit_nav, navigation: __og_kit_navigation };\n";
|
|
48
|
+
const KIT_DISCLOSE_VERSION = `((globalThis.__ogygia ??= {}).v ??= new Set()).add(${JSON.stringify(OGYGIA_VERSION)});\n`;
|
|
47
49
|
/** css-ish file the dev bridge manages (mirrors the bridge's glob). */
|
|
48
50
|
const DEV_CSS_FILE_RE = /\.(css|scss|sass|less|styl)$/;
|
|
49
51
|
const CSS_EXT_RE = /\.css$/;
|
|
@@ -290,9 +292,11 @@ function ogygia(options = {}) {
|
|
|
290
292
|
__OGYGIA_SERVER_DELTA__: JSON.stringify(server_delta),
|
|
291
293
|
__OGYGIA_DEVTOOLS__: JSON.stringify(devtools_effective),
|
|
292
294
|
__OGYGIA_DEVTOOLS_LAZY__: JSON.stringify(devtools_lazy),
|
|
295
|
+
__OGYGIA_RULES__: JSON.stringify(process.env.OGYGIA_RULES === "1"),
|
|
293
296
|
__OGYGIA_BEACON__: JSON.stringify(measure || devtools_effective),
|
|
294
297
|
__OGYGIA_CLIENT_PLUGINS__: JSON.stringify(client_plugins.length > 0),
|
|
295
|
-
__OGYGIA_KIT_MAJOR__: JSON.stringify(kit_major(path.resolve(userConfig.root ?? ".")))
|
|
298
|
+
__OGYGIA_KIT_MAJOR__: JSON.stringify(kit_major(path.resolve(userConfig.root ?? "."))),
|
|
299
|
+
__OGYGIA_VERSION__: JSON.stringify(OGYGIA_VERSION)
|
|
296
300
|
},
|
|
297
301
|
server: { fs: { allow: [PKG_ROOT] } },
|
|
298
302
|
build: { rolldownOptions: { preserveEntrySignatures: "exports-only" } }
|
|
@@ -305,7 +309,10 @@ function ogygia(options = {}) {
|
|
|
305
309
|
svelte_async = svelte_async_enabled(config.plugins);
|
|
306
310
|
if (config.command === "serve") {
|
|
307
311
|
const own = (config.optimizeDeps?.include ?? []).filter((d) => is_own_specifier(d));
|
|
308
|
-
if (own.length) config.logger.warn(
|
|
312
|
+
if (own.length) config.logger.warn(line("optimize_deps_includes_ogygia", {
|
|
313
|
+
specifiers: own.join(", "),
|
|
314
|
+
count: own.length
|
|
315
|
+
}));
|
|
309
316
|
}
|
|
310
317
|
const app_dir_define = config.define?.["__SVELTEKIT_APP_DIR__"];
|
|
311
318
|
if (typeof app_dir_define === "string") try {
|
|
@@ -338,7 +345,7 @@ function ogygia(options = {}) {
|
|
|
338
345
|
}
|
|
339
346
|
const env_secret = process.env.OGYGIA_SECRET?.trim() || "";
|
|
340
347
|
if (env_secret) {
|
|
341
|
-
if (is_build && !secret_has_min_entropy(env_secret)) throw new
|
|
348
|
+
if (is_build && !secret_has_min_entropy(env_secret)) throw new OgygiaError("secret_too_short", { min_bytes: 16 });
|
|
342
349
|
id_salt = derive_id_salt(env_secret);
|
|
343
350
|
} else id_salt = "";
|
|
344
351
|
({kit_wire_path, kit_remote_index, universal_hooks, client_hooks, kit_transport_init} = resolve_kit_paths(root));
|
|
@@ -418,7 +425,7 @@ function ogygia(options = {}) {
|
|
|
418
425
|
emitRuntime: emit_runtime,
|
|
419
426
|
loaded
|
|
420
427
|
});
|
|
421
|
-
if (skipped && isMainThread) console.log(
|
|
428
|
+
if (skipped && isMainThread) console.log(line("island_chunks_not_emitted", { count: skipped }));
|
|
422
429
|
compiled_css.clear();
|
|
423
430
|
const tree_css = tree_css_walk(this);
|
|
424
431
|
router_css_refs.clear();
|
|
@@ -504,7 +511,7 @@ function ogygia(options = {}) {
|
|
|
504
511
|
fs.mkdirSync(path.dirname(handoff), { recursive: true });
|
|
505
512
|
fs.writeFileSync(handoff, JSON.stringify(compiler.ssr_transformed_hosts()));
|
|
506
513
|
} catch (e) {
|
|
507
|
-
if (isMainThread)
|
|
514
|
+
if (isMainThread) warn("island_handoff_write_failed", e);
|
|
508
515
|
}
|
|
509
516
|
if (__P) {
|
|
510
517
|
const keys = [...__outHash.keys()].sort();
|
|
@@ -571,7 +578,7 @@ function ogygia(options = {}) {
|
|
|
571
578
|
}
|
|
572
579
|
const ssr = options?.ssr === true;
|
|
573
580
|
if (!ssr && source === "__sveltekit/remote") {
|
|
574
|
-
if (!kit_remote_index) throw new
|
|
581
|
+
if (!kit_remote_index) throw new OgygiaError("kit_remote_src_missing");
|
|
575
582
|
return kit_remote_index;
|
|
576
583
|
}
|
|
577
584
|
if (!ssr && importer && importer.includes("/remote-functions/")) {
|
|
@@ -641,7 +648,7 @@ function ogygia(options = {}) {
|
|
|
641
648
|
},
|
|
642
649
|
async transform(code, id, options) {
|
|
643
650
|
let source = code;
|
|
644
|
-
if (!options?.ssr && KIT_CLIENT_APP_RE.test(id)) source += KIT_PAGE_THREAD;
|
|
651
|
+
if (!options?.ssr && KIT_CLIENT_APP_RE.test(id)) source += KIT_PAGE_THREAD + KIT_DISCLOSE_VERSION;
|
|
645
652
|
const result = await compiler.transform_module(source, id, {
|
|
646
653
|
ssr: options?.ssr === true,
|
|
647
654
|
emitFile: (chunk) => this.emitFile(chunk)
|
|
@@ -739,7 +746,7 @@ function ogygia(options = {}) {
|
|
|
739
746
|
fs.mkdirSync(dir, { recursive: true });
|
|
740
747
|
const manifest = flags_manifest(program.flag_sites);
|
|
741
748
|
fs.writeFileSync(path.join(dir, "flags-manifest.json"), JSON.stringify(manifest, null, " ") + "\n");
|
|
742
|
-
console.log(
|
|
749
|
+
console.log(line("flags_manifest_written", { count: manifest.names.length }));
|
|
743
750
|
} catch {}
|
|
744
751
|
await follow_pending_page_calls(program, (s, importer) => this.resolve(s, importer));
|
|
745
752
|
const remote_hash = (id) => remote_hash_of(id, process.cwd());
|
package/dist/vite/kit-dirs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_KIT_DIRS, set_kit_dirs, set_kit_inline_style_threshold } from "../compiler/kit.js";
|
|
2
|
+
import { warn } from "../messages/build.js";
|
|
2
3
|
import { existsSync } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { pathToFileURL } from "node:url";
|
|
@@ -47,7 +48,12 @@ async function kit_options_from_file(root) {
|
|
|
47
48
|
try {
|
|
48
49
|
return (await import(pathToFileURL(file).href)).default?.kit ?? {};
|
|
49
50
|
} catch (e) {
|
|
50
|
-
|
|
51
|
+
warn("kit_config_unreadable", {
|
|
52
|
+
file: path.relative(root, file),
|
|
53
|
+
routes: DEFAULT_KIT_DIRS.routes,
|
|
54
|
+
out: DEFAULT_KIT_DIRS.out,
|
|
55
|
+
reason: e instanceof Error ? e.message : String(e)
|
|
56
|
+
});
|
|
51
57
|
return null;
|
|
52
58
|
}
|
|
53
59
|
}
|
package/dist/vite/options.d.ts
CHANGED
|
@@ -178,7 +178,8 @@ export interface OgygiaOptions {
|
|
|
178
178
|
*/
|
|
179
179
|
standalone?: boolean;
|
|
180
180
|
}
|
|
181
|
-
/** The rename map: a legacy key errors with its new
|
|
181
|
+
/** The rename map (`RETIRED_OPTIONS`, with the messages): a legacy key errors with its new
|
|
182
|
+
* spelling, never silently no-ops. */
|
|
182
183
|
export declare function assert_no_legacy_options(options: OgygiaOptions): void;
|
|
183
184
|
/**
|
|
184
185
|
* Config-time region-preset validation — the transform re-checks on USE (with file/line context), but
|
package/dist/vite/options.js
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
|
+
import { OgygiaError, RETIRED_OPTIONS } from "../messages/build.js";
|
|
1
2
|
// src/vite/options.ts
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* rename map, never silent aliasing (a legacy key that silently did nothing would un-tune real apps).
|
|
5
|
-
*/
|
|
6
|
-
const LEGACY_OPTION_RENAMES = {
|
|
7
|
-
regions: "`regions` is gone — its keys sit at the root now: write `visible`, `presets`, `ttl` and `maxPageAge` directly in `ogygia({ … })`.",
|
|
8
|
-
continuity: "`continuity` is gone — form continuity rides the router. Write `router: { forms: false }` to disable it.",
|
|
9
|
-
regionTtl: "`regionTtl` is `ttl` now — write `ogygia({ ttl: … })`.",
|
|
10
|
-
preload: "`preload` is gone — there is nothing to choose any more. The page carries each island’s chunk list as data, and the runtime preloads an island’s whole graph when it wakes (after the page has painted), so no island code moves before its wake and none waits on a waterfall after it. Remove the key.",
|
|
11
|
-
plugins: "`plugins` is gone — ogygia plugins are Vite plugins: list them beside `ogygia()` in vite.config, `plugins: [ogygia(), flags(), sveltekit()]`.",
|
|
12
|
-
freeze: "`freeze` is a plugin now, named postrender — install `@ogygia/postrender` and list `postrender({ ttl, default })` (from `@ogygia/postrender/vite`) beside `ogygia()` in vite.config `plugins`.",
|
|
13
|
-
content: "`content` is a plugin now — install `@ogygia/content` and list `content({ markdown, presets })` (from `@ogygia/content/vite`) beside `ogygia()` in vite.config `plugins`; the svelte config takes `preprocess()` / `extensions()` from there too.",
|
|
14
|
-
devtools: "`devtools` is a plugin now — install `@ogygia/devtools` and list `devtools()` (from `@ogygia/devtools/vite`) beside `ogygia()` in vite.config `plugins`; only where you want it, e.g. `...(mode !== 'production' ? [devtools()] : [])`.",
|
|
15
|
-
profiler: "`profiler` is part of the devtools plugin now — install `@ogygia/devtools` and list `devtools({ profiler: { … } })` (from `@ogygia/devtools/vite`) beside `ogygia()` in vite.config `plugins`."
|
|
16
|
-
};
|
|
17
|
-
/** The rename map: a legacy key errors with its new spelling, never silently no-ops. */
|
|
3
|
+
/** The rename map (`RETIRED_OPTIONS`, with the messages): a legacy key errors with its new
|
|
4
|
+
* spelling, never silently no-ops. */
|
|
18
5
|
function assert_no_legacy_options(options) {
|
|
19
|
-
for (const key of Object.keys(
|
|
6
|
+
for (const key of Object.keys(RETIRED_OPTIONS)) if (key in options) throw new OgygiaError("option_retired", { option: key });
|
|
20
7
|
}
|
|
21
8
|
const REGION_PRESET_KEYS = /* @__PURE__ */ new Set([
|
|
22
9
|
"render",
|
|
@@ -36,8 +23,12 @@ const REGION_PRESET_KEYS = /* @__PURE__ */ new Set([
|
|
|
36
23
|
*/
|
|
37
24
|
function validate_region_presets(presets) {
|
|
38
25
|
for (const [name, bag] of Object.entries(presets)) {
|
|
39
|
-
if (!bag || typeof bag !== "object" || Object.keys(bag).length === 0) throw new
|
|
40
|
-
for (const k of Object.keys(bag)) if (!REGION_PRESET_KEYS.has(k)) throw new
|
|
26
|
+
if (!bag || typeof bag !== "object" || Object.keys(bag).length === 0) throw new OgygiaError("preset_empty", { name });
|
|
27
|
+
for (const k of Object.keys(bag)) if (!REGION_PRESET_KEYS.has(k)) throw new OgygiaError("preset_key_unknown", {
|
|
28
|
+
name,
|
|
29
|
+
key: k,
|
|
30
|
+
allowed: [...REGION_PRESET_KEYS].join(", ")
|
|
31
|
+
});
|
|
41
32
|
}
|
|
42
33
|
}
|
|
43
34
|
/**
|
|
@@ -57,7 +48,7 @@ function resolve_options(options, defaultRegionTtl, defaultRenewWindow = 691200)
|
|
|
57
48
|
const session_cookie = typeof options.sessionCookie === "string" && options.sessionCookie.length > 0 ? options.sessionCookie : "";
|
|
58
49
|
const region_ttl = Math.min(86400, Math.max(60, Math.floor(options.ttl ?? defaultRegionTtl)));
|
|
59
50
|
const renew_raw = options.maxPageAge;
|
|
60
|
-
if (renew_raw !== void 0 && !(typeof renew_raw === "number" && Number.isFinite(renew_raw) && renew_raw >= 0)) throw new
|
|
51
|
+
if (renew_raw !== void 0 && !(typeof renew_raw === "number" && Number.isFinite(renew_raw) && renew_raw >= 0)) throw new OgygiaError("max_page_age_invalid", { value: String(renew_raw) });
|
|
61
52
|
const renew_window = Math.min(31536e4, Math.floor(renew_raw ?? defaultRenewWindow));
|
|
62
53
|
const router_enabled = options.router !== false;
|
|
63
54
|
return {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { OWN_PACKAGE_NAMES } from "../own-package.js";
|
|
2
|
+
import { OgygiaError, warn } from "../messages/build.js";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { globSync } from "tinyglobby";
|
|
@@ -37,7 +38,10 @@ function discover_package_files(app_root) {
|
|
|
37
38
|
const pkg_dir = path.join(app_root, "node_modules", ...name.split("/"));
|
|
38
39
|
const declared = (read_manifest(pkg_dir)?.ogygia)?.files;
|
|
39
40
|
if (declared == null) continue;
|
|
40
|
-
if (!Array.isArray(declared) || !declared.every((p) => typeof p === "string")) throw new
|
|
41
|
+
if (!Array.isArray(declared) || !declared.every((p) => typeof p === "string")) throw new OgygiaError("package_files_not_array", {
|
|
42
|
+
package: name,
|
|
43
|
+
got: JSON.stringify(declared)
|
|
44
|
+
});
|
|
41
45
|
let root;
|
|
42
46
|
try {
|
|
43
47
|
root = fs.realpathSync(pkg_dir);
|
|
@@ -61,12 +65,18 @@ function discover_package_files(app_root) {
|
|
|
61
65
|
continue;
|
|
62
66
|
}
|
|
63
67
|
const abs = path.resolve(root, entry);
|
|
64
|
-
if (abs !== root && !abs.startsWith(root + path.sep)) throw new
|
|
68
|
+
if (abs !== root && !abs.startsWith(root + path.sep)) throw new OgygiaError("package_files_escapes", {
|
|
69
|
+
package: name,
|
|
70
|
+
entry
|
|
71
|
+
});
|
|
65
72
|
let stat;
|
|
66
73
|
try {
|
|
67
74
|
stat = fs.statSync(abs);
|
|
68
75
|
} catch {
|
|
69
|
-
|
|
76
|
+
warn("package_files_missing", {
|
|
77
|
+
package: name,
|
|
78
|
+
entry
|
|
79
|
+
});
|
|
70
80
|
continue;
|
|
71
81
|
}
|
|
72
82
|
if (stat.isDirectory()) dirs.push(posix(fs.realpathSync(abs)));
|