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

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 (71) hide show
  1. package/package.json +16 -10
  2. package/src/constants.js +6 -0
  3. package/src/core/adapt/builder.js +128 -33
  4. package/src/core/adapt/index.js +3 -0
  5. package/src/core/config/index.js +4 -7
  6. package/src/core/env.js +39 -14
  7. package/src/core/generate_manifest/index.js +42 -43
  8. package/src/core/postbuild/analyse.js +4 -4
  9. package/src/core/postbuild/fallback.js +1 -1
  10. package/src/core/postbuild/prerender.js +4 -4
  11. package/src/core/sync/create_manifest_data/index.js +0 -1
  12. package/src/core/sync/write_app_manifest.js +3 -2
  13. package/src/core/sync/write_server.js +3 -17
  14. package/src/core/utils.js +10 -0
  15. package/src/exports/adapter.js +22 -0
  16. package/src/exports/public.d.ts +101 -49
  17. package/src/exports/vite/build/index.js +1173 -0
  18. package/src/exports/vite/build/remote.js +4 -4
  19. package/src/exports/vite/build/service-worker.js +98 -0
  20. package/src/exports/vite/dev/generate_manifest.js +308 -0
  21. package/src/exports/vite/dev/index.js +40 -282
  22. package/src/exports/vite/index.js +156 -1717
  23. package/src/exports/vite/plugins/env-vars.js +53 -34
  24. package/src/exports/vite/plugins/guard.js +217 -0
  25. package/src/exports/vite/plugins/remote.js +237 -0
  26. package/src/exports/vite/preview/index.js +8 -8
  27. package/src/exports/vite/static_analysis/index.js +15 -15
  28. package/src/exports/vite/utils.js +98 -1
  29. package/src/runner.js +4 -3
  30. package/src/runtime/app/paths/server.js +2 -2
  31. package/src/runtime/app/server/index.js +3 -3
  32. package/src/runtime/app/server/public.d.ts +114 -57
  33. package/src/runtime/app/server/remote/query.js +2 -2
  34. package/src/runtime/app/server/remote/requested.js +31 -15
  35. package/src/runtime/app/state/client.svelte.js +3 -1
  36. package/src/runtime/client/client.js +43 -198
  37. package/src/runtime/client/fetcher.js +6 -6
  38. package/src/runtime/client/focus.js +120 -0
  39. package/src/runtime/client/remote-functions/command.svelte.js +20 -9
  40. package/src/runtime/client/remote-functions/form.svelte.js +12 -7
  41. package/src/runtime/client/remote-functions/query/instance.svelte.js +19 -5
  42. package/src/runtime/client/remote-functions/shared.svelte.js +22 -1
  43. package/src/runtime/client/scroll.js +39 -0
  44. package/src/runtime/client/utils.js +28 -0
  45. package/src/runtime/form-utils.js +254 -264
  46. package/src/runtime/server/data/index.js +14 -36
  47. package/src/runtime/server/errors.js +7 -10
  48. package/src/runtime/server/fetch.js +21 -25
  49. package/src/runtime/server/index.js +35 -31
  50. package/src/runtime/server/internal.js +34 -5
  51. package/src/runtime/server/page/actions.js +6 -8
  52. package/src/runtime/server/page/data_serializer.js +6 -10
  53. package/src/runtime/server/page/index.js +18 -28
  54. package/src/runtime/server/page/load_data.js +2 -2
  55. package/src/runtime/server/page/render.js +22 -40
  56. package/src/runtime/server/page/respond_with_error.js +10 -13
  57. package/src/runtime/server/page/server_routing.js +21 -27
  58. package/src/runtime/server/remote-functions.js +136 -136
  59. package/src/runtime/server/respond.js +66 -64
  60. package/src/runtime/server/state.js +2 -0
  61. package/src/runtime/server/utils.js +4 -11
  62. package/src/runtime/shared.js +9 -0
  63. package/src/runtime/utils.js +41 -0
  64. package/src/types/ambient-private.d.ts +1 -2
  65. package/src/types/global-private.d.ts +8 -0
  66. package/src/types/internal.d.ts +56 -17
  67. package/src/utils/filesystem.js +44 -28
  68. package/src/utils/streaming.js +5 -15
  69. package/src/version.js +1 -1
  70. package/types/index.d.ts +235 -93
  71. package/types/index.d.ts.map +9 -2
@@ -3,7 +3,6 @@
3
3
 
4
4
  import fs from 'node:fs';
5
5
  import path from 'node:path';
6
- import { Parser } from 'acorn';
7
6
  import MagicString from 'magic-string';
8
7
  import { posixify } from '../../../utils/os.js';
9
8
 
@@ -59,11 +58,12 @@ export async function treeshake_prerendered_remotes(
59
58
  const chunk_path = posixify(path.relative(cwd, `${out}/server/${remote_chunk.fileName}`));
60
59
 
61
60
  const code = fs.readFileSync(chunk_path, 'utf-8');
62
- const parsed = Parser.parse(code, { sourceType: 'module', ecmaVersion: 'latest' });
61
+ const parsed = vite.parseSync(chunk_path, code);
62
+ if (parsed.errors.length) throw new Error(parsed.errors[0].message);
63
63
  const modified_code = new MagicString(code);
64
64
 
65
65
  for (const fn of prerendered) {
66
- for (const node of parsed.body) {
66
+ for (const node of parsed.program.body) {
67
67
  const declaration =
68
68
  node.type === 'ExportNamedDeclaration'
69
69
  ? node.declaration
@@ -85,7 +85,7 @@ export async function treeshake_prerendered_remotes(
85
85
  }
86
86
  }
87
87
 
88
- for (const node of parsed.body) {
88
+ for (const node of parsed.program.body) {
89
89
  if (node.type === 'ExportDefaultDeclaration') {
90
90
  modified_code.remove(node.start, node.end);
91
91
  }
@@ -0,0 +1,98 @@
1
+ /** @import { ValidatedConfig } from 'types' */
2
+ /** @import { Plugin, UserConfig } from 'vite' */
3
+ import { runtime_directory } from '../../../core/utils.js';
4
+ import { warn_overridden_config } from '../utils.js';
5
+
6
+ /**
7
+ * @param {ValidatedConfig} kit
8
+ * @param {() => { service_worker_entry_file: string | null; kit_global: string; out: string; initial_config: UserConfig; }} get_config
9
+ * @returns {Plugin}
10
+ */
11
+ export function plugin_service_worker_build(kit, get_config) {
12
+ return {
13
+ name: 'vite-plugin-sveltekit-service-worker',
14
+
15
+ config(config) {
16
+ const { service_worker_entry_file, kit_global, out, initial_config } = get_config();
17
+
18
+ if (!service_worker_entry_file) return;
19
+
20
+ if (kit.paths.assets) {
21
+ throw new Error('Cannot use service worker alongside config.paths.assets');
22
+ }
23
+
24
+ const user_service_worker_output_config =
25
+ config.environments?.serviceWorker?.build?.rolldownOptions?.output;
26
+
27
+ /** @type {UserConfig} */
28
+ const new_config = {
29
+ environments: {
30
+ serviceWorker: {
31
+ define: {
32
+ __SVELTEKIT_PAYLOAD__: kit_global
33
+ },
34
+ build: {
35
+ modulePreload: false,
36
+ rolldownOptions: {
37
+ external: [`${kit.paths.base}/${kit.appDir}/env.js`],
38
+ input: {
39
+ 'service-worker': service_worker_entry_file
40
+ },
41
+ output: {
42
+ format: 'es',
43
+ entryFileNames: 'service-worker.js',
44
+ assetFileNames: `${kit.appDir}/immutable/assets/[name].[hash][extname]`,
45
+ codeSplitting:
46
+ (Array.isArray(user_service_worker_output_config)
47
+ ? user_service_worker_output_config[0].codeSplitting
48
+ : user_service_worker_output_config?.codeSplitting) ?? false
49
+ }
50
+ },
51
+ outDir: `${out}/client`,
52
+ minify: initial_config.build?.minify,
53
+ // avoid overwriting the client build Vite manifest
54
+ manifest: '.vite/service-worker-manifest.json'
55
+ },
56
+ consumer: 'client'
57
+ }
58
+ }
59
+ };
60
+
61
+ warn_overridden_config(config, new_config);
62
+
63
+ return new_config;
64
+ },
65
+
66
+ // our serviceWorker environment only exists when building because Vite only
67
+ // supports the default client environment during development (for now)
68
+ applyToEnvironment(environment) {
69
+ return environment.name === 'serviceWorker';
70
+ },
71
+
72
+ generateBundle(_, bundle) {
73
+ const invalid_modules = new Set();
74
+ const modules = new Map([
75
+ [`${runtime_directory}/app/forms/index.js`, '$app/forms'],
76
+ [`${runtime_directory}/app/navigation/index.js`, '$app/navigation'],
77
+ [`${runtime_directory}/app/state/index.js`, '$app/state']
78
+ ]);
79
+
80
+ for (const output of Object.values(bundle)) {
81
+ if (output.type !== 'chunk') continue;
82
+
83
+ for (const id of output.moduleIds) {
84
+ const module = modules.get(id);
85
+ if (module) invalid_modules.add(module);
86
+ }
87
+ }
88
+
89
+ if (invalid_modules.size > 0) {
90
+ throw new Error(
91
+ `Cannot import ${Array.from(modules.values())
92
+ .filter((module) => invalid_modules.has(module))
93
+ .join(', ')} into service-worker code.`
94
+ );
95
+ }
96
+ }
97
+ };
98
+ }
@@ -0,0 +1,308 @@
1
+ /** @import { EnvironmentModuleNode, ErrorPayload, ViteDevServer } from 'vite' */
2
+ /** @import { ModuleRunner } from 'vite/module-runner' */
3
+ /** @import { ManifestData, SSRManifest, SSRNode, RemoteChunk, UniversalNode, ValidatedConfig } from 'types' */
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { get_mime_lookup, get_runtime_base } from '../../../core/utils.js';
7
+ import { from_fs, to_fs } from '../../../utils/vite.js';
8
+ import { compact } from '../../../utils/array.js';
9
+ import { styleText } from 'node:util';
10
+
11
+ // vite-specifc queries that we should skip handling for css urls
12
+ const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
13
+
14
+ /**
15
+ * @param {typeof import('vite')} vite
16
+ * @param {ViteDevServer} vite_dev_server
17
+ * @param {ModuleRunner} runner
18
+ * @param {ValidatedConfig} svelte_config
19
+ * @param {ManifestData} manifest_data
20
+ * @param {string} root
21
+ * @param {() => RemoteChunk[]} get_remotes
22
+ * @returns {SSRManifest}
23
+ */
24
+ export function generate_manifest(
25
+ vite,
26
+ vite_dev_server,
27
+ runner,
28
+ svelte_config,
29
+ manifest_data,
30
+ root,
31
+ get_remotes
32
+ ) {
33
+ return {
34
+ app_dir: svelte_config.appDir,
35
+ app_path: svelte_config.appDir,
36
+ assets: new Set(manifest_data.assets.map((asset) => asset.file)),
37
+ mime_types: get_mime_lookup(manifest_data),
38
+ client: {
39
+ start: `${get_runtime_base(root)}/client/entry.js`,
40
+ app: `${to_fs(svelte_config.outDir)}/generated/dev/client/app.js`,
41
+ imports: [],
42
+ stylesheets: [],
43
+ fonts: [],
44
+ uses_env_dynamic_public: true,
45
+ nodes:
46
+ svelte_config.router.resolution === 'client'
47
+ ? undefined
48
+ : manifest_data.nodes.map((node, i) => {
49
+ if (node.component || node.universal) {
50
+ return `${svelte_config.paths.base}${to_fs(svelte_config.outDir)}/generated/dev/client/nodes/${i}.js`;
51
+ }
52
+ }),
53
+ // `css` is not necessary in dev, as the JS file from `nodes` will reference the CSS file
54
+ routes:
55
+ svelte_config.router.resolution === 'client'
56
+ ? undefined
57
+ : compact(
58
+ manifest_data.routes.map((route) => {
59
+ if (!route.page) return;
60
+
61
+ return {
62
+ id: route.id,
63
+ pattern: route.pattern,
64
+ params: route.params,
65
+ layouts: route.page.layouts.map((l) =>
66
+ l !== undefined ? [!!manifest_data.nodes[l].server, l] : undefined
67
+ ),
68
+ errors: route.page.errors,
69
+ leaf: [!!manifest_data.nodes[route.page.leaf].server, route.page.leaf]
70
+ };
71
+ })
72
+ )
73
+ },
74
+ server_assets: new Proxy(
75
+ {},
76
+ {
77
+ has: (_, /** @type {string} */ file) => fs.existsSync(from_fs(file)),
78
+ get: (_, /** @type {string} */ file) => fs.statSync(from_fs(file)).size
79
+ }
80
+ ),
81
+ nodes: manifest_data.nodes.map((node, index) => {
82
+ return async () => {
83
+ const result = /** @type {SSRNode} */ ({});
84
+ result.index = index;
85
+ result.universal_id = node.universal;
86
+ result.server_id = node.server;
87
+
88
+ // these are unused in dev, but it's easier to include them
89
+ result.imports = [];
90
+ result.stylesheets = [];
91
+ result.fonts = [];
92
+
93
+ /** @type {EnvironmentModuleNode[]} */
94
+ const module_nodes = [];
95
+
96
+ if (node.component) {
97
+ result.component = async () => {
98
+ const { module_node, module } = await resolve(
99
+ vite,
100
+ vite_dev_server,
101
+ runner,
102
+ /** @type {string} */ (node.component)
103
+ );
104
+
105
+ module_nodes.push(module_node);
106
+
107
+ return module.default;
108
+ };
109
+ }
110
+
111
+ if (node.universal) {
112
+ if (node.page_options?.ssr === false) {
113
+ result.universal = /** @type {UniversalNode} */ (node.page_options);
114
+ } else {
115
+ // TODO: explain why the file was loaded on the server if we fail to load it
116
+ const { module, module_node } = await resolve(
117
+ vite,
118
+ vite_dev_server,
119
+ runner,
120
+ node.universal
121
+ );
122
+ module_nodes.push(module_node);
123
+ result.universal = module;
124
+ }
125
+ }
126
+
127
+ if (node.server) {
128
+ const { module } = await resolve(vite, vite_dev_server, runner, node.server);
129
+ result.server = module;
130
+ }
131
+
132
+ // in dev we inline all styles to avoid FOUC. this gets populated lazily so that
133
+ // components/stylesheets loaded via import() during `load` are included
134
+ result.inline_styles = async () => {
135
+ /** @type {Set<EnvironmentModuleNode>} */
136
+ const deps = new Set();
137
+
138
+ for (const module_node of module_nodes) {
139
+ await find_deps(vite_dev_server, module_node, deps);
140
+ }
141
+
142
+ /** @type {Record<string, string>} */
143
+ const styles = {};
144
+
145
+ for (const dep of deps) {
146
+ if (vite.isCSSRequest(dep.url) && !vite_css_query_regex.test(dep.url)) {
147
+ const inlineCssUrl = dep.url.includes('?')
148
+ ? dep.url.replace('?', '?inline&')
149
+ : dep.url + '?inline';
150
+ try {
151
+ const mod = await runner.import(inlineCssUrl);
152
+ styles[dep.url] = mod.default;
153
+ } catch {
154
+ // this can happen with dynamically imported modules, I think
155
+ // because the Vite module graph doesn't distinguish between
156
+ // static and dynamic imports? TODO investigate, submit fix
157
+ }
158
+ }
159
+ }
160
+
161
+ return styles;
162
+ };
163
+
164
+ return result;
165
+ };
166
+ }),
167
+ prerendered_routes: new Set(),
168
+ get remotes() {
169
+ return Object.fromEntries(
170
+ get_remotes().map((remote) => [
171
+ remote.hash,
172
+ () => runner.import(remote.file).then((module) => ({ default: module }))
173
+ ])
174
+ );
175
+ },
176
+ routes: compact(
177
+ manifest_data.routes.map((route) => {
178
+ if (!route.page && !route.endpoint) return null;
179
+
180
+ const endpoint = route.endpoint;
181
+
182
+ return {
183
+ id: route.id,
184
+ pattern: route.pattern,
185
+ params: route.params,
186
+ page: route.page,
187
+ endpoint: endpoint
188
+ ? async () => {
189
+ const url = path.resolve(root, endpoint.file);
190
+ return await loud_ssr_load_module(vite, vite_dev_server, runner, url);
191
+ }
192
+ : null,
193
+ endpoint_id: endpoint?.file
194
+ };
195
+ })
196
+ ),
197
+ matchers: async () => {
198
+ if (!manifest_data.params) return {};
199
+
200
+ const url = path.resolve(root, manifest_data.params);
201
+ const module = await runner.import(url);
202
+
203
+ if (!module.params) {
204
+ throw new Error(`${manifest_data.params} does not export \`params\` from \`defineParams\``);
205
+ }
206
+
207
+ return module.params;
208
+ }
209
+ };
210
+ }
211
+
212
+ /**
213
+ * @param {typeof import('vite')} vite
214
+ * @param {ViteDevServer} vite_dev_server
215
+ * @param {ModuleRunner} runner
216
+ * @param {string} url
217
+ * @returns {Promise<Record<string, any>>}
218
+ */
219
+ export async function loud_ssr_load_module(vite, vite_dev_server, runner, url) {
220
+ try {
221
+ return await runner.import(url);
222
+ } catch (/** @type {any} */ err) {
223
+ const msg = vite.buildErrorMessage(err, [
224
+ styleText('red', `Internal server error: ${err.message}`)
225
+ ]);
226
+
227
+ if (!vite_dev_server.config.logger.hasErrorLogged(err)) {
228
+ vite_dev_server.config.logger.error(msg, { error: err });
229
+ }
230
+
231
+ // TODO this is inadequate — it doesn't reliably show the overlay on every page load,
232
+ // and when it does appear it may immediately vanish. `hot.send` broadcasts
233
+ // to all connected clients, even ones that are unaffected by the error.
234
+ // we need a more considered approach
235
+ vite_dev_server.environments.client.hot.send({
236
+ type: 'error',
237
+ err: /** @type {ErrorPayload['err']} */ ({
238
+ ...err,
239
+ // these properties are non-enumerable and will
240
+ // not be serialized unless we explicitly include them
241
+ message: err.message,
242
+ stack: err.stack ?? ''
243
+ })
244
+ });
245
+
246
+ throw err;
247
+ }
248
+ }
249
+
250
+ /**
251
+ * @param {typeof import('vite')} vite
252
+ * @param {ViteDevServer} vite_dev_server
253
+ * @param {ModuleRunner} runner
254
+ * @param {string} id
255
+ */
256
+ async function resolve(vite, vite_dev_server, runner, id) {
257
+ const url = id.startsWith('..') ? to_fs(path.resolve(id)) : `/${id}`;
258
+
259
+ const module = await loud_ssr_load_module(vite, vite_dev_server, runner, url);
260
+
261
+ const module_node = await vite_dev_server.environments.ssr.moduleGraph.getModuleByUrl(url);
262
+ if (!module_node) throw new Error(`Could not find node for ${url}`);
263
+
264
+ return { module, module_node, url };
265
+ }
266
+
267
+ /**
268
+ * @param {ViteDevServer} vite
269
+ * @param {EnvironmentModuleNode} node
270
+ * @param {Set<EnvironmentModuleNode>} deps
271
+ */
272
+ async function find_deps(vite, node, deps) {
273
+ // since `transformResult.deps` contains URLs instead of `ModuleNode`s, this process is asynchronous.
274
+ // instead of using `await`, we resolve all branches in parallel.
275
+ /** @type {Promise<void>[]} */
276
+ const branches = [];
277
+
278
+ /** @param {EnvironmentModuleNode} node */
279
+ async function add(node) {
280
+ if (!deps.has(node)) {
281
+ deps.add(node);
282
+ await find_deps(vite, node, deps);
283
+ }
284
+ }
285
+
286
+ /** @param {string} url */
287
+ async function add_by_url(url) {
288
+ const node = await vite.environments.ssr.moduleGraph.getModuleByUrl(url);
289
+
290
+ if (node) {
291
+ await add(node);
292
+ }
293
+ }
294
+
295
+ if (node.transformResult) {
296
+ if (node.transformResult.deps) {
297
+ node.transformResult.deps.forEach((url) => branches.push(add_by_url(url)));
298
+ }
299
+
300
+ if (node.transformResult.dynamicDeps) {
301
+ node.transformResult.dynamicDeps.forEach((url) => branches.push(add_by_url(url)));
302
+ }
303
+ } else {
304
+ node.importedModules.forEach((node) => branches.push(add(node)));
305
+ }
306
+
307
+ await Promise.all(branches);
308
+ }