-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
index.js
92 lines (80 loc) · 2.87 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { s } from '../../utils/misc.js';
import { get_mime_lookup } from '../utils.js';
/**
* Generates the data used to write the server-side manifest.js file. This data is used in the Vite
* build process, to power routing, etc.
* @param {{
* build_data: import('types').BuildData;
* relative_path: string;
* routes: import('types').RouteData[];
* format?: 'esm' | 'cjs'
* }} opts
*/
export function generate_manifest({ build_data, relative_path, routes, format = 'esm' }) {
/** @typedef {{ index: number, path: string }} LookupEntry */
/** @type {Map<import('types').PageNode, LookupEntry>} */
const bundled_nodes = new Map();
build_data.manifest_data.nodes.forEach((node, i) => {
bundled_nodes.set(node, {
path: `${relative_path}/nodes/${i}.js`,
index: i
});
});
/** @type {(path: string) => string} */
const load =
format === 'esm'
? (path) => `import('${path}')`
: (path) => `Promise.resolve().then(() => require('${path}'))`;
/** @type {(path: string) => string} */
const loader = (path) => `() => ${load(path)}`;
const assets = build_data.manifest_data.assets.map((asset) => asset.file);
if (build_data.service_worker) {
assets.push(build_data.service_worker);
}
const matchers = new Set();
// prettier-ignore
// String representation of
/** @type {import('types').SSRManifest} */
return `{
appDir: ${s(build_data.app_dir)},
assets: new Set(${s(assets)}),
mimeTypes: ${s(get_mime_lookup(build_data.manifest_data))},
_: {
entry: ${s(build_data.client.entry)},
nodes: [
${Array.from(bundled_nodes.values()).map(node => loader(node.path)).join(',\n\t\t\t\t')}
],
routes: [
${routes.map(route => {
route.types.forEach(type => {
if (type) matchers.add(type);
});
if (!route.page && !route.endpoint) return;
return `{
id: ${s(route.id)},
pattern: ${route.pattern},
names: ${s(route.names)},
types: ${s(route.types)},
page: ${route.page ? `{ layouts: ${get_nodes(route.page.layouts)}, errors: ${get_nodes(route.page.errors)}, leaf: ${route.page.leaf} }` : 'null'},
endpoint: ${route.endpoint ? loader(`${relative_path}/${build_data.server.vite_manifest[route.endpoint.file].file}`) : 'null'}
}`;
}).filter(Boolean).join(',\n\t\t\t\t')}
],
matchers: async () => {
${Array.from(matchers).map(type => `const { match: ${type} } = await ${load(`${relative_path}/entries/matchers/${type}.js`)}`).join('\n\t\t\t\t')}
return { ${Array.from(matchers).join(', ')} };
}
}
}`.replace(/^\t/gm, '');
}
/** @param {Array<number | undefined>} indexes */
function get_nodes(indexes) {
let string = indexes.map((n) => n ?? '').join(',');
if (indexes.at(-1) === undefined) {
// since JavaScript ignores trailing commas, we need to insert a dummy
// comma so that the array has the correct length if the last item
// is undefined
string += ',';
}
return `[${string}]`;
}