@sveltejs/kit 3.0.0-next.25 → 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 (59) hide show
  1. package/package.json +5 -7
  2. package/src/core/adapt/builder.js +127 -31
  3. package/src/core/adapt/index.js +3 -0
  4. package/src/core/config/index.js +4 -7
  5. package/src/core/env.js +36 -8
  6. package/src/core/generate_manifest/index.js +42 -43
  7. package/src/core/postbuild/analyse.js +4 -4
  8. package/src/core/postbuild/fallback.js +1 -1
  9. package/src/core/postbuild/prerender.js +2 -2
  10. package/src/core/sync/create_manifest_data/index.js +0 -1
  11. package/src/core/sync/write_app_manifest.js +3 -2
  12. package/src/exports/public.d.ts +100 -48
  13. package/src/exports/vite/build/index.js +1173 -0
  14. package/src/exports/vite/build/remote.js +4 -4
  15. package/src/exports/vite/dev/generate_manifest.js +308 -0
  16. package/src/exports/vite/dev/index.js +28 -284
  17. package/src/exports/vite/index.js +117 -1308
  18. package/src/exports/vite/plugins/env-vars.js +11 -34
  19. package/src/exports/vite/plugins/guard.js +19 -7
  20. package/src/exports/vite/plugins/remote.js +237 -0
  21. package/src/exports/vite/preview/index.js +8 -8
  22. package/src/exports/vite/static_analysis/index.js +15 -15
  23. package/src/exports/vite/utils.js +1 -1
  24. package/src/runner.js +4 -3
  25. package/src/runtime/app/paths/server.js +2 -2
  26. package/src/runtime/app/server/index.js +3 -3
  27. package/src/runtime/app/server/public.d.ts +114 -57
  28. package/src/runtime/app/server/remote/requested.js +31 -15
  29. package/src/runtime/app/state/client.svelte.js +3 -1
  30. package/src/runtime/client/client.js +39 -194
  31. package/src/runtime/client/fetcher.js +6 -6
  32. package/src/runtime/client/focus.js +120 -0
  33. package/src/runtime/client/remote-functions/command.svelte.js +20 -9
  34. package/src/runtime/client/remote-functions/form.svelte.js +12 -7
  35. package/src/runtime/client/remote-functions/query/instance.svelte.js +19 -5
  36. package/src/runtime/client/remote-functions/shared.svelte.js +22 -1
  37. package/src/runtime/client/scroll.js +39 -0
  38. package/src/runtime/client/utils.js +28 -0
  39. package/src/runtime/form-utils.js +243 -245
  40. package/src/runtime/server/data/index.js +3 -10
  41. package/src/runtime/server/fetch.js +13 -15
  42. package/src/runtime/server/index.js +8 -7
  43. package/src/runtime/server/internal.js +1 -2
  44. package/src/runtime/server/page/index.js +10 -15
  45. package/src/runtime/server/page/load_data.js +2 -2
  46. package/src/runtime/server/page/render.js +8 -13
  47. package/src/runtime/server/page/respond_with_error.js +4 -5
  48. package/src/runtime/server/page/server_routing.js +21 -27
  49. package/src/runtime/server/remote-functions.js +14 -14
  50. package/src/runtime/server/respond.js +17 -40
  51. package/src/runtime/server/state.js +1 -0
  52. package/src/runtime/server/utils.js +4 -4
  53. package/src/runtime/shared.js +9 -0
  54. package/src/types/ambient-private.d.ts +1 -2
  55. package/src/types/internal.d.ts +49 -6
  56. package/src/utils/filesystem.js +43 -27
  57. package/src/version.js +1 -1
  58. package/types/index.d.ts +215 -92
  59. package/types/index.d.ts.map +6 -2
@@ -27,9 +27,6 @@ export function plugin_env_vars(config, callback) {
27
27
  /** @type {ResolvedConfig} */
28
28
  let resolved_config;
29
29
 
30
- /** @type {string | null} */
31
- let resolved_entry = null;
32
-
33
30
  /** @type {Set<string>} */
34
31
  let deps = new Set();
35
32
 
@@ -39,12 +36,8 @@ export function plugin_env_vars(config, callback) {
39
36
  let generated;
40
37
 
41
38
  async function generate() {
42
- const synced = await sync.env(
43
- config,
44
- resolved_entry,
45
- resolved_config.root,
46
- resolved_config.mode
47
- );
39
+ const entry = resolve_env_entry(config, resolved_config.root);
40
+ const synced = await sync.env(config, entry, resolved_config.root, resolved_config.mode);
48
41
 
49
42
  deps = synced.deps;
50
43
 
@@ -56,7 +49,7 @@ export function plugin_env_vars(config, callback) {
56
49
  vars,
57
50
  env,
58
51
  dir,
59
- resolved_entry && posixify(path.relative(dir, resolved_entry)),
52
+ entry && posixify(path.relative(dir, entry)),
60
53
  !is_build
61
54
  );
62
55
 
@@ -85,34 +78,18 @@ export function plugin_env_vars(config, callback) {
85
78
  // runs once via the memo — per-process, whichever environment starts first
86
79
  // (environment names vary by adapter), and never in the postbuild forks,
87
80
  // which resolve the config without building
88
- await (generated ??= (async () => {
89
- resolved_entry = resolve_env_entry(config, resolved_config.root);
90
- await generate();
91
- })());
81
+ await (generated ??= generate());
92
82
  },
93
83
 
94
- configureServer(server) {
95
- // `handleHotUpdate` only fires for `change` events on files Vite already knows about,
96
- // so it doesn't cover the env entry being created or deleted while the dev server is
97
- // running. Watch for those events explicitly, re-resolve the entry, regenerate the
98
- // modules and trigger a full reload (mirroring the previous behaviour).
99
- const on_entry_add_unlink = async (/** @type {string} */ file) => {
100
- const resolved = resolve_env_entry(config, resolved_config.root);
101
-
102
- if (file === resolved_entry || file === resolved) {
103
- resolved_entry = resolved;
104
- await generate();
105
- server.hot.send({ type: 'full-reload' });
106
- }
107
- };
108
-
109
- server.watcher.on('add', on_entry_add_unlink);
110
- server.watcher.on('unlink', on_entry_add_unlink);
111
- },
84
+ async hotUpdate({ type, file }) {
85
+ // runs for every environment; the generated modules are shared, so do the work once
86
+ if (this.environment.name !== 'client') return;
87
+
88
+ const created = type === 'create' && file === resolve_env_entry(config, resolved_config.root);
89
+ if (!deps.has(file) && !created) return;
112
90
 
113
- async handleHotUpdate(update) {
114
- if (!deps.has(update.file)) return;
115
91
  await generate();
92
+ if (type !== 'update') this.environment.hot.send({ type: 'full-reload' });
116
93
  }
117
94
  };
118
95
  }
@@ -78,7 +78,7 @@ export function plugin_guard(kit, get_config, get_manifest_data) {
78
78
  // composable filters only work during build so we still need this guard for dev
79
79
  // see https://github.com/vitejs/rolldown-vite/issues/605
80
80
  if (importer && !importer.endsWith('index.html')) {
81
- const resolved = await this.resolve(id, importer, { ...options, skipSelf: true });
81
+ const resolved = await this.resolve(id, importer, options);
82
82
 
83
83
  if (resolved) {
84
84
  const normalized = normalize_id(resolved.id, normalized_aliases, normalized_cwd);
@@ -111,7 +111,7 @@ export function plugin_guard(kit, get_config, get_manifest_data) {
111
111
  let is_server_only = normalized === '$app/env/private' || normalized === '$app/server';
112
112
 
113
113
  // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context
114
- if (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules)) {
114
+ if (id.startsWith(normalized_cwd + '/') && !id.startsWith(normalized_node_modules + '/')) {
115
115
  // e.g. `server.ts` or `foo.server.ts`
116
116
  is_server_only ||= server_only_module_pattern.test(id);
117
117
 
@@ -128,16 +128,28 @@ export function plugin_guard(kit, get_config, get_manifest_data) {
128
128
 
129
129
  /** @type {Set<string>} */
130
130
  const entrypoints = new Set();
131
+
132
+ /**
133
+ * Entrypoints must be normalized like the import map keys, or files
134
+ * outside the project root (e.g. hooks) would never match an importer
135
+ * @param {string} file - absolute, or relative to the project root
136
+ */
137
+ const add_entrypoint = (file) => {
138
+ entrypoints.add(
139
+ normalize_id(posixify(path.resolve(root, file)), normalized_aliases, normalized_cwd)
140
+ );
141
+ };
142
+
131
143
  for (const node of manifest_data.nodes) {
132
- if (node.component) entrypoints.add(node.component);
133
- if (node.universal) entrypoints.add(node.universal);
144
+ if (node.component) add_entrypoint(node.component);
145
+ if (node.universal) add_entrypoint(node.universal);
134
146
  }
135
147
 
136
- if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client);
137
- if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal);
148
+ if (manifest_data.hooks.client) add_entrypoint(manifest_data.hooks.client);
149
+ if (manifest_data.hooks.universal) add_entrypoint(manifest_data.hooks.universal);
138
150
 
139
151
  if (service_worker_entry_file) {
140
- entrypoints.add(posixify(path.relative(root, service_worker_entry_file)));
152
+ add_entrypoint(service_worker_entry_file);
141
153
  }
142
154
 
143
155
  // Walk up the import graph from the server-only module, looking for a chain
@@ -0,0 +1,237 @@
1
+ /** @import { RemoteChunk, RemoteInternals, ServerMetadata, ValidatedConfig } from 'types' */
2
+ /** @import { Plugin, ViteDevServer } from 'vite' */
3
+ import path from 'node:path';
4
+ import { prefixRegex } from '@rolldown/pluginutils';
5
+ import MagicString from 'magic-string';
6
+ import { error_for_missing_config, is_remote_module, remote_module_pattern } from '../utils.js';
7
+ import { create_exported_declarations } from '../../../core/env.js';
8
+ import { dedent } from '../../../core/sync/utils.js';
9
+ import { runtime_directory } from '../../../core/utils.js';
10
+ import { get_runner } from '../../../runner.js';
11
+ import { hash } from '../../../utils/hash.js';
12
+ import { s } from '../../../utils/misc.js';
13
+ import { posixify } from '../../../utils/os.js';
14
+
15
+ /**
16
+ * @param {ValidatedConfig} svelte_config
17
+ * @param {() => { root: string; vite: typeof import('vite'); }} get_config
18
+ * @param {() => ServerMetadata | null} get_build_metadata
19
+ * @param {(remote_metadata: {remotes: RemoteChunk[]; remote_original_by_hash: Map<string, string>}) => void} set_remote_metadata
20
+ * @returns {Plugin}
21
+ */
22
+ export function plugin_remote(svelte_config, get_config, get_build_metadata, set_remote_metadata) {
23
+ /** @type {string} */
24
+ let root;
25
+ /** @type {typeof import('vite')} */
26
+ let vite;
27
+
28
+ /** @type {ViteDevServer} */
29
+ let dev_server;
30
+
31
+ /** @type {ServerMetadata | null} */
32
+ let build_metadata;
33
+
34
+ /** @type {RemoteChunk[]} */
35
+ let remotes = [];
36
+
37
+ /** @type {Map<string, string>} Maps remote hash -> original module id */
38
+ const remote_original_by_hash = new Map();
39
+ /** @type {Set<string>} Track which remote hashes have already been emitted */
40
+ const emitted_remote_hashes = new Set();
41
+
42
+ return {
43
+ name: 'vite-plugin-sveltekit-remote',
44
+
45
+ configResolved() {
46
+ ({ root, vite } = get_config());
47
+ },
48
+
49
+ configureServer(_dev_server) {
50
+ dev_server = _dev_server;
51
+ },
52
+
53
+ applyToEnvironment(environment) {
54
+ return svelte_config.experimental.remoteFunctions && environment.name !== 'serviceWorker';
55
+ },
56
+
57
+ perEnvironmentStartEndDuringDev: true,
58
+
59
+ buildStart() {
60
+ // avoid stale data when building with watch mode
61
+ if (this.meta.watchMode && this.environment.config.consumer === 'server') {
62
+ remotes = [];
63
+ remote_original_by_hash.clear();
64
+ emitted_remote_hashes.clear();
65
+ }
66
+
67
+ build_metadata = get_build_metadata();
68
+ set_remote_metadata({ remotes, remote_original_by_hash });
69
+ },
70
+
71
+ // prevent other plugins from resolving our remote virtual module
72
+ resolveId: {
73
+ filter: {
74
+ id: prefixRegex('\0sveltekit-remote:')
75
+ },
76
+ handler(id) {
77
+ return id;
78
+ }
79
+ },
80
+
81
+ load: {
82
+ filter: {
83
+ id: prefixRegex('\0sveltekit-remote:')
84
+ },
85
+ handler(id) {
86
+ // On-the-fly generated entry point for remote file just forwards the original module
87
+ // We're not using manualChunks because it can cause problems with circular dependencies
88
+ // (e.g. https://github.com/sveltejs/kit/issues/14679) and module ordering in general
89
+ // (e.g. https://github.com/sveltejs/kit/issues/14590).
90
+ const hash_id = id.slice('\0sveltekit-remote:'.length);
91
+ const original = remote_original_by_hash.get(hash_id);
92
+ if (!original) throw new Error(`Expected to find metadata for remote file ${id}`);
93
+ return `import * as m from ${s(original)};\nexport default m;`;
94
+ }
95
+ },
96
+
97
+ transform: {
98
+ filter: {
99
+ id: remote_module_pattern
100
+ },
101
+ async handler(code, id) {
102
+ if (!is_remote_module(id)) return;
103
+
104
+ const file = posixify(path.relative(root, id));
105
+ const remote = {
106
+ hash: hash(file),
107
+ file
108
+ };
109
+
110
+ if (this.environment.config.consumer === 'server') {
111
+ remotes.push(remote);
112
+
113
+ // we need to add an `await Promise.resolve()` because if the user imports this function
114
+ // on the client AND in a load function when loading the client module we will trigger
115
+ // an import during dev. During a link preload, the module can be mistakenly
116
+ // loaded and transformed twice and the first time all its exports would be undefined
117
+ // triggering a dev server error. By adding a microtask we ensure that the module is fully loaded
118
+ const ms = new MagicString(code);
119
+
120
+ // Extra newlines to prevent syntax errors around missing semicolons or comments
121
+ ms.append(
122
+ '\n\n' +
123
+ dedent`
124
+ import * as $$_self_$$ from './${path.basename(id)}';
125
+ import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal/server';
126
+
127
+ ${dev_server ? 'await Promise.resolve()' : ''}
128
+
129
+ $$_init_$$($$_self_$$, ${s(file)}, ${s(remote.hash)});
130
+
131
+ for (const [name, fn] of Object.entries($$_self_$$)) {
132
+ fn.__.id = ${s(remote.hash)} + '/' + name;
133
+ fn.__.name = name;
134
+ }
135
+ `
136
+ );
137
+
138
+ // Emit a dedicated entry chunk for this remote in SSR builds (prod only)
139
+ if (!dev_server) {
140
+ remote_original_by_hash.set(remote.hash, id);
141
+
142
+ if (!emitted_remote_hashes.has(remote.hash)) {
143
+ this.emitFile({
144
+ type: 'chunk',
145
+ id: `\0sveltekit-remote:${remote.hash}`,
146
+ name: `remote-${remote.hash}`
147
+ });
148
+ emitted_remote_hashes.add(remote.hash);
149
+ }
150
+ }
151
+
152
+ return {
153
+ code: ms.toString(),
154
+ map: ms.generateMap({ hires: 'boundary' })
155
+ };
156
+ }
157
+
158
+ // For the client, read the exports and create a new module that only contains fetch functions with the correct metadata
159
+
160
+ /** @type {Map<string, RemoteInternals['type']>} */
161
+ const map = new Map();
162
+
163
+ // in dev, load the server module here (which will result in this hook
164
+ // being called again with `opts.ssr === true` if the module isn't
165
+ // already loaded) so we can determine what it exports
166
+ if (dev_server) {
167
+ const module = await get_runner(vite, dev_server).import(id);
168
+
169
+ for (const [name, value] of Object.entries(module)) {
170
+ const type = value?.__?.type;
171
+ if (type) map.set(name, type);
172
+ }
173
+ }
174
+ // in prod, we already built and analysed the server code before
175
+ // building the client code, so `remotes` is populated
176
+ else if (build_metadata?.remotes) {
177
+ const exports = build_metadata.remotes.get(remote.hash);
178
+ if (!exports) throw new Error('Expected to find metadata for remote file ' + id);
179
+
180
+ for (const [name, value] of exports) {
181
+ map.set(name, value.type);
182
+ }
183
+ }
184
+
185
+ const { namespace, declarations, reexports } = create_exported_declarations(
186
+ map.keys(),
187
+ (name, ns) => `${ns}.${map.get(name)}('${remote.hash}/${name}')`,
188
+ '__remote'
189
+ );
190
+
191
+ const relative = posixify(
192
+ path.relative(path.dirname(id), `${runtime_directory}/client/remote-functions/index.js`)
193
+ );
194
+
195
+ let result = `import * as ${namespace} from '${relative}';\n\n${declarations.join('\n')}`;
196
+ if (reexports.length > 0) {
197
+ result += `\nexport { ${reexports.join(', ')} };`;
198
+ }
199
+ result += '\n';
200
+
201
+ if (dev_server) {
202
+ result += `\nimport.meta.hot?.accept();\n`;
203
+ }
204
+
205
+ return {
206
+ code: result,
207
+ map: null
208
+ };
209
+ }
210
+ }
211
+ };
212
+ }
213
+
214
+ /**
215
+ * @param {ValidatedConfig} svelte_config
216
+ * @returns {Plugin}
217
+ */
218
+ export function plugin_remote_guard(svelte_config) {
219
+ return {
220
+ name: 'vite-plugin-sveltekit-remote-guard',
221
+
222
+ applyToEnvironment() {
223
+ return !svelte_config.experimental.remoteFunctions;
224
+ },
225
+
226
+ transform: {
227
+ filter: {
228
+ id: new RegExp(
229
+ `.remote(${svelte_config.moduleExtensions.join('|')})$`.replaceAll('.', '\\.')
230
+ )
231
+ },
232
+ handler() {
233
+ error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true');
234
+ }
235
+ }
236
+ };
237
+ }
@@ -1,5 +1,5 @@
1
1
  /** @import { NextHandleFunction } from 'connect' */
2
- /** @import { PreviewServer, ResolvedConfig } from 'vite' */
2
+ /** @import { PreviewServer } from 'vite' */
3
3
  /** @import { ValidatedConfig, ServerInternalModule, ServerModule } from 'types' */
4
4
  import fs from 'node:fs';
5
5
  import { join } from 'node:path';
@@ -15,15 +15,14 @@ import { stackless } from '../../../utils/error.js';
15
15
 
16
16
  /**
17
17
  * @param {PreviewServer} vite
18
- * @param {ResolvedConfig} vite_config
19
18
  * @param {ValidatedConfig} svelte_config
20
19
  */
21
- export async function preview(vite, vite_config, svelte_config) {
20
+ export async function preview(vite, svelte_config) {
22
21
  const { paths } = svelte_config;
23
22
  const base = paths.base;
24
23
  const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base;
25
24
 
26
- const protocol = vite_config.preview.https ? 'https' : 'http';
25
+ const protocol = vite.config.preview.https ? 'https' : 'http';
27
26
 
28
27
  const etag = `"${Date.now()}"`;
29
28
 
@@ -44,6 +43,7 @@ export async function preview(vite, vite_config, svelte_config) {
44
43
  /** @type {ServerModule} */
45
44
  const { Server } = await import(pathToFileURL(join(dir, 'index.js')).href);
46
45
 
46
+ /** @type {{ manifest: import('types').SSRManifest }} */
47
47
  const { manifest } = await import(pathToFileURL(join(dir, 'manifest.js')).href);
48
48
 
49
49
  set_assets(assets);
@@ -52,7 +52,7 @@ export async function preview(vite, vite_config, svelte_config) {
52
52
 
53
53
  try {
54
54
  await server.init({
55
- env: loadEnv(vite_config.mode, svelte_config.env.dir, ''),
55
+ env: loadEnv(vite.config.mode, svelte_config.env.dir, ''),
56
56
  read: (file) => createReadableStream(`${dir}/${file}`)
57
57
  });
58
58
  } catch (error) {
@@ -205,13 +205,13 @@ export async function preview(vite, vite_config, svelte_config) {
205
205
  vite.middlewares.use(async (req, res) => {
206
206
  const host = req.headers[':authority'] || req.headers.host;
207
207
 
208
- const request = getRequest({
208
+ const request = (svelte_config.adapter?.vite?.getRequest ?? getRequest)({
209
209
  base: `${protocol}://${host}`,
210
210
  request: req,
211
211
  response: res
212
212
  });
213
213
 
214
- setResponse(
214
+ (svelte_config.adapter?.vite?.setResponse ?? setResponse)(
215
215
  res,
216
216
  await server.respond(request, {
217
217
  getClientAddress: () => {
@@ -220,7 +220,7 @@ export async function preview(vite, vite_config, svelte_config) {
220
220
  throw new Error('Could not determine clientAddress');
221
221
  },
222
222
  read: (file) => {
223
- if (file in manifest._.server_assets) {
223
+ if (file in manifest.server_assets) {
224
224
  return fs.readFileSync(join(dir, file));
225
225
  }
226
226
 
@@ -1,7 +1,7 @@
1
1
  /** @import { PageOptions } from './types.js' */
2
+ /** @import { ESTree } from 'vite' */
2
3
  import path from 'node:path';
3
- import { tsPlugin } from '@sveltejs/acorn-typescript';
4
- import { Parser } from 'acorn';
4
+ import { parseSync } from 'vite';
5
5
  import { read } from '../../../utils/filesystem.js';
6
6
 
7
7
  export const valid_page_options_array = /** @type {const} */ ([
@@ -21,8 +21,6 @@ const skip_parsing_regex = new RegExp(
21
21
  `${Array.from(valid_page_options).join('|')}|(?:export[\\s\\n]+\\*[\\s\\n]+from)`
22
22
  );
23
23
 
24
- const parser = Parser.extend(tsPlugin());
25
-
26
24
  /**
27
25
  * Collects page options from a +page.js/+layout.js file, ignoring reassignments
28
26
  * and using the declared value (except for load functions, for which the value is `true`).
@@ -39,15 +37,13 @@ export function statically_analyse_page_options(filename, input) {
39
37
  }
40
38
 
41
39
  try {
42
- const source = parser.parse(input, {
43
- sourceType: 'module',
44
- ecmaVersion: 'latest'
45
- });
40
+ const source = parseSync(filename, input, { sourceType: 'module' });
41
+ if (source.errors.length) throw new Error(source.errors[0].message);
46
42
 
47
- /** @type {Map<string, import('acorn').Literal['value']>} */
43
+ /** @type {Map<string, Extract<ESTree.Expression, { type: 'Literal' }>['value']>} */
48
44
  const page_options = new Map();
49
45
 
50
- for (const statement of source.body) {
46
+ for (const statement of source.program.body) {
51
47
  // ignore export all declarations with aliases that are not page options
52
48
  if (
53
49
  statement.type === 'ExportAllDeclaration' &&
@@ -82,7 +78,7 @@ export function statically_analyse_page_options(filename, input) {
82
78
  export_specifiers.set(get_name(specifier.local), exported_name);
83
79
  }
84
80
 
85
- for (const statement of source.body) {
81
+ for (const statement of source.program.body) {
86
82
  switch (statement.type) {
87
83
  case 'ImportDeclaration': {
88
84
  for (const import_specifier of statement.specifiers) {
@@ -105,7 +101,10 @@ export function statically_analyse_page_options(filename, input) {
105
101
 
106
102
  // class and function declarations
107
103
  if (declaration.type !== 'VariableDeclaration') {
108
- if (export_specifiers.has(declaration.id.name)) {
104
+ if (
105
+ declaration.id?.type === 'Identifier' &&
106
+ export_specifiers.has(declaration.id.name)
107
+ ) {
109
108
  return null;
110
109
  }
111
110
  break;
@@ -156,9 +155,10 @@ export function statically_analyse_page_options(filename, input) {
156
155
 
157
156
  // class and function declarations
158
157
  if (statement.declaration.type !== 'VariableDeclaration') {
159
- if (valid_page_options.has(statement.declaration.id.name)) {
158
+ const { id } = statement.declaration;
159
+ if (id?.type === 'Identifier' && valid_page_options.has(id.name)) {
160
160
  // Special case: We only want to know that 'load' is exported (in a way that doesn't cause truthy checks in other places to trigger)
161
- if (statement.declaration.id.name === 'load') {
161
+ if (id.name === 'load') {
162
162
  page_options.set('load', null);
163
163
  } else {
164
164
  return null;
@@ -202,7 +202,7 @@ export function statically_analyse_page_options(filename, input) {
202
202
  }
203
203
 
204
204
  /**
205
- * @param {import('acorn').Identifier | import('acorn').Literal} node
205
+ * @param {ESTree.ModuleExportName} node
206
206
  * @returns {string}
207
207
  */
208
208
  function get_name(node) {
@@ -134,7 +134,7 @@ export function normalize_id(id, aliases, cwd) {
134
134
  }
135
135
  }
136
136
 
137
- if (id.startsWith(cwd)) {
137
+ if (id.startsWith(cwd + '/')) {
138
138
  id = path.relative(cwd, id);
139
139
  }
140
140
 
package/src/runner.js CHANGED
@@ -1,13 +1,14 @@
1
+ /** @import * as vite from 'vite' */
1
2
  /** @import { ViteDevServer } from 'vite' */
2
3
 
3
4
  /**
4
- * @param {typeof import('vite')} vite the peer resolved vite module
5
+ * @param {typeof vite} vite the vite module that created the server
5
6
  * @param {ViteDevServer} server
6
7
  */
7
- export function get_runner(vite, server) {
8
+ export function get_runner({ isRunnableDevEnvironment }, server) {
8
9
  // `isRunnableDevEnvironment` does an `instanceof` check and will fail if
9
10
  // we're using different instances of Vite
10
- if (!vite.isRunnableDevEnvironment(server.environments.ssr)) {
11
+ if (!isRunnableDevEnvironment(server.environments.ssr)) {
11
12
  throw new Error('The configured Vite SSR environment must be a RunnableDevEnvironment');
12
13
  }
13
14
 
@@ -83,8 +83,8 @@ export async function match(url) {
83
83
  resolved_path = resolved_path.slice(base.length) || '/';
84
84
  }
85
85
 
86
- const matchers = await manifest._.matchers();
87
- const result = find_route(resolved_path, manifest._.routes, matchers);
86
+ const matchers = await manifest.matchers();
87
+ const result = find_route(resolved_path, manifest.routes, matchers);
88
88
 
89
89
  if (result) {
90
90
  return {
@@ -59,9 +59,9 @@ export function read(asset) {
59
59
  : asset.slice(assets.length + 1)
60
60
  );
61
61
 
62
- if (file in manifest._.server_assets) {
63
- const length = manifest._.server_assets[file];
64
- const type = manifest.mimeTypes[file.slice(file.lastIndexOf('.'))];
62
+ if (file in manifest.server_assets) {
63
+ const length = manifest.server_assets[file];
64
+ const type = manifest.mime_types[file.slice(file.lastIndexOf('.'))];
65
65
 
66
66
  return new Response(read_implementation(file), {
67
67
  headers: {