-
Notifications
You must be signed in to change notification settings - Fork 507
/
server-assets.ts
120 lines (109 loc) · 3.11 KB
/
server-assets.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
118
119
120
import { promises as fsp } from "node:fs";
import type { Plugin } from "rollup";
import createEtag from "etag";
import mime from "mime";
import { resolve } from "pathe";
import { normalizeKey } from "unstorage";
import { globby } from "globby";
import type { Nitro } from "../../types";
import { virtual } from "./virtual";
export interface ServerAssetOptions {
inline: boolean;
dirs: {
[assetdir: string]: {
dir: string;
meta?: boolean;
};
};
}
interface ResolvedAsset {
fsPath: string;
meta: {
type?: string;
etag?: string;
mtime?: string;
};
}
export function serverAssets(nitro: Nitro): Plugin {
// Development: Use filesystem
if (nitro.options.dev || nitro.options.preset === "nitro-prerender") {
return virtual(
{ "#internal/nitro/virtual/server-assets": getAssetsDev(nitro) },
nitro.vfs
);
}
// Production: Bundle assets
return virtual(
{
"#internal/nitro/virtual/server-assets": async () => {
// Scan all assets
const assets: Record<string, ResolvedAsset> = {};
for (const asset of nitro.options.serverAssets) {
const files = await globby("**/*.*", {
cwd: asset.dir,
absolute: false,
});
for (const _id of files) {
const fsPath = resolve(asset.dir, _id);
const id = asset.baseName + "/" + _id;
assets[id] = { fsPath, meta: {} };
// @ts-ignore TODO: Use mime@2 types
let type = mime.getType(id) || "text/plain";
if (type.startsWith("text")) {
type += "; charset=utf-8";
}
const etag = createEtag(await fsp.readFile(fsPath));
const mtime = await fsp.stat(fsPath).then((s) => s.mtime.toJSON());
assets[id].meta = { type, etag, mtime };
}
}
return getAssetProd(assets);
},
},
nitro.vfs
);
}
function getAssetsDev(nitro: Nitro) {
return `
import { createStorage } from 'unstorage'
import fsDriver from 'unstorage/drivers/fs'
const serverAssets = ${JSON.stringify(nitro.options.serverAssets)}
export const assets = createStorage()
for (const asset of serverAssets) {
assets.mount(asset.baseName, fsDriver({ base: asset.dir }))
}`;
}
function getAssetProd(assets: Record<string, ResolvedAsset>) {
return `
const _assets = {\n${Object.entries(assets)
.map(
([id, asset]) =>
` [${JSON.stringify(
normalizeKey(id)
)}]: {\n import: () => import(${JSON.stringify(
"raw:" + asset.fsPath
)}).then(r => r.default || r),\n meta: ${JSON.stringify(
asset.meta
)}\n }`
)
.join(",\n")}\n}
const normalizeKey = ${normalizeKey.toString()}
export const assets = {
getKeys() {
return Promise.resolve(Object.keys(_assets))
},
hasItem (id) {
id = normalizeKey(id)
return Promise.resolve(id in _assets)
},
getItem (id) {
id = normalizeKey(id)
return Promise.resolve(_assets[id] ? _assets[id].import() : null)
},
getMeta (id) {
id = normalizeKey(id)
return Promise.resolve(_assets[id] ? _assets[id].meta : {})
}
}
`;
}