UNPKG

wcz-layout

Version:

142 lines (141 loc) 5.34 kB
import z$1 from "zod"; import axios from "axios"; import fs from "node:fs"; import https from "node:https"; import path from "node:path"; import { loadEnv } from "vite"; //#region src/models/VaultConfig.ts const VaultConfigSchema = z$1.object({ VAULT_ADDRESS: z$1.url(), VAULT_USERNAME: z$1.string().min(1), VAULT_PASSWORD: z$1.string().min(1), VAULT_SECRET_PATH: z$1.string().min(1), VAULT_MOUNT_POINT: z$1.string().default("release") }); //#endregion //#region src/lib/vite-plugin.ts async function fetchVaultSecrets(env) { const { VAULT_ADDRESS, VAULT_USERNAME, VAULT_PASSWORD, VAULT_SECRET_PATH, VAULT_MOUNT_POINT } = VaultConfigSchema.parse(env); const client = axios.create({ baseURL: VAULT_ADDRESS, httpsAgent: new https.Agent({ rejectUnauthorized: false }) }); const { data: loginData } = await client.post(`/v1/auth/userpass/login/${VAULT_USERNAME}`, { password: VAULT_PASSWORD }); const { data: secretData } = await client.get(`/v1/${VAULT_MOUNT_POINT}/data/${VAULT_SECRET_PATH}`, { headers: { "X-Vault-Token": loginData.auth.client_token } }); const secrets = secretData?.data?.data; if (!secrets) throw new Error("No secrets found"); return Object.fromEntries(Object.entries(secrets).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)])); } async function loadVaultSecrets(command) { if (command !== "serve") return; const env = loadEnv("development", process.cwd(), ""); if (!env.VAULT_ADDRESS) return; try { const secrets = await fetchVaultSecrets(env); Object.entries(secrets).forEach(([key, value]) => { process.env[key] ??= value; }); } catch (e) { console.warn("[vite:wcz-layout] Vault failed:", e instanceof Error ? e.message : e); } } function loadLocaleResources(localesPath, addWatchFile) { if (!fs.existsSync(localesPath)) fs.mkdirSync(localesPath, { recursive: true }); const enPath = path.join(localesPath, "en.json"); if (!fs.existsSync(enPath)) fs.writeFileSync(enPath, JSON.stringify({})); const files = fs.readdirSync(localesPath); const resources = {}; for (const file of files.filter((f) => f.endsWith(".json"))) { const lang = path.basename(file, ".json"); const filePath = path.join(localesPath, file); try { resources[lang] = { translation: JSON.parse(fs.readFileSync(filePath, "utf-8")) }; } catch { resources[lang] = { translation: {} }; } addWatchFile(filePath); } return resources; } function ensurePermissionsFile(permissionsPath, addWatchFile) { const dir = path.dirname(permissionsPath); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); if (!fs.existsSync(permissionsPath)) fs.writeFileSync(permissionsPath, "export const permissions = {\n admin: [\"wcz-developers\"]\n} as const;"); addWatchFile(permissionsPath); } function ensureScopesFile(scopesPath, addWatchFile) { const dir = path.dirname(scopesPath); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); if (!fs.existsSync(scopesPath)) fs.writeFileSync(scopesPath, "export const scopes = {\n} as const;"); addWatchFile(scopesPath); } function viteWczLayout() { const virtualModuleId = "virtual:wcz-layout"; const resolvedVirtualModuleId = "\0" + virtualModuleId; let localesPath; let permissionsPath; let scopesPath; return { name: "vite:wcz-layout", enforce: "pre", configResolved(resolvedConfig) { localesPath = path.resolve(resolvedConfig.root, "src/locales"); permissionsPath = path.resolve(resolvedConfig.root, "src/lib/auth/permissions.ts"); scopesPath = path.resolve(resolvedConfig.root, "src/lib/auth/scopes.ts"); }, async config(_, { command }) { await loadVaultSecrets(command); return { optimizeDeps: { exclude: [virtualModuleId], include: [ "prop-types", "react-is", "hoist-non-react-statics", "url-parse", "file-saver", "attr-accept" ] } }; }, configureServer(server) { const refresh = (filePath) => { if (filePath.includes(localesPath) || filePath === permissionsPath || filePath === scopesPath) { const module = server.moduleGraph.getModuleById(resolvedVirtualModuleId); if (module) server.moduleGraph.invalidateModule(module); server.ws.send({ type: "full-reload", path: "*" }); } }; server.watcher.add([ localesPath, permissionsPath, scopesPath ]); server.watcher.on("add", refresh); server.watcher.on("change", refresh); server.watcher.on("unlink", refresh); }, resolveId(id) { if (id === virtualModuleId) return resolvedVirtualModuleId; return null; }, load(id) { if (id !== resolvedVirtualModuleId) return null; const resources = loadLocaleResources(localesPath, this.addWatchFile.bind(this)); ensurePermissionsFile(permissionsPath, this.addWatchFile.bind(this)); ensureScopesFile(scopesPath, this.addWatchFile.bind(this)); const normalizedPermissionsPath = permissionsPath.split(path.sep).join(path.posix.sep); const normalizedScopesPath = scopesPath.split(path.sep).join(path.posix.sep); return ` export const resources = ${JSON.stringify(resources)}; export { permissions } from "${normalizedPermissionsPath}"; export { scopes } from "${normalizedScopesPath}"; `; } }; } //#endregion export { viteWczLayout }; //# sourceMappingURL=vite.js.map