everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 18.6 kB
Source Map (JSON)
{"version":3,"file":"init.cjs","names":["fetchParentConfig","parseBosUrl","resolve","timePhase","detectGitRemoteUrl","process","resolveSourceDir","scaffoldMinimalProject","personalizeConfig","convertChildConfigToAppForm","buildInitPatterns","buildPluginRouteExclusions","buildStarterRouteExclusions","copyFilteredFiles","existsSync","join","saveBosConfig","pruneUnusedUiFiles","writeInitSnapshot","personalizeAgentsMd","syncResolvedSharedDeps","openResolution","materializeViaLayer","Effect","makeProjectEnv","runPnpmInstall","runTypesGen","generateDatabaseMigrations","generateCodeArtifacts"],"sources":["../../src/commands/init.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport {\n buildInitPatterns,\n buildPluginRouteExclusions,\n buildStarterRouteExclusions,\n convertChildConfigToAppForm,\n copyFilteredFiles,\n detectGitRemoteUrl,\n fetchParentConfig,\n generateDatabaseMigrations,\n personalizeAgentsMd,\n personalizeConfig,\n removeStrayLockfiles,\n resolveSourceDir,\n runPnpmInstall,\n runTypesGen,\n scaffoldMinimalProject,\n writeDevOverlayTemplate,\n writeInitSnapshot,\n} from \"../cli/init\";\nimport { pruneUnusedUiFiles } from \"../cli/prune\";\nimport { generateCodeArtifacts } from \"../code-artifacts\";\nimport type { OverrideSection, PhaseTiming } from \"../contract\";\nimport { makeProjectEnv } from \"../env/project-env\";\nimport { parseBosUrl } from \"../fastkv\";\nimport { materializeViaLayer } from \"../infra/materializer\";\nimport { timePhase } from \"../progress\";\nimport { openResolution } from \"../resolution/session\";\nimport { syncResolvedSharedDeps } from \"../shared-deps\";\nimport type { BosConfig, BosConfigInput, StarterLevel } from \"../types\";\nimport { saveBosConfig } from \"../utils/save-config\";\nimport type { BosBuilder } from \"./shared\";\n\nexport async function fetchInitParent(\n extendsAccount: string,\n extendsGateway: string,\n): Promise<{ parentConfig: BosConfig; parentPluginKeys: string[] }> {\n const parentConfig = await fetchParentConfig(extendsAccount, extendsGateway);\n const parentPluginKeys =\n parentConfig?.plugins && typeof parentConfig.plugins === \"object\"\n ? Object.keys(parentConfig.plugins)\n : [];\n return { parentConfig, parentPluginKeys };\n}\n\nfunction normalizeExtendsRef(extendsInput: string | undefined, fallback: string): string {\n if (!extendsInput) return fallback;\n return extendsInput.startsWith(\"bos://\") ? extendsInput : `bos://${extendsInput}`;\n}\n\nexport function registerInit(builder: BosBuilder) {\n return {\n init: builder.init.handler(async ({ input }) => {\n try {\n const timings: PhaseTiming[] = [];\n let extendsAccount = \"\";\n let extendsGateway = \"\";\n let directory = input.directory;\n const account = input.account;\n const domain = input.domain;\n let overrides = input.overrides as OverrideSection[] | undefined;\n let plugins = input.plugins;\n\n if (input.extends) {\n try {\n const { accountId, gatewayId } = parseBosUrl(normalizeExtendsRef(input.extends, \"\"));\n extendsAccount = accountId;\n extendsGateway = gatewayId;\n } catch {\n extendsAccount = \"\";\n extendsGateway = \"\";\n }\n }\n\n extendsAccount = extendsAccount || \"dev.everything.near\";\n extendsGateway = extendsGateway || \"everything.dev\";\n\n directory = directory || domain || extendsGateway;\n const targetDir = resolve(directory);\n const extendsRef = `bos://${extendsAccount}/${extendsGateway}`;\n\n let parentPluginKeys: string[] = [];\n let parentConfig: BosConfig | null = null;\n try {\n const parent = await timePhase(timings, \"parent config\", () =>\n fetchInitParent(extendsAccount, extendsGateway),\n );\n parentConfig = parent.parentConfig;\n parentPluginKeys = parent.parentPluginKeys;\n } catch (e) {\n console.warn(\n `[init] Failed to fetch parent config from ${extendsAccount}/${extendsGateway}: ${\n e instanceof Error ? e.message : String(e)\n }`,\n );\n return {\n status: \"error\" as const,\n directory,\n extendsRef,\n account,\n domain,\n extends: extendsRef,\n plugins,\n overrides,\n filesCopied: 0,\n timings,\n error: `No config found at ${extendsRef} — are you sure this is the right parent?`,\n };\n }\n\n overrides = overrides?.length ? overrides : ([\"ui\", \"api\"] as OverrideSection[]);\n const level: StarterLevel = input.level ?? \"simple\";\n if (overrides.includes(\"plugins\") && plugins === undefined) {\n plugins = parentPluginKeys;\n }\n plugins = plugins ?? [];\n\n const pluginDirMap: Record<string, string> = {};\n if (parentConfig?.plugins) {\n for (const plugin of plugins) {\n const entry = (parentConfig.plugins as Record<string, unknown>)?.[plugin];\n if (entry && typeof entry === \"object\") {\n const dev = (entry as Record<string, unknown>).development;\n if (typeof dev === \"string\") {\n const match = dev.match(/^local:plugins\\/(.+)$/);\n if (match?.[1] && match[1] !== plugin) pluginDirMap[plugin] = match[1];\n }\n }\n }\n }\n\n const repository =\n (await detectGitRemoteUrl(process.cwd()).catch(() => undefined)) ??\n parentConfig?.repository;\n\n const {\n sourceDir,\n parentConfig: resolvedParentConfig,\n cleanup,\n } = await timePhase(timings, \"template source\", () =>\n resolveSourceDir({\n extendsAccount,\n extendsGateway,\n source: input.source,\n }),\n );\n\n parentConfig = resolvedParentConfig;\n\n const isMinimalScaffold = sourceDir === \"\";\n\n try {\n let filesCopied: number;\n let childBosConfig: BosConfigInput | null = null;\n\n if (isMinimalScaffold) {\n filesCopied = await timePhase(timings, \"scaffold project\", () =>\n scaffoldMinimalProject(targetDir, parentConfig as unknown as BosConfigInput, {\n extendsAccount,\n extendsGateway,\n account: account || extendsAccount,\n domain,\n plugins,\n overrides,\n repository,\n title: parentConfig?.title,\n description: parentConfig?.description,\n starter: level,\n }),\n );\n\n await timePhase(timings, \"personalize config\", () =>\n personalizeConfig(targetDir, {\n extendsAccount,\n extendsGateway,\n account: account || extendsAccount,\n domain: domain || extendsGateway,\n plugins,\n overrides,\n mode: \"init\",\n repository,\n title: parentConfig?.title,\n description: parentConfig?.description,\n testnet: parentConfig?.testnet,\n staging: parentConfig?.staging,\n starter: level,\n }),\n );\n\n childBosConfig = await timePhase(timings, \"authored config form\", () =>\n convertChildConfigToAppForm(targetDir),\n );\n\n writeDevOverlayTemplate(targetDir, {\n extendsRef: `bos://${extendsAccount}/${extendsGateway}`,\n });\n } else {\n const patterns = buildInitPatterns(overrides, plugins, pluginDirMap);\n const routeExclusions = overrides.includes(\"ui\")\n ? buildPluginRouteExclusions(parentConfig, plugins)\n : [];\n const starterExclusions = overrides.includes(\"ui\")\n ? buildStarterRouteExclusions(level, parentConfig)\n : [];\n const copyIgnore = [...routeExclusions, ...starterExclusions];\n\n filesCopied = await timePhase(timings, \"copy files\", () =>\n copyFilteredFiles(sourceDir, targetDir, patterns, {\n overrides,\n plugins,\n ignore: copyIgnore,\n }),\n );\n\n // The child's authored config is always generated, never copied:\n // a TS-form parent's bos.app.ts imports everything-dev and cannot\n // load before the child's install. Write the JSON form from the\n // loaded parent config — the personalization +\n // convertChildConfigToAppForm below produce the child's own\n // authored bos.app.ts.\n if (!existsSync(join(targetDir, \"bos.config.json\"))) {\n await saveBosConfig(targetDir, parentConfig);\n }\n\n await timePhase(timings, \"personalize config\", () =>\n personalizeConfig(targetDir, {\n extendsAccount,\n extendsGateway,\n account: account || extendsAccount,\n domain: domain || extendsGateway,\n plugins,\n overrides,\n workspaceOpts: { sourceDir },\n repository,\n title: parentConfig?.title,\n description: parentConfig?.description,\n testnet: parentConfig?.testnet,\n staging: parentConfig?.staging,\n starter: level,\n }),\n );\n\n childBosConfig = await timePhase(timings, \"authored config form\", () =>\n convertChildConfigToAppForm(targetDir),\n );\n\n writeDevOverlayTemplate(targetDir, {\n extendsRef: `bos://${extendsAccount}/${extendsGateway}`,\n });\n\n if (overrides.includes(\"ui\")) {\n await timePhase(timings, \"prune unused ui files\", async () =>\n pruneUnusedUiFiles(targetDir, { log: console.log }),\n );\n }\n\n await timePhase(timings, \"write snapshot\", () =>\n writeInitSnapshot(targetDir, extendsAccount, extendsGateway, sourceDir, patterns, {\n overrides,\n plugins,\n ignore: copyIgnore,\n starter: level,\n }),\n );\n\n await timePhase(timings, \"personalize agents\", () =>\n personalizeAgentsMd(targetDir, { overrides, plugins }),\n );\n }\n\n await timePhase(timings, \"sync shared deps\", () =>\n syncResolvedSharedDeps({\n configDir: targetDir,\n hostMode: \"local\",\n bosConfig: childBosConfig\n ? (childBosConfig as unknown as Record<string, unknown>)\n : undefined,\n }),\n );\n\n // A stray lockfile (copied or left from a previous run) would pin\n // stale framework resolutions — the fresh install re-resolves.\n removeStrayLockfiles(targetDir);\n\n const initConfig = await timePhase(timings, \"resolve config\", () =>\n openResolution({ cwd: targetDir }).catch((error: unknown) => {\n console.warn(\n \"[init] Skipping config resolution — the child has no node_modules yet; `bos dev` resolves after `pnpm install`.\",\n error instanceof Error ? error.message : error,\n );\n return null;\n }),\n );\n const initRuntime = initConfig?.runtime;\n if (initRuntime) {\n await timePhase(timings, \"generate env/docker\", async () => {\n await materializeViaLayer(targetDir, initRuntime);\n });\n }\n await timePhase(timings, \"create env file\", async () => {\n await Effect.runPromise(makeProjectEnv().ensureFile(targetDir));\n });\n\n if (!input.noInstall) {\n await timePhase(timings, \"install dependencies\", () => runPnpmInstall(targetDir));\n await timePhase(timings, \"generate types\", () => runTypesGen(targetDir));\n await timePhase(timings, \"generate migrations\", () =>\n generateDatabaseMigrations(targetDir),\n );\n }\n\n const initArtifactsConfig = initConfig?.config;\n if (input.noInstall && initArtifactsConfig) {\n await timePhase(timings, \"generate code artifacts\", () =>\n generateCodeArtifacts(targetDir, initArtifactsConfig),\n );\n }\n\n return {\n status: \"initialized\" as const,\n directory,\n extendsRef,\n account,\n domain,\n extends: extendsRef,\n plugins,\n overrides,\n filesCopied,\n timings,\n targetDir,\n };\n } finally {\n await cleanup();\n }\n } catch (error) {\n const extendsRef = normalizeExtendsRef(\n input.extends,\n \"bos://dev.everything.near/everything.dev\",\n );\n return {\n status: \"error\" as const,\n directory: input.directory ?? \"\",\n extendsRef,\n account: input.account,\n domain: input.domain,\n extends: extendsRef,\n plugins: input.plugins ?? [],\n overrides: input.overrides,\n filesCopied: 0,\n timings: [],\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }),\n };\n}\n"],"mappings":"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"}