| 80 | ]; |
| 81 | |
| 82 | // MIME types for all file extensions found in the static asset directories |
| 83 | const MIME_TYPES: Record<string, string> = { |
| 84 | ".graphite": "application/json", |
| 85 | ".ico": "image/x-icon", |
| 86 | ".png": "image/png", |
| 87 | ".svg": "image/svg+xml", |
| 88 | ".webmanifest": "application/manifest+json", |
| 89 | ".xml": "application/xml", |
| 90 | }; |
| 91 | |
| 92 | return { |
| 93 | name: "static-assets", |
| 94 | // Dev: serve files from the listed directories via middleware |
| 95 | configureServer(server) { |
| 96 | server.middlewares.use((req, res, next) => { |
| 97 | if (!req.url) return next(); |
| 98 | const urlPath = decodeURIComponent(req.url.split("?")[0]); |
| 99 | |
| 100 | const match = STATIC_ASSET_DIRS.find(({ source, urlPrefix }) => { |
| 101 | if (urlPrefix && !urlPath.startsWith(urlPrefix + "/") && urlPath !== urlPrefix) return false; |
| 102 | if (!urlPrefix && urlPath.startsWith("/@")) return false; |
| 103 | |
| 104 | const relativePath = urlPrefix ? urlPath.slice(urlPrefix.length) : urlPath; |
| 105 | const filePath = path.resolve(projectRootDir, source, "." + relativePath); |
| 106 | |
| 107 | const sourceDir = path.resolve(projectRootDir, source) + path.sep; |
| 108 | if (!filePath.startsWith(sourceDir)) return false; |
| 109 | |
| 110 | return existsSync(filePath) && !statSync(filePath).isDirectory(); |
| 111 | }); |
| 112 | if (!match) return next(); |
| 113 | const { source, urlPrefix } = match; |