UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

70 lines (68 loc) • 3.02 kB
import { getSecretGroups, renderEnvFile, renderEnvTestFile } from "../cli/infra.mjs"; import { InfraError } from "./types.mjs"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { Context, Effect, Layer } from "effect"; //#region src/infra/materializer.ts var InfraMaterializer = class extends Context.Service()("InfraMaterializer") {}; function ensureDir(filePath) { mkdirSync(dirname(filePath), { recursive: true }); } function writeIfChanged(filePath, content) { if (existsSync(filePath) && readFileSync(filePath, "utf-8") === content) return; ensureDir(filePath); writeFileSync(filePath, content); } function writeContentEffect(filePath, content, phase) { return Effect.try({ try: () => writeIfChanged(filePath, content), catch: (cause) => new InfraError({ phase, message: `failed to write ${filePath}`, cause }) }); } const makeMaterializer = () => ({ materializeTemplate: (configDir, runtimeConfig) => Effect.gen(function* () { const groups = getSecretGroups(runtimeConfig); yield* writeContentEffect(join(configDir, ".env.example"), renderEnvFile(groups, { forExample: true }), "materialize-env"); }), materializeTestInfra: (configDir, runtimeConfig) => Effect.gen(function* () { const groups = getSecretGroups(runtimeConfig); yield* writeContentEffect(join(configDir, ".env.test"), renderEnvTestFile(groups), "materialize-env"); }) }); const InfraMaterializerLive = Layer.succeed(InfraMaterializer, makeMaterializer()); /** * Single source of truth for "should we persist port state?". * Lives next to the only thing that still persists dev ports (the planner). */ function shouldPersistPortState() { return process.env.BOS_NO_PERSIST_PORTS !== "1" && process.env.BOS_TEST !== "1" && process.env.NODE_ENV !== "test"; } /** * True when the run is ephemeral (regression, CI, local test). * In ephemeral mode we must not rewrite `.env.example` because it's a * committed reference template — every regression run was previously * baking the resolved regression port into it, polluting the file. */ function isEphemeralRun() { return process.env.BOS_NO_PERSIST_PORTS === "1" || process.env.BOS_TEST === "1" || process.env.NODE_ENV === "test"; } /** * Orchestration helper: materializes the env templates in the canonical * order. docker-compose.yml is a static committed file — nothing here * generates or rewrites it. */ async function materializeViaLayer(configDir, runtimeConfig, options = {}) { const ephemeral = options.ephemeral ?? isEphemeralRun(); await Effect.runPromise(Effect.gen(function* () { const m = yield* InfraMaterializer; if (!ephemeral) yield* m.materializeTemplate(configDir, runtimeConfig); yield* m.materializeTestInfra(configDir, runtimeConfig); }).pipe(Effect.provide(InfraMaterializerLive))); } //#endregion export { InfraMaterializer, InfraMaterializerLive, isEphemeralRun, materializeViaLayer, shouldPersistPortState }; //# sourceMappingURL=materializer.mjs.map