@sveltejs/kit 1.0.0-next.46 → 1.0.0-next.460

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.
Files changed (115) hide show
  1. package/README.md +12 -9
  2. package/package.json +93 -65
  3. package/scripts/special-types/$env+dynamic+private.md +8 -0
  4. package/scripts/special-types/$env+dynamic+public.md +8 -0
  5. package/scripts/special-types/$env+static+private.md +19 -0
  6. package/scripts/special-types/$env+static+public.md +7 -0
  7. package/scripts/special-types/$lib.md +1 -0
  8. package/src/cli.js +112 -0
  9. package/src/constants.js +7 -0
  10. package/src/core/adapt/builder.js +207 -0
  11. package/src/core/adapt/index.js +31 -0
  12. package/src/core/config/default-error.html +56 -0
  13. package/src/core/config/index.js +105 -0
  14. package/src/core/config/options.js +498 -0
  15. package/src/core/config/types.d.ts +1 -0
  16. package/src/core/env.js +112 -0
  17. package/src/core/generate_manifest/index.js +78 -0
  18. package/src/core/prerender/crawl.js +194 -0
  19. package/src/core/prerender/prerender.js +425 -0
  20. package/src/core/prerender/queue.js +80 -0
  21. package/src/core/sync/create_manifest_data/index.js +452 -0
  22. package/src/core/sync/create_manifest_data/types.d.ts +37 -0
  23. package/src/core/sync/sync.js +59 -0
  24. package/src/core/sync/utils.js +33 -0
  25. package/src/core/sync/write_ambient.js +53 -0
  26. package/src/core/sync/write_client_manifest.js +94 -0
  27. package/src/core/sync/write_matchers.js +25 -0
  28. package/src/core/sync/write_root.js +91 -0
  29. package/src/core/sync/write_tsconfig.js +195 -0
  30. package/src/core/sync/write_types/index.js +595 -0
  31. package/src/core/utils.js +70 -0
  32. package/src/exports/hooks/index.js +1 -0
  33. package/src/exports/hooks/sequence.js +44 -0
  34. package/src/exports/index.js +45 -0
  35. package/src/exports/node/index.js +145 -0
  36. package/src/exports/node/polyfills.js +40 -0
  37. package/src/exports/vite/build/build_server.js +349 -0
  38. package/src/exports/vite/build/build_service_worker.js +90 -0
  39. package/src/exports/vite/build/utils.js +160 -0
  40. package/src/exports/vite/dev/index.js +543 -0
  41. package/src/exports/vite/index.js +595 -0
  42. package/src/exports/vite/preview/index.js +186 -0
  43. package/src/exports/vite/types.d.ts +3 -0
  44. package/src/exports/vite/utils.js +345 -0
  45. package/src/runtime/app/env.js +1 -0
  46. package/src/runtime/app/environment.js +11 -0
  47. package/src/runtime/app/navigation.js +22 -0
  48. package/src/runtime/app/paths.js +1 -0
  49. package/src/runtime/app/stores.js +102 -0
  50. package/src/runtime/client/ambient.d.ts +24 -0
  51. package/src/runtime/client/client.js +1387 -0
  52. package/src/runtime/client/fetcher.js +60 -0
  53. package/src/runtime/client/parse.js +60 -0
  54. package/src/runtime/client/singletons.js +21 -0
  55. package/src/runtime/client/start.js +45 -0
  56. package/src/runtime/client/types.d.ts +88 -0
  57. package/src/runtime/client/utils.js +140 -0
  58. package/src/runtime/components/error.svelte +16 -0
  59. package/{assets → src/runtime}/components/layout.svelte +0 -0
  60. package/src/runtime/control.js +33 -0
  61. package/src/runtime/env/dynamic/private.js +1 -0
  62. package/src/runtime/env/dynamic/public.js +1 -0
  63. package/src/runtime/env-private.js +6 -0
  64. package/src/runtime/env-public.js +6 -0
  65. package/src/runtime/env.js +6 -0
  66. package/src/runtime/hash.js +16 -0
  67. package/src/runtime/paths.js +11 -0
  68. package/src/runtime/server/data/index.js +146 -0
  69. package/src/runtime/server/endpoint.js +63 -0
  70. package/src/runtime/server/index.js +339 -0
  71. package/src/runtime/server/page/cookie.js +25 -0
  72. package/src/runtime/server/page/crypto.js +239 -0
  73. package/src/runtime/server/page/csp.js +249 -0
  74. package/src/runtime/server/page/fetch.js +269 -0
  75. package/src/runtime/server/page/index.js +404 -0
  76. package/src/runtime/server/page/load_data.js +124 -0
  77. package/src/runtime/server/page/render.js +358 -0
  78. package/src/runtime/server/page/respond_with_error.js +92 -0
  79. package/src/runtime/server/page/serialize_data.js +58 -0
  80. package/src/runtime/server/page/types.d.ts +44 -0
  81. package/src/runtime/server/utils.js +209 -0
  82. package/src/utils/array.js +9 -0
  83. package/src/utils/error.js +22 -0
  84. package/src/utils/escape.js +46 -0
  85. package/src/utils/filesystem.js +108 -0
  86. package/src/utils/functions.js +16 -0
  87. package/src/utils/http.js +55 -0
  88. package/src/utils/misc.js +1 -0
  89. package/src/utils/routing.js +137 -0
  90. package/src/utils/url.js +142 -0
  91. package/svelte-kit.js +1 -1
  92. package/types/ambient.d.ts +332 -0
  93. package/types/index.d.ts +343 -0
  94. package/types/internal.d.ts +383 -0
  95. package/types/private.d.ts +213 -0
  96. package/CHANGELOG.md +0 -456
  97. package/assets/components/error.svelte +0 -13
  98. package/assets/runtime/app/env.js +0 -5
  99. package/assets/runtime/app/navigation.js +0 -44
  100. package/assets/runtime/app/paths.js +0 -1
  101. package/assets/runtime/app/stores.js +0 -93
  102. package/assets/runtime/chunks/utils.js +0 -22
  103. package/assets/runtime/internal/singletons.js +0 -23
  104. package/assets/runtime/internal/start.js +0 -771
  105. package/assets/runtime/paths.js +0 -12
  106. package/dist/chunks/index.js +0 -3522
  107. package/dist/chunks/index2.js +0 -587
  108. package/dist/chunks/index3.js +0 -246
  109. package/dist/chunks/index4.js +0 -539
  110. package/dist/chunks/index5.js +0 -763
  111. package/dist/chunks/index6.js +0 -322
  112. package/dist/chunks/standard.js +0 -99
  113. package/dist/chunks/utils.js +0 -83
  114. package/dist/cli.js +0 -546
  115. package/dist/ssr.js +0 -2581
@@ -0,0 +1,404 @@
1
+ import { devalue } from 'devalue';
2
+ import { negotiate } from '../../../utils/http.js';
3
+ import { render_response } from './render.js';
4
+ import { respond_with_error } from './respond_with_error.js';
5
+ import {
6
+ method_not_allowed,
7
+ error_to_pojo,
8
+ allowed_methods,
9
+ get_option,
10
+ static_error_page
11
+ } from '../utils.js';
12
+ import { create_fetch } from './fetch.js';
13
+ import { HttpError, Redirect } from '../../control.js';
14
+ import { error, json } from '../../../exports/index.js';
15
+ import { compact } from '../../../utils/array.js';
16
+ import { normalize_error } from '../../../utils/error.js';
17
+ import { load_data, load_server_data } from './load_data.js';
18
+ import { DATA_SUFFIX } from '../../../constants.js';
19
+
20
+ /**
21
+ * @typedef {import('./types.js').Loaded} Loaded
22
+ * @typedef {import('types').SSRNode} SSRNode
23
+ * @typedef {import('types').SSROptions} SSROptions
24
+ * @typedef {import('types').SSRState} SSRState
25
+ */
26
+
27
+ /**
28
+ * @param {import('types').RequestEvent} event
29
+ * @param {import('types').SSRRoute} route
30
+ * @param {import('types').PageNodeIndexes} page
31
+ * @param {import('types').SSROptions} options
32
+ * @param {import('types').SSRState} state
33
+ * @param {import('types').RequiredResolveOptions} resolve_opts
34
+ * @returns {Promise<Response>}
35
+ */
36
+ export async function render_page(event, route, page, options, state, resolve_opts) {
37
+ if (state.initiator === route) {
38
+ // infinite request cycle detected
39
+ return new Response(`Not found: ${event.url.pathname}`, {
40
+ status: 404
41
+ });
42
+ }
43
+
44
+ const accept = negotiate(event.request.headers.get('accept') || 'text/html', [
45
+ 'text/html',
46
+ 'application/json'
47
+ ]);
48
+
49
+ if (
50
+ accept === 'application/json' &&
51
+ event.request.method !== 'GET' &&
52
+ event.request.method !== 'HEAD'
53
+ ) {
54
+ const node = await options.manifest._.nodes[page.leaf]();
55
+ if (node.server) {
56
+ return handle_json_request(event, options, node.server);
57
+ }
58
+ }
59
+
60
+ try {
61
+ const nodes = await Promise.all([
62
+ // we use == here rather than === because [undefined] serializes as "[null]"
63
+ ...page.layouts.map((n) => (n == undefined ? n : options.manifest._.nodes[n]())),
64
+ options.manifest._.nodes[page.leaf]()
65
+ ]);
66
+
67
+ const leaf_node = /** @type {import('types').SSRNode} */ (nodes.at(-1));
68
+
69
+ let status = 200;
70
+
71
+ /** @type {HttpError | Error} */
72
+ let mutation_error;
73
+
74
+ /** @type {Record<string, string> | undefined} */
75
+ let validation_errors;
76
+
77
+ if (leaf_node.server && event.request.method !== 'GET' && event.request.method !== 'HEAD') {
78
+ // for non-GET requests, first call handler in +page.server.js
79
+ // (this also determines status code)
80
+ try {
81
+ const method = /** @type {'POST' | 'PATCH' | 'PUT' | 'DELETE'} */ (event.request.method);
82
+ const handler = leaf_node.server[method];
83
+ if (handler) {
84
+ const result = await handler.call(null, event);
85
+
86
+ if (result?.errors) {
87
+ validation_errors = result.errors;
88
+ status = result.status ?? 400;
89
+ }
90
+
91
+ if (event.request.method === 'POST' && result?.location) {
92
+ return redirect_response(303, result.location);
93
+ }
94
+ } else {
95
+ event.setHeaders({
96
+ allow: allowed_methods(leaf_node.server).join(', ')
97
+ });
98
+
99
+ mutation_error = error(405, 'Method not allowed');
100
+ }
101
+ } catch (e) {
102
+ if (e instanceof Redirect) {
103
+ return redirect_response(e.status, e.location);
104
+ }
105
+
106
+ mutation_error = /** @type {HttpError | Error} */ (e);
107
+ }
108
+ }
109
+
110
+ const should_prerender_data = nodes.some((node) => node?.server);
111
+ const data_pathname = event.url.pathname.replace(/\/$/, '') + DATA_SUFFIX;
112
+
113
+ // it's crucial that we do this before returning the non-SSR response, otherwise
114
+ // SvelteKit will erroneously believe that the path has been prerendered,
115
+ // causing functions to be omitted from the manifesst generated later
116
+ const should_prerender = get_option(nodes, 'prerender') ?? false;
117
+ if (should_prerender) {
118
+ const mod = leaf_node.server;
119
+ if (mod && (mod.POST || mod.PUT || mod.DELETE || mod.PATCH)) {
120
+ throw new Error('Cannot prerender pages that have mutative methods');
121
+ }
122
+ } else if (state.prerendering) {
123
+ // if the page isn't marked as prerenderable, then bail out at this point
124
+ return new Response(undefined, {
125
+ status: 204
126
+ });
127
+ }
128
+
129
+ const { fetcher, fetched, cookies } = create_fetch({
130
+ event,
131
+ options,
132
+ state,
133
+ route,
134
+ prerender_default: should_prerender
135
+ });
136
+
137
+ if (get_option(nodes, 'ssr') === false) {
138
+ return await render_response({
139
+ branch: [],
140
+ validation_errors: undefined,
141
+ fetched,
142
+ cookies,
143
+ page_config: {
144
+ ssr: false,
145
+ csr: get_option(nodes, 'csr') ?? true
146
+ },
147
+ status,
148
+ error: null,
149
+ event,
150
+ options,
151
+ state,
152
+ resolve_opts
153
+ });
154
+ }
155
+
156
+ /** @type {Array<Loaded | null>} */
157
+ let branch = [];
158
+
159
+ /** @type {Error | null} */
160
+ let load_error = null;
161
+
162
+ /** @type {Array<Promise<import('types').ServerDataNode | null>>} */
163
+ const server_promises = nodes.map((node, i) => {
164
+ if (load_error) {
165
+ // if an error happens immediately, don't bother with the rest of the nodes
166
+ throw load_error;
167
+ }
168
+
169
+ return Promise.resolve().then(async () => {
170
+ try {
171
+ if (node === leaf_node && mutation_error) {
172
+ // we wait until here to throw the error so that we can use
173
+ // any nested +error.svelte components that were defined
174
+ throw mutation_error;
175
+ }
176
+
177
+ return await load_server_data({
178
+ event,
179
+ state,
180
+ node,
181
+ parent: async () => {
182
+ /** @type {Record<string, any>} */
183
+ const data = {};
184
+ for (let j = 0; j < i; j += 1) {
185
+ const parent = await server_promises[j];
186
+ if (parent) Object.assign(data, await parent.data);
187
+ }
188
+ return data;
189
+ }
190
+ });
191
+ } catch (e) {
192
+ load_error = /** @type {Error} */ (e);
193
+ throw load_error;
194
+ }
195
+ });
196
+ });
197
+
198
+ /** @type {Array<Promise<Record<string, any> | null>>} */
199
+ const load_promises = nodes.map((node, i) => {
200
+ if (load_error) throw load_error;
201
+ return Promise.resolve().then(async () => {
202
+ try {
203
+ return await load_data({
204
+ event,
205
+ fetcher,
206
+ node,
207
+ parent: async () => {
208
+ const data = {};
209
+ for (let j = 0; j < i; j += 1) {
210
+ Object.assign(data, await load_promises[j]);
211
+ }
212
+ return data;
213
+ },
214
+ server_data_promise: server_promises[i],
215
+ state
216
+ });
217
+ } catch (e) {
218
+ load_error = /** @type {Error} */ (e);
219
+ throw load_error;
220
+ }
221
+ });
222
+ });
223
+
224
+ // if we don't do this, rejections will be unhandled
225
+ for (const p of server_promises) p.catch(() => {});
226
+ for (const p of load_promises) p.catch(() => {});
227
+
228
+ for (let i = 0; i < nodes.length; i += 1) {
229
+ const node = nodes[i];
230
+
231
+ if (node) {
232
+ try {
233
+ const server_data = await server_promises[i];
234
+ const data = await load_promises[i];
235
+
236
+ branch.push({ node, server_data, data });
237
+ } catch (e) {
238
+ const error = normalize_error(e);
239
+
240
+ if (error instanceof Redirect) {
241
+ if (state.prerendering && should_prerender_data) {
242
+ const body = `window.__sveltekit_data = ${JSON.stringify({
243
+ type: 'redirect',
244
+ location: error.location
245
+ })}`;
246
+
247
+ state.prerendering.dependencies.set(data_pathname, {
248
+ response: new Response(body),
249
+ body
250
+ });
251
+ }
252
+
253
+ return redirect_response(error.status, error.location);
254
+ }
255
+
256
+ if (!(error instanceof HttpError)) {
257
+ options.handle_error(/** @type {Error} */ (error), event);
258
+ }
259
+
260
+ const status = error instanceof HttpError ? error.status : 500;
261
+
262
+ while (i--) {
263
+ if (page.errors[i]) {
264
+ const index = /** @type {number} */ (page.errors[i]);
265
+ const node = await options.manifest._.nodes[index]();
266
+
267
+ let j = i;
268
+ while (!branch[j]) j -= 1;
269
+
270
+ return await render_response({
271
+ event,
272
+ options,
273
+ state,
274
+ resolve_opts,
275
+ page_config: { ssr: true, csr: true },
276
+ status,
277
+ error,
278
+ branch: compact(branch.slice(0, j + 1)).concat({
279
+ node,
280
+ data: null,
281
+ server_data: null
282
+ }),
283
+ fetched,
284
+ cookies,
285
+ validation_errors: undefined
286
+ });
287
+ }
288
+ }
289
+
290
+ // if we're still here, it means the error happened in the root layout,
291
+ // which means we have to fall back to error.html
292
+ return static_error_page(
293
+ options,
294
+ status,
295
+ /** @type {HttpError | Error} */ (error).message
296
+ );
297
+ }
298
+ } else {
299
+ // push an empty slot so we can rewind past gaps to the
300
+ // layout that corresponds with an +error.svelte page
301
+ branch.push(null);
302
+ }
303
+ }
304
+
305
+ if (state.prerendering && should_prerender_data) {
306
+ const body = `window.__sveltekit_data = ${devalue({
307
+ type: 'data',
308
+ nodes: branch.map((branch_node) => branch_node?.server_data)
309
+ })}`;
310
+
311
+ state.prerendering.dependencies.set(data_pathname, {
312
+ response: new Response(body),
313
+ body
314
+ });
315
+ }
316
+
317
+ // TODO use validation_errors
318
+
319
+ return await render_response({
320
+ event,
321
+ options,
322
+ state,
323
+ resolve_opts,
324
+ page_config: {
325
+ csr: get_option(nodes, 'csr') ?? true,
326
+ ssr: true
327
+ },
328
+ status,
329
+ error: null,
330
+ branch: compact(branch),
331
+ validation_errors,
332
+ fetched,
333
+ cookies
334
+ });
335
+ } catch (error) {
336
+ // if we end up here, it means the data loaded successfull
337
+ // but the page failed to render, or that a prerendering error occurred
338
+ options.handle_error(/** @type {Error} */ (error), event);
339
+
340
+ return await respond_with_error({
341
+ event,
342
+ options,
343
+ state,
344
+ status: 500,
345
+ error: /** @type {Error} */ (error),
346
+ resolve_opts
347
+ });
348
+ }
349
+ }
350
+
351
+ /**
352
+ * @param {import('types').RequestEvent} event
353
+ * @param {import('types').SSROptions} options
354
+ * @param {import('types').SSRNode['server']} mod
355
+ */
356
+ export async function handle_json_request(event, options, mod) {
357
+ const method = /** @type {'POST' | 'PUT' | 'PATCH' | 'DELETE'} */ (event.request.method);
358
+ const handler = mod[method];
359
+
360
+ if (!handler) {
361
+ return method_not_allowed(mod, method);
362
+ }
363
+
364
+ try {
365
+ // @ts-ignore
366
+ const result = await handler.call(null, event);
367
+
368
+ if (result?.errors) {
369
+ // @ts-ignore
370
+ return json({ errors: result.errors }, { status: result.status || 400 });
371
+ }
372
+
373
+ return new Response(undefined, {
374
+ status: 204,
375
+ // @ts-ignore
376
+ headers: result?.location ? { location: result.location } : undefined
377
+ });
378
+ } catch (e) {
379
+ const error = normalize_error(e);
380
+
381
+ if (error instanceof Redirect) {
382
+ return redirect_response(error.status, error.location);
383
+ }
384
+
385
+ if (!(error instanceof HttpError)) {
386
+ options.handle_error(error, event);
387
+ }
388
+
389
+ return json(error_to_pojo(error, options.get_stack), {
390
+ status: error instanceof HttpError ? error.status : 500
391
+ });
392
+ }
393
+ }
394
+
395
+ /**
396
+ * @param {number} status
397
+ * @param {string} location
398
+ */
399
+ function redirect_response(status, location) {
400
+ return new Response(undefined, {
401
+ status,
402
+ headers: { location }
403
+ });
404
+ }
@@ -0,0 +1,124 @@
1
+ import { disable_search, make_trackable } from '../../../utils/url.js';
2
+
3
+ /**
4
+ * Calls the user's `load` function.
5
+ * @param {{
6
+ * event: import('types').RequestEvent;
7
+ * state: import('types').SSRState;
8
+ * node: import('types').SSRNode | undefined;
9
+ * parent: () => Promise<Record<string, any>>;
10
+ * }} opts
11
+ * @returns {Promise<import('types').ServerDataNode | null>}
12
+ */
13
+ export async function load_server_data({ event, state, node, parent }) {
14
+ if (!node?.server) return null;
15
+
16
+ const uses = {
17
+ dependencies: new Set(),
18
+ params: new Set(),
19
+ parent: false,
20
+ url: false
21
+ };
22
+
23
+ const url = make_trackable(event.url, () => {
24
+ uses.url = true;
25
+ });
26
+
27
+ if (state.prerendering) {
28
+ disable_search(url);
29
+ }
30
+
31
+ const result = await node.server.load?.call(null, {
32
+ ...event,
33
+ /** @param {string[]} deps */
34
+ depends: (...deps) => {
35
+ for (const dep of deps) {
36
+ const { href } = new URL(dep, event.url);
37
+ uses.dependencies.add(href);
38
+ }
39
+ },
40
+ params: new Proxy(event.params, {
41
+ get: (target, key) => {
42
+ uses.params.add(key);
43
+ return target[/** @type {string} */ (key)];
44
+ }
45
+ }),
46
+ parent: async () => {
47
+ uses.parent = true;
48
+ return parent();
49
+ },
50
+ url
51
+ });
52
+
53
+ const data = result ? await unwrap_promises(result) : null;
54
+
55
+ return {
56
+ type: 'data',
57
+ data,
58
+ uses: {
59
+ dependencies: uses.dependencies.size > 0 ? Array.from(uses.dependencies) : undefined,
60
+ params: uses.params.size > 0 ? Array.from(uses.params) : undefined,
61
+ parent: uses.parent ? 1 : undefined,
62
+ url: uses.url ? 1 : undefined
63
+ }
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Calls the user's `load` function.
69
+ * @param {{
70
+ * event: import('types').RequestEvent;
71
+ * fetcher: typeof fetch;
72
+ * node: import('types').SSRNode | undefined;
73
+ * parent: () => Promise<Record<string, any>>;
74
+ * server_data_promise: Promise<import('types').ServerDataNode | null>;
75
+ * state: import('types').SSRState;
76
+ * }} opts
77
+ * @returns {Promise<Record<string, any> | null>}
78
+ */
79
+ export async function load_data({ event, fetcher, node, parent, server_data_promise }) {
80
+ const server_data_node = await server_data_promise;
81
+
82
+ if (!node?.shared?.load) {
83
+ return server_data_node?.data ?? null;
84
+ }
85
+
86
+ const load_event = {
87
+ url: event.url,
88
+ params: event.params,
89
+ data: server_data_node?.data ?? null,
90
+ routeId: event.routeId,
91
+ fetch: fetcher,
92
+ setHeaders: event.setHeaders,
93
+ depends: () => {},
94
+ parent
95
+ };
96
+
97
+ // TODO remove this for 1.0
98
+ Object.defineProperties(load_event, {
99
+ session: {
100
+ get() {
101
+ throw new Error(
102
+ 'session is no longer available. See https://github.com/sveltejs/kit/discussions/5883'
103
+ );
104
+ },
105
+ enumerable: false
106
+ }
107
+ });
108
+
109
+ const data = await node.shared.load.call(null, load_event);
110
+
111
+ return data ? unwrap_promises(data) : null;
112
+ }
113
+
114
+ /** @param {Record<string, any>} object */
115
+ async function unwrap_promises(object) {
116
+ /** @type {Record<string, any>} */
117
+ const unwrapped = {};
118
+
119
+ for (const key in object) {
120
+ unwrapped[key] = await object[key];
121
+ }
122
+
123
+ return unwrapped;
124
+ }