@sveltejs/kit 1.0.0-next.270 → 1.0.0-next.274
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/assets/client/start.js +23 -10
- package/assets/server/index.js +65 -31
- package/dist/cli.js +2 -2
- package/package.json +1 -1
- package/types/hooks.d.ts +6 -3
- package/types/index.d.ts +8 -1
package/assets/client/start.js
CHANGED
|
@@ -83,6 +83,8 @@ class Router {
|
|
|
83
83
|
history.replaceState({ ...history.state, 'sveltekit:index': 0 }, '', location.href);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
this.hash_navigating = false;
|
|
87
|
+
|
|
86
88
|
this.callbacks = {
|
|
87
89
|
/** @type {Array<({ from, to, cancel }: { from: URL, to: URL | null, cancel: () => void }) => void>} */
|
|
88
90
|
before_navigate: [],
|
|
@@ -210,9 +212,10 @@ class Router {
|
|
|
210
212
|
// Removing the hash does a full page navigation in the browser, so make sure a hash is present
|
|
211
213
|
const [base, hash] = url.href.split('#');
|
|
212
214
|
if (hash !== undefined && base === location.href.split('#')[0]) {
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
|
|
215
|
+
// set this flag to distinguish between navigations triggered by
|
|
216
|
+
// clicking a hash link and those triggered by popstate
|
|
217
|
+
this.hash_navigating = true;
|
|
218
|
+
|
|
216
219
|
const info = this.parse(url);
|
|
217
220
|
if (info) {
|
|
218
221
|
return this.renderer.update(info, [], false);
|
|
@@ -256,6 +259,19 @@ class Router {
|
|
|
256
259
|
});
|
|
257
260
|
}
|
|
258
261
|
});
|
|
262
|
+
|
|
263
|
+
addEventListener('hashchange', () => {
|
|
264
|
+
// if the hashchange happened as a result of clicking on a link,
|
|
265
|
+
// we need to update history, otherwise we have to leave it alone
|
|
266
|
+
if (this.hash_navigating) {
|
|
267
|
+
this.hash_navigating = false;
|
|
268
|
+
history.replaceState(
|
|
269
|
+
{ ...history.state, 'sveltekit:index': ++this.current_history_index },
|
|
270
|
+
'',
|
|
271
|
+
location.href
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
259
275
|
}
|
|
260
276
|
|
|
261
277
|
/**
|
|
@@ -720,11 +736,12 @@ class Renderer {
|
|
|
720
736
|
* status: number;
|
|
721
737
|
* error: Error;
|
|
722
738
|
* nodes: Array<Promise<CSRComponent>>;
|
|
723
|
-
* url: URL;
|
|
724
739
|
* params: Record<string, string>;
|
|
725
740
|
* }} selected
|
|
726
741
|
*/
|
|
727
|
-
async start({ status, error, nodes,
|
|
742
|
+
async start({ status, error, nodes, params }) {
|
|
743
|
+
const url = new URL(location.href);
|
|
744
|
+
|
|
728
745
|
/** @type {Array<import('./types').BranchNode | undefined>} */
|
|
729
746
|
const branch = [];
|
|
730
747
|
|
|
@@ -736,9 +753,6 @@ class Renderer {
|
|
|
736
753
|
|
|
737
754
|
let error_args;
|
|
738
755
|
|
|
739
|
-
// url.hash is empty when coming from the server
|
|
740
|
-
url.hash = window.location.hash;
|
|
741
|
-
|
|
742
756
|
try {
|
|
743
757
|
for (let i = 0; i < nodes.length; i += 1) {
|
|
744
758
|
const is_leaf = i === nodes.length - 1;
|
|
@@ -1279,7 +1293,7 @@ class Renderer {
|
|
|
1279
1293
|
|
|
1280
1294
|
if (has_shadow && i === a.length - 1) {
|
|
1281
1295
|
const res = await fetch(
|
|
1282
|
-
`${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json`,
|
|
1296
|
+
`${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json${url.search}`,
|
|
1283
1297
|
{
|
|
1284
1298
|
headers: {
|
|
1285
1299
|
'x-sveltekit-load': 'true'
|
|
@@ -1467,7 +1481,6 @@ class Renderer {
|
|
|
1467
1481
|
* status: number;
|
|
1468
1482
|
* error: Error;
|
|
1469
1483
|
* nodes: Array<Promise<import('types/internal').CSRComponent>>;
|
|
1470
|
-
* url: URL;
|
|
1471
1484
|
* params: Record<string, string>;
|
|
1472
1485
|
* };
|
|
1473
1486
|
* }} opts
|
package/assets/server/index.js
CHANGED
|
@@ -80,7 +80,7 @@ function is_pojo(body) {
|
|
|
80
80
|
|
|
81
81
|
// body could be a node Readable, but we don't want to import
|
|
82
82
|
// node built-ins, so we use duck typing
|
|
83
|
-
if (body._readableState && body.
|
|
83
|
+
if (body._readableState && typeof body.pipe === 'function') return false;
|
|
84
84
|
|
|
85
85
|
// similarly, it could be a web ReadableStream
|
|
86
86
|
if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) return false;
|
|
@@ -1057,7 +1057,7 @@ const updated = {
|
|
|
1057
1057
|
* error?: Error;
|
|
1058
1058
|
* url: URL;
|
|
1059
1059
|
* params: Record<string, string>;
|
|
1060
|
-
*
|
|
1060
|
+
* resolve_opts: import('types/hooks').RequiredResolveOptions;
|
|
1061
1061
|
* stuff: Record<string, any>;
|
|
1062
1062
|
* }} opts
|
|
1063
1063
|
*/
|
|
@@ -1071,7 +1071,7 @@ async function render_response({
|
|
|
1071
1071
|
error,
|
|
1072
1072
|
url,
|
|
1073
1073
|
params,
|
|
1074
|
-
|
|
1074
|
+
resolve_opts,
|
|
1075
1075
|
stuff
|
|
1076
1076
|
}) {
|
|
1077
1077
|
if (state.prerender) {
|
|
@@ -1103,7 +1103,7 @@ async function render_response({
|
|
|
1103
1103
|
error.stack = options.get_stack(error);
|
|
1104
1104
|
}
|
|
1105
1105
|
|
|
1106
|
-
if (ssr) {
|
|
1106
|
+
if (resolve_opts.ssr) {
|
|
1107
1107
|
branch.forEach(({ node, props, loaded, fetched, uses_credentials }) => {
|
|
1108
1108
|
if (node.css) node.css.forEach((url) => stylesheets.add(url));
|
|
1109
1109
|
if (node.js) node.js.forEach((url) => modulepreloads.add(url));
|
|
@@ -1199,9 +1199,9 @@ async function render_response({
|
|
|
1199
1199
|
throw new Error(`Failed to serialize session data: ${error.message}`);
|
|
1200
1200
|
})},
|
|
1201
1201
|
route: ${!!page_config.router},
|
|
1202
|
-
spa: ${!ssr},
|
|
1202
|
+
spa: ${!resolve_opts.ssr},
|
|
1203
1203
|
trailing_slash: ${s(options.trailing_slash)},
|
|
1204
|
-
hydrate: ${ssr && page_config.hydrate ? `{
|
|
1204
|
+
hydrate: ${resolve_opts.ssr && page_config.hydrate ? `{
|
|
1205
1205
|
status: ${status},
|
|
1206
1206
|
error: ${serialize_error(error)},
|
|
1207
1207
|
nodes: [
|
|
@@ -1209,7 +1209,6 @@ async function render_response({
|
|
|
1209
1209
|
.map(({ node }) => `import(${s(options.prefix + node.entry)})`)
|
|
1210
1210
|
.join(',\n\t\t\t\t\t\t')}
|
|
1211
1211
|
],
|
|
1212
|
-
url: new URL(${s(url.href)}),
|
|
1213
1212
|
params: ${devalue(params)}
|
|
1214
1213
|
}` : 'null'}
|
|
1215
1214
|
});
|
|
@@ -1327,7 +1326,9 @@ async function render_response({
|
|
|
1327
1326
|
const assets =
|
|
1328
1327
|
options.paths.assets || (segments.length > 0 ? segments.map(() => '..').join('/') : '.');
|
|
1329
1328
|
|
|
1330
|
-
const html =
|
|
1329
|
+
const html = resolve_opts.transformPage({
|
|
1330
|
+
html: options.template({ head, body, assets, nonce: /** @type {string} */ (csp.nonce) })
|
|
1331
|
+
});
|
|
1331
1332
|
|
|
1332
1333
|
const headers = new Headers({
|
|
1333
1334
|
'content-type': 'text/html',
|
|
@@ -1879,7 +1880,7 @@ async function load_shadow_data(route, event, options, prerender) {
|
|
|
1879
1880
|
const mod = await route.shadow();
|
|
1880
1881
|
|
|
1881
1882
|
if (prerender && (mod.post || mod.put || mod.del || mod.patch)) {
|
|
1882
|
-
throw new Error('Cannot prerender pages that have
|
|
1883
|
+
throw new Error('Cannot prerender pages that have endpoints with mutative methods');
|
|
1883
1884
|
}
|
|
1884
1885
|
|
|
1885
1886
|
const method = normalize_request_method(event);
|
|
@@ -1986,7 +1987,7 @@ function validate_shadow_output(result) {
|
|
|
1986
1987
|
if (headers instanceof Headers) {
|
|
1987
1988
|
if (headers.has('set-cookie')) {
|
|
1988
1989
|
throw new Error(
|
|
1989
|
-
'
|
|
1990
|
+
'Endpoint request handler cannot use Headers interface with Set-Cookie headers'
|
|
1990
1991
|
);
|
|
1991
1992
|
}
|
|
1992
1993
|
} else {
|
|
@@ -1994,7 +1995,7 @@ function validate_shadow_output(result) {
|
|
|
1994
1995
|
}
|
|
1995
1996
|
|
|
1996
1997
|
if (!is_pojo(body)) {
|
|
1997
|
-
throw new Error('Body returned from
|
|
1998
|
+
throw new Error('Body returned from endpoint request handler must be a plain object');
|
|
1998
1999
|
}
|
|
1999
2000
|
|
|
2000
2001
|
return { status, headers, body };
|
|
@@ -2014,10 +2015,18 @@ function validate_shadow_output(result) {
|
|
|
2014
2015
|
* $session: any;
|
|
2015
2016
|
* status: number;
|
|
2016
2017
|
* error: Error;
|
|
2017
|
-
*
|
|
2018
|
+
* resolve_opts: import('types/hooks').RequiredResolveOptions;
|
|
2018
2019
|
* }} opts
|
|
2019
2020
|
*/
|
|
2020
|
-
async function respond_with_error({
|
|
2021
|
+
async function respond_with_error({
|
|
2022
|
+
event,
|
|
2023
|
+
options,
|
|
2024
|
+
state,
|
|
2025
|
+
$session,
|
|
2026
|
+
status,
|
|
2027
|
+
error,
|
|
2028
|
+
resolve_opts
|
|
2029
|
+
}) {
|
|
2021
2030
|
try {
|
|
2022
2031
|
const default_layout = await options.manifest._.nodes[0](); // 0 is always the root layout
|
|
2023
2032
|
const default_error = await options.manifest._.nodes[1](); // 1 is always the root error
|
|
@@ -2073,7 +2082,7 @@ async function respond_with_error({ event, options, state, $session, status, err
|
|
|
2073
2082
|
branch: [layout_loaded, error_loaded],
|
|
2074
2083
|
url: event.url,
|
|
2075
2084
|
params,
|
|
2076
|
-
|
|
2085
|
+
resolve_opts
|
|
2077
2086
|
});
|
|
2078
2087
|
} catch (err) {
|
|
2079
2088
|
const error = coalesce_to_error(err);
|
|
@@ -2099,19 +2108,19 @@ async function respond_with_error({ event, options, state, $session, status, err
|
|
|
2099
2108
|
* options: SSROptions;
|
|
2100
2109
|
* state: SSRState;
|
|
2101
2110
|
* $session: any;
|
|
2111
|
+
* resolve_opts: import('types/hooks').RequiredResolveOptions;
|
|
2102
2112
|
* route: import('types/internal').SSRPage;
|
|
2103
2113
|
* params: Record<string, string>;
|
|
2104
|
-
* ssr: boolean;
|
|
2105
2114
|
* }} opts
|
|
2106
2115
|
* @returns {Promise<Response | undefined>}
|
|
2107
2116
|
*/
|
|
2108
2117
|
async function respond$1(opts) {
|
|
2109
|
-
const { event, options, state, $session, route,
|
|
2118
|
+
const { event, options, state, $session, route, resolve_opts } = opts;
|
|
2110
2119
|
|
|
2111
2120
|
/** @type {Array<SSRNode | undefined>} */
|
|
2112
2121
|
let nodes;
|
|
2113
2122
|
|
|
2114
|
-
if (!ssr) {
|
|
2123
|
+
if (!resolve_opts.ssr) {
|
|
2115
2124
|
return await render_response({
|
|
2116
2125
|
...opts,
|
|
2117
2126
|
branch: [],
|
|
@@ -2141,7 +2150,7 @@ async function respond$1(opts) {
|
|
|
2141
2150
|
$session,
|
|
2142
2151
|
status: 500,
|
|
2143
2152
|
error,
|
|
2144
|
-
|
|
2153
|
+
resolve_opts
|
|
2145
2154
|
});
|
|
2146
2155
|
}
|
|
2147
2156
|
|
|
@@ -2172,7 +2181,7 @@ async function respond$1(opts) {
|
|
|
2172
2181
|
|
|
2173
2182
|
let stuff = {};
|
|
2174
2183
|
|
|
2175
|
-
ssr: if (ssr) {
|
|
2184
|
+
ssr: if (resolve_opts.ssr) {
|
|
2176
2185
|
for (let i = 0; i < nodes.length; i += 1) {
|
|
2177
2186
|
const node = nodes[i];
|
|
2178
2187
|
|
|
@@ -2277,7 +2286,7 @@ async function respond$1(opts) {
|
|
|
2277
2286
|
$session,
|
|
2278
2287
|
status,
|
|
2279
2288
|
error,
|
|
2280
|
-
|
|
2289
|
+
resolve_opts
|
|
2281
2290
|
}),
|
|
2282
2291
|
set_cookie_headers
|
|
2283
2292
|
);
|
|
@@ -2358,10 +2367,10 @@ function with_cookies(response, set_cookie_headers) {
|
|
|
2358
2367
|
* @param {import('types/internal').SSRPage} route
|
|
2359
2368
|
* @param {import('types/internal').SSROptions} options
|
|
2360
2369
|
* @param {import('types/internal').SSRState} state
|
|
2361
|
-
* @param {
|
|
2370
|
+
* @param {import('types/hooks').RequiredResolveOptions} resolve_opts
|
|
2362
2371
|
* @returns {Promise<Response | undefined>}
|
|
2363
2372
|
*/
|
|
2364
|
-
async function render_page(event, route, options, state,
|
|
2373
|
+
async function render_page(event, route, options, state, resolve_opts) {
|
|
2365
2374
|
if (state.initiator === route) {
|
|
2366
2375
|
// infinite request cycle detected
|
|
2367
2376
|
return new Response(`Not found: ${event.url.pathname}`, {
|
|
@@ -2387,9 +2396,9 @@ async function render_page(event, route, options, state, ssr) {
|
|
|
2387
2396
|
options,
|
|
2388
2397
|
state,
|
|
2389
2398
|
$session,
|
|
2399
|
+
resolve_opts,
|
|
2390
2400
|
route,
|
|
2391
|
-
params: event.params
|
|
2392
|
-
ssr
|
|
2401
|
+
params: event.params // TODO this is redundant
|
|
2393
2402
|
});
|
|
2394
2403
|
|
|
2395
2404
|
if (response) {
|
|
@@ -2461,6 +2470,9 @@ function negotiate(accept, types) {
|
|
|
2461
2470
|
|
|
2462
2471
|
const DATA_SUFFIX = '/__data.json';
|
|
2463
2472
|
|
|
2473
|
+
/** @param {{ html: string }} opts */
|
|
2474
|
+
const default_transform = ({ html }) => html;
|
|
2475
|
+
|
|
2464
2476
|
/** @type {import('types/internal').Respond} */
|
|
2465
2477
|
async function respond(request, options, state = {}) {
|
|
2466
2478
|
const url = new URL(request.url);
|
|
@@ -2544,13 +2556,22 @@ async function respond(request, options, state = {}) {
|
|
|
2544
2556
|
rawBody: body_getter
|
|
2545
2557
|
});
|
|
2546
2558
|
|
|
2547
|
-
|
|
2559
|
+
/** @type {import('types/hooks').RequiredResolveOptions} */
|
|
2560
|
+
let resolve_opts = {
|
|
2561
|
+
ssr: true,
|
|
2562
|
+
transformPage: default_transform
|
|
2563
|
+
};
|
|
2548
2564
|
|
|
2549
2565
|
try {
|
|
2550
2566
|
const response = await options.hooks.handle({
|
|
2551
2567
|
event,
|
|
2552
2568
|
resolve: async (event, opts) => {
|
|
2553
|
-
if (opts
|
|
2569
|
+
if (opts) {
|
|
2570
|
+
resolve_opts = {
|
|
2571
|
+
ssr: opts.ssr !== false,
|
|
2572
|
+
transformPage: opts.transformPage || default_transform
|
|
2573
|
+
};
|
|
2574
|
+
}
|
|
2554
2575
|
|
|
2555
2576
|
if (state.prerender && state.prerender.fallback) {
|
|
2556
2577
|
return await render_response({
|
|
@@ -2563,7 +2584,10 @@ async function respond(request, options, state = {}) {
|
|
|
2563
2584
|
stuff: {},
|
|
2564
2585
|
status: 200,
|
|
2565
2586
|
branch: [],
|
|
2566
|
-
|
|
2587
|
+
resolve_opts: {
|
|
2588
|
+
...resolve_opts,
|
|
2589
|
+
ssr: false
|
|
2590
|
+
}
|
|
2567
2591
|
});
|
|
2568
2592
|
}
|
|
2569
2593
|
|
|
@@ -2577,7 +2601,17 @@ async function respond(request, options, state = {}) {
|
|
|
2577
2601
|
}
|
|
2578
2602
|
|
|
2579
2603
|
const is_data_request = decoded.endsWith(DATA_SUFFIX);
|
|
2580
|
-
|
|
2604
|
+
|
|
2605
|
+
if (is_data_request) {
|
|
2606
|
+
decoded = decoded.slice(0, -DATA_SUFFIX.length) || '/';
|
|
2607
|
+
|
|
2608
|
+
const normalized = normalize_path(
|
|
2609
|
+
url.pathname.slice(0, -DATA_SUFFIX.length),
|
|
2610
|
+
options.trailing_slash
|
|
2611
|
+
);
|
|
2612
|
+
|
|
2613
|
+
event.url = new URL(event.url.origin + normalized + event.url.search);
|
|
2614
|
+
}
|
|
2581
2615
|
|
|
2582
2616
|
for (const route of options.manifest._.routes) {
|
|
2583
2617
|
const match = route.pattern.exec(decoded);
|
|
@@ -2622,7 +2656,7 @@ async function respond(request, options, state = {}) {
|
|
|
2622
2656
|
response =
|
|
2623
2657
|
route.type === 'endpoint'
|
|
2624
2658
|
? await render_endpoint(event, await route.load())
|
|
2625
|
-
: await render_page(event, route, options, state,
|
|
2659
|
+
: await render_page(event, route, options, state, resolve_opts);
|
|
2626
2660
|
}
|
|
2627
2661
|
|
|
2628
2662
|
if (response) {
|
|
@@ -2674,7 +2708,7 @@ async function respond(request, options, state = {}) {
|
|
|
2674
2708
|
$session,
|
|
2675
2709
|
status: 404,
|
|
2676
2710
|
error: new Error(`Not found: ${event.url.pathname}`),
|
|
2677
|
-
|
|
2711
|
+
resolve_opts
|
|
2678
2712
|
});
|
|
2679
2713
|
}
|
|
2680
2714
|
|
|
@@ -2710,7 +2744,7 @@ async function respond(request, options, state = {}) {
|
|
|
2710
2744
|
$session,
|
|
2711
2745
|
status: 500,
|
|
2712
2746
|
error,
|
|
2713
|
-
|
|
2747
|
+
resolve_opts
|
|
2714
2748
|
});
|
|
2715
2749
|
} catch (/** @type {unknown} */ e) {
|
|
2716
2750
|
const error = coalesce_to_error(e);
|
package/dist/cli.js
CHANGED
|
@@ -998,7 +998,7 @@ async function launch(port, https) {
|
|
|
998
998
|
exec(`${cmd} ${https ? 'https' : 'http'}://localhost:${port}`);
|
|
999
999
|
}
|
|
1000
1000
|
|
|
1001
|
-
const prog = sade('svelte-kit').version('1.0.0-next.
|
|
1001
|
+
const prog = sade('svelte-kit').version('1.0.0-next.274');
|
|
1002
1002
|
|
|
1003
1003
|
prog
|
|
1004
1004
|
.command('dev')
|
|
@@ -1156,7 +1156,7 @@ async function check_port(port) {
|
|
|
1156
1156
|
function welcome({ port, host, https, open, loose, allow, cwd }) {
|
|
1157
1157
|
if (open) launch(port, https);
|
|
1158
1158
|
|
|
1159
|
-
console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.
|
|
1159
|
+
console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.274'}\n`));
|
|
1160
1160
|
|
|
1161
1161
|
const protocol = https ? 'https:' : 'http:';
|
|
1162
1162
|
const exposed = typeof host !== 'undefined' && host !== 'localhost' && host !== '127.0.0.1';
|
package/package.json
CHANGED
package/types/hooks.d.ts
CHANGED
|
@@ -14,14 +14,17 @@ export interface GetSession {
|
|
|
14
14
|
(event: RequestEvent): MaybePromise<App.Session>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export interface
|
|
18
|
-
ssr
|
|
17
|
+
export interface RequiredResolveOptions {
|
|
18
|
+
ssr: boolean;
|
|
19
|
+
transformPage: ({ html }: { html: string }) => string;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
export type ResolveOptions = Partial<RequiredResolveOptions>;
|
|
23
|
+
|
|
21
24
|
export interface Handle {
|
|
22
25
|
(input: {
|
|
23
26
|
event: RequestEvent;
|
|
24
|
-
resolve(event: RequestEvent, opts?:
|
|
27
|
+
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
|
|
25
28
|
}): MaybePromise<Response>;
|
|
26
29
|
}
|
|
27
30
|
|
package/types/index.d.ts
CHANGED
|
@@ -14,4 +14,11 @@ export {
|
|
|
14
14
|
} from './config';
|
|
15
15
|
export { EndpointOutput, RequestHandler } from './endpoint';
|
|
16
16
|
export { ErrorLoad, ErrorLoadInput, Load, LoadInput, LoadOutput } from './page';
|
|
17
|
-
export {
|
|
17
|
+
export {
|
|
18
|
+
ExternalFetch,
|
|
19
|
+
GetSession,
|
|
20
|
+
Handle,
|
|
21
|
+
HandleError,
|
|
22
|
+
RequestEvent,
|
|
23
|
+
ResolveOptions
|
|
24
|
+
} from './hooks';
|