@sveltejs/kit 2.3.5 → 2.4.1
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/package.json +1 -1
- package/src/core/adapt/builder.js +8 -0
- package/src/core/generate_manifest/find_server_assets.js +52 -0
- package/src/core/generate_manifest/index.js +22 -4
- package/src/core/postbuild/analyse.js +68 -17
- package/src/core/postbuild/prerender.js +5 -1
- package/src/core/sync/create_manifest_data/index.js +19 -1
- package/src/core/sync/write_server.js +2 -1
- package/src/exports/node/index.js +12 -0
- package/src/exports/public.d.ts +21 -0
- package/src/exports/vite/build/utils.js +7 -5
- package/src/exports/vite/dev/index.js +27 -3
- package/src/exports/vite/graph_analysis/index.js +6 -2
- package/src/exports/vite/index.js +44 -3
- package/src/exports/vite/module_ids.js +10 -1
- package/src/exports/vite/preview/index.js +3 -2
- package/src/runtime/app/server/index.js +70 -0
- package/src/runtime/client/client.js +2 -4
- package/src/runtime/client/fetcher.js +1 -16
- package/src/runtime/server/index.js +10 -2
- package/src/runtime/server/page/index.js +2 -5
- package/src/runtime/server/page/load_data.js +1 -19
- package/src/runtime/server/page/load_page_nodes.js +11 -0
- package/src/runtime/server/respond.js +22 -5
- package/src/runtime/utils.js +34 -0
- package/src/types/ambient-private.d.ts +10 -0
- package/src/types/global-private.d.ts +15 -0
- package/src/types/internal.d.ts +15 -1
- package/src/utils/features.js +24 -0
- package/src/utils/route_config.js +20 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +48 -0
- package/types/index.d.ts.map +5 -1
|
@@ -31,7 +31,8 @@ import {
|
|
|
31
31
|
env_static_public,
|
|
32
32
|
service_worker,
|
|
33
33
|
sveltekit_environment,
|
|
34
|
-
sveltekit_paths
|
|
34
|
+
sveltekit_paths,
|
|
35
|
+
sveltekit_server
|
|
35
36
|
} from './module_ids.js';
|
|
36
37
|
import { pathToFileURL } from 'node:url';
|
|
37
38
|
|
|
@@ -224,6 +225,13 @@ async function kit({ svelte_config }) {
|
|
|
224
225
|
const service_worker_entry_file = resolve_entry(kit.files.serviceWorker);
|
|
225
226
|
const parsed_service_worker = path.parse(kit.files.serviceWorker);
|
|
226
227
|
|
|
228
|
+
/**
|
|
229
|
+
* A map showing which features (such as `$app/server:read`) are defined
|
|
230
|
+
* in which chunks, so that we can later determine which routes use which features
|
|
231
|
+
* @type {Record<string, string[]>}
|
|
232
|
+
*/
|
|
233
|
+
const tracked_features = {};
|
|
234
|
+
|
|
227
235
|
const sourcemapIgnoreList = /** @param {string} relative_path */ (relative_path) =>
|
|
228
236
|
relative_path.includes('node_modules') || relative_path.includes(kit.outDir);
|
|
229
237
|
|
|
@@ -492,13 +500,29 @@ async function kit({ svelte_config }) {
|
|
|
492
500
|
}
|
|
493
501
|
`;
|
|
494
502
|
}
|
|
503
|
+
|
|
504
|
+
case sveltekit_server: {
|
|
505
|
+
return dedent`
|
|
506
|
+
export let read_implementation = null;
|
|
507
|
+
|
|
508
|
+
export let manifest = null;
|
|
509
|
+
|
|
510
|
+
export function set_read_implementation(fn) {
|
|
511
|
+
read_implementation = fn;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export function set_manifest(_) {
|
|
515
|
+
manifest = _;
|
|
516
|
+
}
|
|
517
|
+
`;
|
|
518
|
+
}
|
|
495
519
|
}
|
|
496
520
|
}
|
|
497
521
|
};
|
|
498
522
|
|
|
499
523
|
/**
|
|
500
524
|
* Ensures that client-side code can't accidentally import server-side code,
|
|
501
|
-
* whether in `*.server.js` files, `$lib/server`, or `$env/[static|dynamic]/private`
|
|
525
|
+
* whether in `*.server.js` files, `$app/server`, `$lib/server`, or `$env/[static|dynamic]/private`
|
|
502
526
|
* @type {import('vite').Plugin}
|
|
503
527
|
*/
|
|
504
528
|
const plugin_guard = {
|
|
@@ -621,7 +645,7 @@ async function kit({ svelte_config }) {
|
|
|
621
645
|
preserveEntrySignatures: 'strict'
|
|
622
646
|
},
|
|
623
647
|
ssrEmitAssets: true,
|
|
624
|
-
target: ssr ? 'node18.13' :
|
|
648
|
+
target: ssr ? 'node18.13' : undefined
|
|
625
649
|
},
|
|
626
650
|
publicDir: kit.files.assets,
|
|
627
651
|
worker: {
|
|
@@ -685,6 +709,19 @@ async function kit({ svelte_config }) {
|
|
|
685
709
|
}
|
|
686
710
|
},
|
|
687
711
|
|
|
712
|
+
renderChunk(code, chunk) {
|
|
713
|
+
if (code.includes('__SVELTEKIT_TRACK__')) {
|
|
714
|
+
return {
|
|
715
|
+
code: code.replace(/__SVELTEKIT_TRACK__\('(.+?)'\)/g, (_, label) => {
|
|
716
|
+
(tracked_features[chunk.name + '.js'] ??= []).push(label);
|
|
717
|
+
// put extra whitespace at the end of the comment to preserve the source size and avoid interfering with source maps
|
|
718
|
+
return `/* track ${label} */`;
|
|
719
|
+
}),
|
|
720
|
+
map: null // TODO we may need to generate a sourcemap in future
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
|
|
688
725
|
generateBundle() {
|
|
689
726
|
if (vite_config.build.ssr) return;
|
|
690
727
|
|
|
@@ -716,6 +753,7 @@ async function kit({ svelte_config }) {
|
|
|
716
753
|
app_dir: kit.appDir,
|
|
717
754
|
app_path: `${kit.paths.base.slice(1)}${kit.paths.base ? '/' : ''}${kit.appDir}`,
|
|
718
755
|
manifest_data,
|
|
756
|
+
out_dir: out,
|
|
719
757
|
service_worker: service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable?
|
|
720
758
|
client: null,
|
|
721
759
|
server_manifest
|
|
@@ -738,6 +776,9 @@ async function kit({ svelte_config }) {
|
|
|
738
776
|
|
|
739
777
|
const metadata = await analyse({
|
|
740
778
|
manifest_path,
|
|
779
|
+
manifest_data,
|
|
780
|
+
server_manifest,
|
|
781
|
+
tracked_features,
|
|
741
782
|
env: { ...env.private, ...env.public }
|
|
742
783
|
});
|
|
743
784
|
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
|
|
1
3
|
export const env_static_private = '\0virtual:$env/static/private';
|
|
2
4
|
export const env_static_public = '\0virtual:$env/static/public';
|
|
3
5
|
export const env_dynamic_private = '\0virtual:$env/dynamic/private';
|
|
4
6
|
export const env_dynamic_public = '\0virtual:$env/dynamic/public';
|
|
7
|
+
|
|
5
8
|
export const service_worker = '\0virtual:$service-worker';
|
|
6
|
-
|
|
9
|
+
|
|
7
10
|
export const sveltekit_environment = '\0virtual:__sveltekit/environment';
|
|
11
|
+
export const sveltekit_paths = '\0virtual:__sveltekit/paths';
|
|
12
|
+
export const sveltekit_server = '\0virtual:__sveltekit/server';
|
|
13
|
+
|
|
14
|
+
export const app_server = fileURLToPath(
|
|
15
|
+
new URL('../../runtime/app/server/index.js', import.meta.url)
|
|
16
|
+
);
|
|
@@ -4,7 +4,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
4
4
|
import { lookup } from 'mrmime';
|
|
5
5
|
import sirv from 'sirv';
|
|
6
6
|
import { loadEnv, normalizePath } from 'vite';
|
|
7
|
-
import { getRequest, setResponse } from '../../../exports/node/index.js';
|
|
7
|
+
import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js';
|
|
8
8
|
import { installPolyfills } from '../../../exports/node/polyfills.js';
|
|
9
9
|
import { SVELTE_KIT_ASSETS } from '../../../constants.js';
|
|
10
10
|
import { not_found } from '../utils.js';
|
|
@@ -47,7 +47,8 @@ export async function preview(vite, vite_config, svelte_config) {
|
|
|
47
47
|
|
|
48
48
|
const server = new Server(manifest);
|
|
49
49
|
await server.init({
|
|
50
|
-
env: loadEnv(vite_config.mode, svelte_config.kit.env.dir, '')
|
|
50
|
+
env: loadEnv(vite_config.mode, svelte_config.kit.env.dir, ''),
|
|
51
|
+
read: (file) => createReadableStream(`${dir}/${file}`)
|
|
51
52
|
});
|
|
52
53
|
|
|
53
54
|
return () => {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { read_implementation, manifest } from '__sveltekit/server';
|
|
2
|
+
import { base } from '__sveltekit/paths';
|
|
3
|
+
import { DEV } from 'esm-env';
|
|
4
|
+
import { b64_decode } from '../../utils.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Read the contents of an imported asset from the filesystem
|
|
8
|
+
* @example
|
|
9
|
+
* ```js
|
|
10
|
+
* import { read } from '$app/server';
|
|
11
|
+
* import somefile from './somefile.txt';
|
|
12
|
+
*
|
|
13
|
+
* const asset = read(somefile);
|
|
14
|
+
* const text = await asset.text();
|
|
15
|
+
* ```
|
|
16
|
+
* @param {string} asset
|
|
17
|
+
* @returns {Response}
|
|
18
|
+
* @since 2.4.0
|
|
19
|
+
*/
|
|
20
|
+
export function read(asset) {
|
|
21
|
+
__SVELTEKIT_TRACK__('$app/server:read');
|
|
22
|
+
|
|
23
|
+
if (!read_implementation) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
'No `read` implementation was provided. Please ensure that your adapter is up to date and supports this feature'
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// handle inline assets internally
|
|
30
|
+
if (asset.startsWith('data:')) {
|
|
31
|
+
const [prelude, data] = asset.split(';');
|
|
32
|
+
const type = prelude.slice(5) || 'application/octet-stream';
|
|
33
|
+
|
|
34
|
+
if (data.startsWith('base64,')) {
|
|
35
|
+
const decoded = b64_decode(data.slice(7));
|
|
36
|
+
|
|
37
|
+
return new Response(decoded, {
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Length': decoded.byteLength.toString(),
|
|
40
|
+
'Content-Type': type
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const decoded = decodeURIComponent(data);
|
|
46
|
+
|
|
47
|
+
return new Response(decoded, {
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Length': decoded.length.toString(),
|
|
50
|
+
'Content-Type': type
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const file = DEV && asset.startsWith('/@fs') ? asset : asset.slice(base.length + 1);
|
|
56
|
+
|
|
57
|
+
if (file in manifest._.server_assets) {
|
|
58
|
+
const length = manifest._.server_assets[file];
|
|
59
|
+
const type = manifest.mimeTypes[file.slice(file.lastIndexOf('.'))];
|
|
60
|
+
|
|
61
|
+
return new Response(read_implementation(file), {
|
|
62
|
+
headers: {
|
|
63
|
+
'Content-Length': '' + length,
|
|
64
|
+
'Content-Type': type
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
throw new Error(`Asset does not exist: ${file}`);
|
|
70
|
+
}
|
|
@@ -1330,7 +1330,7 @@ async function navigate({
|
|
|
1330
1330
|
fn(/** @type {import('@sveltejs/kit').OnNavigate} */ (nav.navigation))
|
|
1331
1331
|
)
|
|
1332
1332
|
)
|
|
1333
|
-
).filter((value) => typeof value === 'function');
|
|
1333
|
+
).filter(/** @returns {value is () => void} */ (value) => typeof value === 'function');
|
|
1334
1334
|
|
|
1335
1335
|
if (after_navigate.length > 0) {
|
|
1336
1336
|
function cleanup() {
|
|
@@ -1341,9 +1341,7 @@ async function navigate({
|
|
|
1341
1341
|
}
|
|
1342
1342
|
|
|
1343
1343
|
after_navigate.push(cleanup);
|
|
1344
|
-
|
|
1345
|
-
// @ts-ignore
|
|
1346
|
-
callbacks.after_navigate.push(...after_navigate);
|
|
1344
|
+
after_navigate_callbacks.push(...after_navigate);
|
|
1347
1345
|
}
|
|
1348
1346
|
|
|
1349
1347
|
root.$set(navigation_result.props);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BROWSER, DEV } from 'esm-env';
|
|
2
2
|
import { hash } from '../hash.js';
|
|
3
|
+
import { b64_decode } from '../utils.js';
|
|
3
4
|
|
|
4
5
|
let loading = 0;
|
|
5
6
|
|
|
@@ -77,22 +78,6 @@ if (DEV && BROWSER) {
|
|
|
77
78
|
|
|
78
79
|
const cache = new Map();
|
|
79
80
|
|
|
80
|
-
/**
|
|
81
|
-
* @param {string} text
|
|
82
|
-
* @returns {ArrayBufferLike}
|
|
83
|
-
*/
|
|
84
|
-
function b64_decode(text) {
|
|
85
|
-
const d = atob(text);
|
|
86
|
-
|
|
87
|
-
const u8 = new Uint8Array(d.length);
|
|
88
|
-
|
|
89
|
-
for (let i = 0; i < d.length; i++) {
|
|
90
|
-
u8[i] = d.charCodeAt(i);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return u8.buffer;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
81
|
/**
|
|
97
82
|
* Should be called on the initial run of load functions that hydrate the page.
|
|
98
83
|
* Saves any requests with cache-control max-age to the cache.
|
|
@@ -4,6 +4,7 @@ import { options, get_hooks } from '__SERVER__/internal.js';
|
|
|
4
4
|
import { DEV } from 'esm-env';
|
|
5
5
|
import { filter_private_env, filter_public_env } from '../../utils/env.js';
|
|
6
6
|
import { prerendering } from '__sveltekit/environment';
|
|
7
|
+
import { set_read_implementation, set_manifest } from '__sveltekit/server';
|
|
7
8
|
|
|
8
9
|
/** @type {ProxyHandler<{ type: 'public' | 'private' }>} */
|
|
9
10
|
const prerender_env_handler = {
|
|
@@ -26,14 +27,17 @@ export class Server {
|
|
|
26
27
|
/** @type {import('types').SSROptions} */
|
|
27
28
|
this.#options = options;
|
|
28
29
|
this.#manifest = manifest;
|
|
30
|
+
|
|
31
|
+
set_manifest(manifest);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
/**
|
|
32
35
|
* @param {{
|
|
33
|
-
* env: Record<string, string
|
|
36
|
+
* env: Record<string, string>;
|
|
37
|
+
* read?: (file: string) => ReadableStream;
|
|
34
38
|
* }} opts
|
|
35
39
|
*/
|
|
36
|
-
async init({ env }) {
|
|
40
|
+
async init({ env, read }) {
|
|
37
41
|
// Take care: Some adapters may have to call `Server.init` per-request to set env vars,
|
|
38
42
|
// so anything that shouldn't be rerun should be wrapped in an `if` block to make sure it hasn't
|
|
39
43
|
// been done already.
|
|
@@ -55,6 +59,10 @@ export class Server {
|
|
|
55
59
|
);
|
|
56
60
|
set_safe_public_env(public_env);
|
|
57
61
|
|
|
62
|
+
if (read) {
|
|
63
|
+
set_read_implementation(read);
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
if (!this.#options.hooks) {
|
|
59
67
|
try {
|
|
60
68
|
const module = await get_hooks();
|
|
@@ -15,6 +15,7 @@ import { render_response } from './render.js';
|
|
|
15
15
|
import { respond_with_error } from './respond_with_error.js';
|
|
16
16
|
import { get_option } from '../../../utils/options.js';
|
|
17
17
|
import { get_data_json } from '../data/index.js';
|
|
18
|
+
import { load_page_nodes } from './load_page_nodes.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* The maximum request depth permitted before assuming we're stuck in an infinite loop
|
|
@@ -44,11 +45,7 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
try {
|
|
47
|
-
const nodes = await
|
|
48
|
-
// we use == here rather than === because [undefined] serializes as "[null]"
|
|
49
|
-
...page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
|
|
50
|
-
manifest._.nodes[page.leaf]()
|
|
51
|
-
]);
|
|
48
|
+
const nodes = await load_page_nodes(page, manifest);
|
|
52
49
|
|
|
53
50
|
const leaf_node = /** @type {import('types').SSRNode} */ (nodes.at(-1));
|
|
54
51
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DEV } from 'esm-env';
|
|
2
2
|
import { disable_search, make_trackable } from '../../../utils/url.js';
|
|
3
3
|
import { validate_depends } from '../../shared.js';
|
|
4
|
+
import { b64_encode } from '../../utils.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Calls the user's server `load` function.
|
|
@@ -207,25 +208,6 @@ export async function load_data({
|
|
|
207
208
|
return result ?? null;
|
|
208
209
|
}
|
|
209
210
|
|
|
210
|
-
/**
|
|
211
|
-
* @param {ArrayBuffer} buffer
|
|
212
|
-
* @returns {string}
|
|
213
|
-
*/
|
|
214
|
-
function b64_encode(buffer) {
|
|
215
|
-
if (globalThis.Buffer) {
|
|
216
|
-
return Buffer.from(buffer).toString('base64');
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const little_endian = new Uint8Array(new Uint16Array([1]).buffer)[0] > 0;
|
|
220
|
-
|
|
221
|
-
// The Uint16Array(Uint8Array(...)) ensures the code points are padded with 0's
|
|
222
|
-
return btoa(
|
|
223
|
-
new TextDecoder(little_endian ? 'utf-16le' : 'utf-16be').decode(
|
|
224
|
-
new Uint16Array(new Uint8Array(buffer))
|
|
225
|
-
)
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
211
|
/**
|
|
230
212
|
* @param {Pick<import('@sveltejs/kit').RequestEvent, 'fetch' | 'url' | 'request' | 'route'>} event
|
|
231
213
|
* @param {import('types').SSRState} state
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {import('types').PageNodeIndexes} page
|
|
3
|
+
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
4
|
+
*/
|
|
5
|
+
export function load_page_nodes(page, manifest) {
|
|
6
|
+
return Promise.all([
|
|
7
|
+
// we use == here rather than === because [undefined] serializes as "[null]"
|
|
8
|
+
...page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
|
|
9
|
+
manifest._.nodes[page.leaf]()
|
|
10
|
+
]);
|
|
11
|
+
}
|
|
@@ -31,6 +31,8 @@ import { json, text } from '../../exports/index.js';
|
|
|
31
31
|
import { action_json_redirect, is_action_json_request } from './page/actions.js';
|
|
32
32
|
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
|
|
33
33
|
import { get_public_env } from './env_module.js';
|
|
34
|
+
import { load_page_nodes } from './page/load_page_nodes.js';
|
|
35
|
+
import { get_page_config } from '../../utils/route_config.js';
|
|
34
36
|
|
|
35
37
|
/* global __SVELTEKIT_ADAPTER_NAME__ */
|
|
36
38
|
|
|
@@ -217,11 +219,7 @@ export async function respond(request, options, manifest, state) {
|
|
|
217
219
|
if (url.pathname === base || url.pathname === base + '/') {
|
|
218
220
|
trailing_slash = 'always';
|
|
219
221
|
} else if (route.page) {
|
|
220
|
-
const nodes = await
|
|
221
|
-
// we use == here rather than === because [undefined] serializes as "[null]"
|
|
222
|
-
...route.page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
|
|
223
|
-
manifest._.nodes[route.page.leaf]()
|
|
224
|
-
]);
|
|
222
|
+
const nodes = await load_page_nodes(route.page, manifest);
|
|
225
223
|
|
|
226
224
|
if (DEV) {
|
|
227
225
|
const layouts = nodes.slice(0, -1);
|
|
@@ -272,6 +270,25 @@ export async function respond(request, options, manifest, state) {
|
|
|
272
270
|
});
|
|
273
271
|
}
|
|
274
272
|
}
|
|
273
|
+
|
|
274
|
+
if (DEV && state.before_handle) {
|
|
275
|
+
let config = {};
|
|
276
|
+
|
|
277
|
+
/** @type {import('types').PrerenderOption} */
|
|
278
|
+
let prerender = false;
|
|
279
|
+
|
|
280
|
+
if (route.endpoint) {
|
|
281
|
+
const node = await route.endpoint();
|
|
282
|
+
config = node.config ?? config;
|
|
283
|
+
prerender = node.prerender ?? prerender;
|
|
284
|
+
} else if (route.page) {
|
|
285
|
+
const nodes = await load_page_nodes(route.page, manifest);
|
|
286
|
+
config = get_page_config(nodes);
|
|
287
|
+
prerender = get_option(nodes, 'prerender') ?? false;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
state.before_handle(event, config, prerender);
|
|
291
|
+
}
|
|
275
292
|
}
|
|
276
293
|
|
|
277
294
|
const { cookies, new_cookies, get_cookie_header, set_internal } = get_cookies(
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} text
|
|
3
|
+
* @returns {ArrayBufferLike}
|
|
4
|
+
*/
|
|
5
|
+
export function b64_decode(text) {
|
|
6
|
+
const d = atob(text);
|
|
7
|
+
|
|
8
|
+
const u8 = new Uint8Array(d.length);
|
|
9
|
+
|
|
10
|
+
for (let i = 0; i < d.length; i++) {
|
|
11
|
+
u8[i] = d.charCodeAt(i);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return u8.buffer;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {ArrayBuffer} buffer
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
export function b64_encode(buffer) {
|
|
22
|
+
if (globalThis.Buffer) {
|
|
23
|
+
return Buffer.from(buffer).toString('base64');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const little_endian = new Uint8Array(new Uint16Array([1]).buffer)[0] > 0;
|
|
27
|
+
|
|
28
|
+
// The Uint16Array(Uint8Array(...)) ensures the code points are padded with 0's
|
|
29
|
+
return btoa(
|
|
30
|
+
new TextDecoder(little_endian ? 'utf-16le' : 'utf-16be').decode(
|
|
31
|
+
new Uint16Array(new Uint8Array(buffer))
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -16,3 +16,13 @@ declare module '__sveltekit/paths' {
|
|
|
16
16
|
export function override(paths: { base: string; assets: string }): void;
|
|
17
17
|
export function set_assets(path: string): void;
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
/** Internal version of $app/server */
|
|
21
|
+
declare module '__sveltekit/server' {
|
|
22
|
+
import { SSRManifest } from '@sveltejs/kit';
|
|
23
|
+
|
|
24
|
+
export let manifest: SSRManifest;
|
|
25
|
+
export function read_implementation(path: string): ReadableStream;
|
|
26
|
+
export function set_manifest(manifest: SSRManifest): void;
|
|
27
|
+
export function set_read_implementation(fn: (path: string) => ReadableStream): void;
|
|
28
|
+
}
|
|
@@ -4,6 +4,21 @@ declare global {
|
|
|
4
4
|
const __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: number;
|
|
5
5
|
const __SVELTEKIT_DEV__: boolean;
|
|
6
6
|
const __SVELTEKIT_EMBEDDED__: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* This makes the use of specific features visible at both dev and build time, in such a
|
|
9
|
+
* way that we can error when they are not supported by the target platform.
|
|
10
|
+
*
|
|
11
|
+
* During dev, `globalThis.__SVELTEKIT_TRACK__` is a function that grabs the current `event`
|
|
12
|
+
* and route `config` (from an AsyncLocalStorage instance) and calls the relevant `supports`
|
|
13
|
+
* function on the adapter (e.g. `adapter.supports.read(...)`).
|
|
14
|
+
*
|
|
15
|
+
* At build time, if the function containing the `__SVELTEKIT_TRACK__` call is untreeshaken,
|
|
16
|
+
* we locate it in the `renderChunk` build hook and a) make a note of the chunk that contains
|
|
17
|
+
* it and b) replace it with a comment. Later, we can use this information to establish
|
|
18
|
+
* which routes use which feature, and use the same `adapter.supports.read(...)` function
|
|
19
|
+
* to throw an error if the feature would fail in production.
|
|
20
|
+
*/
|
|
21
|
+
var __SVELTEKIT_TRACK__: (label: string) => void;
|
|
7
22
|
var Bun: object;
|
|
8
23
|
var Deno: object;
|
|
9
24
|
}
|
package/src/types/internal.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
HandleFetch,
|
|
14
14
|
Actions,
|
|
15
15
|
HandleClientError,
|
|
16
|
-
Reroute
|
|
16
|
+
Reroute,
|
|
17
|
+
RequestEvent,
|
|
18
|
+
SSRManifest
|
|
17
19
|
} from '@sveltejs/kit';
|
|
18
20
|
import {
|
|
19
21
|
HttpMethod,
|
|
@@ -30,9 +32,11 @@ export interface ServerModule {
|
|
|
30
32
|
export interface ServerInternalModule {
|
|
31
33
|
set_assets(path: string): void;
|
|
32
34
|
set_building(): void;
|
|
35
|
+
set_manifest(manifest: SSRManifest): void;
|
|
33
36
|
set_prerendering(): void;
|
|
34
37
|
set_private_env(environment: Record<string, string>): void;
|
|
35
38
|
set_public_env(environment: Record<string, string>): void;
|
|
39
|
+
set_read_implementation(implementation: (path: string) => ReadableStream): void;
|
|
36
40
|
set_safe_public_env(environment: Record<string, string>): void;
|
|
37
41
|
set_version(version: string): void;
|
|
38
42
|
set_fix_stack_trace(fix_stack_trace: (error: unknown) => string): void;
|
|
@@ -45,6 +49,7 @@ export interface Asset {
|
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
export interface AssetDependencies {
|
|
52
|
+
assets: string[];
|
|
48
53
|
file: string;
|
|
49
54
|
imports: string[];
|
|
50
55
|
stylesheets: string[];
|
|
@@ -55,6 +60,7 @@ export interface BuildData {
|
|
|
55
60
|
app_dir: string;
|
|
56
61
|
app_path: string;
|
|
57
62
|
manifest_data: ManifestData;
|
|
63
|
+
out_dir: string;
|
|
58
64
|
service_worker: string | null;
|
|
59
65
|
client: {
|
|
60
66
|
start: string;
|
|
@@ -120,12 +126,19 @@ export class InternalServer extends Server {
|
|
|
120
126
|
options: RequestOptions & {
|
|
121
127
|
prerendering?: PrerenderOptions;
|
|
122
128
|
read: (file: string) => Buffer;
|
|
129
|
+
/** A hook called before `handle` during dev, so that `AsyncLocalStorage` can be populated */
|
|
130
|
+
before_handle?: (event: RequestEvent, config: any, prerender: PrerenderOption) => void;
|
|
123
131
|
}
|
|
124
132
|
): Promise<Response>;
|
|
125
133
|
}
|
|
126
134
|
|
|
127
135
|
export interface ManifestData {
|
|
128
136
|
assets: Asset[];
|
|
137
|
+
hooks: {
|
|
138
|
+
client: string | null;
|
|
139
|
+
server: string | null;
|
|
140
|
+
universal: string | null;
|
|
141
|
+
};
|
|
129
142
|
nodes: PageNode[];
|
|
130
143
|
routes: RouteData[];
|
|
131
144
|
matchers: Record<string, string>;
|
|
@@ -404,6 +417,7 @@ export interface SSRState {
|
|
|
404
417
|
*/
|
|
405
418
|
prerender_default?: PrerenderOption;
|
|
406
419
|
read?: (file: string) => Buffer;
|
|
420
|
+
before_handle?: (event: RequestEvent, config: any, prerender: PrerenderOption) => void;
|
|
407
421
|
}
|
|
408
422
|
|
|
409
423
|
export type StrictBody = string | ArrayBufferView;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} route_id
|
|
3
|
+
* @param {any} config
|
|
4
|
+
* @param {string} feature
|
|
5
|
+
* @param {import('@sveltejs/kit').Adapter | undefined} adapter
|
|
6
|
+
*/
|
|
7
|
+
export function check_feature(route_id, config, feature, adapter) {
|
|
8
|
+
if (!adapter) return;
|
|
9
|
+
|
|
10
|
+
switch (feature) {
|
|
11
|
+
case '$app/server:read': {
|
|
12
|
+
const supported = adapter.supports?.read?.({
|
|
13
|
+
route: { id: route_id },
|
|
14
|
+
config
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
if (!supported) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Cannot use \`read\` from \`$app/server\` in ${route_id} when using ${adapter.name}. Please ensure that your adapter is up to date and supports this feature.`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Do a shallow merge (first level) of the config object
|
|
3
|
+
* @param {Array<import('types').SSRNode | undefined>} nodes
|
|
4
|
+
*/
|
|
5
|
+
export function get_page_config(nodes) {
|
|
6
|
+
/** @type {any} */
|
|
7
|
+
let current = {};
|
|
8
|
+
|
|
9
|
+
for (const node of nodes) {
|
|
10
|
+
if (!node?.universal?.config && !node?.server?.config) continue;
|
|
11
|
+
|
|
12
|
+
current = {
|
|
13
|
+
...current,
|
|
14
|
+
...node?.universal?.config,
|
|
15
|
+
...node?.server?.config
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return Object.keys(current).length ? current : undefined;
|
|
20
|
+
}
|
package/src/version.js
CHANGED