wcz-layout
Version:
1 lines • 14.2 kB
Source Map (JSON)
{"version":3,"file":"vite.mjs","names":["z","VaultConfigSchema","object","VAULT_ADDRESS","url","VAULT_USERNAME","string","min","VAULT_PASSWORD","VAULT_SECRET_PATH","VAULT_MOUNT_POINT","default","VaultConfig","infer","fs","https","createRequire","path","axios","loadEnv","VaultConfigSchema","Resource","Plugin","fetchVaultSecrets","env","Record","Promise","config","parse","VAULT_ADDRESS","VAULT_USERNAME","VAULT_PASSWORD","VAULT_SECRET_PATH","VAULT_MOUNT_POINT","client","create","baseURL","httpsAgent","Agent","rejectUnauthorized","data","loginData","post","password","secretData","get","headers","auth","client_token","secrets","Error","Object","fromEntries","entries","map","key","value","JSON","stringify","loadVaultSecrets","command","process","cwd","forEach","trim","e","console","warn","message","loadLocaleResources","localesPath","addWatchFile","existsSync","mkdirSync","recursive","enPath","join","writeFileSync","files","readdirSync","resources","file","filter","f","endsWith","lang","basename","filePath","translation","readFileSync","require","import","meta","url","dayjsLocaleImports","keys","toLowerCase","resolve","ensurePermissionsFile","permissionsPath","dir","dirname","ensureScopesFile","scopesPath","loadManifest","manifestPath","name","viteWczLayout","virtualModuleId","resolvedVirtualModuleId","envPath","enforce","configResolved","resolvedConfig","root","_","configureServer","server","refresh","includes","module","moduleGraph","getModuleById","invalidateModule","ws","send","type","watcher","add","on","resolveId","id","load","bind","manifest","normalizedPermissionsPath","split","sep","posix","normalizedScopesPath","normalizedEnvPath"],"sources":["../src/models/VaultConfig.ts","../src/lib/vite-plugin.ts"],"sourcesContent":["import z from \"zod\";\n\nexport const VaultConfigSchema = z.object({\n VAULT_ADDRESS: z.url(),\n VAULT_USERNAME: z.string().min(1),\n VAULT_PASSWORD: z.string().min(1),\n VAULT_SECRET_PATH: z.string().min(1),\n VAULT_MOUNT_POINT: z.string().default(\"release\"),\n});\n\nexport type VaultConfig = z.infer<typeof VaultConfigSchema>;\n","import fs from \"node:fs\";\nimport https from \"node:https\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport axios from \"axios\";\nimport { loadEnv } from \"vite\";\nimport { VaultConfigSchema } from \"../models/VaultConfig\";\nimport type { Resource } from \"i18next\";\nimport type { Plugin } from \"vite\";\n\nasync function fetchVaultSecrets(env: Record<string, string>): Promise<Record<string, string>> {\n const config = VaultConfigSchema.parse(env);\n const { VAULT_ADDRESS, VAULT_USERNAME, VAULT_PASSWORD, VAULT_SECRET_PATH, VAULT_MOUNT_POINT } =\n config;\n\n const client = axios.create({\n baseURL: VAULT_ADDRESS,\n httpsAgent: new https.Agent({ rejectUnauthorized: false }),\n });\n\n const { data: loginData } = await client.post(`/v1/auth/userpass/login/${VAULT_USERNAME}`, {\n password: VAULT_PASSWORD,\n });\n\n const { data: secretData } = await client.get(\n `/v1/${VAULT_MOUNT_POINT}/data/${VAULT_SECRET_PATH}`,\n {\n headers: { \"X-Vault-Token\": loginData.auth.client_token },\n },\n );\n\n const secrets = secretData?.data?.data;\n if (!secrets) throw new Error(\"No secrets found\");\n\n return Object.fromEntries(\n Object.entries(secrets).map(([key, value]) => [\n key,\n typeof value === \"string\" ? value : JSON.stringify(value),\n ]),\n );\n}\n\nasync function loadVaultSecrets(command: string): Promise<void> {\n if (command !== \"serve\") return;\n\n const env = loadEnv(\"development\", process.cwd(), \"\");\n if (!env.VAULT_ADDRESS) return;\n\n try {\n const secrets = await fetchVaultSecrets(env);\n Object.entries(secrets).forEach(([key, value]) => {\n process.env[key] = env[key]?.trim() ? env[key] : value;\n });\n } catch (e) {\n console.warn(\"[vite:wcz-layout] Vault failed:\", e instanceof Error ? e.message : e);\n }\n}\n\nfunction loadLocaleResources(localesPath: string, addWatchFile: (path: string) => void): Resource {\n if (!fs.existsSync(localesPath)) fs.mkdirSync(localesPath, { recursive: true });\n\n const enPath = path.join(localesPath, \"en.json\");\n if (!fs.existsSync(enPath)) fs.writeFileSync(enPath, JSON.stringify({}));\n\n const files = fs.readdirSync(localesPath);\n const resources: Resource = {};\n\n for (const file of files.filter((f) => f.endsWith(\".json\"))) {\n const lang = path.basename(file, \".json\");\n const filePath = path.join(localesPath, file);\n try {\n resources[lang] = { translation: JSON.parse(fs.readFileSync(filePath, \"utf-8\")) };\n } catch {\n resources[lang] = { translation: {} };\n }\n addWatchFile(filePath);\n }\n\n return resources;\n}\n\nconst require = createRequire(import.meta.url);\n\nfunction dayjsLocaleImports(resources: Resource): string {\n return Object.keys(resources)\n .map((lang) => lang.toLowerCase())\n .filter((lang) => {\n try {\n require.resolve(`dayjs/locale/${lang}.js`);\n return true;\n } catch {\n return false;\n }\n })\n .map((lang) => `import \"dayjs/locale/${lang}\";`)\n .join(\"\\n\");\n}\n\nfunction ensurePermissionsFile(\n permissionsPath: string,\n addWatchFile: (path: string) => void,\n): void {\n const dir = path.dirname(permissionsPath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n if (!fs.existsSync(permissionsPath)) {\n fs.writeFileSync(\n permissionsPath,\n 'import type { Permissions } from \"wcz-layout/models\";\\n\\n' +\n \"export const permissions = {\\n\" +\n ' admin: [\"wcz-developers\"],\\n' +\n \"} as const satisfies Permissions;\\n\",\n );\n }\n addWatchFile(permissionsPath);\n}\n\nfunction ensureScopesFile(scopesPath: string, addWatchFile: (path: string) => void): void {\n const dir = path.dirname(scopesPath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n if (!fs.existsSync(scopesPath)) {\n fs.writeFileSync(\n scopesPath,\n 'import type { Scopes } from \"wcz-layout/models\";\\n\\n' +\n \"export const scopes = {\\n\" +\n ' graph: \"User.Read\",\\n' +\n ' api: \"api://wistron.com/app-scope/access_as_user\",\\n' +\n \"} as const satisfies Scopes;\\n\",\n );\n }\n addWatchFile(scopesPath);\n}\n\nfunction loadManifest(\n manifestPath: string,\n addWatchFile: (path: string) => void,\n): { name: string } & Record<string, unknown> {\n addWatchFile(manifestPath);\n try {\n return JSON.parse(fs.readFileSync(manifestPath, \"utf-8\"));\n } catch {\n return { name: \"\" };\n }\n}\n\nexport function viteWczLayout(): Plugin {\n const virtualModuleId = \"virtual:wcz-layout\";\n const resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n let localesPath: string;\n let permissionsPath: string;\n let scopesPath: string;\n let envPath: string;\n let manifestPath: string;\n\n return {\n name: \"vite:wcz-layout\",\n enforce: \"pre\",\n configResolved(resolvedConfig) {\n localesPath = path.resolve(resolvedConfig.root, \"src/lib/locales\");\n permissionsPath = path.resolve(resolvedConfig.root, \"src/lib/auth/permissions.ts\");\n scopesPath = path.resolve(resolvedConfig.root, \"src/lib/auth/scopes.ts\");\n envPath = path.resolve(resolvedConfig.root, \"src/env.ts\");\n manifestPath = path.resolve(resolvedConfig.root, \"public/manifest.json\");\n },\n async config(_, { command }) {\n await loadVaultSecrets(command);\n },\n configureServer(server) {\n const refresh = (filePath: string) => {\n if (\n filePath.includes(localesPath) ||\n filePath === permissionsPath ||\n filePath === scopesPath ||\n filePath === envPath ||\n filePath === manifestPath\n ) {\n const module = server.moduleGraph.getModuleById(resolvedVirtualModuleId);\n if (module) server.moduleGraph.invalidateModule(module);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n }\n };\n\n server.watcher.add([localesPath, permissionsPath, scopesPath, envPath, manifestPath]);\n server.watcher.on(\"add\", refresh);\n server.watcher.on(\"change\", refresh);\n server.watcher.on(\"unlink\", refresh);\n },\n resolveId(id) {\n if (id === virtualModuleId) return resolvedVirtualModuleId;\n return null;\n },\n load(id) {\n if (id !== resolvedVirtualModuleId) return null;\n\n const resources = loadLocaleResources(localesPath, this.addWatchFile.bind(this));\n ensurePermissionsFile(permissionsPath, this.addWatchFile.bind(this));\n ensureScopesFile(scopesPath, this.addWatchFile.bind(this));\n const manifest = loadManifest(manifestPath, this.addWatchFile.bind(this));\n\n const normalizedPermissionsPath = permissionsPath.split(path.sep).join(path.posix.sep);\n const normalizedScopesPath = scopesPath.split(path.sep).join(path.posix.sep);\n const normalizedEnvPath = envPath.split(path.sep).join(path.posix.sep);\n return `\n ${dayjsLocaleImports(resources)}\n export const resources = ${JSON.stringify(resources)};\n export const manifest = ${JSON.stringify(manifest)};\n export { permissions } from \"${normalizedPermissionsPath}\";\n export { scopes } from \"${normalizedScopesPath}\";\n export { serverEnv } from \"${normalizedEnvPath}\";\n `;\n },\n };\n}\n"],"mappings":"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"}