-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
load-file.ts
117 lines (112 loc) · 3 KB
/
load-file.ts
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { existsSync } from 'node:fs';
import { unlink, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { build as esbuild } from 'esbuild';
import { CONFIG_FILE_NAMES, VIRTUAL_MODULE_ID } from './consts.js';
import { getConfigVirtualModContents } from './integration/vite-plugin-db.js';
import { getDbDirectoryUrl } from './utils.js';
export async function loadDbConfigFile(
root: URL
): Promise<{ mod: { default?: unknown } | undefined; dependencies: string[] }> {
let configFileUrl: URL | undefined;
for (const fileName of CONFIG_FILE_NAMES) {
const fileUrl = new URL(fileName, getDbDirectoryUrl(root));
if (existsSync(fileUrl)) {
configFileUrl = fileUrl;
}
}
if (!configFileUrl) {
return { mod: undefined, dependencies: [] };
}
const { code, dependencies } = await bundleFile({
virtualModContents: getConfigVirtualModContents(),
root,
fileUrl: configFileUrl,
});
return {
mod: await importBundledFile({ code, root }),
dependencies,
};
}
/**
* Bundle arbitrary `mjs` or `ts` file.
* Simplified fork from Vite's `bundleConfigFile` function.
*
* @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L961
*/
export async function bundleFile({
fileUrl,
root,
virtualModContents,
}: {
fileUrl: URL;
root: URL;
virtualModContents: string;
}) {
const result = await esbuild({
absWorkingDir: process.cwd(),
entryPoints: [fileURLToPath(fileUrl)],
outfile: 'out.js',
packages: 'external',
write: false,
target: ['node16'],
platform: 'node',
bundle: true,
format: 'esm',
sourcemap: 'inline',
metafile: true,
define: {
'import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL': 'undefined',
},
plugins: [
{
name: 'resolve-astro-db',
setup(build) {
build.onResolve({ filter: /^astro:db$/ }, ({ path }) => {
return { path, namespace: VIRTUAL_MODULE_ID };
});
build.onLoad({ namespace: VIRTUAL_MODULE_ID, filter: /.*/ }, () => {
return {
contents: virtualModContents,
// Needed to resolve runtime dependencies
resolveDir: fileURLToPath(root),
};
});
},
},
],
});
const file = result.outputFiles[0];
if (!file) {
throw new Error(`Unexpected: no output file`);
}
return {
code: file.text,
dependencies: Object.keys(result.metafile.inputs),
};
}
/**
* Forked from Vite config loader, replacing CJS-based path concat with ESM only
*
* @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L1074
*/
export async function importBundledFile({
code,
root,
}: {
code: string;
root: URL;
}): Promise<{ default?: unknown }> {
// Write it to disk, load it with native Node ESM, then delete the file.
const tmpFileUrl = new URL(`./db.timestamp-${Date.now()}.mjs`, root);
await writeFile(tmpFileUrl, code, { encoding: 'utf8' });
try {
return await import(/* @vite-ignore */ tmpFileUrl.toString());
} finally {
try {
await unlink(tmpFileUrl);
} catch {
// already removed if this function is called twice simultaneously
}
}
}