@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.
- package/package.json +5 -7
- package/src/core/adapt/builder.js +127 -31
- package/src/core/adapt/index.js +3 -0
- package/src/core/config/index.js +4 -7
- package/src/core/env.js +36 -8
- package/src/core/generate_manifest/index.js +42 -43
- package/src/core/postbuild/analyse.js +4 -4
- package/src/core/postbuild/fallback.js +1 -1
- package/src/core/postbuild/prerender.js +2 -2
- package/src/core/sync/create_manifest_data/index.js +0 -1
- package/src/core/sync/write_app_manifest.js +3 -2
- package/src/exports/public.d.ts +100 -48
- package/src/exports/vite/build/index.js +1173 -0
- package/src/exports/vite/build/remote.js +4 -4
- package/src/exports/vite/dev/generate_manifest.js +308 -0
- package/src/exports/vite/dev/index.js +28 -284
- package/src/exports/vite/index.js +117 -1308
- package/src/exports/vite/plugins/env-vars.js +11 -34
- package/src/exports/vite/plugins/guard.js +19 -7
- package/src/exports/vite/plugins/remote.js +237 -0
- package/src/exports/vite/preview/index.js +8 -8
- package/src/exports/vite/static_analysis/index.js +15 -15
- package/src/exports/vite/utils.js +1 -1
- package/src/runner.js +4 -3
- package/src/runtime/app/paths/server.js +2 -2
- package/src/runtime/app/server/index.js +3 -3
- package/src/runtime/app/server/public.d.ts +114 -57
- package/src/runtime/app/server/remote/requested.js +31 -15
- package/src/runtime/app/state/client.svelte.js +3 -1
- package/src/runtime/client/client.js +39 -194
- package/src/runtime/client/fetcher.js +6 -6
- package/src/runtime/client/focus.js +120 -0
- package/src/runtime/client/remote-functions/command.svelte.js +20 -9
- package/src/runtime/client/remote-functions/form.svelte.js +12 -7
- package/src/runtime/client/remote-functions/query/instance.svelte.js +19 -5
- package/src/runtime/client/remote-functions/shared.svelte.js +22 -1
- package/src/runtime/client/scroll.js +39 -0
- package/src/runtime/client/utils.js +28 -0
- package/src/runtime/form-utils.js +243 -245
- package/src/runtime/server/data/index.js +3 -10
- package/src/runtime/server/fetch.js +13 -15
- package/src/runtime/server/index.js +8 -7
- package/src/runtime/server/internal.js +1 -2
- package/src/runtime/server/page/index.js +10 -15
- package/src/runtime/server/page/load_data.js +2 -2
- package/src/runtime/server/page/render.js +8 -13
- package/src/runtime/server/page/respond_with_error.js +4 -5
- package/src/runtime/server/page/server_routing.js +21 -27
- package/src/runtime/server/remote-functions.js +14 -14
- package/src/runtime/server/respond.js +17 -40
- package/src/runtime/server/state.js +1 -0
- package/src/runtime/server/utils.js +4 -4
- package/src/runtime/shared.js +9 -0
- package/src/types/ambient-private.d.ts +1 -2
- package/src/types/internal.d.ts +49 -6
- package/src/utils/filesystem.js +43 -27
- package/src/version.js +1 -1
- package/types/index.d.ts +215 -92
- 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
|
|
43
|
-
|
|
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
|
-
|
|
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 ??= (
|
|
89
|
-
resolved_entry = resolve_env_entry(config, resolved_config.root);
|
|
90
|
-
await generate();
|
|
91
|
-
})());
|
|
81
|
+
await (generated ??= generate());
|
|
92
82
|
},
|
|
93
83
|
|
|
94
|
-
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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,
|
|
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)
|
|
133
|
-
if (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)
|
|
137
|
-
if (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
|
-
|
|
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
|
|
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,
|
|
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 =
|
|
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(
|
|
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.
|
|
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 {
|
|
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 =
|
|
43
|
-
|
|
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,
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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 {
|
|
205
|
+
* @param {ESTree.ModuleExportName} node
|
|
206
206
|
* @returns {string}
|
|
207
207
|
*/
|
|
208
208
|
function get_name(node) {
|
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
|
|
5
|
+
* @param {typeof vite} vite the vite module that created the server
|
|
5
6
|
* @param {ViteDevServer} server
|
|
6
7
|
*/
|
|
7
|
-
export function get_runner(
|
|
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 (!
|
|
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.
|
|
87
|
-
const result = find_route(resolved_path, manifest.
|
|
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.
|
|
63
|
-
const length = manifest.
|
|
64
|
-
const type = manifest.
|
|
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: {
|