opencode/packages/app/vite.icons.ts

51 lines
1.8 KiB
TypeScript

import { readFileSync } from "node:fs"
import type { Plugin } from "vite"
import manifest from "./manifest.json" with { type: "json" }
export function icons(channel: string): Plugin {
const selected = channel === "beta" || channel === "prod" ? channel : "dev"
const prefix = `icons/${selected}`
const files = [
...Object.entries({
"favicon.ico": "icon.ico",
"apple-touch-icon.png": "ios/AppIcon-60x60@3x.png",
"web-app-manifest-192x192.png": "android/mipmap-xxxhdpi/ic_launcher.png",
"web-app-manifest-512x512.png": "icon.png",
}).map(([name, source]) => ({
fileName: `${prefix}/${name}`,
source: readFileSync(new URL(`../desktop/icons/${selected}/${source}`, import.meta.url)),
type: name.endsWith(".ico") ? "image/x-icon" : "image/png",
})),
{
fileName: "site.webmanifest",
source: JSON.stringify({
...manifest,
icons: manifest.icons.map((icon) => ({ ...icon, src: `/${prefix}${icon.src}` })),
}),
type: "application/manifest+json",
},
]
return {
name: "opencode-app:icons",
generateBundle() {
files.forEach((file) => this.emitFile({ type: "asset", fileName: file.fileName, source: file.source }))
},
configureServer(server) {
server.middlewares.use((request, response, next) => {
const file = files.find((file) => `/${file.fileName}` === request.url?.split("?")[0])
if (!file) return next()
response.setHeader("Content-Type", file.type)
response.end(file.source)
})
},
transformIndexHtml: {
order: "pre",
handler(html) {
return html
.replace("%OPENCODE_FAVICON%", `/${prefix}/favicon.ico`)
.replace("%OPENCODE_APPLE_TOUCH_ICON%", `/${prefix}/apple-touch-icon.png`)
},
},
}
}