UNPKG

everything-dev

Version:

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

1 lines • 28.3 kB
{"version":3,"file":"planner.cjs","names":["createHash","resolve","Effect","loadPortState","PortAllocator","isAuthMirrorPluginEntry","ownerOfPort","Clock","InfraError","getSecretGroups","buildConventionalDatabases","buildConventionalRedis","shouldPersistPortState","buildDescription"],"sources":["../../src/infra/planner.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport { Clock, Effect } from \"effect\";\nimport { PortAllocator, type PortBlockEntry } from \"../app\";\nimport {\n buildConventionalDatabases,\n buildConventionalRedis,\n getSecretGroups,\n loadPortState,\n savePortState,\n} from \"../cli/infra\";\nimport {\n type AuthSlotShape,\n buildDescription,\n isAuthMirrorPluginEntry,\n} from \"../service-descriptor\";\nimport type { RuntimeConfig } from \"../types\";\nimport { shouldPersistPortState } from \"./materializer\";\nimport { ownerOfPort } from \"./port-ownership\";\nimport type {\n ClaimRecord,\n CliPorts,\n DatabasePlan,\n InfraInput,\n InfraPlan,\n RedisPlan,\n ResolvedPorts,\n RuntimeLaunchSpec,\n ServiceDescriptorPlan,\n} from \"./types\";\nimport { InfraError } from \"./types\";\n\nconst DEFAULT_HOST_PORT = 3000;\n\nconst POSTGRES_USER = \"everythingdev\";\nconst POSTGRES_PASSWORD = \"everythingdev\";\n\nexport function workspaceKey(configDir: string): string {\n const hash = createHash(\"sha256\").update(resolve(configDir)).digest(\"hex\");\n return hash.slice(0, 12);\n}\n\nfunction normalizeCliPorts(input: InfraInput[\"cli\"]): CliPorts {\n return {\n host: input.port,\n api: input.apiPort,\n auth: input.authPort,\n ui: input.uiPort,\n pluginsStart: input.pluginPortStart,\n plugins: input.plugins,\n };\n}\n\ninterface AllocateServicesResult {\n ports: ResolvedPorts;\n claims: ClaimRecord[];\n devPortsState: {\n host?: number;\n api?: number;\n auth?: number;\n ui?: number;\n pluginPortStart?: number;\n };\n}\n\nexport interface ServiceSources {\n host?: \"local\" | \"remote\";\n api?: \"local\" | \"remote\";\n auth?: \"local\" | \"remote\";\n ui?: \"local\" | \"remote\";\n}\n\nconst PLUGIN_START_OFFSET = 10;\nconst BLOCK_STEP = 100;\n\nfunction allocateServices(\n cliPorts: CliPorts,\n plugins: Record<\n string,\n { source: string; localPath?: string; ui?: { source: string; localPath?: string } }\n >,\n configDir: string,\n auth?: AuthSlotShape,\n sources?: ServiceSources,\n): Effect.Effect<AllocateServicesResult, InfraError, PortAllocator> {\n return Effect.gen(function* () {\n const wKey = workspaceKey(configDir);\n const persisted = loadPortState(configDir).devPorts;\n const allocator = yield* PortAllocator;\n\n const base = cliPorts.host ?? persisted?.host ?? DEFAULT_HOST_PORT;\n const pluginStartPreferred =\n cliPorts.pluginsStart ?? persisted?.pluginPortStart ?? base + PLUGIN_START_OFFSET;\n const pluginStartPinned =\n cliPorts.pluginsStart !== undefined || persisted?.pluginPortStart !== undefined;\n\n const entries: PortBlockEntry[] = [];\n const addEntry = (\n key: string,\n flag: number | undefined,\n persistedValue: number | undefined,\n derived: number,\n ) => {\n if (flag !== undefined) {\n entries.push({ key, preferred: flag, pinned: true });\n } else if (persistedValue !== undefined) {\n entries.push({ key, preferred: persistedValue, pinned: true });\n } else {\n entries.push({ key, preferred: derived, pinned: false });\n }\n };\n\n // Remote-source services spawn nothing locally (ADR 0009 start stack:\n // remotes load over MF from their published origins) — no port is\n // allocated for them. The host is the exception: even when loaded as a\n // remote module, runServer binds its own port.\n addEntry(\"host\", cliPorts.host, undefined, base);\n if (sources?.api !== \"remote\") {\n addEntry(\"api\", cliPorts.api, persisted?.api, base + 1);\n }\n if (sources?.auth !== \"remote\") {\n addEntry(\"auth\", cliPorts.auth, persisted?.auth, base + 2);\n }\n if (sources?.ui !== \"remote\") {\n addEntry(\"ui\", cliPorts.ui, persisted?.ui, base + 3);\n }\n\n const pluginKeys = Object.keys(plugins).sort();\n const isAuthMirrorFor = (\n pluginId: string,\n pluginCfg: { source: string; localPath?: string } | undefined,\n ) => pluginCfg !== undefined && isAuthMirrorPluginEntry(auth, pluginId, pluginCfg);\n\n let pluginSlot = 0;\n for (const pluginId of pluginKeys) {\n const pluginCfg = plugins[pluginId];\n const pluginIsLocal = pluginCfg?.source === \"local\";\n const slotBase = pluginStartPinned ? pluginStartPreferred : base + PLUGIN_START_OFFSET;\n // The auth mirror's backend is owned by the `auth` app slot — no api\n // port. Its ui surface is still real: without a port the runtime config\n // advertises an empty ui.url and the browser can never load the remote\n // (the /login page never renders).\n if (!isAuthMirrorFor(pluginId, pluginCfg) && pluginIsLocal) {\n addEntry(\n `plugin:${pluginId}`,\n cliPorts.plugins?.[pluginId]?.api,\n undefined,\n slotBase + pluginSlot,\n );\n pluginSlot += 1;\n }\n if (\n pluginCfg?.source === \"local\" &&\n pluginCfg?.localPath &&\n pluginCfg?.ui?.source === \"local\"\n ) {\n addEntry(\n `plugin-ui:${pluginId}`,\n cliPorts.plugins?.[pluginId]?.ui,\n undefined,\n slotBase + pluginSlot,\n );\n pluginSlot += 1;\n }\n }\n\n const allocation = yield* allocator.acquireBlock({ base, step: BLOCK_STEP, entries });\n\n if (allocation.base !== base) {\n yield* Effect.logError(\n `[Dev] Preferred port block starting at ${base} is occupied — using ${allocation.base} (this run only; restarts will retry ${base})`,\n );\n for (const conflict of allocation.conflicts.slice(0, 6)) {\n if (conflict.claimed) {\n yield* Effect.logError(\n `[Dev] port ${conflict.port} (${conflict.key}) — live bos session (registry claim)`,\n );\n } else {\n const owner = yield* ownerOfPort(conflict.port);\n yield* Effect.logError(\n `[Dev] port ${conflict.port} (${conflict.key}) — ${\n owner ? `pid ${owner.pid} (${owner.command})` : \"foreign holder (lsof unavailable)\"\n }`,\n );\n }\n }\n }\n\n const pluginApiPorts: Record<string, number> = {};\n const pluginUiPorts: Record<string, number> = {};\n for (const pluginId of pluginKeys) {\n const api = allocation.ports[`plugin:${pluginId}`];\n if (api !== undefined) pluginApiPorts[pluginId] = api;\n const ui = allocation.ports[`plugin-ui:${pluginId}`];\n if (ui !== undefined) pluginUiPorts[pluginId] = ui;\n }\n\n const resolved: ResolvedPorts = {\n host: allocation.ports.host,\n api: allocation.ports.api,\n auth: allocation.ports.auth,\n ui: allocation.ports.ui,\n plugins: Object.fromEntries(\n pluginKeys.map((k) => [k, { api: pluginApiPorts[k], ui: pluginUiPorts[k] }]),\n ),\n };\n\n const devPortsState = {\n host: cliPorts.host,\n api: cliPorts.api,\n auth: cliPorts.auth,\n ui: cliPorts.ui,\n pluginPortStart: cliPorts.pluginsStart,\n };\n\n const claimPorts: Record<string, number> = {};\n for (const [key, port] of Object.entries(allocation.ports)) {\n claimPorts[key] = port;\n }\n\n const claim: ClaimRecord = {\n resourceKey: `workspace:${wKey}`,\n pid: process.pid,\n configDir,\n ports: claimPorts,\n startedAt: yield* Clock.currentTimeMillis,\n };\n\n return { ports: resolved, claims: [claim], devPortsState };\n }).pipe(\n Effect.mapError(\n (portErr) =>\n new InfraError({\n phase: \"allocate-services\",\n message: `Port allocation failed: ${String(portErr)}`,\n cause: portErr,\n }),\n ),\n );\n}\n\nfunction allocateDatabases(runtimeConfig: RuntimeConfig): Effect.Effect<\n {\n dbs: DatabasePlan[];\n redisPlans: RedisPlan[];\n },\n InfraError,\n PortAllocator\n> {\n return Effect.gen(function* () {\n const groups = getSecretGroups(runtimeConfig);\n const allSecrets = groups.flatMap((group) => group.secrets);\n const allocator = yield* PortAllocator;\n\n const conventionalDatabases = buildConventionalDatabases(allSecrets);\n const conventionalRedis = buildConventionalRedis(allSecrets);\n\n const dbs: DatabasePlan[] = [];\n const allocatedByDesired = new Map<number, number>();\n for (const db of conventionalDatabases) {\n let port: number;\n if (allocatedByDesired.has(db.port)) {\n port = allocatedByDesired.get(db.port)!;\n } else {\n port = yield* allocator.pickAvailable(db.port);\n allocatedByDesired.set(db.port, port);\n }\n dbs.push({\n secret: db.secret,\n slug: db.slug,\n port,\n dbName: db.databaseName,\n url: `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${port}/${db.databaseName}`,\n });\n }\n\n const redisPlans: RedisPlan[] = [];\n for (const r of conventionalRedis) {\n const port = yield* allocator.pickAvailable(r.port);\n redisPlans.push({\n secret: r.secret,\n slug: r.slug,\n port,\n url: `redis://localhost:${port}`,\n });\n }\n\n return { dbs, redisPlans };\n }).pipe(\n Effect.mapError(\n (portErr) =>\n new InfraError({\n phase: \"allocate-databases\",\n message: `Database port allocation failed: ${String(portErr)}`,\n cause: portErr,\n }),\n ),\n );\n}\n\nexport function buildServiceDescriptors(\n runtimeConfig: RuntimeConfig,\n resolvedPorts: ResolvedPorts,\n): ServiceDescriptorPlan[] {\n const descriptors: ServiceDescriptorPlan[] = [];\n\n if (runtimeConfig.host) {\n const isLocal = runtimeConfig.host.source === \"local\";\n descriptors.push({\n key: \"host\",\n source: runtimeConfig.host.source,\n url: isLocal ? `http://localhost:${resolvedPorts.host}` : runtimeConfig.host.url,\n port: isLocal ? resolvedPorts.host : undefined,\n localPath: isLocal ? runtimeConfig.host.localPath : undefined,\n });\n }\n\n if (runtimeConfig.api) {\n const isLocal = runtimeConfig.api.source === \"local\";\n descriptors.push({\n key: \"api\",\n source: runtimeConfig.api.source,\n url: isLocal ? `http://localhost:${resolvedPorts.api}` : runtimeConfig.api.url,\n port: isLocal ? resolvedPorts.api : undefined,\n localPath: isLocal ? runtimeConfig.api.localPath : undefined,\n });\n }\n\n if (runtimeConfig.auth) {\n const isLocal = runtimeConfig.auth.source === \"local\";\n descriptors.push({\n key: \"auth\",\n source: runtimeConfig.auth.source,\n url: isLocal ? `http://localhost:${resolvedPorts.auth}` : runtimeConfig.auth.url,\n port: isLocal ? resolvedPorts.auth : undefined,\n localPath: isLocal ? runtimeConfig.auth.localPath : undefined,\n });\n }\n\n if (runtimeConfig.ui) {\n const isLocal = runtimeConfig.ui.source === \"local\";\n descriptors.push({\n key: \"ui\",\n source: runtimeConfig.ui.source,\n url: isLocal ? `http://localhost:${resolvedPorts.ui}` : runtimeConfig.ui.url,\n port: isLocal ? resolvedPorts.ui : undefined,\n localPath: isLocal ? runtimeConfig.ui.localPath : undefined,\n });\n }\n\n if (runtimeConfig.plugins) {\n for (const [pluginId, pluginCfg] of Object.entries(runtimeConfig.plugins)) {\n const pluginIsLocal = pluginCfg.source === \"local\";\n const p = resolvedPorts.plugins[pluginId];\n const isAuthMirror = isAuthMirrorPluginEntry(runtimeConfig.auth, pluginId, pluginCfg);\n if (pluginIsLocal && p?.api && !isAuthMirror) {\n descriptors.push({\n key: `plugin:${pluginId}`,\n source: \"local\",\n url: `http://localhost:${p.api}`,\n port: p.api,\n localPath: pluginCfg.localPath,\n });\n }\n if (!pluginIsLocal && pluginCfg.url && !isAuthMirror) {\n descriptors.push({\n key: `plugin:${pluginId}`,\n source: \"remote\",\n url: pluginCfg.url,\n port: undefined,\n localPath: undefined,\n });\n }\n if (pluginIsLocal && p?.ui && pluginCfg.ui?.source === \"local\") {\n descriptors.push({\n key: `plugin-ui:${pluginId}`,\n source: \"local\",\n url: `http://localhost:${p.ui}`,\n port: p.ui,\n localPath: pluginCfg.ui?.localPath,\n });\n }\n }\n }\n\n return descriptors;\n}\n\nexport function buildLaunchSpec(\n runtimeConfig: RuntimeConfig,\n resolvedPorts: ResolvedPorts,\n): RuntimeLaunchSpec {\n const hostPort =\n runtimeConfig.host?.source === \"local\" ? resolvedPorts.host : runtimeConfig.host?.port;\n const corsOrigin = hostPort ? `http://localhost:${hostPort}` : `http://localhost:3000`;\n\n return {\n port: resolvedPorts.host,\n hostUrl: runtimeConfig.host?.url,\n corsOrigin,\n env: {\n ...(resolvedPorts.host ? { PORT: String(resolvedPorts.host) } : {}),\n ...(resolvedPorts.api ? { API_PORT: String(resolvedPorts.api) } : {}),\n ...(resolvedPorts.ui ? { UI_PORT: String(resolvedPorts.ui) } : {}),\n ...(resolvedPorts.auth ? { AUTH_PORT: String(resolvedPorts.auth) } : {}),\n },\n runtimeConfig,\n };\n}\n\nexport function buildEnvGenerated(\n resolvedPorts: ResolvedPorts,\n dbs: DatabasePlan[],\n redisPlans: RedisPlan[],\n): Record<string, string> {\n const env: Record<string, string> = {};\n\n if (resolvedPorts.host) {\n env.CORS_ORIGIN = `http://localhost:${resolvedPorts.host}`;\n // The host origin for plugins that derive absolute URLs from it (e.g. the\n // auth plugin's Better Auth baseURL — email links, passkey RP id).\n env.BASE_URL = `http://localhost:${resolvedPorts.host}`;\n }\n\n for (const db of dbs) {\n env[db.secret] = db.url;\n }\n for (const r of redisPlans) {\n env[r.secret] = r.url;\n }\n\n return env;\n}\n\nexport function planInfra(input: InfraInput): Effect.Effect<InfraPlan, InfraError, PortAllocator> {\n return Effect.gen(function* () {\n const cliPorts = normalizeCliPorts(input.cli);\n const wKey = workspaceKey(input.configDir);\n\n const plugins = (input.bosConfig.plugins ?? {}) as Record<\n string,\n { source: string; localPath?: string; ui?: { source: string; localPath?: string } }\n >;\n\n const {\n ports: svcPorts,\n claims,\n devPortsState,\n } = yield* allocateServices(cliPorts, plugins, input.configDir, input.bosConfig.auth, {\n host: input.bosConfig.host?.source,\n api: input.bosConfig.api?.source,\n auth: input.bosConfig.auth?.source,\n ui: input.bosConfig.ui?.source,\n });\n\n const { dbs, redisPlans } = yield* allocateDatabases(input.bosConfig);\n\n const resolvedPorts: ResolvedPorts = { ...svcPorts };\n\n // Write merged state once after all allocations succeed\n // Skip persistence for regression tests / ephemeral runs\n // devPorts pins are explicit choices only (ADR 0012 §4): this run's flags,\n // falling back to previously-persisted explicit choices — never drift.\n const previousDevPorts = loadPortState(input.configDir).devPorts ?? {};\n const devPorts = {\n host: devPortsState.host ?? previousDevPorts.host,\n api: devPortsState.api ?? previousDevPorts.api,\n auth: devPortsState.auth ?? previousDevPorts.auth,\n ui: devPortsState.ui ?? previousDevPorts.ui,\n pluginPortStart: devPortsState.pluginPortStart ?? previousDevPorts.pluginPortStart,\n };\n if (shouldPersistPortState()) {\n savePortState(input.configDir, { devPorts });\n }\n\n const hostIsLocal = input.bosConfig.host?.source === \"local\";\n const apiIsLocal = input.bosConfig.api?.source === \"local\";\n const uiIsLocal = input.bosConfig.ui?.source === \"local\";\n const authIsLocal = input.bosConfig.auth?.source === \"local\";\n const assignedRuntimeConfig: RuntimeConfig = {\n ...input.bosConfig,\n host: resolvedPorts.host\n ? {\n ...input.bosConfig.host,\n port: resolvedPorts.host,\n url: `http://localhost:${resolvedPorts.host}`,\n remoteUrl: !hostIsLocal\n ? (input.bosConfig.host.remoteUrl ?? input.bosConfig.host.url)\n : undefined,\n }\n : input.bosConfig.host,\n api:\n apiIsLocal && resolvedPorts.api\n ? {\n ...input.bosConfig.api,\n port: resolvedPorts.api,\n url: `http://localhost:${resolvedPorts.api}`,\n }\n : input.bosConfig.api,\n ui:\n uiIsLocal && resolvedPorts.ui\n ? {\n ...input.bosConfig.ui,\n port: resolvedPorts.ui,\n url: `http://localhost:${resolvedPorts.ui}`,\n ssrUrl: undefined,\n }\n : input.bosConfig.ui,\n auth:\n authIsLocal && resolvedPorts.auth && input.bosConfig.auth\n ? {\n ...input.bosConfig.auth,\n port: resolvedPorts.auth,\n url: `http://localhost:${resolvedPorts.auth}`,\n }\n : input.bosConfig.auth,\n plugins: input.bosConfig.plugins\n ? Object.fromEntries(\n Object.entries(input.bosConfig.plugins).map(([id, p]) => {\n const isAuthMirror = isAuthMirrorPluginEntry(input.bosConfig.auth, id, p);\n const pluginPort = resolvedPorts.plugins[id];\n const patchedUi = (() => {\n if (p.ui?.source !== \"local\" || !p.ui?.localPath || !pluginPort?.ui) return p.ui;\n return {\n ...p.ui,\n port: pluginPort.ui,\n url: `http://localhost:${pluginPort.ui}`,\n ssrUrl: undefined,\n };\n })();\n if (isAuthMirror) {\n return [id, { ...p, ui: patchedUi }];\n }\n if (p.source === \"local\" && pluginPort?.api) {\n return [\n id,\n {\n ...p,\n port: pluginPort.api,\n url: `http://localhost:${pluginPort.api}`,\n ui: patchedUi,\n },\n ];\n }\n return [id, p];\n }),\n )\n : undefined,\n };\n\n const serviceDescriptors = buildServiceDescriptors(assignedRuntimeConfig, resolvedPorts);\n\n const launch = buildLaunchSpec(input.bosConfig, resolvedPorts);\n const envGenerated = buildEnvGenerated(resolvedPorts, dbs, redisPlans);\n\n const packages = serviceDescriptors.map((d) => d.key);\n const descriptionMap = new Map(serviceDescriptors.map((d) => [d.key, d]));\n const description = buildDescription(descriptionMap);\n\n const orchestrator = {\n packages,\n env: {},\n description,\n port: resolvedPorts.host,\n interactive: input.cli.interactive,\n };\n\n return {\n workspaceKey: wKey,\n cliPorts,\n resolvedPorts,\n runtimeConfig: assignedRuntimeConfig,\n launch,\n description,\n serviceDescriptors: new Map(serviceDescriptors.map((d) => [d.key, d])),\n envGenerated,\n claims,\n orchestrator,\n };\n });\n}\n"],"mappings":"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"}