UNPKG

everything-dev

Version:

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

1 lines 56.7 kB
{"version":3,"file":"init.cjs","names":["require","resolveExtendsRef","fetchBosConfigFromFastKv","saveBosConfig","loadManifestNormalizationSpec","normalizePackageManifestsInTree","writeSnapshot"],"sources":["../../src/cli/init.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport {\n createWriteStream,\n existsSync,\n lstatSync,\n mkdirSync,\n mkdtempSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport { execa } from \"execa\";\nimport { glob } from \"glob\";\nimport type { OverrideSection } from \"../contract\";\nimport { fetchBosConfigFromFastKv } from \"../fastkv\";\nimport {\n loadManifestNormalizationSpec,\n normalizePackageManifestsInTree,\n} from \"../internal/manifest-normalizer\";\nimport { resolveExtendsRef } from \"../merge\";\nimport type { BosConfig, BosConfigInput } from \"../types\";\nimport { saveBosConfig } from \"../utils/save-config\";\nimport { writeSnapshot } from \"./snapshot\";\n\nconst require = createRequire(import.meta.url);\n\nexport const INIT_ROOT_PATTERNS = [\n \"bos.config.json\",\n \"package.json\",\n \".env.example\",\n \".gitignore\",\n \"biome.json\",\n \"bunfig.toml\",\n \"Dockerfile\",\n \"railway.json\",\n \"AGENTS.md\",\n \".changeset/config.json\",\n \".changeset/README.md\",\n \"README.md\",\n \"CONTRIBUTING.md\",\n \".github/templates/**\",\n] as const;\n\nconst OVERRIDE_WORKSPACE_MAP: Record<OverrideSection, string[]> = {\n ui: [\"ui\"],\n api: [\"api\"],\n host: [\"host\"],\n plugins: [],\n};\n\ninterface SourceResult {\n sourceDir: string;\n parentConfig: BosConfig;\n cleanup: () => Promise<void>;\n}\n\nexport interface CatalogChainSource {\n catalog: Record<string, string>;\n repository?: string;\n extendsChain: string[];\n}\n\nfunction getExtendsRef(config: Record<string, unknown>): string | undefined {\n if (typeof config.extends === \"string\") {\n return config.extends;\n }\n\n if (config.extends && typeof config.extends === \"object\") {\n return resolveExtendsRef(config.extends as Record<string, string>, \"production\");\n }\n\n return undefined;\n}\n\nfunction parseBosRef(ref: string): { account: string; gateway: string } | null {\n const match = ref.match(/^bos:\\/\\/([^/]+)\\/(.+)$/);\n if (!match?.[1] || !match[2]) return null;\n return { account: match[1], gateway: match[2] };\n}\n\nfunction readWorkspaceCatalog(sourceDir: string): Record<string, string> {\n const pkgPath = join(sourceDir, \"package.json\");\n if (!existsSync(pkgPath)) {\n return {};\n }\n\n const pkg = readJsonFile<{ workspaces?: { catalog?: Record<string, string> } }>(pkgPath);\n return { ...(pkg.workspaces?.catalog ?? {}) };\n}\n\nexport async function resolveCatalogChainSource(opts: {\n extendsAccount: string;\n extendsGateway: string;\n sourceDir?: string;\n}): Promise<CatalogChainSource> {\n const catalogs: Record<string, string>[] = [];\n const cleanups: Array<() => Promise<void>> = [];\n const extendsChain: string[] = [];\n const visited = new Set<string>();\n let repository: string | undefined;\n let currentRef = `bos://${opts.extendsAccount}/${opts.extendsGateway}`;\n let sourceDir = opts.sourceDir ? resolve(opts.sourceDir) : undefined;\n let configPath = sourceDir ? join(sourceDir, \"bos.config.json\") : undefined;\n\n try {\n while (true) {\n if (visited.has(currentRef)) {\n throw new Error(`Circular extends detected while resolving catalog source: ${currentRef}`);\n }\n\n visited.add(currentRef);\n extendsChain.push(currentRef);\n\n let config: Record<string, unknown>;\n let currentSourceDir = sourceDir;\n let cleanup: () => Promise<void> = async () => {};\n\n if (configPath) {\n config = readJsonFile<Record<string, unknown>>(configPath);\n currentSourceDir = dirname(configPath);\n } else {\n const parsed = parseBosRef(currentRef);\n if (!parsed) {\n break;\n }\n const sourceResult = await resolveSourceDir({\n extendsAccount: parsed.account,\n extendsGateway: parsed.gateway,\n });\n config = sourceResult.parentConfig as Record<string, unknown>;\n currentSourceDir = sourceResult.sourceDir || undefined;\n cleanup = sourceResult.cleanup;\n }\n\n cleanups.push(cleanup);\n catalogs.push(currentSourceDir ? readWorkspaceCatalog(currentSourceDir) : {});\n\n if (typeof config.repository === \"string\") {\n repository = config.repository;\n }\n\n const nextExtendsRef = getExtendsRef(config);\n if (!nextExtendsRef) {\n break;\n }\n\n if (nextExtendsRef.startsWith(\"bos://\")) {\n currentRef = nextExtendsRef;\n sourceDir = undefined;\n configPath = undefined;\n continue;\n }\n\n if (!currentSourceDir) {\n break;\n }\n\n const nextConfigPath = resolve(currentSourceDir, nextExtendsRef);\n if (!existsSync(nextConfigPath)) {\n break;\n }\n\n currentRef = nextConfigPath;\n sourceDir = dirname(nextConfigPath);\n configPath = nextConfigPath;\n }\n } finally {\n for (const cleanup of cleanups.reverse()) {\n await cleanup();\n }\n }\n\n return {\n catalog: Object.assign({}, ...catalogs.reverse()),\n repository,\n extendsChain,\n };\n}\n\nexport async function resolveSourceDir(opts: {\n extendsAccount: string;\n extendsGateway: string;\n source?: string;\n}): Promise<SourceResult> {\n if (opts.source) {\n const sourceDir = resolve(opts.source);\n if (!existsSync(join(sourceDir, \"bos.config.json\"))) {\n throw new Error(`No bos.config.json found in source directory: ${sourceDir}`);\n }\n const parentConfig = JSON.parse(\n readFileSync(join(sourceDir, \"bos.config.json\"), \"utf-8\"),\n ) as BosConfig;\n return { sourceDir, parentConfig, cleanup: async () => {} };\n }\n\n const parentConfig = await fetchParentConfig(opts.extendsAccount, opts.extendsGateway);\n\n if (parentConfig.repository) {\n const { dir: sourceDir, cleanup } = await downloadTarball(parentConfig.repository);\n return { sourceDir, parentConfig, cleanup };\n }\n\n const chainResult = await resolveRepositoryViaExtendsChain(\n opts.extendsAccount,\n opts.extendsGateway,\n );\n if (chainResult?.repository) {\n const { dir: sourceDir, cleanup } = await downloadTarball(chainResult.repository);\n return { sourceDir, parentConfig: chainResult.config, cleanup };\n }\n\n return {\n sourceDir: \"\",\n parentConfig,\n cleanup: async () => {},\n };\n}\n\nexport function buildInitPatterns(overrides: OverrideSection[], plugins?: string[]): string[] {\n const has = (section: OverrideSection) => overrides.includes(section);\n const patterns: string[] = [...INIT_ROOT_PATTERNS];\n\n if (has(\"ui\")) patterns.push(\"ui/**\");\n if (has(\"api\")) patterns.push(\"api/**\");\n if (has(\"host\")) patterns.push(\"host/**\");\n if (has(\"plugins\")) {\n for (const plugin of plugins ?? []) {\n patterns.push(`plugins/${plugin}/**`);\n }\n }\n\n return patterns;\n}\n\nexport function sourcePathToDestinationPath(filePath: string): string {\n return filePath.startsWith(\".github/templates/\")\n ? filePath.replace(/^\\.github\\/templates\\//, \".github/\")\n : filePath;\n}\n\nexport async function fetchParentConfig(\n extendsAccount: string,\n extendsGateway: string,\n): Promise<BosConfig> {\n const bosUrl = `bos://${extendsAccount}/${extendsGateway}`;\n return fetchBosConfigFromFastKv<BosConfig>(bosUrl);\n}\n\nexport async function resolveRepositoryViaExtendsChain(\n extendsAccount: string,\n extendsGateway: string,\n visited = new Set<string>(),\n): Promise<{ repository: string; config: BosConfig } | null> {\n const key = `bos://${extendsAccount}/${extendsGateway}`;\n if (visited.has(key)) return null;\n visited.add(key);\n\n try {\n const config = await fetchParentConfig(extendsAccount, extendsGateway);\n if (config.repository) {\n return { repository: config.repository, config };\n }\n\n const extendsRef = getExtendsRef(config as Record<string, unknown>);\n if (extendsRef) {\n const normalized = extendsRef.startsWith(\"bos://\") ? extendsRef : `bos://${extendsRef}`;\n const parsed = parseBosRef(normalized);\n if (parsed) {\n const result = await resolveRepositoryViaExtendsChain(\n parsed.account,\n parsed.gateway,\n visited,\n );\n if (result) return result;\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\nexport async function detectGitRemoteUrl(directory: string): Promise<string | undefined> {\n try {\n const { stdout } = await execa(\"git\", [\"remote\", \"get-url\", \"origin\"], {\n cwd: directory,\n stdio: \"pipe\",\n });\n const url = stdout.trim();\n if (!url) return undefined;\n return normalizeGitUrl(url);\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeGitUrl(url: string): string | undefined {\n const sshMatch = url.match(/^git@github\\.com:([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (sshMatch) {\n return `https://github.com/${sshMatch[1]}/${sshMatch[2]}`;\n }\n const httpsMatch = url.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:\\/.*)?$/);\n if (httpsMatch) {\n return `https://github.com/${httpsMatch[1]}/${httpsMatch[2]}`;\n }\n return url.endsWith(\".git\") ? url.slice(0, -4) : url;\n}\n\nexport async function downloadTarball(\n repoUrl: string,\n): Promise<{ dir: string; cleanup: () => Promise<void> }> {\n const parsed = parseGitHubUrl(repoUrl);\n if (!parsed) {\n throw new Error(`Cannot parse repository URL: ${repoUrl}`);\n }\n\n const { owner, repo } = parsed;\n let response: Response | null = null;\n\n for (const branch of [\"main\", \"master\"]) {\n const candidate = await fetch(\n `https://api.github.com/repos/${owner}/${repo}/tarball/${branch}`,\n {\n headers: { \"User-Agent\": \"everything-dev\" },\n redirect: \"follow\",\n },\n );\n if (candidate.ok) {\n response = candidate;\n break;\n }\n if (candidate.status !== 404) {\n throw new Error(\n `GitHub tarball download failed: ${candidate.status} ${candidate.statusText}`,\n );\n }\n }\n\n if (!response) {\n throw new Error(`GitHub tarball download failed for ${repoUrl}: tried main and master`);\n }\n\n if (!response.body) {\n throw new Error(\"GitHub tarball download returned empty body\");\n }\n\n const tmpDir = mkTmpDir(\"bos-init-tarball-\");\n const tarballPath = join(tmpDir, \"source.tar.gz\");\n\n const fileStream = createWriteStream(tarballPath);\n const reader = response.body as unknown as NodeJS.ReadableStream;\n await pipeline(reader, fileStream);\n\n const extractDir = mkTmpDir(\"bos-init-extract-\");\n try {\n const tar = require(\"tar\") as {\n extract: (opts: { cwd: string; file: string; strip: number }) => Promise<void>;\n };\n await tar.extract({ cwd: extractDir, file: tarballPath, strip: 1 });\n } catch {\n await execCommand(\"tar\", [\"-xzf\", tarballPath, \"--strip-components=1\", \"-C\", extractDir]);\n }\n\n rmSync(tmpDir, { recursive: true, force: true });\n\n return {\n dir: extractDir,\n cleanup: async () => {\n rmSync(extractDir, { recursive: true, force: true });\n },\n };\n}\n\nfunction parseGitHubUrl(url: string): { owner: string; repo: string } | null {\n const httpsMatch = url.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:\\/.*)?$/);\n if (httpsMatch) {\n return { owner: httpsMatch[1], repo: httpsMatch[2] };\n }\n\n const sshMatch = url.match(/^git@github\\.com:([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (sshMatch) {\n return { owner: sshMatch[1], repo: sshMatch[2] };\n }\n\n return null;\n}\n\nexport async function copyFilteredFiles(\n sourceDir: string,\n destination: string,\n patterns: string[],\n _options: {\n overrides: OverrideSection[];\n plugins?: string[];\n },\n): Promise<number> {\n if (patterns.length === 0) {\n return 0;\n }\n\n const allFiles = new Set<string>();\n for (const pattern of patterns) {\n const matches = await glob(pattern, {\n cwd: sourceDir,\n nodir: true,\n dot: true,\n absolute: false,\n ignore: [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\", \"**/.bos/**\"],\n });\n for (const match of matches) {\n allFiles.add(match);\n }\n }\n\n mkdirSync(destination, { recursive: true });\n\n let count = 0;\n for (const filePath of allFiles) {\n const src = join(sourceDir, filePath);\n const stat = lstatSync(src);\n if (!stat.isFile()) continue;\n\n const destPath = sourcePathToDestinationPath(filePath);\n const dest = join(destination, destPath);\n mkdirSync(dirname(dest), { recursive: true });\n const content = readFileSync(src);\n writeFileSync(dest, content);\n count++;\n }\n\n return count;\n}\n\nfunction stripProductionFields(entry: Record<string, unknown>): void {\n delete entry.production;\n delete entry.integrity;\n delete entry.ssr;\n delete entry.ssrIntegrity;\n}\n\nfunction buildRootTypecheckScript(sections: {\n ui: boolean;\n api: boolean;\n host: boolean;\n plugins: boolean;\n}): string {\n const commands = [\"bun run types:gen\"];\n\n if (sections.ui) {\n commands.push(\"if [ -d ui ]; then bun run --cwd ui typecheck; fi\");\n }\n if (sections.api) {\n commands.push(\"if [ -d api ]; then bun run --cwd api typecheck; fi\");\n }\n if (sections.host) {\n commands.push(\"if [ -d host ]; then bun run --cwd host typecheck; fi\");\n }\n if (sections.plugins) {\n commands.push(\n 'if [ -d plugins ]; then for dir in plugins/*; do if [ -f \"$dir/package.json\" ]; then bun run --cwd \"$dir\" typecheck; fi; done; fi',\n );\n }\n\n return commands.join(\" && \");\n}\n\nexport function buildChildRootScripts(sections: {\n ui: boolean;\n api: boolean;\n host: boolean;\n plugins: boolean;\n}): Record<string, string> {\n const scripts: Record<string, string> = {\n dev: \"node_modules/.bin/bos dev --host remote\",\n \"dev:proxy\": \"node_modules/.bin/bos dev --proxy\",\n build: \"node_modules/.bin/bos build\",\n deploy: \"node_modules/.bin/bos build --deploy\",\n publish: \"node_modules/.bin/bos publish\",\n start: \"node_modules/.bin/bos start\",\n typecheck: buildRootTypecheckScript(sections),\n lint: \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n format: \"biome format --write .\",\n \"format:check\": \"biome format .\",\n changeset: \"changeset\",\n version: \"changeset version\",\n release: \"echo 'Packages versioned - app release handled by workflow'\",\n postinstall: \"node_modules/.bin/bos types gen || true\",\n \"types:gen\": \"node_modules/.bin/bos types gen\",\n bos: \"node_modules/.bin/bos\",\n };\n\n if (sections.api) {\n scripts[\"db:push\"] = \"bun run --cwd api drizzle-kit push\";\n scripts[\"db:studio\"] = \"bun run --cwd api drizzle-kit studio\";\n scripts[\"db:generate\"] = \"bun run --cwd api drizzle-kit generate\";\n scripts[\"db:migrate\"] = \"bun run --cwd api drizzle-kit migrate\";\n scripts[\"test:api\"] = \"cd api && bun run test tests/integration/ tests/unit/\";\n scripts[\"test:integration\"] = \"cd api && bun run test tests/integration/\";\n }\n\n if (sections.host) {\n scripts[\"test:e2e\"] = \"bun run --cwd host test:e2e\";\n }\n\n if (sections.api && sections.host) {\n scripts.test = \"bun run test:api && bun run test:e2e\";\n } else if (sections.api) {\n scripts.test = \"bun run test:api\";\n } else if (sections.host) {\n scripts.test = \"bun run test:e2e\";\n }\n\n if (sections.api || sections.host) {\n scripts[\"dev:postgres\"] = \"docker compose up -d --wait && bun run dev\";\n scripts[\"dev:postgres:down\"] = \"docker compose down\";\n scripts[\"dev:postgres:reset\"] = \"docker compose down -v && docker compose up -d --wait\";\n }\n\n if (sections.ui) {\n scripts[\"dev:ui\"] = \"node_modules/.bin/bos dev --ui local --api remote\";\n }\n if (sections.api) {\n scripts[\"dev:api\"] = \"node_modules/.bin/bos dev --ui remote --api local\";\n }\n\n return scripts;\n}\n\nexport async function personalizeConfig(\n destination: string,\n opts: {\n extendsAccount: string;\n extendsGateway: string;\n account?: string;\n domain?: string;\n plugins?: string[];\n overrides: OverrideSection[];\n pluginRoutes?: Record<string, string[]>;\n workspaceOpts?: { localOverrides?: boolean; sourceDir?: string };\n mode?: \"init\" | \"sync\";\n existingConfig?: Record<string, unknown>;\n repository?: string;\n title?: string;\n description?: string;\n testnet?: string;\n staging?: unknown;\n },\n): Promise<void> {\n const has = (section: OverrideSection) => opts.overrides.includes(section);\n const existingApp =\n opts.mode === \"sync\" && opts.existingConfig?.app && typeof opts.existingConfig.app === \"object\"\n ? (opts.existingConfig.app as Record<string, unknown>)\n : undefined;\n const preservedAuth = existingApp?.auth;\n\n const explicitRootKeys = new Set(\n Object.entries(opts)\n .filter(\n ([key, value]) =>\n value !== undefined &&\n ![\n \"extendsAccount\",\n \"extendsGateway\",\n \"plugins\",\n \"overrides\",\n \"pluginRoutes\",\n \"workspaceOpts\",\n \"mode\",\n \"existingConfig\",\n ].includes(key),\n )\n .map(([key]) => key),\n );\n\n const configPath = join(destination, \"bos.config.json\");\n if (existsSync(configPath)) {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>;\n\n config.extends = `bos://${opts.extendsAccount}/${opts.extendsGateway}`;\n\n if (opts.account) {\n config.account = opts.account;\n }\n if (opts.domain) {\n config.domain = opts.domain;\n }\n if (opts.repository) {\n config.repository = opts.repository;\n } else {\n delete config.repository;\n }\n\n const inheritableFields = [\"title\", \"description\", \"testnet\", \"staging\"] as const;\n for (const field of inheritableFields) {\n if (!(field in opts)) {\n delete config[field];\n }\n }\n\n if (config.app && typeof config.app === \"object\") {\n const app = config.app as Record<string, unknown>;\n\n for (const entryKey of Object.keys(app)) {\n if (\n !has(entryKey as OverrideSection) &&\n (entryKey === \"host\" || entryKey === \"ui\" || entryKey === \"api\")\n ) {\n delete app[entryKey];\n continue;\n }\n if (entryKey === \"auth\") {\n delete app[entryKey];\n continue;\n }\n const entry = app[entryKey];\n if (entry && typeof entry === \"object\") {\n stripProductionFields(entry as Record<string, unknown>);\n }\n }\n\n if (preservedAuth !== undefined) {\n app.auth = preservedAuth;\n }\n\n if (Object.keys(app).length === 0) {\n delete config.app;\n }\n }\n\n if (has(\"plugins\")) {\n if (config.plugins && typeof config.plugins === \"object\") {\n const plugins = config.plugins as Record<string, unknown>;\n\n if (opts.plugins !== undefined) {\n for (const pluginKey of Object.keys(plugins)) {\n if (!opts.plugins.includes(pluginKey)) {\n delete plugins[pluginKey];\n }\n }\n }\n\n for (const pluginKey of Object.keys(plugins)) {\n const plugin = plugins[pluginKey];\n let pluginObj: Record<string, unknown>;\n\n if (typeof plugin === \"string\") {\n pluginObj = { extends: plugin };\n plugins[pluginKey] = pluginObj;\n } else if (plugin && typeof plugin === \"object\") {\n pluginObj = { ...(plugin as Record<string, unknown>) };\n plugins[pluginKey] = pluginObj;\n } else {\n continue;\n }\n\n stripProductionFields(pluginObj);\n }\n\n if (Object.keys(plugins).length === 0) {\n delete config.plugins;\n }\n }\n } else {\n delete config.plugins;\n }\n\n if (opts.mode === \"sync\" && opts.existingConfig) {\n const managedRootKeys = new Set([\"extends\", \"account\", \"domain\", \"app\", \"plugins\", \"shared\"]);\n const preservedRootKeys = new Set([\n ...managedRootKeys,\n ...Object.keys(opts.existingConfig),\n ...explicitRootKeys,\n ]);\n\n for (const key of Object.keys(config)) {\n if (!preservedRootKeys.has(key)) {\n delete config[key];\n }\n }\n\n for (const [key, value] of Object.entries(opts.existingConfig)) {\n if (!(key in config) && !managedRootKeys.has(key) && !explicitRootKeys.has(key)) {\n config[key] = value;\n }\n }\n }\n\n await saveBosConfig(destination, config);\n }\n\n const pkgPath = join(destination, \"package.json\");\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n const childScripts = buildChildRootScripts({\n ui: has(\"ui\"),\n api: has(\"api\"),\n host: has(\"host\"),\n plugins: has(\"plugins\"),\n });\n\n if (typeof pkg.name !== \"string\" || pkg.name.length === 0) {\n pkg.name = \"monorepo\";\n }\n pkg.private = true;\n pkg.type = \"module\";\n delete pkg.module;\n delete pkg.peerDependencies;\n\n if (pkg.workspaces && typeof pkg.workspaces === \"object\") {\n const ws = pkg.workspaces as { packages?: string[] };\n if (Array.isArray(ws.packages)) {\n ws.packages = ws.packages.filter((p: string) => {\n if (p.startsWith(\"packages/\")) return false;\n if (p === \"ui\") return has(\"ui\");\n if (p === \"api\") return has(\"api\");\n if (p === \"host\") return has(\"host\");\n if (p.startsWith(\"plugins/\")) return false;\n return true;\n });\n\n if (has(\"plugins\")) {\n if (!ws.packages.includes(\"plugins/*\")) {\n ws.packages.push(\"plugins/*\");\n }\n }\n }\n }\n\n if (!pkg.scripts || typeof pkg.scripts !== \"object\") {\n pkg.scripts = {};\n }\n const scripts = pkg.scripts as Record<string, string>;\n for (const [key, value] of Object.entries(childScripts)) {\n scripts[key] = value;\n }\n for (const obsoleteScript of [\n \"init\",\n \"sync-catalog\",\n \"db:push\",\n \"db:studio\",\n \"db:generate\",\n \"db:migrate\",\n \"test\",\n \"test:api\",\n \"test:integration\",\n \"test:e2e\",\n \"dev:postgres\",\n \"dev:postgres:down\",\n \"dev:postgres:reset\",\n \"dev:ui\",\n \"dev:api\",\n ]) {\n if (!(obsoleteScript in childScripts)) {\n delete scripts[obsoleteScript];\n }\n }\n\n if (pkg.devDependencies && typeof pkg.devDependencies === \"object\") {\n const deps = pkg.devDependencies as Record<string, string>;\n delete deps[\"every-plugin\"];\n delete deps[\"everything-dev\"];\n }\n\n if (!pkg.workspaces || typeof pkg.workspaces !== \"object\") {\n pkg.workspaces = { packages: [], catalog: {} };\n }\n const workspaces = pkg.workspaces as { packages?: string[]; catalog?: Record<string, string> };\n if (!workspaces.catalog || typeof workspaces.catalog !== \"object\") {\n workspaces.catalog = {};\n }\n\n if (!pkg.dependencies) pkg.dependencies = {};\n const deps = pkg.dependencies as Record<string, string>;\n const spec = opts.workspaceOpts?.sourceDir\n ? loadManifestNormalizationSpec(opts.workspaceOpts.sourceDir)\n : null;\n if (spec) {\n workspaces.catalog[\"everything-dev\"] = spec.rootCatalog[\"everything-dev\"];\n workspaces.catalog[\"every-plugin\"] = spec.rootCatalog[\"every-plugin\"];\n }\n const frameworkCatalog = (\n await resolveCatalogChainSource({\n extendsAccount: opts.extendsAccount,\n extendsGateway: opts.extendsGateway,\n sourceDir: opts.workspaceOpts?.sourceDir,\n })\n ).catalog;\n for (const [name, version] of Object.entries(frameworkCatalog)) {\n workspaces.catalog[name] = version;\n }\n if (!deps[\"everything-dev\"]) deps[\"everything-dev\"] = \"catalog:\";\n if (!deps[\"every-plugin\"]) deps[\"every-plugin\"] = \"catalog:\";\n\n writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n }\n\n const apiTsConfigPath = join(destination, \"api\", \"tsconfig.json\");\n if (existsSync(apiTsConfigPath)) {\n const apiTsConfig = JSON.parse(readFileSync(apiTsConfigPath, \"utf-8\")) as {\n files?: string[];\n [key: string]: unknown;\n };\n if (apiTsConfig.files) {\n const validFiles = apiTsConfig.files.filter((f) => existsSync(join(destination, \"api\", f)));\n if (validFiles.length !== apiTsConfig.files.length) {\n if (validFiles.length === 0) {\n delete apiTsConfig.files;\n } else {\n apiTsConfig.files = validFiles;\n }\n writeFileSync(apiTsConfigPath, `${JSON.stringify(apiTsConfig, null, 2)}\\n`);\n }\n }\n }\n\n await resolveWorkspaceRefs(destination, opts.workspaceOpts);\n\n if (has(\"ui\")) {\n const genContractPath = join(destination, \"ui\", \"src\", \"lib\", \"api-types.gen.ts\");\n if (!existsSync(genContractPath)) {\n mkdirSync(dirname(genContractPath), { recursive: true });\n writeFileSync(genContractPath, `export type ApiContract = Record<string, never>;\\n`);\n }\n }\n\n if (has(\"api\")) {\n const pluginsClientGenPath = join(destination, \"api\", \"src\", \"lib\", \"plugins-types.gen.ts\");\n if (!existsSync(pluginsClientGenPath)) {\n mkdirSync(dirname(pluginsClientGenPath), { recursive: true });\n writeFileSync(\n pluginsClientGenPath,\n `import type { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";\\ntype ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;\\nexport type PluginsClient = Record<string, never>;\\n`,\n );\n }\n }\n\n const authTypesContent = generateAuthTypesTemplate();\n const authTypesPaths: string[] = [];\n if (has(\"ui\")) {\n authTypesPaths.push(join(destination, \"ui\", \"src\", \"lib\", \"auth-types.gen.ts\"));\n }\n if (has(\"api\")) {\n authTypesPaths.push(join(destination, \"api\", \"src\", \"lib\", \"auth-types.gen.ts\"));\n }\n if (has(\"host\") && existsSync(join(destination, \"host\", \"src\"))) {\n authTypesPaths.push(join(destination, \"host\", \"src\", \"lib\", \"auth-types.gen.ts\"));\n }\n for (const authTypesGenPath of authTypesPaths) {\n if (!existsSync(authTypesGenPath)) {\n mkdirSync(dirname(authTypesGenPath), { recursive: true });\n writeFileSync(authTypesGenPath, authTypesContent);\n }\n }\n\n if (has(\"plugins\")) {\n for (const plugin of opts.plugins ?? []) {\n const pluginSrcDir = join(destination, \"plugins\", plugin, \"src\");\n const pluginIndexPath = join(pluginSrcDir, \"index.ts\");\n const pluginClientGenPath = join(pluginSrcDir, \"plugins-client.gen.ts\");\n if (!existsSync(pluginIndexPath) || existsSync(pluginClientGenPath)) {\n continue;\n }\n const pluginIndex = readFileSync(pluginIndexPath, \"utf-8\");\n if (!pluginIndex.includes(\"./plugins-client.gen\")) {\n continue;\n }\n writeFileSync(pluginClientGenPath, \"export type PluginsClient = Record<string, never>;\\n\");\n }\n }\n}\n\nfunction generateAuthTypesTemplate(): string {\n return `import type { Auth } from \"better-auth\";\nexport type { Auth } from \"better-auth\";\nexport type AuthSessionUser = NonNullable<Auth[\"$Infer\"][\"Session\"][\"user\"]> & {\n role?: string | null;\n isAnonymous?: boolean | null;\n walletAddress?: string | null;\n banned?: boolean | null;\n};\nexport type AuthSessionData = NonNullable<Auth[\"$Infer\"][\"Session\"][\"session\"]> & {\n activeOrganizationId?: string | null;\n};\nexport type AuthSession = {\n user: AuthSessionUser | null;\n session: AuthSessionData | null;\n};\nexport interface AuthOrganizationContext {\n activeOrganizationId: string | null;\n organization: { id: string; name: string; slug: string; logo?: string | null; metadata?: Record<string, unknown> } | null;\n member: { id: string; role: string } | null;\n isPersonal: boolean;\n hasOrganization: boolean;\n}\nexport interface AuthRequestContext {\n user: AuthSessionUser | null;\n userId: string | null;\n isAuthenticated: boolean;\n authMethod: \"session\" | \"apiKey\" | \"anonymous\" | \"none\";\n near: {\n primaryAccountId: string | null;\n linkedAccounts: Array<{ accountId: string; network: string; publicKey: string; isPrimary: boolean }>;\n hasNearAccount: boolean;\n };\n organization: AuthOrganizationContext;\n organizations?: Array<{ id: string; role: string; name?: string; slug?: string }>;\n}\nexport type AuthActiveMember = { id: string | null; role: string | null; organizationId: string | null };\nexport type AuthOrganization = NonNullable<AuthOrganizationContext[\"organization\"]>;\nexport type AuthOrganizationMember = NonNullable<AuthOrganizationContext[\"member\"]>;\nexport type AuthOrganizationSummary = NonNullable<AuthRequestContext[\"organizations\"]>[number];\nexport type AuthBaseSession = Auth[\"$Infer\"][\"Session\"];\nexport type createAuthInstance = never;\nexport interface AuthServices {\n auth: Auth;\n db: unknown;\n driver: { close(): Promise<void> };\n handler: (req: Request) => Promise<Response>;\n}\n`;\n}\n\nexport async function runBunInstall(\n destination: string,\n spinner?: { message: (msg: string) => void },\n): Promise<void> {\n await runWithProgress(\n \"bun\",\n [\"install\", \"--ignore-scripts\"],\n destination,\n spinner,\n \"Installing dependencies\",\n );\n}\n\nexport async function runBunInstallForUpgrade(\n destination: string,\n spinner?: { message: (msg: string) => void },\n): Promise<void> {\n await runWithProgress(\n \"bun\",\n [\"install\", \"--force\"],\n destination,\n spinner,\n \"Installing dependencies\",\n );\n}\n\nexport async function runTypesGen(\n destination: string,\n spinner?: { message: (msg: string) => void },\n): Promise<void> {\n const localBosBin = join(destination, \"node_modules\", \".bin\", \"bos\");\n if (existsSync(localBosBin)) {\n await runWithProgress(\n \"node_modules/.bin/bos\",\n [\"types\", \"gen\"],\n destination,\n spinner,\n \"Generating types\",\n );\n return;\n }\n\n throw new Error(\"Unable to locate bos CLI for types generation\");\n}\n\nexport async function runDockerComposeUp(destination: string): Promise<void> {\n await execCommand(\"docker\", [\"compose\", \"up\", \"-d\", \"--wait\"], destination, { stdio: \"inherit\" });\n}\n\nasync function runWithProgress(\n command: string,\n args: string[],\n cwd: string,\n spinner: { message: (msg: string) => void } | undefined,\n label: string,\n): Promise<void> {\n const timeout = COMMAND_TIMEOUTS[command] ?? 2 * 60_000;\n const child = execa(command, args, { cwd, stdio: \"inherit\", timeout });\n\n if (spinner) {\n const start = Date.now();\n const interval = setInterval(() => {\n const elapsed = Math.round((Date.now() - start) / 1000);\n spinner.message(`${label}... (${elapsed}s)`);\n }, 2000);\n try {\n await child;\n } finally {\n clearInterval(interval);\n }\n } else {\n await child;\n }\n}\n\nexport function stripOrphanedWorkspacesFromLockfile(\n lockfilePath: string,\n allowedWorkspaces: string[],\n): void {\n if (!existsSync(lockfilePath)) return;\n\n const content = readFileSync(lockfilePath, \"utf-8\");\n let lockfile: Record<string, unknown>;\n try {\n lockfile = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return;\n }\n\n const workspaces = lockfile.workspaces;\n if (!workspaces || typeof workspaces !== \"object\") return;\n\n const workspaceMap = workspaces as Record<string, unknown>;\n const allowed = new Set([\"\", ...allowedWorkspaces]);\n\n const keys = Object.keys(workspaceMap);\n let changed = false;\n for (const key of keys) {\n if (allowed.has(key)) continue;\n if (\n allowedWorkspaces.some(\n (pattern) => pattern.endsWith(\"/*\") && key.startsWith(pattern.slice(0, -1)),\n )\n )\n continue;\n delete workspaceMap[key];\n changed = true;\n }\n\n if (changed) {\n writeFileSync(lockfilePath, `${JSON.stringify(lockfile, null, 2)}\\n`);\n }\n}\n\nexport function removeInitLockfile(lockfilePath: string): void {\n if (!existsSync(lockfilePath)) return;\n rmSync(lockfilePath, { force: true });\n}\n\nfunction readJsonFile<T>(filePath: string): T {\n return JSON.parse(readFileSync(filePath, \"utf-8\")) as T;\n}\n\nexport async function scaffoldMinimalProject(\n destination: string,\n parentConfig: BosConfigInput,\n opts: {\n extendsAccount: string;\n extendsGateway: string;\n account?: string;\n domain?: string;\n plugins?: string[];\n overrides: OverrideSection[];\n repository?: string;\n title?: string;\n description?: string;\n },\n): Promise<number> {\n mkdirSync(destination, { recursive: true });\n\n const has = (section: OverrideSection) => opts.overrides.includes(section);\n\n const config: Record<string, unknown> = {\n extends: `bos://${opts.extendsAccount}/${opts.extendsGateway}`,\n account: opts.account || opts.extendsAccount,\n ...(opts.domain ? { domain: opts.domain } : {}),\n ...(opts.repository ? { repository: opts.repository } : {}),\n ...(opts.title ? { title: opts.title } : {}),\n ...(opts.description ? { description: opts.description } : {}),\n };\n\n if (parentConfig.app && typeof parentConfig.app === \"object\") {\n const app: Record<string, unknown> = {};\n const parentApp = parentConfig.app as Record<string, Record<string, unknown>>;\n\n if (has(\"host\") && parentApp.host) {\n app.host = { ...parentApp.host };\n stripProductionFields(app.host as Record<string, unknown>);\n }\n\n if (has(\"ui\") && parentApp.ui) {\n app.ui = { ...parentApp.ui };\n stripProductionFields(app.ui as Record<string, unknown>);\n }\n\n if (has(\"api\") && parentApp.api) {\n app.api = { ...parentApp.api };\n stripProductionFields(app.api as Record<string, unknown>);\n }\n\n if (Object.keys(app).length > 0) {\n config.app = app;\n }\n }\n\n if (has(\"plugins\") && opts.plugins && opts.plugins.length > 0 && parentConfig.plugins) {\n const plugins: Record<string, unknown> = {};\n for (const key of opts.plugins) {\n const parentPlugin = (parentConfig.plugins as Record<string, unknown>)?.[key];\n if (parentPlugin) {\n if (typeof parentPlugin === \"string\") {\n plugins[key] = { extends: parentPlugin };\n } else {\n const pluginCopy = { ...(parentPlugin as Record<string, unknown>) };\n stripProductionFields(pluginCopy);\n plugins[key] = pluginCopy;\n }\n }\n }\n config.plugins = plugins;\n }\n\n await saveBosConfig(destination, config);\n\n const workspacePackages: string[] = [];\n for (const section of opts.overrides) {\n workspacePackages.push(...OVERRIDE_WORKSPACE_MAP[section]);\n }\n if (has(\"plugins\")) {\n workspacePackages.push(\"plugins/*\");\n }\n\n const catalog = (\n await resolveCatalogChainSource({\n extendsAccount: opts.extendsAccount,\n extendsGateway: opts.extendsGateway,\n })\n ).catalog;\n\n const pkg: Record<string, unknown> = {\n name: \"monorepo\",\n private: true,\n type: \"module\",\n scripts: buildChildRootScripts({\n ui: has(\"ui\"),\n api: has(\"api\"),\n host: has(\"host\"),\n plugins: has(\"plugins\"),\n }),\n dependencies: {\n \"everything-dev\": \"catalog:\",\n \"every-plugin\": \"catalog:\",\n },\n devDependencies: {},\n workspaces: {\n packages: workspacePackages,\n catalog,\n },\n };\n writeFileSync(join(destination, \"package.json\"), `${JSON.stringify(pkg, null, 2)}\\n`);\n\n writeFileSync(join(destination, \".gitignore\"), generateGitignore());\n\n return 4;\n}\n\nasync function resolveWorkspaceRefs(\n destination: string,\n options?: { localOverrides?: boolean; sourceDir?: string },\n): Promise<void> {\n await normalizePackageManifestsInTree({\n sourceRootDir: options?.sourceDir ?? destination,\n targetDir: destination,\n resolveCatalogRefs: false,\n preserveCatalogRefs: true,\n removeWorkspaceDeps: [\"host\"],\n });\n}\n\nexport async function writeInitSnapshot(\n destination: string,\n extendsAccount: string,\n extendsGateway: string,\n sourceDir: string,\n patterns: string[],\n _options: {\n overrides: OverrideSection[];\n plugins?: string[];\n },\n): Promise<void> {\n const allFiles = new Set<string>();\n for (const pattern of patterns) {\n const matches = await glob(pattern, {\n cwd: sourceDir,\n nodir: true,\n dot: true,\n absolute: false,\n ignore: [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\", \"**/.bos/**\"],\n });\n for (const match of matches) {\n allFiles.add(match);\n }\n }\n\n const fileHashes: Record<string, string> = {};\n for (const filePath of allFiles) {\n const src = join(sourceDir, filePath);\n const stat = lstatSync(src);\n if (!stat.isFile()) continue;\n const content = readFileSync(src);\n const destPath = sourcePathToDestinationPath(filePath);\n fileHashes[destPath] = computeHash(content);\n }\n\n await writeSnapshot(destination, {\n parentRef: `bos://${extendsAccount}/${extendsGateway}`,\n files: fileHashes,\n });\n}\n\nfunction computeHash(data: Uint8Array): string {\n return createHash(\"sha256\").update(data).digest(\"hex\").substring(0, 16);\n}\n\nfunction mkTmpDir(prefix: string): string {\n return mkdtempSync(join(tmpdir(), `${prefix}-`));\n}\n\nexport async function generateDatabaseMigrations(destination: string): Promise<void> {\n const drizzleConfigs = await glob(\"**/drizzle.config.ts\", {\n cwd: destination,\n nodir: true,\n dot: false,\n absolute: false,\n ignore: [\"**/node_modules/**\"],\n });\n\n for (const configPath of drizzleConfigs) {\n const workspaceDir = dirname(configPath);\n const pkgPath = join(destination, workspaceDir, \"package.json\");\n if (!existsSync(pkgPath)) continue;\n\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n const scripts = pkg.scripts as Record<string, string> | undefined;\n if (!scripts?.[\"db:generate\"]) continue;\n\n const cwd = join(destination, workspaceDir);\n await execCommand(\"bun\", [\"run\", \"db:generate\"], cwd);\n }\n}\n\nconst COMMAND_TIMEOUTS: Record<string, number> = {\n bun: 5 * 60_000,\n docker: 5 * 60_000,\n node_modules: 2 * 60_000,\n tar: 60_000,\n};\n\nexport async function execCommand(\n command: string,\n args: string[],\n cwd?: string,\n options?: { stdio?: \"pipe\" | \"inherit\" },\n): Promise<void> {\n const timeout = COMMAND_TIMEOUTS[command] ?? 2 * 60_000;\n await execa(command, args, { cwd, stdio: options?.stdio ?? \"pipe\", timeout });\n}\n\nfunction generateGitignore(): string {\n return `node_modules/\ndist/\n.env\n.bos/\n*.gen.ts\n*.gen.tsx\n`;\n}\n"],"mappings":"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