@sveltejs/kit 1.5.2 → 1.5.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.
- package/package.json +1 -1
- package/src/core/adapt/builder.js +8 -23
- package/src/core/postbuild/fallback.js +40 -29
- package/src/exports/node/polyfills.js +7 -2
- package/src/runtime/app/stores.js +18 -3
- package/src/runtime/client/client.js +11 -10
- package/src/runtime/server/page/render.js +26 -1
- package/src/runtime/server/utils.js +1 -1
- package/types/ambient.d.ts +7 -1
- package/types/index.d.ts +1 -2
package/package.json
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { fork } from 'node:child_process';
|
|
2
1
|
import { existsSync, statSync, createReadStream, createWriteStream } from 'node:fs';
|
|
3
2
|
import { pipeline } from 'node:stream';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
3
|
import { promisify } from 'node:util';
|
|
6
4
|
import zlib from 'node:zlib';
|
|
7
5
|
import glob from 'tiny-glob';
|
|
@@ -9,6 +7,8 @@ import { copy, rimraf, mkdirp } from '../../utils/filesystem.js';
|
|
|
9
7
|
import { generate_manifest } from '../generate_manifest/index.js';
|
|
10
8
|
import { get_route_segments } from '../../utils/routing.js';
|
|
11
9
|
import { get_env } from '../../exports/vite/utils.js';
|
|
10
|
+
import generate_fallback from '../postbuild/fallback.js';
|
|
11
|
+
import { write } from '../sync/utils.js';
|
|
12
12
|
|
|
13
13
|
const pipe = promisify(pipeline);
|
|
14
14
|
|
|
@@ -142,31 +142,16 @@ export function create_builder({
|
|
|
142
142
|
}
|
|
143
143
|
},
|
|
144
144
|
|
|
145
|
-
generateFallback(dest) {
|
|
146
|
-
// do prerendering in a subprocess so any dangling stuff gets killed upon completion
|
|
147
|
-
const script = fileURLToPath(new URL('../postbuild/fallback.js', import.meta.url));
|
|
148
|
-
|
|
145
|
+
async generateFallback(dest) {
|
|
149
146
|
const manifest_path = `${config.kit.outDir}/output/server/manifest-full.js`;
|
|
150
|
-
|
|
151
147
|
const env = get_env(config.kit.env, 'production');
|
|
152
148
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
[dest, manifest_path, JSON.stringify({ ...env.private, ...env.public })],
|
|
157
|
-
{
|
|
158
|
-
stdio: 'inherit'
|
|
159
|
-
}
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
child.on('exit', (code) => {
|
|
163
|
-
if (code) {
|
|
164
|
-
reject(new Error(`Could not create a fallback page — failed with code ${code}`));
|
|
165
|
-
} else {
|
|
166
|
-
fulfil(undefined);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
149
|
+
const fallback = await generate_fallback({
|
|
150
|
+
manifest_path,
|
|
151
|
+
env: { ...env.private, ...env.public }
|
|
169
152
|
});
|
|
153
|
+
|
|
154
|
+
write(dest, fallback);
|
|
170
155
|
},
|
|
171
156
|
|
|
172
157
|
generateManifest: ({ relativePath, routes: subset }) => {
|
|
@@ -1,43 +1,54 @@
|
|
|
1
|
-
import { readFileSync
|
|
2
|
-
import {
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { mkdirp } from '../../utils/filesystem.js';
|
|
5
4
|
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
6
5
|
import { load_config } from '../config/index.js';
|
|
6
|
+
import { forked } from '../../utils/fork.js';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
export default forked(import.meta.url, generate_fallback);
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* @param {{
|
|
12
|
+
* manifest_path: string;
|
|
13
|
+
* env: Record<string, string>
|
|
14
|
+
* }} opts
|
|
15
|
+
*/
|
|
16
|
+
async function generate_fallback({ manifest_path, env }) {
|
|
17
|
+
/** @type {import('types').ValidatedKitConfig} */
|
|
18
|
+
const config = (await load_config()).kit;
|
|
12
19
|
|
|
13
|
-
installPolyfills();
|
|
20
|
+
installPolyfills();
|
|
14
21
|
|
|
15
|
-
const server_root = join(config.outDir, 'output');
|
|
22
|
+
const server_root = join(config.outDir, 'output');
|
|
16
23
|
|
|
17
|
-
/** @type {import('types').ServerInternalModule} */
|
|
18
|
-
const { set_building } = await import(pathToFileURL(`${server_root}/server/internal.js`).href);
|
|
24
|
+
/** @type {import('types').ServerInternalModule} */
|
|
25
|
+
const { set_building } = await import(pathToFileURL(`${server_root}/server/internal.js`).href);
|
|
19
26
|
|
|
20
|
-
/** @type {import('types').ServerModule} */
|
|
21
|
-
const { Server } = await import(pathToFileURL(`${server_root}/server/index.js`).href);
|
|
27
|
+
/** @type {import('types').ServerModule} */
|
|
28
|
+
const { Server } = await import(pathToFileURL(`${server_root}/server/index.js`).href);
|
|
22
29
|
|
|
23
|
-
/** @type {import('types').SSRManifest} */
|
|
24
|
-
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
|
|
30
|
+
/** @type {import('types').SSRManifest} */
|
|
31
|
+
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
|
|
25
32
|
|
|
26
|
-
set_building(true);
|
|
33
|
+
set_building(true);
|
|
27
34
|
|
|
28
|
-
const server = new Server(manifest);
|
|
29
|
-
await server.init({ env
|
|
35
|
+
const server = new Server(manifest);
|
|
36
|
+
await server.init({ env });
|
|
30
37
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
38
|
+
const response = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
|
|
39
|
+
getClientAddress: () => {
|
|
40
|
+
throw new Error('Cannot read clientAddress during prerendering');
|
|
41
|
+
},
|
|
42
|
+
prerendering: {
|
|
43
|
+
fallback: true,
|
|
44
|
+
dependencies: new Map()
|
|
45
|
+
},
|
|
46
|
+
read: (file) => readFileSync(join(config.files.assets, file))
|
|
47
|
+
});
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
if (response.ok) {
|
|
50
|
+
return await response.text();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
throw new Error(`Could not create a fallback page — failed with status ${response.status}`);
|
|
54
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { ReadableStream, TransformStream, WritableStream } from 'node:stream/web';
|
|
2
|
+
import buffer from 'node:buffer';
|
|
2
3
|
import { webcrypto as crypto } from 'node:crypto';
|
|
3
|
-
import { fetch, Response, Request, Headers, FormData } from 'undici';
|
|
4
|
+
import { fetch, Response, Request, Headers, FormData, File as UndiciFile } from 'undici';
|
|
5
|
+
|
|
6
|
+
// @ts-expect-error
|
|
7
|
+
const File = buffer.File ?? UndiciFile;
|
|
4
8
|
|
|
5
9
|
/** @type {Record<string, any>} */
|
|
6
10
|
const globals = {
|
|
@@ -12,7 +16,8 @@ const globals = {
|
|
|
12
16
|
ReadableStream,
|
|
13
17
|
TransformStream,
|
|
14
18
|
WritableStream,
|
|
15
|
-
FormData
|
|
19
|
+
FormData,
|
|
20
|
+
File
|
|
16
21
|
};
|
|
17
22
|
|
|
18
23
|
// exported for dev/preview and node environments
|
|
@@ -23,7 +23,7 @@ export const getStores = () => {
|
|
|
23
23
|
export const page = {
|
|
24
24
|
/** @param {(value: any) => void} fn */
|
|
25
25
|
subscribe(fn) {
|
|
26
|
-
const store = getStores().page;
|
|
26
|
+
const store = __SVELTEKIT_DEV__ ? get_store('page') : getStores().page;
|
|
27
27
|
return store.subscribe(fn);
|
|
28
28
|
}
|
|
29
29
|
};
|
|
@@ -31,7 +31,7 @@ export const page = {
|
|
|
31
31
|
/** @type {typeof import('$app/stores').navigating} */
|
|
32
32
|
export const navigating = {
|
|
33
33
|
subscribe(fn) {
|
|
34
|
-
const store = getStores().navigating;
|
|
34
|
+
const store = __SVELTEKIT_DEV__ ? get_store('navigating') : getStores().navigating;
|
|
35
35
|
return store.subscribe(fn);
|
|
36
36
|
}
|
|
37
37
|
};
|
|
@@ -39,7 +39,7 @@ export const navigating = {
|
|
|
39
39
|
/** @type {typeof import('$app/stores').updated} */
|
|
40
40
|
export const updated = {
|
|
41
41
|
subscribe(fn) {
|
|
42
|
-
const store = getStores().updated;
|
|
42
|
+
const store = __SVELTEKIT_DEV__ ? get_store('updated') : getStores().updated;
|
|
43
43
|
|
|
44
44
|
if (browser) {
|
|
45
45
|
updated.check = store.check;
|
|
@@ -55,3 +55,18 @@ export const updated = {
|
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @template {keyof ReturnType<typeof getStores>} Name
|
|
61
|
+
* @param {Name} name
|
|
62
|
+
* @returns {ReturnType<typeof getStores>[Name]}
|
|
63
|
+
*/
|
|
64
|
+
function get_store(name) {
|
|
65
|
+
try {
|
|
66
|
+
return getStores()[name];
|
|
67
|
+
} catch (e) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Cannot subscribe to '${name}' store on the server outside of a Svelte component, as it is bound to the current request via component context. This prevents state from leaking between users.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -221,14 +221,8 @@ export function create_client({ target }) {
|
|
|
221
221
|
});
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
/** @param {
|
|
225
|
-
async function preload_data(
|
|
226
|
-
const intent = get_navigation_intent(url, false);
|
|
227
|
-
|
|
228
|
-
if (!intent) {
|
|
229
|
-
throw new Error(`Attempted to preload a URL that does not belong to this app: ${url}`);
|
|
230
|
-
}
|
|
231
|
-
|
|
224
|
+
/** @param {import('./types').NavigationIntent} intent */
|
|
225
|
+
async function preload_data(intent) {
|
|
232
226
|
load_cache = {
|
|
233
227
|
id: intent.id,
|
|
234
228
|
promise: load_route(intent).then((result) => {
|
|
@@ -1261,7 +1255,8 @@ export function create_client({ target }) {
|
|
|
1261
1255
|
|
|
1262
1256
|
if (!options.reload) {
|
|
1263
1257
|
if (priority <= options.preload_data) {
|
|
1264
|
-
|
|
1258
|
+
const intent = get_navigation_intent(/** @type {URL} */ (url), false);
|
|
1259
|
+
if (intent) preload_data(intent);
|
|
1265
1260
|
} else if (priority <= options.preload_code) {
|
|
1266
1261
|
preload_code(get_url_path(/** @type {URL} */ (url)));
|
|
1267
1262
|
}
|
|
@@ -1347,7 +1342,13 @@ export function create_client({ target }) {
|
|
|
1347
1342
|
|
|
1348
1343
|
preload_data: async (href) => {
|
|
1349
1344
|
const url = new URL(href, get_base_uri(document));
|
|
1350
|
-
|
|
1345
|
+
const intent = get_navigation_intent(url, false);
|
|
1346
|
+
|
|
1347
|
+
if (!intent) {
|
|
1348
|
+
throw new Error(`Attempted to preload a URL that does not belong to this app: ${url}`);
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
await preload_data(intent);
|
|
1351
1352
|
},
|
|
1352
1353
|
|
|
1353
1354
|
preload_code,
|
|
@@ -113,7 +113,32 @@ export async function render_response({
|
|
|
113
113
|
form: form_value
|
|
114
114
|
};
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
if (__SVELTEKIT_DEV__) {
|
|
117
|
+
const fetch = globalThis.fetch;
|
|
118
|
+
let warned = false;
|
|
119
|
+
globalThis.fetch = (info, init) => {
|
|
120
|
+
if (typeof info === 'string' && !/^\w+:\/\//.test(info)) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
`Cannot call \`fetch\` eagerly during server side rendering with relative URL (${info}) — put your \`fetch\` calls inside \`onMount\` or a \`load\` function instead`
|
|
123
|
+
);
|
|
124
|
+
} else if (!warned) {
|
|
125
|
+
console.warn(
|
|
126
|
+
`Avoid calling \`fetch\` eagerly during server side rendering — put your \`fetch\` calls inside \`onMount\` or a \`load\` function instead`
|
|
127
|
+
);
|
|
128
|
+
warned = true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return fetch(info, init);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
rendered = options.root.render(props);
|
|
136
|
+
} finally {
|
|
137
|
+
globalThis.fetch = fetch;
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
rendered = options.root.render(props);
|
|
141
|
+
}
|
|
117
142
|
|
|
118
143
|
for (const { node } of branch) {
|
|
119
144
|
if (node.imports) {
|
|
@@ -41,7 +41,7 @@ export function method_not_allowed(mod, method) {
|
|
|
41
41
|
export function allowed_methods(mod) {
|
|
42
42
|
const allowed = [];
|
|
43
43
|
|
|
44
|
-
for (const method
|
|
44
|
+
for (const method of ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']) {
|
|
45
45
|
if (method in mod) allowed.push(method);
|
|
46
46
|
}
|
|
47
47
|
|
package/types/ambient.d.ts
CHANGED
|
@@ -292,16 +292,22 @@ declare module '$app/stores' {
|
|
|
292
292
|
|
|
293
293
|
/**
|
|
294
294
|
* A readable store whose value contains page data.
|
|
295
|
+
*
|
|
296
|
+
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
|
|
295
297
|
*/
|
|
296
298
|
export const page: Readable<Page>;
|
|
297
299
|
/**
|
|
298
300
|
* A readable store.
|
|
299
301
|
* When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties.
|
|
300
302
|
* When navigating finishes, its value reverts to `null`.
|
|
303
|
+
*
|
|
304
|
+
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
|
|
301
305
|
*/
|
|
302
306
|
export const navigating: Readable<Navigation | null>;
|
|
303
307
|
/**
|
|
304
|
-
*
|
|
308
|
+
* A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
|
|
309
|
+
*
|
|
310
|
+
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
|
|
305
311
|
*/
|
|
306
312
|
export const updated: Readable<boolean> & { check(): Promise<boolean> };
|
|
307
313
|
|
package/types/index.d.ts
CHANGED
|
@@ -542,8 +542,7 @@ export interface KitConfig {
|
|
|
542
542
|
*/
|
|
543
543
|
version?: {
|
|
544
544
|
/**
|
|
545
|
-
* The current app version string.
|
|
546
|
-
* @default Date.now().toString()
|
|
545
|
+
* The current app version string. If specified, this must be deterministic (e.g. a commit ref rather than `Math.random()` or Date.now().toString()`), otherwise defaults to a timestamp of the build
|
|
547
546
|
*/
|
|
548
547
|
name?: string;
|
|
549
548
|
/**
|