@sveltejs/kit 2.15.2 → 2.16.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "2.15.2",
3
+ "version": "2.16.0",
4
4
  "description": "SvelteKit is the fastest way to build Svelte apps",
5
5
  "keywords": [
6
6
  "framework",
@@ -21,15 +21,14 @@
21
21
  "@types/cookie": "^0.6.0",
22
22
  "cookie": "^0.6.0",
23
23
  "devalue": "^5.1.0",
24
- "esm-env": "^1.2.1",
24
+ "esm-env": "^1.2.2",
25
25
  "import-meta-resolve": "^4.1.0",
26
26
  "kleur": "^4.1.5",
27
27
  "magic-string": "^0.30.5",
28
28
  "mrmime": "^2.0.0",
29
29
  "sade": "^1.8.1",
30
30
  "set-cookie-parser": "^2.6.0",
31
- "sirv": "^3.0.0",
32
- "tiny-glob": "^0.2.9"
31
+ "sirv": "^3.0.0"
33
32
  },
34
33
  "devDependencies": {
35
34
  "@playwright/test": "^1.44.1",
@@ -59,8 +58,7 @@
59
58
  "!src/core/**/fixtures",
60
59
  "!src/core/**/test",
61
60
  "types",
62
- "svelte-kit.js",
63
- "postinstall.js"
61
+ "svelte-kit.js"
64
62
  ],
65
63
  "exports": {
66
64
  "./package.json": "./package.json",
@@ -99,7 +97,6 @@
99
97
  "test:cross-platform:dev": "pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test:cross-platform:dev",
100
98
  "test:cross-platform:build": "pnpm test:unit && pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test:cross-platform:build",
101
99
  "test:unit": "vitest --config kit.vitest.config.js run",
102
- "postinstall": "node postinstall.js",
103
100
  "generate:version": "node scripts/generate-version.js",
104
101
  "generate:types": "node scripts/generate-dts.js"
105
102
  }
@@ -3,15 +3,8 @@ import path from 'node:path';
3
3
  import { mkdirp } from '../../utils/filesystem.js';
4
4
  import { resolve_peer_dependency } from '../../utils/import.js';
5
5
 
6
- /** @type {string} */
7
- let VERSION;
8
-
9
- try {
10
- ({ VERSION } = await resolve_peer_dependency('svelte/compiler'));
11
- } catch {
12
- // we can end up here from e.g. unit tests. this is the simplest fix
13
- ({ VERSION } = await import('svelte/compiler'));
14
- }
6
+ /** @type {{ VERSION: string }} */
7
+ const { VERSION } = await resolve_peer_dependency('svelte/compiler');
15
8
 
16
9
  /** @type {Map<string, string>} */
17
10
  const previous_contents = new Map();
@@ -270,6 +270,12 @@ function update_types(config, routes, route, to_delete = new Set()) {
270
270
  'export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>'
271
271
  );
272
272
  }
273
+
274
+ if (route.leaf.server) {
275
+ exports.push('export type PageProps = { data: PageData; form: ActionData }');
276
+ } else {
277
+ exports.push('export type PageProps = { data: PageData }');
278
+ }
273
279
  }
274
280
 
275
281
  if (route.layout) {
@@ -333,6 +339,10 @@ function update_types(config, routes, route, to_delete = new Set()) {
333
339
 
334
340
  if (proxies.server?.modified) to_delete.delete(proxies.server.file_name);
335
341
  if (proxies.universal?.modified) to_delete.delete(proxies.universal.file_name);
342
+
343
+ exports.push(
344
+ 'export type LayoutProps = { data: LayoutData; children: import("svelte").Snippet }'
345
+ );
336
346
  }
337
347
 
338
348
  if (route.endpoint) {
@@ -585,7 +595,7 @@ function replace_ext_with_js(file_path) {
585
595
  function generate_params_type(params, outdir, config) {
586
596
  /** @param {string} matcher */
587
597
  const path_to_matcher = (matcher) =>
588
- posixify(path.relative(outdir, path.join(config.kit.files.params, matcher)));
598
+ posixify(path.relative(outdir, path.join(config.kit.files.params, matcher + '.js')));
589
599
 
590
600
  return `{ ${params
591
601
  .map(
@@ -84,6 +84,14 @@ export function isHttpError(e, status) {
84
84
  /**
85
85
  * Redirect a request. When called during request handling, SvelteKit will return a redirect response.
86
86
  * Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.
87
+ *
88
+ * Most common status codes:
89
+ * * `303 See Other`: redirect as a GET request (often used after a form POST request)
90
+ * * `307 Temporary Redirect`: redirect will keep the request method
91
+ * * `308 Permanent Redirect`: redirect will keep the request method, SEO will be transferred to the new page
92
+ *
93
+ * [See all redirect status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages)
94
+ *
87
95
  * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number)} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.
88
96
  * @param {string | URL} location The location to redirect to.
89
97
  * @throws {Redirect} This error instructs SvelteKit to redirect to the specified location.
@@ -34,7 +34,7 @@ export interface Adapter {
34
34
  * This function is called after SvelteKit has built your app.
35
35
  * @param builder An object provided by SvelteKit that contains methods for adapting the app
36
36
  */
37
- adapt(builder: Builder): MaybePromise<void>;
37
+ adapt: (builder: Builder) => MaybePromise<void>;
38
38
  /**
39
39
  * Checks called during dev and build to determine whether specific features will work in production with this adapter
40
40
  */
@@ -49,7 +49,7 @@ export interface Adapter {
49
49
  * Creates an `Emulator`, which allows the adapter to influence the environment
50
50
  * during dev, build and prerendering
51
51
  */
52
- emulate?(): MaybePromise<Emulator>;
52
+ emulate?: () => MaybePromise<Emulator>;
53
53
  }
54
54
 
55
55
  export type LoadProperties<input extends Record<string, any> | void> = input extends void
@@ -94,9 +94,9 @@ export interface Builder {
94
94
  /** Print messages to the console. `log.info` and `log.minor` are silent unless Vite's `logLevel` is `info`. */
95
95
  log: Logger;
96
96
  /** Remove `dir` and all its contents. */
97
- rimraf(dir: string): void;
97
+ rimraf: (dir: string) => void;
98
98
  /** Create `dir` and any required parent directories. */
99
- mkdirp(dir: string): void;
99
+ mkdirp: (dir: string) => void;
100
100
 
101
101
  /** The fully resolved `svelte.config.js`. */
102
102
  config: ValidatedConfig;
@@ -111,59 +111,59 @@ export interface Builder {
111
111
  * @param fn A function that groups a set of routes into an entry point
112
112
  * @deprecated Use `builder.routes` instead
113
113
  */
114
- createEntries(fn: (route: RouteDefinition) => AdapterEntry): Promise<void>;
114
+ createEntries: (fn: (route: RouteDefinition) => AdapterEntry) => Promise<void>;
115
115
 
116
116
  /**
117
117
  * Find all the assets imported by server files belonging to `routes`
118
118
  */
119
- findServerAssets(routes: RouteDefinition[]): string[];
119
+ findServerAssets: (routes: RouteDefinition[]) => string[];
120
120
 
121
121
  /**
122
122
  * Generate a fallback page for a static webserver to use when no route is matched. Useful for single-page apps.
123
123
  */
124
- generateFallback(dest: string): Promise<void>;
124
+ generateFallback: (dest: string) => Promise<void>;
125
125
 
126
126
  /**
127
127
  * Generate a module exposing build-time environment variables as `$env/dynamic/public`.
128
128
  */
129
- generateEnvModule(): void;
129
+ generateEnvModule: () => void;
130
130
 
131
131
  /**
132
132
  * Generate a server-side manifest to initialise the SvelteKit [server](https://svelte.dev/docs/kit/@sveltejs-kit#Server) with.
133
133
  * @param opts a relative path to the base directory of the app and optionally in which format (esm or cjs) the manifest should be generated
134
134
  */
135
- generateManifest(opts: { relativePath: string; routes?: RouteDefinition[] }): string;
135
+ generateManifest: (opts: { relativePath: string; routes?: RouteDefinition[] }) => string;
136
136
 
137
137
  /**
138
138
  * Resolve a path to the `name` directory inside `outDir`, e.g. `/path/to/.svelte-kit/my-adapter`.
139
139
  * @param name path to the file, relative to the build directory
140
140
  */
141
- getBuildDirectory(name: string): string;
141
+ getBuildDirectory: (name: string) => string;
142
142
  /** Get the fully resolved path to the directory containing client-side assets, including the contents of your `static` directory. */
143
- getClientDirectory(): string;
143
+ getClientDirectory: () => string;
144
144
  /** Get the fully resolved path to the directory containing server-side code. */
145
- getServerDirectory(): string;
145
+ getServerDirectory: () => string;
146
146
  /** Get the application path including any configured `base` path, e.g. `my-base-path/_app`. */
147
- getAppPath(): string;
147
+ getAppPath: () => string;
148
148
 
149
149
  /**
150
150
  * Write client assets to `dest`.
151
151
  * @param dest the destination folder
152
152
  * @returns an array of files written to `dest`
153
153
  */
154
- writeClient(dest: string): string[];
154
+ writeClient: (dest: string) => string[];
155
155
  /**
156
156
  * Write prerendered files to `dest`.
157
157
  * @param dest the destination folder
158
158
  * @returns an array of files written to `dest`
159
159
  */
160
- writePrerendered(dest: string): string[];
160
+ writePrerendered: (dest: string) => string[];
161
161
  /**
162
162
  * Write server-side code to `dest`.
163
163
  * @param dest the destination folder
164
164
  * @returns an array of files written to `dest`
165
165
  */
166
- writeServer(dest: string): string[];
166
+ writeServer: (dest: string) => string[];
167
167
  /**
168
168
  * Copy a file or directory.
169
169
  * @param from the source file or directory
@@ -172,20 +172,20 @@ export interface Builder {
172
172
  * @param opts.replace a map of strings to replace
173
173
  * @returns an array of files that were copied
174
174
  */
175
- copy(
175
+ copy: (
176
176
  from: string,
177
177
  to: string,
178
178
  opts?: {
179
179
  filter?(basename: string): boolean;
180
180
  replace?: Record<string, string>;
181
181
  }
182
- ): string[];
182
+ ) => string[];
183
183
 
184
184
  /**
185
185
  * Compress files in `directory` with gzip and brotli, where appropriate. Generates `.gz` and `.br` files alongside the originals.
186
186
  * @param {string} directory The directory containing the files to be compressed
187
187
  */
188
- compress(directory: string): Promise<void>;
188
+ compress: (directory: string) => Promise<void>;
189
189
  }
190
190
 
191
191
  export interface Config {
@@ -215,13 +215,13 @@ export interface Cookies {
215
215
  * @param name the name of the cookie
216
216
  * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options)
217
217
  */
218
- get(name: string, opts?: import('cookie').CookieParseOptions): string | undefined;
218
+ get: (name: string, opts?: import('cookie').CookieParseOptions) => string | undefined;
219
219
 
220
220
  /**
221
221
  * Gets all cookies that were previously set with `cookies.set`, or from the request headers.
222
222
  * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options)
223
223
  */
224
- getAll(opts?: import('cookie').CookieParseOptions): Array<{ name: string; value: string }>;
224
+ getAll: (opts?: import('cookie').CookieParseOptions) => Array<{ name: string; value: string }>;
225
225
 
226
226
  /**
227
227
  * Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request.
@@ -233,11 +233,11 @@ export interface Cookies {
233
233
  * @param value the cookie value
234
234
  * @param opts the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options)
235
235
  */
236
- set(
236
+ set: (
237
237
  name: string,
238
238
  value: string,
239
239
  opts: import('cookie').CookieSerializeOptions & { path: string }
240
- ): void;
240
+ ) => void;
241
241
 
242
242
  /**
243
243
  * Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.
@@ -246,7 +246,7 @@ export interface Cookies {
246
246
  * @param name the name of the cookie
247
247
  * @param opts the options, passed directly to `cookie.serialize`. The `path` must match the path of the cookie you want to delete. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options)
248
248
  */
249
- delete(name: string, opts: import('cookie').CookieSerializeOptions & { path: string }): void;
249
+ delete: (name: string, opts: import('cookie').CookieSerializeOptions & { path: string }) => void;
250
250
 
251
251
  /**
252
252
  * Serialize a cookie name-value pair into a `Set-Cookie` header string, but don't apply it to the response.
@@ -259,11 +259,11 @@ export interface Cookies {
259
259
  * @param value the cookie value
260
260
  * @param opts the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options)
261
261
  */
262
- serialize(
262
+ serialize: (
263
263
  name: string,
264
264
  value: string,
265
265
  opts: import('cookie').CookieSerializeOptions & { path: string }
266
- ): string;
266
+ ) => string;
267
267
  }
268
268
 
269
269
  /**
@@ -499,11 +499,41 @@ export interface KitConfig {
499
499
  */
500
500
  preloadStrategy?: 'modulepreload' | 'preload-js' | 'preload-mjs';
501
501
  /**
502
+ * The bundle strategy option affects how your app's JavaScript and CSS files are loaded.
502
503
  * - If `'split'`, splits the app up into multiple .js/.css files so that they are loaded lazily as the user navigates around the app. This is the default, and is recommended for most scenarios.
503
504
  * - If `'single'`, creates just one .js bundle and one .css file containing code for the entire app.
504
505
  * - If `'inline'`, inlines all JavaScript and CSS of the entire app into the HTML. The result is usable without a server (i.e. you can just open the file in your browser).
505
506
  *
506
- * When using `'split'`, you can also adjust the bundling behaviour by setting [`output.experimentalMinChunkSize`](https://rollupjs.org/configuration-options/#output-experimentalminchunksize) and [`output.manualChunks`](https://rollupjs.org/configuration-options/#output-manualchunks)inside your Vite config's [`build.rollupOptions`](https://vite.dev/config/build-options.html#build-rollupoptions).
507
+ * When using `'split'`, you can also adjust the bundling behaviour by setting [`output.experimentalMinChunkSize`](https://rollupjs.org/configuration-options/#output-experimentalminchunksize) and [`output.manualChunks`](https://rollupjs.org/configuration-options/#output-manualchunks) inside your Vite config's [`build.rollupOptions`](https://vite.dev/config/build-options.html#build-rollupoptions).
508
+ *
509
+ * If you want to inline your assets, you'll need to set Vite's [`build.assetsInlineLimit`](https://vite.dev/config/build-options.html#build-assetsinlinelimit) option to an appropriate size then import your assets through Vite.
510
+ *
511
+ * ```js
512
+ * /// file: vite.config.js
513
+ * import { sveltekit } from '@sveltejs/kit/vite';
514
+ * import { defineConfig } from 'vite';
515
+ *
516
+ * export default defineConfig({
517
+ * plugins: [sveltekit()],
518
+ * build: {
519
+ * // inline all imported assets
520
+ * assetsInlineLimit: Infinity
521
+ * }
522
+ * });
523
+ * ```
524
+ *
525
+ * ```svelte
526
+ * /// file: src/routes/+layout.svelte
527
+ * <script>
528
+ * // import the asset through Vite
529
+ * import favicon from './favicon.png';
530
+ * </script>
531
+ *
532
+ * <svelte:head>
533
+ * <!-- this asset will be inlined as a base64 URL -->
534
+ * <link rel="icon" href={favicon} />
535
+ * </svelte:head>
536
+ * ```
507
537
  * @default 'split'
508
538
  * @since 2.13.0
509
539
  */
@@ -623,7 +653,7 @@ export interface KitConfig {
623
653
  * What type of client-side router to use.
624
654
  * - `'pathname'` is the default and means the current URL pathname determines the route
625
655
  * - `'hash'` means the route is determined by `location.hash`. In this case, SSR and prerendering are disabled. This is only recommended if `pathname` is not an option, for example because you don't control the webserver where your app is deployed.
626
- * It comes with some caveats: you can't use server-side rendering (or indeed any server logic), and you have to make sure that the links in your app all start with /#/, or they won't work. Beyond that, everything works exactly like a normal SvelteKit app.
656
+ * It comes with some caveats: you can't use server-side rendering (or indeed any server logic), and you have to make sure that the links in your app all start with #/, or they won't work. Beyond that, everything works exactly like a normal SvelteKit app.
627
657
  *
628
658
  * @default "pathname"
629
659
  * @since 2.14.0
@@ -708,7 +738,7 @@ export interface KitConfig {
708
738
  */
709
739
  export type Handle = (input: {
710
740
  event: RequestEvent;
711
- resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
741
+ resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>;
712
742
  }) => MaybePromise<Response>;
713
743
 
714
744
  /**
@@ -863,14 +893,14 @@ export interface LoadEvent<
863
893
  *
864
894
  * `setHeaders` has no effect when a `load` function runs in the browser.
865
895
  */
866
- setHeaders(headers: Record<string, string>): void;
896
+ setHeaders: (headers: Record<string, string>) => void;
867
897
  /**
868
898
  * `await parent()` returns data from parent `+layout.js` `load` functions.
869
899
  * Implicitly, a missing `+layout.js` is treated as a `({ data }) => data` function, meaning that it will return and forward data from parent `+layout.server.js` files.
870
900
  *
871
901
  * Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data.
872
902
  */
873
- parent(): Promise<ParentData>;
903
+ parent: () => Promise<ParentData>;
874
904
  /**
875
905
  * This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](https://svelte.dev/docs/kit/$app-navigation#invalidate) to cause `load` to rerun.
876
906
  *
@@ -908,7 +938,7 @@ export interface LoadEvent<
908
938
  * <button on:click={increase}>Increase Count</button>
909
939
  * ```
910
940
  */
911
- depends(...deps: Array<`${string}:${string}`>): void;
941
+ depends: (...deps: Array<`${string}:${string}`>) => void;
912
942
  /**
913
943
  * Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:
914
944
  *
@@ -922,7 +952,7 @@ export interface LoadEvent<
922
952
  * }
923
953
  * ```
924
954
  */
925
- untrack<T>(fn: () => T): T;
955
+ untrack: <T>(fn: () => T) => T;
926
956
  }
927
957
 
928
958
  export interface NavigationEvent<
@@ -1017,7 +1047,7 @@ export interface BeforeNavigate extends Navigation {
1017
1047
  /**
1018
1048
  * Call this to prevent the navigation from starting.
1019
1049
  */
1020
- cancel(): void;
1050
+ cancel: () => void;
1021
1051
  }
1022
1052
 
1023
1053
  /**
@@ -1131,7 +1161,7 @@ export interface RequestEvent<
1131
1161
  /**
1132
1162
  * The client's IP address, set by the adapter.
1133
1163
  */
1134
- getClientAddress(): string;
1164
+ getClientAddress: () => string;
1135
1165
  /**
1136
1166
  * Contains custom data that was added to the request within the [`server handle hook`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle).
1137
1167
  */
@@ -1179,7 +1209,7 @@ export interface RequestEvent<
1179
1209
  *
1180
1210
  * You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://svelte.dev/docs/kit/@sveltejs-kit#Cookies) API instead.
1181
1211
  */
1182
- setHeaders(headers: Record<string, string>): void;
1212
+ setHeaders: (headers: Record<string, string>) => void;
1183
1213
  /**
1184
1214
  * The requested URL.
1185
1215
  */
@@ -1212,20 +1242,20 @@ export interface ResolveOptions {
1212
1242
  * but they will always be split at sensible boundaries such as `%sveltekit.head%` or layout/page components.
1213
1243
  * @param input the html chunk and the info if this is the last chunk
1214
1244
  */
1215
- transformPageChunk?(input: { html: string; done: boolean }): MaybePromise<string | undefined>;
1245
+ transformPageChunk?: (input: { html: string; done: boolean }) => MaybePromise<string | undefined>;
1216
1246
  /**
1217
1247
  * Determines which headers should be included in serialized responses when a `load` function loads a resource with `fetch`.
1218
1248
  * By default, none will be included.
1219
1249
  * @param name header name
1220
1250
  * @param value header value
1221
1251
  */
1222
- filterSerializedResponseHeaders?(name: string, value: string): boolean;
1252
+ filterSerializedResponseHeaders?: (name: string, value: string) => boolean;
1223
1253
  /**
1224
1254
  * Determines what should be added to the `<head>` tag to preload it.
1225
1255
  * By default, `js` and `css` files will be preloaded.
1226
1256
  * @param input the type of the file and its path
1227
1257
  */
1228
- preload?(input: { type: 'font' | 'css' | 'js' | 'asset'; path: string }): boolean;
1258
+ preload?: (input: { type: 'font' | 'css' | 'js' | 'asset'; path: string }) => boolean;
1229
1259
  }
1230
1260
 
1231
1261
  export interface RouteDefinition<Config = any> {
@@ -1267,7 +1297,7 @@ export interface SSRManifest {
1267
1297
  client: NonNullable<BuildData['client']>;
1268
1298
  nodes: SSRNodeLoader[];
1269
1299
  routes: SSRRoute[];
1270
- matchers(): Promise<Record<string, ParamMatcher>>;
1300
+ matchers: () => Promise<Record<string, ParamMatcher>>;
1271
1301
  /** A `[file]: size` map of all assets imported by server code */
1272
1302
  server_assets: Record<string, number>;
1273
1303
  };
@@ -1294,7 +1324,7 @@ export interface ServerLoadEvent<
1294
1324
  *
1295
1325
  * Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data.
1296
1326
  */
1297
- parent(): Promise<ParentData>;
1327
+ parent: () => Promise<ParentData>;
1298
1328
  /**
1299
1329
  * This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](https://svelte.dev/docs/kit/$app-navigation#invalidate) to cause `load` to rerun.
1300
1330
  *
@@ -1332,7 +1362,7 @@ export interface ServerLoadEvent<
1332
1362
  * <button on:click={increase}>Increase Count</button>
1333
1363
  * ```
1334
1364
  */
1335
- depends(...deps: string[]): void;
1365
+ depends: (...deps: string[]) => void;
1336
1366
  /**
1337
1367
  * Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:
1338
1368
  *
@@ -1346,7 +1376,7 @@ export interface ServerLoadEvent<
1346
1376
  * }
1347
1377
  * ```
1348
1378
  */
1349
- untrack<T>(fn: () => T): T;
1379
+ untrack: <T>(fn: () => T) => T;
1350
1380
  }
1351
1381
 
1352
1382
  /**
@@ -1417,7 +1447,7 @@ export type SubmitFunction<
1417
1447
  formElement: HTMLFormElement;
1418
1448
  controller: AbortController;
1419
1449
  submitter: HTMLElement | null;
1420
- cancel(): void;
1450
+ cancel: () => void;
1421
1451
  }) => MaybePromise<
1422
1452
  | void
1423
1453
  | ((opts: {
@@ -1430,7 +1460,7 @@ export type SubmitFunction<
1430
1460
  * @param options Set `reset: false` if you don't want the `<form>` values to be reset after a successful submission.
1431
1461
  * @param invalidateAll Set `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission.
1432
1462
  */
1433
- update(options?: { reset?: boolean; invalidateAll?: boolean }): Promise<void>;
1463
+ update: (options?: { reset?: boolean; invalidateAll?: boolean }) => Promise<void>;
1434
1464
  }) => void)
1435
1465
  >;
1436
1466
 
@@ -3,6 +3,7 @@ import { mkdirp } from '../../../utils/filesystem.js';
3
3
  import { find_deps, resolve_symlinks } from './utils.js';
4
4
  import { s } from '../../../utils/misc.js';
5
5
  import { normalizePath } from 'vite';
6
+ import { basename } from 'node:path';
6
7
 
7
8
  /**
8
9
  * @param {string} out
@@ -17,18 +18,47 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli
17
18
  mkdirp(`${out}/server/nodes`);
18
19
  mkdirp(`${out}/server/stylesheets`);
19
20
 
21
+ /** @type {Map<string, string>} */
20
22
  const stylesheet_lookup = new Map();
21
23
 
22
24
  if (css) {
23
- css.forEach((asset) => {
24
- if (asset.source.length < kit.inlineStyleThreshold) {
25
- const index = stylesheet_lookup.size;
26
- const file = `${out}/server/stylesheets/${index}.js`;
25
+ /** @type {Set<string>} */
26
+ const client_stylesheets = new Set();
27
+ for (const key in client_manifest) {
28
+ const file = client_manifest[key];
29
+ if (file.css?.[0]) {
30
+ client_stylesheets.add(file.css[0]);
31
+ }
32
+ }
33
+
34
+ /** @type {Map<number, string>} */
35
+ const server_stylesheets = new Map();
36
+
37
+ const component_stylesheet_map = new Map(Object.values(server_manifest).map((file) => [file.src, file.css?.[0]]));
27
38
 
28
- fs.writeFileSync(file, `// ${asset.fileName}\nexport default ${s(asset.source)};`);
29
- stylesheet_lookup.set(asset.fileName, index);
39
+ manifest_data.nodes.forEach((node, i) => {
40
+ const server_stylesheet = component_stylesheet_map.get(node.component);
41
+ if (node.component && server_stylesheet) {
42
+ server_stylesheets.set(i, server_stylesheet);
30
43
  }
31
44
  });
45
+
46
+ // ignore dynamically imported stylesheets since we can't inline those
47
+ css.filter(asset => client_stylesheets.has(asset.fileName))
48
+ .forEach((asset) => {
49
+ if (asset.source.length < kit.inlineStyleThreshold) {
50
+ const [index] = basename(asset.fileName).split('.');
51
+ const server_stylesheet = server_stylesheets.get(+index);
52
+ const file = `${out}/server/stylesheets/${index}.js`;
53
+
54
+ // we need to inline the server stylesheet instead of the client one
55
+ // so that asset paths are correct on document load
56
+ const source = fs.readFileSync(`${out}/server/${server_stylesheet}`, 'utf-8');
57
+
58
+ fs.writeFileSync(file, `// ${server_stylesheet}\nexport default ${s(source)};`);
59
+ stylesheet_lookup.set(asset.fileName, index);
60
+ }
61
+ });
32
62
  }
33
63
 
34
64
  manifest_data.nodes.forEach((node, i) => {
@@ -59,13 +89,19 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli
59
89
  }
60
90
 
61
91
  if (node.universal) {
62
- imports.push(`import * as universal from '../${server_manifest[node.universal].file}';`);
92
+ imports.push(
93
+ `import * as universal from '../${
94
+ resolve_symlinks(server_manifest, node.universal).chunk.file
95
+ }';`
96
+ );
63
97
  exports.push('export { universal };');
64
98
  exports.push(`export const universal_id = ${s(node.universal)};`);
65
99
  }
66
100
 
67
101
  if (node.server) {
68
- imports.push(`import * as server from '../${server_manifest[node.server].file}';`);
102
+ imports.push(
103
+ `import * as server from '../${resolve_symlinks(server_manifest, node.server).chunk.file}';`
104
+ );
69
105
  exports.push('export { server };');
70
106
  exports.push(`export const server_id = ${s(node.server)};`);
71
107
  }
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import * as vite from 'vite';
3
3
  import { dedent } from '../../../core/sync/utils.js';
4
4
  import { s } from '../../../utils/misc.js';
5
- import { get_config_aliases, strip_virtual_prefix, get_env } from '../utils.js';
5
+ import { get_config_aliases, strip_virtual_prefix, get_env, normalize_id } from '../utils.js';
6
6
  import { create_static_module } from '../../../core/env.js';
7
7
  import { env_static_public, service_worker } from '../module_ids.js';
8
8
 
@@ -68,7 +68,8 @@ export async function build_service_worker(
68
68
  name: 'service-worker-build-virtual-modules',
69
69
  resolveId(id) {
70
70
  if (id.startsWith('$env/') || id.startsWith('$app/') || id === '$service-worker') {
71
- return `\0virtual:${id}`;
71
+ // ids with :$ don't work with reverse proxies like nginx
72
+ return `\0virtual:${id.substring(1)}`;
72
73
  }
73
74
  },
74
75
 
@@ -83,7 +84,10 @@ export async function build_service_worker(
83
84
  return create_static_module('$env/static/public', env.public);
84
85
  }
85
86
 
86
- const stripped = strip_virtual_prefix(id);
87
+ const normalized_cwd = vite.normalizePath(process.cwd());
88
+ const normalized_lib = vite.normalizePath(kit.files.lib);
89
+ const relative = normalize_id(id, normalized_lib, normalized_cwd);
90
+ const stripped = strip_virtual_prefix(relative);
87
91
  throw new Error(
88
92
  `Cannot import ${stripped} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
89
93
  );
@@ -462,7 +462,7 @@ export async function dev(vite, vite_config, svelte_config) {
462
462
  res.writeHead(200, {
463
463
  'content-type': 'application/javascript'
464
464
  });
465
- res.end(`import '${to_fs(resolved)}';`);
465
+ res.end(`import '${svelte_config.kit.paths.base}${to_fs(resolved)}';`);
466
466
  } else {
467
467
  res.writeHead(404);
468
468
  res.end('not found');
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { posixify } from '../../../utils/filesystem.js';
3
- import { strip_virtual_prefix } from '../utils.js';
3
+ import { normalize_id, strip_virtual_prefix } from '../utils.js';
4
4
  import { app_server, env_dynamic_private, env_static_private } from '../module_ids.js';
5
5
 
6
6
  const ILLEGAL_IMPORTS = new Set([env_dynamic_private, env_static_private, app_server]);
@@ -85,25 +85,3 @@ export function module_guard(context, { cwd, lib }) {
85
85
  }
86
86
  };
87
87
  }
88
-
89
- /**
90
- * Removes cwd/lib path from the start of the id
91
- * @param {string} id
92
- * @param {string} lib
93
- * @param {string} cwd
94
- */
95
- export function normalize_id(id, lib, cwd) {
96
- if (id.startsWith(lib)) {
97
- id = id.replace(lib, '$lib');
98
- }
99
-
100
- if (id.startsWith(cwd)) {
101
- id = path.relative(cwd, id);
102
- }
103
-
104
- if (id === app_server) {
105
- return '$app/server';
106
- }
107
-
108
- return posixify(id);
109
- }