@sveltejs/kit 1.0.0-next.98 → 1.0.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/README.md +5 -1
- package/package.json +91 -77
- package/postinstall.js +47 -0
- package/src/cli.js +44 -0
- package/src/constants.js +5 -0
- package/src/core/adapt/builder.js +221 -0
- package/src/core/adapt/index.js +31 -0
- package/src/core/config/default-error.html +56 -0
- package/src/core/config/index.js +100 -0
- package/src/core/config/options.js +387 -0
- package/src/core/config/types.d.ts +1 -0
- package/src/core/env.js +138 -0
- package/src/core/generate_manifest/index.js +116 -0
- package/src/core/prerender/crawl.js +207 -0
- package/src/core/prerender/entities.js +2252 -0
- package/src/core/prerender/fallback.js +43 -0
- package/src/core/prerender/prerender.js +459 -0
- package/src/core/prerender/queue.js +80 -0
- package/src/core/sync/create_manifest_data/conflict.js +0 -0
- package/src/core/sync/create_manifest_data/index.js +523 -0
- package/src/core/sync/create_manifest_data/sort.js +161 -0
- package/src/core/sync/create_manifest_data/types.d.ts +37 -0
- package/src/core/sync/sync.js +59 -0
- package/src/core/sync/utils.js +33 -0
- package/src/core/sync/write_ambient.js +58 -0
- package/src/core/sync/write_client_manifest.js +107 -0
- package/src/core/sync/write_matchers.js +25 -0
- package/src/core/sync/write_root.js +91 -0
- package/src/core/sync/write_tsconfig.js +195 -0
- package/src/core/sync/write_types/index.js +809 -0
- package/src/core/utils.js +67 -0
- package/src/exports/hooks/index.js +1 -0
- package/src/exports/hooks/sequence.js +44 -0
- package/src/exports/index.js +55 -0
- package/src/exports/node/index.js +172 -0
- package/src/exports/node/polyfills.js +28 -0
- package/src/exports/vite/build/build_server.js +359 -0
- package/src/exports/vite/build/build_service_worker.js +85 -0
- package/src/exports/vite/build/utils.js +230 -0
- package/src/exports/vite/dev/index.js +597 -0
- package/src/exports/vite/graph_analysis/index.js +99 -0
- package/src/exports/vite/graph_analysis/types.d.ts +5 -0
- package/src/exports/vite/graph_analysis/utils.js +6 -0
- package/src/exports/vite/index.js +708 -0
- package/src/exports/vite/preview/index.js +194 -0
- package/src/exports/vite/types.d.ts +3 -0
- package/src/exports/vite/utils.js +184 -0
- package/src/runtime/app/env.js +1 -0
- package/src/runtime/app/environment.js +13 -0
- package/src/runtime/app/forms.js +135 -0
- package/src/runtime/app/navigation.js +22 -0
- package/src/runtime/app/paths.js +1 -0
- package/src/runtime/app/stores.js +57 -0
- package/src/runtime/client/ambient.d.ts +30 -0
- package/src/runtime/client/client.js +1725 -0
- package/src/runtime/client/constants.js +10 -0
- package/src/runtime/client/fetcher.js +127 -0
- package/src/runtime/client/parse.js +60 -0
- package/src/runtime/client/singletons.js +21 -0
- package/src/runtime/client/start.js +45 -0
- package/src/runtime/client/types.d.ts +86 -0
- package/src/runtime/client/utils.js +257 -0
- package/src/runtime/components/error.svelte +6 -0
- package/{assets → src/runtime}/components/layout.svelte +0 -0
- package/src/runtime/control.js +45 -0
- package/src/runtime/env/dynamic/private.js +1 -0
- package/src/runtime/env/dynamic/public.js +1 -0
- package/src/runtime/env-private.js +6 -0
- package/src/runtime/env-public.js +6 -0
- package/src/runtime/env.js +12 -0
- package/src/runtime/hash.js +20 -0
- package/src/runtime/paths.js +11 -0
- package/src/runtime/server/cookie.js +228 -0
- package/src/runtime/server/data/index.js +158 -0
- package/src/runtime/server/endpoint.js +86 -0
- package/src/runtime/server/fetch.js +175 -0
- package/src/runtime/server/index.js +405 -0
- package/src/runtime/server/page/actions.js +267 -0
- package/src/runtime/server/page/crypto.js +239 -0
- package/src/runtime/server/page/csp.js +250 -0
- package/src/runtime/server/page/index.js +326 -0
- package/src/runtime/server/page/load_data.js +270 -0
- package/src/runtime/server/page/render.js +393 -0
- package/src/runtime/server/page/respond_with_error.js +103 -0
- package/src/runtime/server/page/serialize_data.js +87 -0
- package/src/runtime/server/page/types.d.ts +35 -0
- package/src/runtime/server/utils.js +179 -0
- package/src/utils/array.js +9 -0
- package/src/utils/error.js +22 -0
- package/src/utils/escape.js +46 -0
- package/src/utils/exports.js +54 -0
- package/src/utils/filesystem.js +178 -0
- package/src/utils/functions.js +16 -0
- package/src/utils/http.js +72 -0
- package/src/utils/misc.js +1 -0
- package/src/utils/promises.js +17 -0
- package/src/utils/routing.js +201 -0
- package/src/utils/unit_test.js +11 -0
- package/src/utils/url.js +161 -0
- package/svelte-kit.js +1 -1
- package/types/ambient.d.ts +451 -0
- package/types/index.d.ts +1168 -5
- package/types/internal.d.ts +348 -160
- package/types/private.d.ts +237 -0
- package/types/synthetic/$env+dynamic+private.md +10 -0
- package/types/synthetic/$env+dynamic+public.md +8 -0
- package/types/synthetic/$env+static+private.md +19 -0
- package/types/synthetic/$env+static+public.md +7 -0
- package/types/synthetic/$lib.md +5 -0
- package/CHANGELOG.md +0 -819
- package/assets/components/error.svelte +0 -21
- package/assets/runtime/app/env.js +0 -16
- package/assets/runtime/app/navigation.js +0 -53
- package/assets/runtime/app/paths.js +0 -1
- package/assets/runtime/app/stores.js +0 -87
- package/assets/runtime/chunks/utils.js +0 -13
- package/assets/runtime/env.js +0 -8
- package/assets/runtime/internal/singletons.js +0 -20
- package/assets/runtime/internal/start.js +0 -1061
- package/assets/runtime/paths.js +0 -12
- package/dist/chunks/_commonjsHelpers.js +0 -8
- package/dist/chunks/cert.js +0 -29079
- package/dist/chunks/constants.js +0 -3
- package/dist/chunks/index.js +0 -3526
- package/dist/chunks/index2.js +0 -583
- package/dist/chunks/index3.js +0 -31
- package/dist/chunks/index4.js +0 -1005
- package/dist/chunks/index5.js +0 -327
- package/dist/chunks/index6.js +0 -325
- package/dist/chunks/standard.js +0 -99
- package/dist/chunks/utils.js +0 -149
- package/dist/cli.js +0 -711
- package/dist/http.js +0 -66
- package/dist/install-fetch.js +0 -1699
- package/dist/ssr.js +0 -1529
- package/types/ambient-modules.d.ts +0 -115
- package/types/config.d.ts +0 -101
- package/types/endpoint.d.ts +0 -23
- package/types/helper.d.ts +0 -19
- package/types/hooks.d.ts +0 -23
- package/types/page.d.ts +0 -30
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { compact } from '../../../utils/array.js';
|
|
2
|
+
import { normalize_error } from '../../../utils/error.js';
|
|
3
|
+
import { add_data_suffix } from '../../../utils/url.js';
|
|
4
|
+
import { HttpError, Redirect } from '../../control.js';
|
|
5
|
+
import {
|
|
6
|
+
get_option,
|
|
7
|
+
redirect_response,
|
|
8
|
+
static_error_page,
|
|
9
|
+
handle_error_and_jsonify,
|
|
10
|
+
serialize_data_node
|
|
11
|
+
} from '../utils.js';
|
|
12
|
+
import {
|
|
13
|
+
handle_action_json_request,
|
|
14
|
+
handle_action_request,
|
|
15
|
+
is_action_json_request,
|
|
16
|
+
is_action_request
|
|
17
|
+
} from './actions.js';
|
|
18
|
+
import { load_data, load_server_data } from './load_data.js';
|
|
19
|
+
import { render_response } from './render.js';
|
|
20
|
+
import { respond_with_error } from './respond_with_error.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {import('types').RequestEvent} event
|
|
24
|
+
* @param {import('types').SSRRoute} route
|
|
25
|
+
* @param {import('types').PageNodeIndexes} page
|
|
26
|
+
* @param {import('types').SSROptions} options
|
|
27
|
+
* @param {import('types').SSRState} state
|
|
28
|
+
* @param {import('types').RequiredResolveOptions} resolve_opts
|
|
29
|
+
* @returns {Promise<Response>}
|
|
30
|
+
*/
|
|
31
|
+
export async function render_page(event, route, page, options, state, resolve_opts) {
|
|
32
|
+
if (state.initiator === route) {
|
|
33
|
+
// infinite request cycle detected
|
|
34
|
+
return new Response(`Not found: ${event.url.pathname}`, {
|
|
35
|
+
status: 404
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
state.initiator = route;
|
|
40
|
+
|
|
41
|
+
if (is_action_json_request(event)) {
|
|
42
|
+
const node = await options.manifest._.nodes[page.leaf]();
|
|
43
|
+
return handle_action_json_request(event, options, node?.server);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const nodes = await Promise.all([
|
|
48
|
+
// we use == here rather than === because [undefined] serializes as "[null]"
|
|
49
|
+
...page.layouts.map((n) => (n == undefined ? n : options.manifest._.nodes[n]())),
|
|
50
|
+
options.manifest._.nodes[page.leaf]()
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
const leaf_node = /** @type {import('types').SSRNode} */ (nodes.at(-1));
|
|
54
|
+
|
|
55
|
+
let status = 200;
|
|
56
|
+
|
|
57
|
+
/** @type {import('types').ActionResult | undefined} */
|
|
58
|
+
let action_result = undefined;
|
|
59
|
+
|
|
60
|
+
if (is_action_request(event, leaf_node)) {
|
|
61
|
+
// for action requests, first call handler in +page.server.js
|
|
62
|
+
// (this also determines status code)
|
|
63
|
+
action_result = await handle_action_request(event, leaf_node.server);
|
|
64
|
+
if (action_result?.type === 'redirect') {
|
|
65
|
+
return redirect_response(303, action_result.location);
|
|
66
|
+
}
|
|
67
|
+
if (action_result?.type === 'error') {
|
|
68
|
+
const error = action_result.error;
|
|
69
|
+
status = error instanceof HttpError ? error.status : 500;
|
|
70
|
+
}
|
|
71
|
+
if (action_result?.type === 'failure') {
|
|
72
|
+
status = action_result.status;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const should_prerender_data = nodes.some((node) => node?.server);
|
|
77
|
+
const data_pathname = add_data_suffix(event.url.pathname);
|
|
78
|
+
|
|
79
|
+
// it's crucial that we do this before returning the non-SSR response, otherwise
|
|
80
|
+
// SvelteKit will erroneously believe that the path has been prerendered,
|
|
81
|
+
// causing functions to be omitted from the manifesst generated later
|
|
82
|
+
const should_prerender = get_option(nodes, 'prerender');
|
|
83
|
+
|
|
84
|
+
if (should_prerender) {
|
|
85
|
+
const mod = leaf_node.server;
|
|
86
|
+
if (mod && mod.actions) {
|
|
87
|
+
throw new Error('Cannot prerender pages with actions');
|
|
88
|
+
}
|
|
89
|
+
} else if (state.prerendering) {
|
|
90
|
+
// Try to render the shell when ssr is false and prerendering not explicitly disabled.
|
|
91
|
+
// People can opt out of this behavior by explicitly setting prerender to false.
|
|
92
|
+
if (
|
|
93
|
+
should_prerender !== false &&
|
|
94
|
+
get_option(nodes, 'ssr') === false &&
|
|
95
|
+
!leaf_node.server?.actions
|
|
96
|
+
) {
|
|
97
|
+
return await render_response({
|
|
98
|
+
branch: [],
|
|
99
|
+
fetched: [],
|
|
100
|
+
page_config: {
|
|
101
|
+
ssr: false,
|
|
102
|
+
csr: get_option(nodes, 'csr') ?? true
|
|
103
|
+
},
|
|
104
|
+
status,
|
|
105
|
+
error: null,
|
|
106
|
+
event,
|
|
107
|
+
options,
|
|
108
|
+
state,
|
|
109
|
+
resolve_opts
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// if the page isn't marked as prerenderable, then bail out at this point
|
|
114
|
+
return new Response(undefined, {
|
|
115
|
+
status: 204
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// if we fetch any endpoints while loading data for this page, they should
|
|
120
|
+
// inherit the prerender option of the page
|
|
121
|
+
state.prerender_default = should_prerender;
|
|
122
|
+
|
|
123
|
+
/** @type {import('./types').Fetched[]} */
|
|
124
|
+
const fetched = [];
|
|
125
|
+
|
|
126
|
+
if (get_option(nodes, 'ssr') === false) {
|
|
127
|
+
return await render_response({
|
|
128
|
+
branch: [],
|
|
129
|
+
fetched,
|
|
130
|
+
page_config: {
|
|
131
|
+
ssr: false,
|
|
132
|
+
csr: get_option(nodes, 'csr') ?? true
|
|
133
|
+
},
|
|
134
|
+
status,
|
|
135
|
+
error: null,
|
|
136
|
+
event,
|
|
137
|
+
options,
|
|
138
|
+
state,
|
|
139
|
+
resolve_opts
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** @type {Array<import('./types.js').Loaded | null>} */
|
|
144
|
+
let branch = [];
|
|
145
|
+
|
|
146
|
+
/** @type {Error | null} */
|
|
147
|
+
let load_error = null;
|
|
148
|
+
|
|
149
|
+
/** @type {Array<Promise<import('types').ServerDataNode | null>>} */
|
|
150
|
+
const server_promises = nodes.map((node, i) => {
|
|
151
|
+
if (load_error) {
|
|
152
|
+
// if an error happens immediately, don't bother with the rest of the nodes
|
|
153
|
+
throw load_error;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return Promise.resolve().then(async () => {
|
|
157
|
+
try {
|
|
158
|
+
if (node === leaf_node && action_result?.type === 'error') {
|
|
159
|
+
// we wait until here to throw the error so that we can use
|
|
160
|
+
// any nested +error.svelte components that were defined
|
|
161
|
+
throw action_result.error;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return await load_server_data({
|
|
165
|
+
event,
|
|
166
|
+
options,
|
|
167
|
+
state,
|
|
168
|
+
node,
|
|
169
|
+
parent: async () => {
|
|
170
|
+
/** @type {Record<string, any>} */
|
|
171
|
+
const data = {};
|
|
172
|
+
for (let j = 0; j < i; j += 1) {
|
|
173
|
+
const parent = await server_promises[j];
|
|
174
|
+
if (parent) Object.assign(data, await parent.data);
|
|
175
|
+
}
|
|
176
|
+
return data;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
} catch (e) {
|
|
180
|
+
load_error = /** @type {Error} */ (e);
|
|
181
|
+
throw load_error;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const csr = get_option(nodes, 'csr') ?? true;
|
|
187
|
+
|
|
188
|
+
/** @type {Array<Promise<Record<string, any> | null>>} */
|
|
189
|
+
const load_promises = nodes.map((node, i) => {
|
|
190
|
+
if (load_error) throw load_error;
|
|
191
|
+
return Promise.resolve().then(async () => {
|
|
192
|
+
try {
|
|
193
|
+
return await load_data({
|
|
194
|
+
event,
|
|
195
|
+
fetched,
|
|
196
|
+
node,
|
|
197
|
+
parent: async () => {
|
|
198
|
+
const data = {};
|
|
199
|
+
for (let j = 0; j < i; j += 1) {
|
|
200
|
+
Object.assign(data, await load_promises[j]);
|
|
201
|
+
}
|
|
202
|
+
return data;
|
|
203
|
+
},
|
|
204
|
+
resolve_opts,
|
|
205
|
+
server_data_promise: server_promises[i],
|
|
206
|
+
state,
|
|
207
|
+
csr
|
|
208
|
+
});
|
|
209
|
+
} catch (e) {
|
|
210
|
+
load_error = /** @type {Error} */ (e);
|
|
211
|
+
throw load_error;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// if we don't do this, rejections will be unhandled
|
|
217
|
+
for (const p of server_promises) p.catch(() => {});
|
|
218
|
+
for (const p of load_promises) p.catch(() => {});
|
|
219
|
+
|
|
220
|
+
for (let i = 0; i < nodes.length; i += 1) {
|
|
221
|
+
const node = nodes[i];
|
|
222
|
+
|
|
223
|
+
if (node) {
|
|
224
|
+
try {
|
|
225
|
+
const server_data = await server_promises[i];
|
|
226
|
+
const data = await load_promises[i];
|
|
227
|
+
|
|
228
|
+
branch.push({ node, server_data, data });
|
|
229
|
+
} catch (e) {
|
|
230
|
+
const err = normalize_error(e);
|
|
231
|
+
|
|
232
|
+
if (err instanceof Redirect) {
|
|
233
|
+
if (state.prerendering && should_prerender_data) {
|
|
234
|
+
const body = JSON.stringify({
|
|
235
|
+
type: 'redirect',
|
|
236
|
+
location: err.location
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
state.prerendering.dependencies.set(data_pathname, {
|
|
240
|
+
response: new Response(body),
|
|
241
|
+
body
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return redirect_response(err.status, err.location);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const status = err instanceof HttpError ? err.status : 500;
|
|
249
|
+
const error = await handle_error_and_jsonify(event, options, err);
|
|
250
|
+
|
|
251
|
+
while (i--) {
|
|
252
|
+
if (page.errors[i]) {
|
|
253
|
+
const index = /** @type {number} */ (page.errors[i]);
|
|
254
|
+
const node = await options.manifest._.nodes[index]();
|
|
255
|
+
|
|
256
|
+
let j = i;
|
|
257
|
+
while (!branch[j]) j -= 1;
|
|
258
|
+
|
|
259
|
+
return await render_response({
|
|
260
|
+
event,
|
|
261
|
+
options,
|
|
262
|
+
state,
|
|
263
|
+
resolve_opts,
|
|
264
|
+
page_config: { ssr: true, csr: true },
|
|
265
|
+
status,
|
|
266
|
+
error,
|
|
267
|
+
branch: compact(branch.slice(0, j + 1)).concat({
|
|
268
|
+
node,
|
|
269
|
+
data: null,
|
|
270
|
+
server_data: null
|
|
271
|
+
}),
|
|
272
|
+
fetched
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// if we're still here, it means the error happened in the root layout,
|
|
278
|
+
// which means we have to fall back to error.html
|
|
279
|
+
return static_error_page(options, status, error.message);
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
// push an empty slot so we can rewind past gaps to the
|
|
283
|
+
// layout that corresponds with an +error.svelte page
|
|
284
|
+
branch.push(null);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (state.prerendering && should_prerender_data) {
|
|
289
|
+
const body = `{"type":"data","nodes":[${branch
|
|
290
|
+
.map((node) => serialize_data_node(node?.server_data))
|
|
291
|
+
.join(',')}]}`;
|
|
292
|
+
|
|
293
|
+
state.prerendering.dependencies.set(data_pathname, {
|
|
294
|
+
response: new Response(body),
|
|
295
|
+
body
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return await render_response({
|
|
300
|
+
event,
|
|
301
|
+
options,
|
|
302
|
+
state,
|
|
303
|
+
resolve_opts,
|
|
304
|
+
page_config: {
|
|
305
|
+
csr: get_option(nodes, 'csr') ?? true,
|
|
306
|
+
ssr: true
|
|
307
|
+
},
|
|
308
|
+
status,
|
|
309
|
+
error: null,
|
|
310
|
+
branch: compact(branch),
|
|
311
|
+
action_result,
|
|
312
|
+
fetched
|
|
313
|
+
});
|
|
314
|
+
} catch (error) {
|
|
315
|
+
// if we end up here, it means the data loaded successfull
|
|
316
|
+
// but the page failed to render, or that a prerendering error occurred
|
|
317
|
+
return await respond_with_error({
|
|
318
|
+
event,
|
|
319
|
+
options,
|
|
320
|
+
state,
|
|
321
|
+
status: 500,
|
|
322
|
+
error,
|
|
323
|
+
resolve_opts
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { disable_search, make_trackable } from '../../../utils/url.js';
|
|
2
|
+
import { unwrap_promises } from '../../../utils/promises.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Calls the user's server `load` function.
|
|
6
|
+
* @param {{
|
|
7
|
+
* event: import('types').RequestEvent;
|
|
8
|
+
* options: import('types').SSROptions;
|
|
9
|
+
* state: import('types').SSRState;
|
|
10
|
+
* node: import('types').SSRNode | undefined;
|
|
11
|
+
* parent: () => Promise<Record<string, any>>;
|
|
12
|
+
* }} opts
|
|
13
|
+
* @returns {Promise<import('types').ServerDataNode | null>}
|
|
14
|
+
*/
|
|
15
|
+
export async function load_server_data({ event, options, state, node, parent }) {
|
|
16
|
+
if (!node?.server) return null;
|
|
17
|
+
|
|
18
|
+
const uses = {
|
|
19
|
+
dependencies: new Set(),
|
|
20
|
+
params: new Set(),
|
|
21
|
+
parent: false,
|
|
22
|
+
route: false,
|
|
23
|
+
url: false
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const url = make_trackable(event.url, () => {
|
|
27
|
+
uses.url = true;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (state.prerendering) {
|
|
31
|
+
disable_search(url);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = await node.server.load?.call(null, {
|
|
35
|
+
...event,
|
|
36
|
+
/** @param {string[]} deps */
|
|
37
|
+
depends: (...deps) => {
|
|
38
|
+
for (const dep of deps) {
|
|
39
|
+
const { href } = new URL(dep, event.url);
|
|
40
|
+
uses.dependencies.add(href);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
params: new Proxy(event.params, {
|
|
44
|
+
get: (target, key) => {
|
|
45
|
+
uses.params.add(key);
|
|
46
|
+
return target[/** @type {string} */ (key)];
|
|
47
|
+
}
|
|
48
|
+
}),
|
|
49
|
+
parent: async () => {
|
|
50
|
+
uses.parent = true;
|
|
51
|
+
return parent();
|
|
52
|
+
},
|
|
53
|
+
route: {
|
|
54
|
+
get id() {
|
|
55
|
+
uses.route = true;
|
|
56
|
+
return event.route.id;
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
url
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const data = result ? await unwrap_promises(result) : null;
|
|
63
|
+
if (options.dev) {
|
|
64
|
+
validate_load_response(data, /** @type {string} */ (event.route.id));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
type: 'data',
|
|
69
|
+
data,
|
|
70
|
+
uses,
|
|
71
|
+
slash: node.server.trailingSlash
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Calls the user's `load` function.
|
|
77
|
+
* @param {{
|
|
78
|
+
* event: import('types').RequestEvent;
|
|
79
|
+
* fetched: import('./types').Fetched[];
|
|
80
|
+
* node: import('types').SSRNode | undefined;
|
|
81
|
+
* parent: () => Promise<Record<string, any>>;
|
|
82
|
+
* resolve_opts: import('types').RequiredResolveOptions;
|
|
83
|
+
* server_data_promise: Promise<import('types').ServerDataNode | null>;
|
|
84
|
+
* state: import('types').SSRState;
|
|
85
|
+
* csr: boolean;
|
|
86
|
+
* }} opts
|
|
87
|
+
* @returns {Promise<Record<string, any> | null>}
|
|
88
|
+
*/
|
|
89
|
+
export async function load_data({
|
|
90
|
+
event,
|
|
91
|
+
fetched,
|
|
92
|
+
node,
|
|
93
|
+
parent,
|
|
94
|
+
server_data_promise,
|
|
95
|
+
state,
|
|
96
|
+
resolve_opts,
|
|
97
|
+
csr
|
|
98
|
+
}) {
|
|
99
|
+
const server_data_node = await server_data_promise;
|
|
100
|
+
|
|
101
|
+
if (!node?.universal?.load) {
|
|
102
|
+
return server_data_node?.data ?? null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const result = await node.universal.load.call(null, {
|
|
106
|
+
url: event.url,
|
|
107
|
+
params: event.params,
|
|
108
|
+
data: server_data_node?.data ?? null,
|
|
109
|
+
route: event.route,
|
|
110
|
+
fetch: async (input, init) => {
|
|
111
|
+
const cloned_body = input instanceof Request && input.body ? input.clone().body : null;
|
|
112
|
+
const response = await event.fetch(input, init);
|
|
113
|
+
|
|
114
|
+
const url = new URL(input instanceof Request ? input.url : input, event.url);
|
|
115
|
+
const same_origin = url.origin === event.url.origin;
|
|
116
|
+
|
|
117
|
+
/** @type {import('types').PrerenderDependency} */
|
|
118
|
+
let dependency;
|
|
119
|
+
|
|
120
|
+
if (same_origin) {
|
|
121
|
+
if (state.prerendering) {
|
|
122
|
+
dependency = { response, body: null };
|
|
123
|
+
state.prerendering.dependencies.set(url.pathname, dependency);
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
// simulate CORS errors server-side for consistency with client-side behaviour
|
|
127
|
+
const mode = input instanceof Request ? input.mode : init?.mode ?? 'cors';
|
|
128
|
+
if (mode !== 'no-cors') {
|
|
129
|
+
const acao = response.headers.get('access-control-allow-origin');
|
|
130
|
+
if (!acao || (acao !== event.url.origin && acao !== '*')) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`CORS error: ${
|
|
133
|
+
acao ? 'Incorrect' : 'No'
|
|
134
|
+
} 'Access-Control-Allow-Origin' header is present on the requested resource`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const proxy = new Proxy(response, {
|
|
141
|
+
get(response, key, _receiver) {
|
|
142
|
+
async function text() {
|
|
143
|
+
const body = await response.text();
|
|
144
|
+
|
|
145
|
+
if (!body || typeof body === 'string') {
|
|
146
|
+
const status_number = Number(response.status);
|
|
147
|
+
if (isNaN(status_number)) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`response.status is not a number. value: "${
|
|
150
|
+
response.status
|
|
151
|
+
}" type: ${typeof response.status}`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
fetched.push({
|
|
156
|
+
url: same_origin ? url.href.slice(event.url.origin.length) : url.href,
|
|
157
|
+
method: event.request.method,
|
|
158
|
+
request_body: /** @type {string | ArrayBufferView | undefined} */ (
|
|
159
|
+
input instanceof Request && cloned_body
|
|
160
|
+
? await stream_to_string(cloned_body)
|
|
161
|
+
: init?.body
|
|
162
|
+
),
|
|
163
|
+
response_body: body,
|
|
164
|
+
response: response
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (dependency) {
|
|
169
|
+
dependency.body = body;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return body;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (key === 'arrayBuffer') {
|
|
176
|
+
return async () => {
|
|
177
|
+
const buffer = await response.arrayBuffer();
|
|
178
|
+
|
|
179
|
+
if (dependency) {
|
|
180
|
+
dependency.body = new Uint8Array(buffer);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// TODO should buffer be inlined into the page (albeit base64'd)?
|
|
184
|
+
// any conditions in which it shouldn't be?
|
|
185
|
+
|
|
186
|
+
return buffer;
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (key === 'text') {
|
|
191
|
+
return text;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (key === 'json') {
|
|
195
|
+
return async () => {
|
|
196
|
+
return JSON.parse(await text());
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return Reflect.get(response, key, response);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (csr) {
|
|
205
|
+
// ensure that excluded headers can't be read
|
|
206
|
+
const get = response.headers.get;
|
|
207
|
+
response.headers.get = (key) => {
|
|
208
|
+
const lower = key.toLowerCase();
|
|
209
|
+
const value = get.call(response.headers, lower);
|
|
210
|
+
if (value && !lower.startsWith('x-sveltekit-')) {
|
|
211
|
+
const included = resolve_opts.filterSerializedResponseHeaders(lower, value);
|
|
212
|
+
if (!included) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://kit.svelte.dev/docs/hooks#server-hooks-handle (at ${event.route})`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return value;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return proxy;
|
|
224
|
+
},
|
|
225
|
+
setHeaders: event.setHeaders,
|
|
226
|
+
depends: () => {},
|
|
227
|
+
parent
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const data = result ? await unwrap_promises(result) : null;
|
|
231
|
+
validate_load_response(data, /** @type {string} */ (event.route.id));
|
|
232
|
+
return data;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @param {ReadableStream<Uint8Array>} stream
|
|
237
|
+
*/
|
|
238
|
+
async function stream_to_string(stream) {
|
|
239
|
+
let result = '';
|
|
240
|
+
const reader = stream.getReader();
|
|
241
|
+
const decoder = new TextDecoder();
|
|
242
|
+
while (true) {
|
|
243
|
+
const { done, value } = await reader.read();
|
|
244
|
+
if (done) {
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
result += decoder.decode(value);
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @param {any} data
|
|
254
|
+
* @param {string} [routeId]
|
|
255
|
+
*/
|
|
256
|
+
function validate_load_response(data, routeId) {
|
|
257
|
+
if (data != null && Object.getPrototypeOf(data) !== Object.prototype) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`a load function related to route '${routeId}' returned ${
|
|
260
|
+
typeof data !== 'object'
|
|
261
|
+
? `a ${typeof data}`
|
|
262
|
+
: data instanceof Response
|
|
263
|
+
? 'a Response object'
|
|
264
|
+
: Array.isArray(data)
|
|
265
|
+
? 'an array'
|
|
266
|
+
: 'a non-plain object'
|
|
267
|
+
}, but must return a plain object at the top level (i.e. \`return {...}\`)`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|