UNPKG

zephyr-astro-integration

Version:
189 lines (188 loc) • 8.83 kB
import "node:module"; import { fileURLToPath } from "node:url"; import { ZeErrors, ZephyrEngine, ZephyrError, assertZephyrBuildTarget, handleGlobalError, rewriteEnvReadsToVirtualModule, zeBuildDashData } from "zephyr-agent"; import { extractAstroAssetsFromBuildHook } from "./internal/extract-astro-assets-map.mjs"; function escapeRegExp(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function nonEmptyString(value) { return 'string' == typeof value && !!value.trim(); } function getLegacyModuleFederationConfig(mfConfigs) { const config = mfConfigs?.length === 1 ? mfConfigs[0] : void 0; if (!config || !nonEmptyString(config.name) || !nonEmptyString(config.filename)) return; return config; } function assertTapModuleFederationMetadata(target, mfConfigs, federation) { if ('tap-app' !== target) return; if (!mfConfigs?.length || !federation?.length) throw new ZephyrError(ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: 'Astro TAP publication requires non-empty mfConfigs and federation metadata arrays.' }); if (mfConfigs.length !== federation.length) throw new ZephyrError(ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: 'Astro TAP mfConfigs and federation metadata must contain the same number of entries.' }); const federationByName = new Map(); const remotes = new Set(); for (const metadata of federation){ if (!nonEmptyString(metadata.name) || !nonEmptyString(metadata.remote)) throw new ZephyrError(ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: 'Astro TAP federation metadata requires a non-empty name and remote for every container.' }); if (federationByName.has(metadata.name) || remotes.has(metadata.remote)) throw new ZephyrError(ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: 'Astro TAP federation metadata entries must not duplicate names or remotes.' }); federationByName.set(metadata.name, metadata); remotes.add(metadata.remote); } const names = new Set(); const filenames = new Set(); for (const config of mfConfigs){ if (!nonEmptyString(config.name) || !nonEmptyString(config.filename)) throw new ZephyrError(ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: 'Astro TAP mfConfigs requires a non-empty name and filename for every container.' }); if (names.has(config.name) || filenames.has(config.filename)) throw new ZephyrError(ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: 'Astro TAP mfConfigs entries must not duplicate names or filenames.' }); if (federationByName.get(config.name)?.remote !== config.filename) throw new ZephyrError(ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: `Astro TAP federation metadata has no matching name and remote for mfConfigs entry "${config.name}" at "${config.filename}".` }); names.add(config.name); filenames.add(config.filename); } } function withZephyr(options) { if (options?.target !== void 0) assertZephyrBuildTarget(options.target, 'withZephyr({ target })'); const preserveTapArtifactBytes = options?.target === 'tap-app'; const { zephyr_engine_defer, zephyr_defer_create } = ZephyrEngine.defer_create(); const hooks = options?.hooks; let cachedSpecifier; const getEnvSpecifier = async ()=>{ if (!cachedSpecifier) { const zephyrEngine = await zephyr_engine_defer; cachedSpecifier = `env:vars:${zephyrEngine.application_uid}`; } return cachedSpecifier; }; const viteZePublicPlugin = { name: 'with-zephyr-astro-env', enforce: 'pre', configResolved: async (config)=>{ if (preserveTapArtifactBytes) return; const vite = await import("vite"); try { const loaded = vite.loadEnv(config.mode || 'production', config.root, ''); for (const [k, v] of Object.entries(loaded))if (k.startsWith('ZE_PUBLIC_') && 'string' == typeof v && !(k in process.env)) process.env[k] = v; } catch (error) { handleGlobalError(error); } }, resolveId: async (source)=>{ if (preserveTapArtifactBytes) return null; try { const specifier = await getEnvSpecifier(); if (source === specifier) { if ('development' === process.env['NODE_ENV']) return '/zephyr-manifest.json'; return { id: source, external: true }; } } catch {} return null; }, transform: { order: 'post', filter: { id: /\.(mjs|cjs|js|ts|jsx|tsx)(?:$|\?)/ }, handler: async (code, id)=>{ if (preserveTapArtifactBytes) return null; try { if (id.includes('node_modules')) return null; const specifier = await getEnvSpecifier(); const result = rewriteEnvReadsToVirtualModule(String(code), specifier); if (result.code !== code) return { code: result.code, map: null }; } catch (error) { handleGlobalError(error); } return null; } }, renderChunk: { order: 'post', handler (code) { if (preserveTapArtifactBytes || !cachedSpecifier) return null; const importWithoutAttribute = new RegExp(`import\\s+([^\\s]+)\\s+from\\s*['"]${escapeRegExp(cachedSpecifier)}['"](?!\\s+with\\s*\\{)`, 'g'); const nextCode = code.replace(importWithoutAttribute, `import $1 from '${cachedSpecifier}' with { type: 'json' }`); return nextCode === code ? null : { code: nextCode, map: null }; } } }; return { name: 'with-zephyr', hooks: { 'astro:config:setup': ({ updateConfig })=>{ if (!preserveTapArtifactBytes) updateConfig({ vite: { plugins: [ viteZePublicPlugin ] } }); }, 'astro:config:done': async ({ config })=>{ const contextPath = fileURLToPath(config.root); zephyr_defer_create({ builder: 'astro', context: contextPath, ...options?.target === void 0 ? {} : { target: options.target } }); }, 'astro:build:done': async ({ dir, ...params })=>{ let zephyr_engine; let buildInProgress = false; try { zephyr_engine = await zephyr_engine_defer; buildInProgress = true; const outputPath = fileURLToPath(dir); zephyr_engine.buildProperties.output = outputPath; await zephyr_engine.start_new_build(); const assets = params.assets; const assetsMap = await extractAstroAssetsFromBuildHook(assets, outputPath, options?.target); assertTapModuleFederationMetadata(options?.target, options?.mfConfigs, options?.federation); const buildStats = await zeBuildDashData(zephyr_engine); const mfConfig = getLegacyModuleFederationConfig(options?.mfConfigs); await zephyr_engine.upload_assets({ assetsMap, buildStats: options?.federation === void 0 ? buildStats : { ...buildStats, federation: options.federation }, ...void 0 === mfConfig ? {} : { mfConfig }, ...options?.mfConfigs === void 0 ? {} : { mfConfigs: options.mfConfigs }, hooks }); buildInProgress = false; await zephyr_engine.build_finished(); } catch (error) { handleGlobalError(error); } finally{ if (buildInProgress && zephyr_engine?.hasActiveBuild !== false) zephyr_engine?.build_failed(); } } } }; } export { withZephyr }; //# sourceMappingURL=astro-integration-zephyr.mjs.map