@sveltejs/kit 3.0.0-next.22 → 3.0.0-next.24

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 (106) hide show
  1. package/package.json +40 -9
  2. package/src/cli.js +3 -3
  3. package/src/constants.js +13 -1
  4. package/src/core/adapt/builder.js +2 -3
  5. package/src/core/env.js +139 -181
  6. package/src/core/postbuild/analyse.js +9 -4
  7. package/src/core/postbuild/prerender.js +22 -23
  8. package/src/core/sync/create_manifest_data/index.js +29 -33
  9. package/src/core/sync/sync.js +23 -40
  10. package/src/core/sync/write_app_manifest.js +83 -0
  11. package/src/core/sync/write_client_manifest.js +6 -4
  12. package/src/core/sync/write_server.js +10 -6
  13. package/src/core/sync/write_types/index.js +2 -2
  14. package/src/core/utils.js +0 -28
  15. package/src/exports/hooks/public.d.ts +9 -1
  16. package/src/exports/index.js +10 -0
  17. package/src/exports/node/index.js +77 -5
  18. package/src/exports/public.d.ts +9 -0
  19. package/src/exports/vite/build/build_server.js +3 -3
  20. package/src/exports/vite/build/utils.js +48 -4
  21. package/src/exports/vite/dev/index.js +11 -22
  22. package/src/exports/vite/index.js +62 -345
  23. package/src/exports/vite/module_ids.js +1 -11
  24. package/src/exports/vite/plugins/env-vars.js +117 -0
  25. package/src/exports/vite/preview/index.js +6 -4
  26. package/src/exports/vite/utils.js +2 -4
  27. package/src/runtime/app/env/{types.d.ts → client.js} +9 -4
  28. package/src/runtime/app/env/index.js +1 -2
  29. package/src/runtime/app/env/private/index.js +1 -0
  30. package/src/runtime/app/env/public/client.js +1 -1
  31. package/src/runtime/app/env/public/server.js +1 -1
  32. package/src/runtime/app/env/{internal.js → server.js} +4 -4
  33. package/src/runtime/app/forms/client.js +263 -0
  34. package/src/runtime/app/forms/index.js +1 -263
  35. package/src/runtime/app/forms/public.d.ts +1 -1
  36. package/src/runtime/app/forms/server.js +6 -0
  37. package/src/runtime/app/forms/shared.js +34 -0
  38. package/src/runtime/app/manifest/index.js +1 -1
  39. package/src/runtime/app/navigation/client.js +15 -0
  40. package/src/runtime/app/navigation/index.js +1 -15
  41. package/src/runtime/app/navigation/public.d.ts +1 -1
  42. package/src/runtime/app/navigation/server.js +15 -0
  43. package/src/runtime/app/paths/server.js +1 -1
  44. package/src/runtime/app/server/public.d.ts +512 -0
  45. package/src/runtime/app/server/remote/command.js +1 -1
  46. package/src/runtime/app/server/remote/form.js +16 -6
  47. package/src/runtime/app/server/remote/prerender.js +2 -3
  48. package/src/runtime/app/server/remote/query.js +2 -2
  49. package/src/runtime/app/server/remote/requested.js +3 -3
  50. package/src/runtime/app/state/client.svelte.js +207 -0
  51. package/src/runtime/app/state/index.js +1 -66
  52. package/src/runtime/app/state/public.d.ts +1 -1
  53. package/src/runtime/client/bundle.js +1 -1
  54. package/src/runtime/client/client.js +206 -274
  55. package/src/runtime/client/fetcher.js +18 -8
  56. package/src/runtime/client/remote-functions/command.svelte.js +1 -1
  57. package/src/runtime/client/remote-functions/form.svelte.js +10 -7
  58. package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
  59. package/src/runtime/client/remote-functions/query/index.js +1 -1
  60. package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -1
  61. package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
  62. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  63. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +4 -3
  64. package/src/runtime/client/remote-functions/query-live/iterator.js +1 -1
  65. package/src/runtime/client/remote-functions/shared.svelte.js +3 -3
  66. package/src/runtime/client/snapshots.js +1 -3
  67. package/src/runtime/client/stream.js +27 -20
  68. package/src/runtime/client/utils.js +7 -3
  69. package/src/runtime/components/root.svelte +5 -5
  70. package/src/runtime/env/dynamic/private.js +1 -1
  71. package/src/runtime/env/static/private.js +1 -1
  72. package/src/runtime/error-chain.js +54 -0
  73. package/src/runtime/form-utils.js +53 -77
  74. package/src/runtime/invalid-import.js +1 -0
  75. package/src/runtime/props.svelte.js +1 -1
  76. package/src/runtime/server/data/index.js +1 -1
  77. package/src/runtime/server/endpoint.js +8 -3
  78. package/src/runtime/server/env_module.js +1 -1
  79. package/src/runtime/server/errors.js +2 -2
  80. package/src/runtime/server/index.js +2 -2
  81. package/src/runtime/server/page/actions.js +77 -122
  82. package/src/runtime/server/page/index.js +37 -69
  83. package/src/runtime/server/page/render.js +18 -23
  84. package/src/runtime/server/remote-functions.js +15 -43
  85. package/src/runtime/server/respond.js +23 -3
  86. package/src/telemetry.js +1 -33
  87. package/src/types/ambient-private.d.ts +9 -17
  88. package/src/types/internal.d.ts +21 -5
  89. package/src/types/private.d.ts +1 -1
  90. package/src/utils/exports.js +1 -0
  91. package/src/utils/filesystem.js +9 -21
  92. package/src/utils/functions.js +10 -0
  93. package/src/utils/promise.js +25 -0
  94. package/src/utils/routing.js +0 -11
  95. package/src/utils/url.js +0 -11
  96. package/src/version.js +1 -1
  97. package/types/index.d.ts +1134 -1136
  98. package/types/index.d.ts.map +50 -50
  99. package/src/exports/remote/index.js +0 -11
  100. package/src/exports/remote/public.d.ts +0 -519
  101. package/src/runtime/app/env/private.js +0 -1
  102. package/src/runtime/app/env/standard-schema.d.ts +0 -0
  103. package/src/runtime/app/state/client.js +0 -63
  104. package/src/runtime/client/state.svelte.js +0 -98
  105. package/src/runtime/server/ambient.d.ts +0 -4
  106. package/src/utils/path.js +0 -23
@@ -116,12 +116,13 @@ function get_raw_body(req, body_size_limit) {
116
116
  /**
117
117
  * @param {{
118
118
  * request: import('http').IncomingMessage;
119
+ * response?: import('http').ServerResponse;
119
120
  * base: string;
120
121
  * bodySizeLimit?: number;
121
122
  * }} options
122
123
  * @returns {Request}
123
124
  */
124
- export function getRequest({ request, base, bodySizeLimit }) {
125
+ export function getRequest({ request, response, base, bodySizeLimit }) {
125
126
  let headers = /** @type {Record<string, string>} */ (request.headers);
126
127
  if (request.httpVersionMajor >= 2) {
127
128
  // the Request constructor rejects headers with ':' in the name
@@ -144,6 +145,15 @@ export function getRequest({ request, base, bodySizeLimit }) {
144
145
  }
145
146
  });
146
147
 
148
+ // `readableAborted` stays false once the request has been fully read (or drained),
149
+ // so a client disconnect must also be detected on the response side. `writableEnded`
150
+ // rather than `writableFinished` because HTTP/2 marks cancelled streams as finished
151
+ response?.once('close', () => {
152
+ if (!response.writableEnded) {
153
+ controller.abort();
154
+ }
155
+ });
156
+
147
157
  return new Request(base + request.url, {
148
158
  // @ts-expect-error
149
159
  duplex: 'half',
@@ -214,14 +224,14 @@ export function setResponse(res, response) {
214
224
  }
215
225
  }
216
226
 
217
- res.writeHead(response.status);
218
-
219
227
  if (!response.body) {
228
+ res.writeHead(response.status);
220
229
  res.end();
221
230
  return;
222
231
  }
223
232
 
224
233
  if (response.body.locked) {
234
+ res.writeHead(response.status);
225
235
  res.end(
226
236
  'Fatal error: Response body is locked. ' +
227
237
  "This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
@@ -249,11 +259,73 @@ export function setResponse(res, response) {
249
259
  res.on('close', cancel);
250
260
  res.on('error', cancel);
251
261
 
252
- void next();
262
+ /** @type {Uint8Array<ArrayBuffer>[]} */
263
+ const buffered = [];
264
+
265
+ /** @type {ReturnType<typeof reader.read> | null} */
266
+ let pending = null;
267
+
268
+ void probe();
269
+
270
+ // a fixed body (a string, buffer or blob, however constructed) settles all its
271
+ // reads before the next macrotask, so it can be measured and sent with a
272
+ // `content-length`; a genuine stream leaves a read pending and only has its
273
+ // headers delayed by a single tick
274
+ async function probe() {
275
+ try {
276
+ /** @type {Promise<undefined>} */
277
+ const deadline = new Promise((fulfil) => setImmediate(() => fulfil(undefined)));
278
+
279
+ while (buffered.length < 2) {
280
+ pending = reader.read();
281
+ const result = await Promise.race([pending, deadline]);
282
+
283
+ if (!result) break; // deadline hit — treat the body as a stream
284
+
285
+ pending = null;
286
+
287
+ if (result.done) {
288
+ // a `content-length` next to a `transfer-encoding` would be invalid
289
+ if (!res.hasHeader('content-length') && !res.hasHeader('transfer-encoding')) {
290
+ res.setHeader(
291
+ 'content-length',
292
+ buffered.reduce((total, chunk) => total + chunk.byteLength, 0)
293
+ );
294
+ }
295
+ break;
296
+ }
297
+
298
+ buffered.push(result.value);
299
+ }
300
+
301
+ if (res.destroyed) return;
302
+
303
+ res.writeHead(response.status);
304
+ await next();
305
+ } catch (error) {
306
+ if (!res.headersSent) res.writeHead(response.status);
307
+ cancel(error instanceof Error ? error : new Error(String(error)));
308
+ }
309
+ }
310
+
253
311
  async function next() {
254
312
  try {
255
313
  for (;;) {
256
- const { done, value } = await reader.read();
314
+ /** @type {Awaited<ReturnType<typeof reader.read>>} */
315
+ let result;
316
+ if (buffered.length > 0) {
317
+ result = {
318
+ done: false,
319
+ value: /** @type {Uint8Array<ArrayBuffer>} */ (buffered.shift())
320
+ };
321
+ } else if (pending) {
322
+ result = await pending;
323
+ pending = null;
324
+ } else {
325
+ result = await reader.read();
326
+ }
327
+
328
+ const { done, value } = result;
257
329
 
258
330
  if (done) break;
259
331
 
@@ -16,6 +16,7 @@ import { BuildData, SSRNodeLoader, SSRRoute, ValidatedConfig } from 'types';
16
16
  import { Plugin } from 'vite';
17
17
  import { RouteId as AppRouteId, LayoutParams as AppLayoutParams } from '$app/types';
18
18
  import { ParamMatcher } from '@sveltejs/kit/params';
19
+ import { StandardSchemaV1 } from '@standard-schema/spec';
19
20
 
20
21
  export { PrerenderOption } from '../types/private.js';
21
22
 
@@ -99,6 +100,14 @@ export interface ActionFailure<T = undefined> {
99
100
  [uniqueSymbol]: true; // necessary or else UnpackValidationError could wrongly unpack objects with the same shape as ActionFailure
100
101
  }
101
102
 
103
+ /**
104
+ * A validation error thrown by `invalid`.
105
+ */
106
+ export interface ValidationError {
107
+ /** The validation issues */
108
+ issues: StandardSchemaV1.Issue[];
109
+ }
110
+
102
111
  type UnpackValidationError<T> =
103
112
  T extends ActionFailure<infer X>
104
113
  ? X
@@ -128,7 +128,7 @@ export function build_server_nodes(
128
128
  /** @type {string[]} */
129
129
  let stylesheets = [];
130
130
 
131
- /** @type {string[]} */
131
+ /** @type {import('types').FontDependency[]} */
132
132
  let fonts = [];
133
133
 
134
134
  /** @type {Set<string>} */
@@ -187,7 +187,7 @@ export function build_server_nodes(
187
187
  }
188
188
 
189
189
  if (client_manifest) {
190
- const entry_path = `${out_dir}/generated/client-optimized/nodes/${i}.js`;
190
+ const entry_path = `${out_dir}/generated/build/client-optimized/nodes/${i}.js`;
191
191
  const entry = find_deps(client_manifest, entry_path, true, root);
192
192
 
193
193
  // Eagerly load client stylesheets and fonts imported by the SSR-ed page to avoid FOUC.
@@ -212,7 +212,7 @@ export function build_server_nodes(
212
212
 
213
213
  imported = entry.imports;
214
214
  stylesheets = Array.from(eager_css);
215
- fonts = filter_fonts(Array.from(eager_assets));
215
+ fonts = filter_fonts(Array.from(eager_assets), client_manifest, root);
216
216
  } else {
217
217
  for (const entry of [component, universal]) {
218
218
  if (!entry) continue;
@@ -94,7 +94,7 @@ export function find_deps(manifest, entry, add_dynamic_css, root) {
94
94
  imports: Array.from(imports),
95
95
  stylesheets: Array.from(stylesheets),
96
96
  // TODO do we need this separately?
97
- fonts: filter_fonts(assets),
97
+ fonts: filter_fonts(assets, manifest, root),
98
98
  stylesheet_map
99
99
  };
100
100
  }
@@ -116,12 +116,56 @@ export function resolve_symlinks(manifest, file, root) {
116
116
  return { chunk, file };
117
117
  }
118
118
 
119
+ /** @type {WeakMap<import('vite').Manifest, Map<string, string>>} */
120
+ const source_maps = new WeakMap();
121
+
119
122
  /**
120
123
  * @param {string[]} assets
121
- * @returns {string[]}
124
+ * @param {import('vite').Manifest} manifest
125
+ * @param {string} root
126
+ * @returns {import('types').FontDependency[]}
122
127
  */
123
- export function filter_fonts(assets) {
124
- return assets.filter((asset) => /\.(woff2?|ttf|otf)$/.test(asset));
128
+ export function filter_fonts(assets, manifest, root) {
129
+ let sources = source_maps.get(manifest);
130
+
131
+ if (!sources) {
132
+ sources = new Map();
133
+ source_maps.set(manifest, sources);
134
+
135
+ // identical files are emitted once but can have several sources — keep the first
136
+ for (const key of Object.keys(manifest).sort()) {
137
+ const { file, src } = manifest[key];
138
+ if (src && !sources.has(file)) {
139
+ sources.set(file, src);
140
+ }
141
+ }
142
+ }
143
+
144
+ return assets
145
+ .filter((asset) => /\.(woff2?|ttf|otf)$/.test(asset))
146
+ .map((file) => {
147
+ const src = sources.get(file) ?? file;
148
+ const marker = '/node_modules/';
149
+ const index = src.lastIndexOf(marker);
150
+
151
+ // Vite follows package manager symlinks when generating the manifest. Prefer the
152
+ // project-local node_modules path when it points to the same file.
153
+ if (index !== -1) {
154
+ const filename = `node_modules/${src.slice(index + marker.length)}`;
155
+ const source = path.resolve(root, src);
156
+ const unresolved = path.resolve(root, filename);
157
+
158
+ if (
159
+ fs.existsSync(source) &&
160
+ fs.existsSync(unresolved) &&
161
+ fs.realpathSync(unresolved) === fs.realpathSync(source)
162
+ ) {
163
+ return { file, filename };
164
+ }
165
+ }
166
+
167
+ return { file, filename: normalizePath(path.relative(root, path.resolve(root, src))) };
168
+ });
125
169
  }
126
170
 
127
171
  /**
@@ -25,6 +25,9 @@ import { SCHEME } from '../../../utils/url.js';
25
25
  import { check_feature } from '../../../utils/features.js';
26
26
  import { escape_html } from '../../../utils/escape.js';
27
27
  import { get_runner } from '../../../runner.js';
28
+ import { write_server } from '../../../core/sync/write_server.js';
29
+ import { write_tsconfig } from '../../../core/sync/write_tsconfig/index.js';
30
+ import create_manifest_data from '../../../core/sync/create_manifest_data/index.js';
28
31
 
29
32
  // vite-specifc queries that we should skip handling for css urls
30
33
  const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
@@ -74,7 +77,7 @@ export async function dev(
74
77
  return fetch(info, init);
75
78
  };
76
79
 
77
- sync.init(svelte_config, root);
80
+ write_tsconfig(svelte_config, root);
78
81
 
79
82
  /** @type {ManifestData} */
80
83
  let manifest_data;
@@ -135,7 +138,8 @@ export async function dev(
135
138
 
136
139
  async function update_manifest() {
137
140
  try {
138
- ({ manifest_data } = sync.create(svelte_config, root));
141
+ manifest_data = create_manifest_data(svelte_config, root);
142
+ sync.create(svelte_config, root, manifest_data, false);
139
143
  set_manifest_data(manifest_data);
140
144
 
141
145
  await load_and_validate_params({
@@ -172,7 +176,7 @@ export async function dev(
172
176
  _: {
173
177
  client: {
174
178
  start: `${get_runtime_base(root)}/client/entry.js`,
175
- app: `${to_fs(svelte_config.outDir)}/generated/client/app.js`,
179
+ app: `${to_fs(svelte_config.outDir)}/generated/dev/client/app.js`,
176
180
  imports: [],
177
181
  stylesheets: [],
178
182
  fonts: [],
@@ -182,7 +186,7 @@ export async function dev(
182
186
  ? undefined
183
187
  : manifest_data.nodes.map((node, i) => {
184
188
  if (node.component || node.universal) {
185
- return `${svelte_config.paths.base}${to_fs(svelte_config.outDir)}/generated/client/nodes/${i}.js`;
189
+ return `${svelte_config.paths.base}${to_fs(svelte_config.outDir)}/generated/dev/client/nodes/${i}.js`;
186
190
  }
187
191
  }),
188
192
  // `css` is not necessary in dev, as the JS file from `nodes` will reference the CSS file
@@ -450,7 +454,7 @@ export async function dev(
450
454
  file.startsWith(serviceWorker) ||
451
455
  file.startsWith(hooks.server)
452
456
  ) {
453
- sync.server(svelte_config, root);
457
+ write_server(svelte_config, path.join(svelte_config.outDir, 'generated', 'dev'), root);
454
458
  }
455
459
  });
456
460
 
@@ -593,7 +597,8 @@ export async function dev(
593
597
 
594
598
  const request = getRequest({
595
599
  base,
596
- request: req
600
+ request: req,
601
+ response: res
597
602
  });
598
603
 
599
604
  if (manifest_error) {
@@ -736,19 +741,3 @@ function has_correct_case(file, assets) {
736
741
 
737
742
  return false;
738
743
  }
739
-
740
- /**
741
- * Invalidates a module in all environments.
742
- * @param {ViteDevServer} server
743
- * @param {string} id
744
- * @returns {void}
745
- */
746
- export function invalidate_module(server, id) {
747
- for (const environment in server.environments) {
748
- const module = server.environments[environment].moduleGraph.getModuleById(id);
749
- if (module) {
750
- server.environments[environment].moduleGraph.invalidateModule(module);
751
- void server.environments[environment].reloadModule(module);
752
- }
753
- }
754
- }