everything-dev 1.38.0 → 1.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/infra.cjs +145 -36
- package/dist/cli/infra.cjs.map +1 -1
- package/dist/cli/infra.mjs +147 -38
- package/dist/cli/infra.mjs.map +1 -1
- package/dist/contract.d.cts +7 -7
- package/dist/contract.d.mts +7 -7
- package/dist/dev-session.cjs +6 -0
- package/dist/dev-session.cjs.map +1 -1
- package/dist/dev-session.mjs +6 -0
- package/dist/dev-session.mjs.map +1 -1
- package/dist/plugin.cjs +6 -0
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.mts +4 -4
- package/dist/plugin.mjs +6 -0
- package/dist/plugin.mjs.map +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- package/package.json +1 -1
package/dist/cli/infra.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"infra.mjs","names":[],"sources":["../../src/cli/infra.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { config as loadDotenv } from \"dotenv\";\nimport type { RuntimeConfig } from \"../types\";\n\nconst POSTGRES_USER = \"everythingdev\";\nconst POSTGRES_PASSWORD = \"everythingdev\";\nconst API_DATABASE_SECRET = \"API_DATABASE_URL\";\nconst AUTH_DATABASE_SECRET = \"AUTH_DATABASE_URL\";\nconst HOST_SECRET = \"CORS_ORIGIN\";\nconst BASE_DATABASE_PORT = 5434;\n\ninterface DatabaseSecretConfig {\n secret: string;\n slug: string;\n fromKey: string;\n port: number;\n serviceName: string;\n containerName: string;\n databaseName: string;\n volumeName: string;\n url: string;\n}\n\ninterface SecretGroup {\n section: string;\n secrets: string[];\n}\n\ninterface GeneratedInfraSpec {\n groups: SecretGroup[];\n databases: DatabaseSecretConfig[];\n}\n\ninterface SyncGeneratedInfraResult {\n secrets: string[];\n envExampleChanged: boolean;\n dockerComposeChanged: boolean;\n}\n\nfunction uniqueSecrets(values: Array<string | undefined>): string[] {\n const secrets: string[] = [];\n const seen = new Set<string>();\n\n for (const value of values) {\n if (!value || seen.has(value)) continue;\n seen.add(value);\n secrets.push(value);\n }\n\n return secrets;\n}\n\nfunction getSecretGroups(runtimeConfig: RuntimeConfig): SecretGroup[] {\n const groups: SecretGroup[] = [];\n const seen = new Set<string>();\n\n const addGroup = (section: string, secrets: string[]) => {\n const filtered = secrets.filter((s) => {\n if (seen.has(s)) return false;\n seen.add(s);\n return true;\n });\n if (filtered.length > 0) {\n groups.push({ section, secrets: filtered });\n }\n };\n\n addGroup(\"app.host\", uniqueSecrets([...(runtimeConfig.host.secrets ?? []), HOST_SECRET]));\n\n addGroup(\"app.api\", uniqueSecrets(runtimeConfig.api.secrets ?? []));\n\n if (runtimeConfig.auth) {\n addGroup(\"app.auth\", uniqueSecrets(runtimeConfig.auth.secrets ?? []));\n }\n\n if (runtimeConfig.plugins) {\n for (const [pluginKey, plugin] of Object.entries(runtimeConfig.plugins)) {\n if (plugin.secrets && plugin.secrets.length > 0) {\n addGroup(`plugins.${pluginKey}`, plugin.secrets);\n }\n }\n }\n\n return groups;\n}\n\nfunction buildGeneratedInfraSpec(\n runtimeConfig: RuntimeConfig,\n configDir?: string,\n): GeneratedInfraSpec {\n const groups = getSecretGroups(runtimeConfig);\n const originMap = configDir ? buildOriginMap(configDir, runtimeConfig) : new Map();\n const databases = buildDatabaseConfigs(\n groups.flatMap((group) => group.secrets),\n originMap,\n );\n return { groups, databases };\n}\n\nfunction normalizeDatabaseSlug(secret: string): string {\n return secret.replace(/_DATABASE_URL$/, \"\").toLowerCase();\n}\n\nfunction buildOriginMap(configDir: string, runtimeConfig: RuntimeConfig): Map<string, string> {\n const configPath = join(configDir, \"bos.config.json\");\n\n const originMap = new Map<string, string>();\n const account = runtimeConfig.account;\n\n const resolveOrigin = (extendsRef: unknown): string | null => {\n if (typeof extendsRef === \"string\") {\n const match = extendsRef.match(/^bos:\\/\\/([^/]+)\\//);\n return match?.[1] ?? null;\n }\n return null;\n };\n\n const rawConfig = existsSync(configPath)\n ? (JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>)\n : null;\n const rawPlugins = rawConfig?.plugins as Record<string, unknown> | undefined;\n\n for (const secret of runtimeConfig.api.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, account);\n }\n\n const rawApp = rawConfig?.app as Record<string, unknown> | undefined;\n const authExtends = (rawApp?.auth as Record<string, unknown> | undefined)?.extends;\n const authOrigin = resolveOrigin(authExtends) ?? account;\n for (const secret of runtimeConfig.auth?.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, authOrigin);\n }\n\n for (const [pluginKey, pluginEntry] of Object.entries(runtimeConfig.plugins ?? {})) {\n const rawPlugin = rawPlugins?.[pluginKey];\n let pluginOrigin: string;\n if (typeof rawPlugin === \"string\") {\n pluginOrigin = resolveOrigin(rawPlugin) ?? account;\n } else if (rawPlugin && typeof rawPlugin === \"object\") {\n pluginOrigin = resolveOrigin((rawPlugin as Record<string, unknown>).extends) ?? account;\n } else {\n pluginOrigin = account;\n }\n for (const secret of pluginEntry.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, pluginOrigin);\n }\n }\n\n for (const secret of runtimeConfig.host.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, account);\n }\n\n return originMap;\n}\n\nfunction buildDatabaseConfigs(\n secrets: string[],\n originMap: Map<string, string>,\n): DatabaseSecretConfig[] {\n const databaseSecrets = uniqueSecrets(\n secrets.filter((secret) => secret.endsWith(\"_DATABASE_URL\")),\n );\n\n const additionalSecrets = databaseSecrets\n .filter((secret) => secret !== API_DATABASE_SECRET && secret !== AUTH_DATABASE_SECRET)\n .sort((a, b) => a.localeCompare(b));\n\n const orderedSecrets = [API_DATABASE_SECRET, AUTH_DATABASE_SECRET, ...additionalSecrets];\n\n return orderedSecrets.map((secret, index) => {\n const slug = normalizeDatabaseSlug(secret);\n const fromKey = originMap.get(secret) ?? \"\";\n const port =\n secret === API_DATABASE_SECRET\n ? 5432\n : secret === AUTH_DATABASE_SECRET\n ? 5433\n : BASE_DATABASE_PORT + index - 2;\n\n const volumeName = fromKey\n ? `${fromKey.replace(/\\./g, \"_\")}_postgres_${slug}_data`\n : `postgres_${slug}_data`;\n\n const containerName = fromKey ? `${fromKey}-postgres-${slug}` : `postgres-${slug}`;\n\n return {\n secret,\n slug,\n fromKey,\n port,\n serviceName: `postgres-${slug.replace(/_/g, \"-\")}`,\n containerName,\n databaseName: `${slug}_db`,\n volumeName,\n url: `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${port}/${slug}_db`,\n };\n });\n}\n\nfunction defaultSecretValue(\n secret: string,\n databases: Map<string, DatabaseSecretConfig>,\n options: { forExample: boolean },\n): string {\n if (secret === \"BETTER_AUTH_SECRET\") {\n return options.forExample ? \"\" : randomBytes(32).toString(\"base64url\");\n }\n\n if (secret === \"CORS_ORIGIN\") {\n return \"http://localhost:3000\";\n }\n\n return databases.get(secret)?.url ?? \"\";\n}\n\nfunction renderEnvFile(\n groups: SecretGroup[],\n databases: DatabaseSecretConfig[],\n options: { forExample: boolean },\n): string {\n const databaseMap = new Map(databases.map((entry) => [entry.secret, entry]));\n const lines: string[] = [\n \"# Generated from configured bos secrets\",\n \"# Update values as needed for your local environment\",\n \"\",\n ];\n\n for (const group of groups) {\n lines.push(`# ${group.section}`);\n for (const secret of group.secrets) {\n lines.push(`${secret}=${defaultSecretValue(secret, databaseMap, options)}`);\n }\n lines.push(\"\");\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction renderDockerCompose(databases: DatabaseSecretConfig[], projectName: string): string {\n const lines = [\n `name: ${projectName}`,\n \"\",\n \"x-pg-common: &pg-common\",\n \" image: postgres:17-alpine\",\n \" environment: &pg-env\",\n ` POSTGRES_USER: ${POSTGRES_USER}`,\n ` POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}`,\n \" healthcheck:\",\n ' test: [\"CMD-SHELL\", \"pg_isready -U everythingdev\"]',\n \" interval: 3s\",\n \" timeout: 3s\",\n \" retries: 5\",\n \"\",\n \"services:\",\n ];\n\n for (const database of databases) {\n lines.push(` ${database.serviceName}:`);\n lines.push(\" <<: *pg-common\");\n lines.push(` container_name: ${database.containerName}`);\n lines.push(\" environment:\");\n lines.push(\" <<: *pg-env\");\n lines.push(` POSTGRES_DB: ${database.databaseName}`);\n lines.push(\" ports:\");\n lines.push(` - \"${database.port}:5432\"`);\n lines.push(\" volumes:\");\n lines.push(` - ${database.volumeName}:/var/lib/postgresql/data`);\n lines.push(\"\");\n }\n\n lines.push(\"volumes:\");\n for (const database of databases) {\n lines.push(` ${database.volumeName}:`);\n lines.push(` name: ${database.volumeName}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction syncTextFile(filePath: string, nextContent: string): boolean {\n if (existsSync(filePath) && readFileSync(filePath, \"utf-8\") === nextContent) {\n return false;\n }\n\n writeFileSync(filePath, nextContent);\n return true;\n}\n\nexport function writeGeneratedInfra(configDir: string, runtimeConfig: RuntimeConfig): string[] {\n return syncGeneratedInfra(configDir, runtimeConfig).secrets;\n}\n\nexport function syncGeneratedInfra(\n configDir: string,\n runtimeConfig: RuntimeConfig,\n): SyncGeneratedInfraResult {\n const spec = buildGeneratedInfraSpec(runtimeConfig, configDir);\n const secrets = spec.groups.flatMap((group) => group.secrets);\n const newEnvContent = renderEnvFile(spec.groups, spec.databases, { forExample: true });\n const newDockerContent = renderDockerCompose(spec.databases, runtimeConfig.account);\n\n const envExamplePath = join(configDir, \".env.example\");\n const dockerComposePath = join(configDir, \"docker-compose.yml\");\n\n return {\n secrets,\n envExampleChanged: syncTextFile(envExamplePath, newEnvContent),\n dockerComposeChanged: syncTextFile(dockerComposePath, newDockerContent),\n };\n}\n\nexport function ensureEnvFile(configDir: string): void {\n const envPath = join(configDir, \".env\");\n const examplePath = join(configDir, \".env.example\");\n\n if (existsSync(envPath) || !existsSync(examplePath)) return;\n\n const content = readFileSync(examplePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n const secret = randomBytes(32).toString(\"base64url\");\n const updated = lines\n .map((line) => {\n if (/^BETTER_AUTH_SECRET=/.test(line)) {\n return `BETTER_AUTH_SECRET=${secret}`;\n }\n return line;\n })\n .join(\"\\n\");\n\n writeFileSync(envPath, updated);\n p.log.info(\"Created .env from generated .env.example with generated BETTER_AUTH_SECRET\");\n}\n\nexport function loadProjectEnv(configDir: string): void {\n const envPath = join(configDir, \".env\");\n if (!existsSync(envPath)) return;\n\n loadDotenv({ path: envPath, processEnv: process.env, quiet: true });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"infra.mjs","names":[],"sources":["../../src/cli/infra.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { config as loadDotenv } from \"dotenv\";\nimport type { RuntimeConfig } from \"../types\";\n\nconst POSTGRES_USER = \"everythingdev\";\nconst POSTGRES_PASSWORD = \"everythingdev\";\nconst API_DATABASE_SECRET = \"API_DATABASE_URL\";\nconst AUTH_DATABASE_SECRET = \"AUTH_DATABASE_URL\";\nconst HOST_SECRET = \"CORS_ORIGIN\";\nconst BASE_POSTGRES_PORT = 5434;\nconst BASE_REDIS_PORT = 6379;\n\ninterface DatabaseSecretConfig {\n secret: string;\n slug: string;\n fromKey: string;\n port: number;\n serviceName: string;\n containerName: string;\n databaseName: string;\n volumeName: string;\n url: string;\n}\n\ninterface RedisSecretConfig {\n secret: string;\n slug: string;\n fromKey: string;\n port: number;\n serviceName: string;\n containerName: string;\n volumeName: string;\n url: string;\n}\n\ninterface SecretGroup {\n section: string;\n secrets: string[];\n}\n\ninterface PortState {\n postgresPorts: Record<string, number>;\n redisPorts: Record<string, number>;\n}\n\ninterface GeneratedInfraSpec {\n groups: SecretGroup[];\n databases: DatabaseSecretConfig[];\n redis: RedisSecretConfig[];\n}\n\ninterface SyncGeneratedInfraResult {\n secrets: string[];\n envExampleChanged: boolean;\n dockerComposeChanged: boolean;\n staleEnvWarnings: string[];\n}\n\nfunction uniqueSecrets(values: Array<string | undefined>): string[] {\n const secrets: string[] = [];\n const seen = new Set<string>();\n\n for (const value of values) {\n if (!value || seen.has(value)) continue;\n seen.add(value);\n secrets.push(value);\n }\n\n return secrets;\n}\n\nfunction loadPortState(configDir?: string): PortState {\n if (!configDir) return { postgresPorts: {}, redisPorts: {} };\n const statePath = join(configDir, \".bos\", \"infra-state.json\");\n if (!existsSync(statePath)) return { postgresPorts: {}, redisPorts: {} };\n try {\n const raw = JSON.parse(readFileSync(statePath, \"utf-8\")) as Partial<PortState>;\n return {\n postgresPorts: raw.postgresPorts ?? {},\n redisPorts: raw.redisPorts ?? {},\n };\n } catch {\n return { postgresPorts: {}, redisPorts: {} };\n }\n}\n\nfunction savePortState(configDir: string, state: PortState): void {\n const statePath = join(configDir, \".bos\", \"infra-state.json\");\n mkdirSync(dirname(statePath), { recursive: true });\n writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\\n`);\n}\n\nfunction resolvePort(slug: string, portMap: Record<string, number>, basePort: number): number {\n if (portMap[slug] !== undefined) return portMap[slug];\n const assigned = Object.values(portMap);\n const next = assigned.length > 0 ? Math.max(...assigned) + 1 : basePort;\n portMap[slug] = next;\n return next;\n}\n\nfunction normalizeRedisSlug(secret: string): string {\n return secret.replace(/_REDIS_URL$/, \"\").toLowerCase();\n}\n\nfunction getSecretGroups(runtimeConfig: RuntimeConfig): SecretGroup[] {\n const groups: SecretGroup[] = [];\n const seen = new Set<string>();\n\n const addGroup = (section: string, secrets: string[]) => {\n const filtered = secrets.filter((s) => {\n if (seen.has(s)) return false;\n seen.add(s);\n return true;\n });\n if (filtered.length > 0) {\n groups.push({ section, secrets: filtered });\n }\n };\n\n addGroup(\"app.host\", uniqueSecrets([...(runtimeConfig.host.secrets ?? []), HOST_SECRET]));\n\n addGroup(\"app.api\", uniqueSecrets(runtimeConfig.api.secrets ?? []));\n\n if (runtimeConfig.auth) {\n addGroup(\"app.auth\", uniqueSecrets(runtimeConfig.auth.secrets ?? []));\n }\n\n if (runtimeConfig.plugins) {\n for (const [pluginKey, plugin] of Object.entries(runtimeConfig.plugins)) {\n if (plugin.secrets && plugin.secrets.length > 0) {\n addGroup(`plugins.${pluginKey}`, plugin.secrets);\n }\n }\n }\n\n return groups;\n}\n\nfunction buildGeneratedInfraSpec(\n runtimeConfig: RuntimeConfig,\n configDir?: string,\n): { spec: GeneratedInfraSpec; portState: PortState } {\n const groups = getSecretGroups(runtimeConfig);\n const allSecrets = groups.flatMap((group) => group.secrets);\n const originMap = configDir ? buildOriginMap(configDir, runtimeConfig) : new Map();\n const portState = loadPortState(configDir);\n\n const databases = buildDatabaseConfigs(allSecrets, originMap, portState.postgresPorts);\n const redis = buildRedisConfigs(allSecrets, originMap, portState.redisPorts);\n\n return { spec: { groups, databases, redis }, portState };\n}\n\nfunction normalizeDatabaseSlug(secret: string): string {\n return secret.replace(/_DATABASE_URL$/, \"\").toLowerCase();\n}\n\nfunction buildOriginMap(configDir: string, runtimeConfig: RuntimeConfig): Map<string, string> {\n const configPath = join(configDir, \"bos.config.json\");\n\n const originMap = new Map<string, string>();\n const account = runtimeConfig.account;\n\n const resolveOrigin = (extendsRef: unknown): string | null => {\n if (typeof extendsRef === \"string\") {\n const match = extendsRef.match(/^bos:\\/\\/([^/]+)\\//);\n return match?.[1] ?? null;\n }\n return null;\n };\n\n const rawConfig = existsSync(configPath)\n ? (JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>)\n : null;\n const rawPlugins = rawConfig?.plugins as Record<string, unknown> | undefined;\n\n for (const secret of runtimeConfig.api.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, account);\n }\n\n const rawApp = rawConfig?.app as Record<string, unknown> | undefined;\n const authExtends = (rawApp?.auth as Record<string, unknown> | undefined)?.extends;\n const authOrigin = resolveOrigin(authExtends) ?? account;\n for (const secret of runtimeConfig.auth?.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, authOrigin);\n }\n\n for (const [pluginKey, pluginEntry] of Object.entries(runtimeConfig.plugins ?? {})) {\n const rawPlugin = rawPlugins?.[pluginKey];\n let pluginOrigin: string;\n if (typeof rawPlugin === \"string\") {\n pluginOrigin = resolveOrigin(rawPlugin) ?? account;\n } else if (rawPlugin && typeof rawPlugin === \"object\") {\n pluginOrigin = resolveOrigin((rawPlugin as Record<string, unknown>).extends) ?? account;\n } else {\n pluginOrigin = account;\n }\n for (const secret of pluginEntry.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, pluginOrigin);\n }\n }\n\n for (const secret of runtimeConfig.host.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, account);\n }\n\n return originMap;\n}\n\nfunction buildDatabaseConfigs(\n secrets: string[],\n originMap: Map<string, string>,\n portMap: Record<string, number>,\n): DatabaseSecretConfig[] {\n const databaseSecrets = uniqueSecrets(\n secrets.filter((secret) => secret.endsWith(\"_DATABASE_URL\")),\n );\n\n const orderedSecrets = [...databaseSecrets];\n\n for (const secret of orderedSecrets) {\n const slug = normalizeDatabaseSlug(secret);\n if (secret === API_DATABASE_SECRET) {\n portMap[slug] = 5432;\n } else if (secret === AUTH_DATABASE_SECRET) {\n portMap[slug] = 5433;\n } else {\n resolvePort(slug, portMap, BASE_POSTGRES_PORT);\n }\n }\n\n return orderedSecrets.map((secret) => {\n const slug = normalizeDatabaseSlug(secret);\n const fromKey = originMap.get(secret) ?? \"\";\n const port = portMap[slug];\n\n const volumeName = fromKey\n ? `${fromKey.replace(/\\./g, \"_\")}_postgres_${slug}_data`\n : `postgres_${slug}_data`;\n\n const containerName = fromKey ? `${fromKey}-postgres-${slug}` : `postgres-${slug}`;\n\n return {\n secret,\n slug,\n fromKey,\n port,\n serviceName: `postgres-${slug.replace(/_/g, \"-\")}`,\n containerName,\n databaseName: `${slug}_db`,\n volumeName,\n url: `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${port}/${slug}_db`,\n };\n });\n}\n\nfunction buildRedisConfigs(\n secrets: string[],\n originMap: Map<string, string>,\n portMap: Record<string, number>,\n): RedisSecretConfig[] {\n const redisSecrets = uniqueSecrets(secrets.filter((secret) => secret.endsWith(\"_REDIS_URL\")));\n\n for (const secret of redisSecrets) {\n const slug = normalizeRedisSlug(secret);\n resolvePort(slug, portMap, BASE_REDIS_PORT);\n }\n\n return redisSecrets.map((secret) => {\n const slug = normalizeRedisSlug(secret);\n const fromKey = originMap.get(secret) ?? \"\";\n const port = portMap[slug];\n\n const volumeName = fromKey\n ? `${fromKey.replace(/\\./g, \"_\")}_redis_${slug}_data`\n : `redis_${slug}_data`;\n\n const containerName = fromKey ? `${fromKey}-redis-${slug}` : `redis-${slug}`;\n\n return {\n secret,\n slug,\n fromKey,\n port,\n serviceName: `redis-${slug.replace(/_/g, \"-\")}`,\n containerName,\n volumeName,\n url: `redis://localhost:${port}`,\n };\n });\n}\n\nfunction extractPortFromUrl(url: string): string | null {\n const match = url.match(/:(\\d{4,5})(?:\\/|$)/);\n return match?.[1] ?? null;\n}\n\nfunction defaultSecretValue(\n secret: string,\n databases: Map<string, DatabaseSecretConfig>,\n redisConfigs: Map<string, RedisSecretConfig>,\n options: { forExample: boolean },\n): string {\n if (secret === \"BETTER_AUTH_SECRET\") {\n return options.forExample ? \"\" : randomBytes(32).toString(\"base64url\");\n }\n\n if (secret === \"CORS_ORIGIN\") {\n return \"http://localhost:3000\";\n }\n\n return databases.get(secret)?.url ?? redisConfigs.get(secret)?.url ?? \"\";\n}\n\nfunction renderEnvFile(\n groups: SecretGroup[],\n databases: DatabaseSecretConfig[],\n redisConfigs: RedisSecretConfig[],\n options: { forExample: boolean },\n): string {\n const databaseMap = new Map(databases.map((entry) => [entry.secret, entry]));\n const redisMap = new Map(redisConfigs.map((entry) => [entry.secret, entry]));\n const lines: string[] = [\n \"# Generated from configured bos secrets\",\n \"# Update values as needed for your local environment\",\n \"\",\n ];\n\n for (const group of groups) {\n lines.push(`# ${group.section}`);\n for (const secret of group.secrets) {\n lines.push(`${secret}=${defaultSecretValue(secret, databaseMap, redisMap, options)}`);\n }\n lines.push(\"\");\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction renderDockerCompose(\n databases: DatabaseSecretConfig[],\n redisConfigs: RedisSecretConfig[],\n projectName: string,\n): string {\n const lines = [`name: ${projectName}`, \"\"];\n\n if (databases.length > 0) {\n lines.push(\n \"x-pg-common: &pg-common\",\n \" image: postgres:17-alpine\",\n \" environment: &pg-env\",\n ` POSTGRES_USER: ${POSTGRES_USER}`,\n ` POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}`,\n \" healthcheck:\",\n ' test: [\"CMD-SHELL\", \"pg_isready -U everythingdev\"]',\n \" interval: 3s\",\n \" timeout: 3s\",\n \" retries: 5\",\n \"\",\n );\n }\n\n if (redisConfigs.length > 0) {\n lines.push(\n \"x-redis-common: &redis-common\",\n \" image: redis:7-alpine\",\n \" command: redis-server --appendonly yes\",\n \" healthcheck:\",\n ' test: [\"CMD\", \"redis-cli\", \"ping\"]',\n \" interval: 3s\",\n \" timeout: 3s\",\n \" retries: 5\",\n \"\",\n );\n }\n\n lines.push(\"services:\");\n\n for (const database of databases) {\n lines.push(` ${database.serviceName}:`);\n lines.push(\" <<: *pg-common\");\n lines.push(` container_name: ${database.containerName}`);\n lines.push(\" environment:\");\n lines.push(\" <<: *pg-env\");\n lines.push(` POSTGRES_DB: ${database.databaseName}`);\n lines.push(\" ports:\");\n lines.push(` - \"${database.port}:5432\"`);\n lines.push(\" volumes:\");\n lines.push(` - ${database.volumeName}:/var/lib/postgresql/data`);\n lines.push(\"\");\n }\n\n for (const redis of redisConfigs) {\n lines.push(` ${redis.serviceName}:`);\n lines.push(\" <<: *redis-common\");\n lines.push(` container_name: ${redis.containerName}`);\n lines.push(\" ports:\");\n lines.push(` - \"${redis.port}:6379\"`);\n lines.push(\" volumes:\");\n lines.push(` - ${redis.volumeName}:/data`);\n lines.push(\"\");\n }\n\n lines.push(\"volumes:\");\n for (const database of databases) {\n lines.push(` ${database.volumeName}:`);\n lines.push(` name: ${database.volumeName}`);\n }\n for (const redis of redisConfigs) {\n lines.push(` ${redis.volumeName}:`);\n lines.push(` name: ${redis.volumeName}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction syncTextFile(filePath: string, nextContent: string): boolean {\n if (existsSync(filePath) && readFileSync(filePath, \"utf-8\") === nextContent) {\n return false;\n }\n\n writeFileSync(filePath, nextContent);\n return true;\n}\n\nexport function writeGeneratedInfra(configDir: string, runtimeConfig: RuntimeConfig): string[] {\n const result = syncGeneratedInfra(configDir, runtimeConfig);\n\n if (result.staleEnvWarnings.length > 0) {\n p.log.warn(\n `.env has ${result.staleEnvWarnings.length} stale value(s) compared to .env.example:`,\n );\n for (const warning of result.staleEnvWarnings) {\n p.log.message(` ${warning}`);\n }\n }\n\n return result.secrets;\n}\n\nexport function syncGeneratedInfra(\n configDir: string,\n runtimeConfig: RuntimeConfig,\n): SyncGeneratedInfraResult {\n const { spec, portState } = buildGeneratedInfraSpec(runtimeConfig, configDir);\n const secrets = spec.groups.flatMap((group) => group.secrets);\n const newEnvContent = renderEnvFile(spec.groups, spec.databases, spec.redis, {\n forExample: true,\n });\n const newDockerContent = renderDockerCompose(spec.databases, spec.redis, runtimeConfig.account);\n\n const envExamplePath = join(configDir, \".env.example\");\n const dockerComposePath = join(configDir, \"docker-compose.yml\");\n\n const staleWarnings = checkEnvStaleness(configDir, spec.databases, spec.redis);\n\n if (configDir) {\n savePortState(configDir, portState);\n }\n\n return {\n secrets,\n envExampleChanged: syncTextFile(envExamplePath, newEnvContent),\n dockerComposeChanged: syncTextFile(dockerComposePath, newDockerContent),\n staleEnvWarnings: staleWarnings,\n };\n}\n\nfunction checkEnvStaleness(\n configDir: string,\n databases: DatabaseSecretConfig[],\n redisConfigs: RedisSecretConfig[],\n): string[] {\n const envPath = join(configDir, \".env\");\n if (!existsSync(envPath)) return [];\n\n const existingEnv = readFileSync(envPath, \"utf-8\");\n const envMap = new Map<string, string>();\n for (const line of existingEnv.split(\"\\n\")) {\n const match = line.match(/^([A-Z_]+)=(.*)$/);\n if (match) envMap.set(match[1], match[2]);\n }\n\n const stale: string[] = [];\n\n for (const db of databases) {\n const existing = envMap.get(db.secret);\n if (existing && existing !== db.url) {\n const oldPort = extractPortFromUrl(existing) ?? \"?\";\n stale.push(`${db.secret}: port ${oldPort} → ${db.port}`);\n }\n }\n\n for (const redis of redisConfigs) {\n const existing = envMap.get(redis.secret);\n if (existing && existing !== redis.url) {\n const oldPort = extractPortFromUrl(existing) ?? \"?\";\n stale.push(`${redis.secret}: port ${oldPort} → ${redis.port}`);\n }\n }\n\n return stale;\n}\n\nexport function ensureEnvFile(configDir: string): void {\n const envPath = join(configDir, \".env\");\n const examplePath = join(configDir, \".env.example\");\n\n if (existsSync(envPath) || !existsSync(examplePath)) return;\n\n const content = readFileSync(examplePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n const secret = randomBytes(32).toString(\"base64url\");\n const updated = lines\n .map((line) => {\n if (/^BETTER_AUTH_SECRET=/.test(line)) {\n return `BETTER_AUTH_SECRET=${secret}`;\n }\n return line;\n })\n .join(\"\\n\");\n\n writeFileSync(envPath, updated);\n p.log.info(\"Created .env from generated .env.example with generated BETTER_AUTH_SECRET\");\n}\n\nexport function loadProjectEnv(configDir: string): void {\n const envPath = join(configDir, \".env\");\n if (!existsSync(envPath)) return;\n\n loadDotenv({ path: envPath, processEnv: process.env, quiet: true });\n}\n"],"mappings":"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"}
|
package/dist/contract.d.cts
CHANGED
|
@@ -28,8 +28,8 @@ declare const DevOptionsSchema: z.ZodObject<{
|
|
|
28
28
|
}, z.core.$strip>;
|
|
29
29
|
declare const DevResultSchema: z.ZodObject<{
|
|
30
30
|
status: z.ZodEnum<{
|
|
31
|
-
started: "started";
|
|
32
31
|
error: "error";
|
|
32
|
+
started: "started";
|
|
33
33
|
}>;
|
|
34
34
|
description: z.ZodString;
|
|
35
35
|
processes: z.ZodArray<z.ZodString>;
|
|
@@ -355,8 +355,8 @@ declare const KeyPublishResultSchema: z.ZodObject<{
|
|
|
355
355
|
}, z.core.$strip>;
|
|
356
356
|
declare const OverrideSectionSchema: z.ZodEnum<{
|
|
357
357
|
plugins: "plugins";
|
|
358
|
-
host: "host";
|
|
359
358
|
ui: "ui";
|
|
359
|
+
host: "host";
|
|
360
360
|
api: "api";
|
|
361
361
|
}>;
|
|
362
362
|
declare const RuntimeOverrideTargetBaseSchema: z.ZodEnum<{
|
|
@@ -378,8 +378,8 @@ declare const InitOptionsSchema: z.ZodObject<{
|
|
|
378
378
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
379
379
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
380
380
|
plugins: "plugins";
|
|
381
|
-
host: "host";
|
|
382
381
|
ui: "ui";
|
|
382
|
+
host: "host";
|
|
383
383
|
api: "api";
|
|
384
384
|
}>>>;
|
|
385
385
|
noInteractive: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -402,8 +402,8 @@ declare const InitResultSchema: z.ZodObject<{
|
|
|
402
402
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
403
403
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
404
404
|
plugins: "plugins";
|
|
405
|
-
host: "host";
|
|
406
405
|
ui: "ui";
|
|
406
|
+
host: "host";
|
|
407
407
|
api: "api";
|
|
408
408
|
}>>>;
|
|
409
409
|
filesCopied: z.ZodNumber;
|
|
@@ -535,8 +535,8 @@ declare const bosContract: {
|
|
|
535
535
|
interactive: z.ZodOptional<z.ZodBoolean>;
|
|
536
536
|
}, z.core.$strip>, z.ZodObject<{
|
|
537
537
|
status: z.ZodEnum<{
|
|
538
|
-
started: "started";
|
|
539
538
|
error: "error";
|
|
539
|
+
started: "started";
|
|
540
540
|
}>;
|
|
541
541
|
description: z.ZodString;
|
|
542
542
|
processes: z.ZodArray<z.ZodString>;
|
|
@@ -860,8 +860,8 @@ declare const bosContract: {
|
|
|
860
860
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
861
861
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
862
862
|
plugins: "plugins";
|
|
863
|
-
host: "host";
|
|
864
863
|
ui: "ui";
|
|
864
|
+
host: "host";
|
|
865
865
|
api: "api";
|
|
866
866
|
}>>>;
|
|
867
867
|
noInteractive: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -879,8 +879,8 @@ declare const bosContract: {
|
|
|
879
879
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
880
880
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
881
881
|
plugins: "plugins";
|
|
882
|
-
host: "host";
|
|
883
882
|
ui: "ui";
|
|
883
|
+
host: "host";
|
|
884
884
|
api: "api";
|
|
885
885
|
}>>>;
|
|
886
886
|
filesCopied: z.ZodNumber;
|
package/dist/contract.d.mts
CHANGED
|
@@ -28,8 +28,8 @@ declare const DevOptionsSchema: z.ZodObject<{
|
|
|
28
28
|
}, z.core.$strip>;
|
|
29
29
|
declare const DevResultSchema: z.ZodObject<{
|
|
30
30
|
status: z.ZodEnum<{
|
|
31
|
-
started: "started";
|
|
32
31
|
error: "error";
|
|
32
|
+
started: "started";
|
|
33
33
|
}>;
|
|
34
34
|
description: z.ZodString;
|
|
35
35
|
processes: z.ZodArray<z.ZodString>;
|
|
@@ -355,8 +355,8 @@ declare const KeyPublishResultSchema: z.ZodObject<{
|
|
|
355
355
|
}, z.core.$strip>;
|
|
356
356
|
declare const OverrideSectionSchema: z.ZodEnum<{
|
|
357
357
|
plugins: "plugins";
|
|
358
|
-
host: "host";
|
|
359
358
|
ui: "ui";
|
|
359
|
+
host: "host";
|
|
360
360
|
api: "api";
|
|
361
361
|
}>;
|
|
362
362
|
declare const RuntimeOverrideTargetBaseSchema: z.ZodEnum<{
|
|
@@ -378,8 +378,8 @@ declare const InitOptionsSchema: z.ZodObject<{
|
|
|
378
378
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
379
379
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
380
380
|
plugins: "plugins";
|
|
381
|
-
host: "host";
|
|
382
381
|
ui: "ui";
|
|
382
|
+
host: "host";
|
|
383
383
|
api: "api";
|
|
384
384
|
}>>>;
|
|
385
385
|
noInteractive: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -402,8 +402,8 @@ declare const InitResultSchema: z.ZodObject<{
|
|
|
402
402
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
403
403
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
404
404
|
plugins: "plugins";
|
|
405
|
-
host: "host";
|
|
406
405
|
ui: "ui";
|
|
406
|
+
host: "host";
|
|
407
407
|
api: "api";
|
|
408
408
|
}>>>;
|
|
409
409
|
filesCopied: z.ZodNumber;
|
|
@@ -535,8 +535,8 @@ declare const bosContract: {
|
|
|
535
535
|
interactive: z.ZodOptional<z.ZodBoolean>;
|
|
536
536
|
}, z.core.$strip>, z.ZodObject<{
|
|
537
537
|
status: z.ZodEnum<{
|
|
538
|
-
started: "started";
|
|
539
538
|
error: "error";
|
|
539
|
+
started: "started";
|
|
540
540
|
}>;
|
|
541
541
|
description: z.ZodString;
|
|
542
542
|
processes: z.ZodArray<z.ZodString>;
|
|
@@ -860,8 +860,8 @@ declare const bosContract: {
|
|
|
860
860
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
861
861
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
862
862
|
plugins: "plugins";
|
|
863
|
-
host: "host";
|
|
864
863
|
ui: "ui";
|
|
864
|
+
host: "host";
|
|
865
865
|
api: "api";
|
|
866
866
|
}>>>;
|
|
867
867
|
noInteractive: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -879,8 +879,8 @@ declare const bosContract: {
|
|
|
879
879
|
plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
880
880
|
overrides: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
881
881
|
plugins: "plugins";
|
|
882
|
-
host: "host";
|
|
883
882
|
ui: "ui";
|
|
883
|
+
host: "host";
|
|
884
884
|
api: "api";
|
|
885
885
|
}>>>;
|
|
886
886
|
filesCopied: z.ZodNumber;
|
package/dist/dev-session.cjs
CHANGED
|
@@ -62,6 +62,12 @@ const runDevSession = (orchestrator, onShutdownReady) => effect.Effect.gen(funct
|
|
|
62
62
|
const services = yield* require_service_descriptor.ServiceDescriptorMap;
|
|
63
63
|
const orderedPackages = sortByOrder(orchestrator.packages);
|
|
64
64
|
const initialProcesses = require_orchestrator.getProcessStates(orderedPackages, services, orchestrator.port);
|
|
65
|
+
if (process.env.DEBUG === "true" || process.env.DEBUG === "1") {
|
|
66
|
+
console.error("[DEBUG session] orchestrator.packages:", orchestrator.packages.join(", "));
|
|
67
|
+
console.error("[DEBUG session] orderedPackages:", orderedPackages.join(", "));
|
|
68
|
+
console.error("[DEBUG session] services keys:", [...services.keys()].join(", "));
|
|
69
|
+
console.error("[DEBUG session] initialProcesses:", initialProcesses.map((p) => `${p.name}=${p.source}`).join(", "));
|
|
70
|
+
}
|
|
65
71
|
const logger = yield* effect.Effect.promise(() => require_dev_logs.createDevLogger(configDir, orchestrator.description));
|
|
66
72
|
const shutdown = yield* effect.Deferred.make();
|
|
67
73
|
onShutdownReady?.(() => {
|
package/dist/dev-session.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-session.cjs","names":["Effect","getProjectRoot","ServiceDescriptorMap","getProcessStates","createDevLogger","Deferred","renderDevView","renderStreamingView","makeDevProcess","ServiceDescriptorMapLive","DevRuntimeConfigLive","NodeContext","Exit"],"sources":["../src/dev-session.ts"],"sourcesContent":["import * as NodeContext from \"@effect/platform-node/NodeContext\";\nimport { Deferred, Effect, Exit } from \"effect\";\nimport {\n type DevViewHandle,\n type LogEntry,\n type ProcessState,\n renderDevView,\n} from \"./components/dev-view\";\nimport { renderStreamingView } from \"./components/streaming-view\";\nimport { getProjectRoot } from \"./config\";\nimport { createDevLogger } from \"./dev-logs\";\nimport {\n getProcessStates,\n makeDevProcess,\n type ProcessCallbacks,\n type ProcessHandle,\n} from \"./orchestrator\";\nimport {\n type AppOrchestrator,\n DevRuntimeConfigLive,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n ServiceDescriptorMapLive,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nconst LOG_NOISE_PATTERNS = [\n /\\[ Federation Runtime \\] Version .* from (host|ui) of shared singleton module/,\n /Executing an Effect versioned \\d+\\.\\d+\\.\\d+ with a Runtime of version/,\n /you may want to dedupe the effect dependencies/,\n];\n\nconst SSR_LOG_ALLOWLIST = [\n /\\bready\\s+built in\\b/i,\n /\\bcompiled\\b.*successfully/i,\n /\\berror\\b/i,\n /\\bfailed\\b/i,\n /\\bexception\\b/i,\n];\n\nconst shouldDisplayLog = (source: string, line: string, isError?: boolean): boolean => {\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") return true;\n if (source === \"ui-ssr\") {\n if (isError) return true;\n return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));\n }\n return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));\n};\n\nconst isInteractiveSupported = (): boolean => {\n return process.stdin.isTTY === true && process.stdout.isTTY === true;\n};\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"auth\", \"api\", \"plugin\", \"host-build\", \"host\"];\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\nfunction formatLogLine(entry: LogEntry): string {\n const ts = new Date(entry.timestamp).toISOString();\n const prefix = entry.isError ? \"ERR\" : \"OUT\";\n return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport const runDevSession = (\n orchestrator: AppOrchestrator,\n onShutdownReady?: (requestShutdown: () => void) => void,\n) =>\n Effect.gen(function* () {\n const configDir = getProjectRoot();\n const services = yield* ServiceDescriptorMap;\n const orderedPackages = sortByOrder(orchestrator.packages);\n const initialProcesses: ProcessState[] = getProcessStates(\n orderedPackages,\n services,\n orchestrator.port,\n );\n\n const logger = yield* Effect.promise(() =>\n createDevLogger(configDir, orchestrator.description),\n );\n\n const shutdown = yield* Deferred.make<void>();\n\n onShutdownReady?.(() => {\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n });\n\n const allLogs: LogEntry[] = [];\n let view: DevViewHandle | null = null;\n let shouldExportLogs = false;\n\n const requestShutdownAndExport = () => {\n shouldExportLogs = true;\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n };\n\n const useInteractive = orchestrator.interactive ?? isInteractiveSupported();\n view = useInteractive\n ? renderDevView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n requestShutdownAndExport,\n )\n : renderStreamingView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n );\n\n const callbacks: ProcessCallbacks = {\n onStatus: (name, status, message) => {\n view?.updateProcess(name, status, message);\n },\n onLog: (name, line, isError) => {\n const entry: LogEntry = {\n id: `${Date.now()}-${allLogs.length + 1}`,\n source: name,\n line,\n timestamp: Date.now(),\n isError,\n };\n allLogs.push(entry);\n if (shouldDisplayLog(name, line, isError)) {\n view?.addLog(name, line, isError);\n }\n if (!orchestrator.noLogs) {\n void logger.write(entry);\n }\n },\n };\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(pkg, callbacks, portOverride).pipe(\n Effect.tapError((err) =>\n Effect.sync(() => {\n callbacks.onLog(pkg, `Failed to start: ${err}`, true);\n callbacks.onStatus(pkg, \"error\");\n }),\n ),\n Effect.catchAll(() =>\n Effect.succeed({\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle),\n ),\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (_pkg: string, handle: ProcessHandle) =>\n handle.waitForReady.pipe(Effect.catchAll(() => Effect.void));\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const allHandles = [...nonHostHandles, ...hostHandles];\n\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n yield* Effect.forEach(allHandles, (h) => h.kill.pipe(Effect.ignore), {\n concurrency: \"unbounded\",\n });\n\n yield* Effect.sleep(\"200 millis\");\n\n view?.unmount();\n\n if (shouldExportLogs) {\n console.log(\"\\n\");\n console.log(\"═\".repeat(70));\n console.log(` SESSION LOGS: ${orchestrator.description}`);\n console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);\n console.log(` Total entries: ${allLogs.length}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n for (const entry of allLogs) {\n console.log(formatLogLine(entry));\n }\n console.log(\"\");\n console.log(\"═\".repeat(70));\n console.log(` Full logs saved to: ${logger.logFile}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n }\n }),\n );\n\n yield* Deferred.await(shutdown);\n });\n\nconst runApp = (\n orchestrator: AppOrchestrator,\n services: Map<string, ServiceDescriptor>,\n runtimeConfig: RuntimeConfig,\n) => {\n let requestShutdown: (() => void) | null = null;\n let signalCount = 0;\n let forceExitTimer: ReturnType<typeof setTimeout> | null = null;\n\n const forceExit = () => {\n console.log(\"\\n[Dev] Force exit\");\n process.exit(0);\n };\n\n const program = Effect.scoped(\n runDevSession(orchestrator, (shutdown) => {\n requestShutdown = shutdown;\n }),\n ).pipe(\n Effect.provide(ServiceDescriptorMapLive(services)),\n Effect.provide(DevRuntimeConfigLive(runtimeConfig)),\n Effect.provide(NodeContext.layer),\n Effect.catchAllDefect((defect) =>\n Effect.sync(() => {\n console.error(\"[Dev] Unhandled defect in orchestrator:\", defect);\n }),\n ),\n );\n\n const handleSignal = () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n console.log(\"\\n[Dev] Shutting down...\");\n forceExitTimer = setTimeout(forceExit, 5000);\n requestShutdown?.();\n };\n\n process.on(\"SIGINT\", handleSignal);\n process.on(\"SIGTERM\", handleSignal);\n\n Effect.runPromiseExit(program).then((exit) => {\n if (forceExitTimer) clearTimeout(forceExitTimer);\n process.exit(Exit.isSuccess(exit) ? 0 : 0);\n });\n};\n\nexport const devApp = runApp;\n\nexport const startApp = runApp;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dev-session.cjs","names":["Effect","getProjectRoot","ServiceDescriptorMap","getProcessStates","createDevLogger","Deferred","renderDevView","renderStreamingView","makeDevProcess","ServiceDescriptorMapLive","DevRuntimeConfigLive","NodeContext","Exit"],"sources":["../src/dev-session.ts"],"sourcesContent":["import * as NodeContext from \"@effect/platform-node/NodeContext\";\nimport { Deferred, Effect, Exit } from \"effect\";\nimport {\n type DevViewHandle,\n type LogEntry,\n type ProcessState,\n renderDevView,\n} from \"./components/dev-view\";\nimport { renderStreamingView } from \"./components/streaming-view\";\nimport { getProjectRoot } from \"./config\";\nimport { createDevLogger } from \"./dev-logs\";\nimport {\n getProcessStates,\n makeDevProcess,\n type ProcessCallbacks,\n type ProcessHandle,\n} from \"./orchestrator\";\nimport {\n type AppOrchestrator,\n DevRuntimeConfigLive,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n ServiceDescriptorMapLive,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nconst LOG_NOISE_PATTERNS = [\n /\\[ Federation Runtime \\] Version .* from (host|ui) of shared singleton module/,\n /Executing an Effect versioned \\d+\\.\\d+\\.\\d+ with a Runtime of version/,\n /you may want to dedupe the effect dependencies/,\n];\n\nconst SSR_LOG_ALLOWLIST = [\n /\\bready\\s+built in\\b/i,\n /\\bcompiled\\b.*successfully/i,\n /\\berror\\b/i,\n /\\bfailed\\b/i,\n /\\bexception\\b/i,\n];\n\nconst shouldDisplayLog = (source: string, line: string, isError?: boolean): boolean => {\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") return true;\n if (source === \"ui-ssr\") {\n if (isError) return true;\n return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));\n }\n return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));\n};\n\nconst isInteractiveSupported = (): boolean => {\n return process.stdin.isTTY === true && process.stdout.isTTY === true;\n};\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"auth\", \"api\", \"plugin\", \"host-build\", \"host\"];\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\nfunction formatLogLine(entry: LogEntry): string {\n const ts = new Date(entry.timestamp).toISOString();\n const prefix = entry.isError ? \"ERR\" : \"OUT\";\n return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport const runDevSession = (\n orchestrator: AppOrchestrator,\n onShutdownReady?: (requestShutdown: () => void) => void,\n) =>\n Effect.gen(function* () {\n const configDir = getProjectRoot();\n const services = yield* ServiceDescriptorMap;\n const orderedPackages = sortByOrder(orchestrator.packages);\n const initialProcesses: ProcessState[] = getProcessStates(\n orderedPackages,\n services,\n orchestrator.port,\n );\n\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") {\n console.error(\"[DEBUG session] orchestrator.packages:\", orchestrator.packages.join(\", \"));\n console.error(\"[DEBUG session] orderedPackages:\", orderedPackages.join(\", \"));\n console.error(\"[DEBUG session] services keys:\", [...services.keys()].join(\", \"));\n console.error(\n \"[DEBUG session] initialProcesses:\",\n initialProcesses.map((p) => `${p.name}=${p.source}`).join(\", \"),\n );\n }\n\n const logger = yield* Effect.promise(() =>\n createDevLogger(configDir, orchestrator.description),\n );\n\n const shutdown = yield* Deferred.make<void>();\n\n onShutdownReady?.(() => {\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n });\n\n const allLogs: LogEntry[] = [];\n let view: DevViewHandle | null = null;\n let shouldExportLogs = false;\n\n const requestShutdownAndExport = () => {\n shouldExportLogs = true;\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n };\n\n const useInteractive = orchestrator.interactive ?? isInteractiveSupported();\n view = useInteractive\n ? renderDevView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n requestShutdownAndExport,\n )\n : renderStreamingView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n );\n\n const callbacks: ProcessCallbacks = {\n onStatus: (name, status, message) => {\n view?.updateProcess(name, status, message);\n },\n onLog: (name, line, isError) => {\n const entry: LogEntry = {\n id: `${Date.now()}-${allLogs.length + 1}`,\n source: name,\n line,\n timestamp: Date.now(),\n isError,\n };\n allLogs.push(entry);\n if (shouldDisplayLog(name, line, isError)) {\n view?.addLog(name, line, isError);\n }\n if (!orchestrator.noLogs) {\n void logger.write(entry);\n }\n },\n };\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(pkg, callbacks, portOverride).pipe(\n Effect.tapError((err) =>\n Effect.sync(() => {\n callbacks.onLog(pkg, `Failed to start: ${err}`, true);\n callbacks.onStatus(pkg, \"error\");\n }),\n ),\n Effect.catchAll(() =>\n Effect.succeed({\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle),\n ),\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (_pkg: string, handle: ProcessHandle) =>\n handle.waitForReady.pipe(Effect.catchAll(() => Effect.void));\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const allHandles = [...nonHostHandles, ...hostHandles];\n\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n yield* Effect.forEach(allHandles, (h) => h.kill.pipe(Effect.ignore), {\n concurrency: \"unbounded\",\n });\n\n yield* Effect.sleep(\"200 millis\");\n\n view?.unmount();\n\n if (shouldExportLogs) {\n console.log(\"\\n\");\n console.log(\"═\".repeat(70));\n console.log(` SESSION LOGS: ${orchestrator.description}`);\n console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);\n console.log(` Total entries: ${allLogs.length}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n for (const entry of allLogs) {\n console.log(formatLogLine(entry));\n }\n console.log(\"\");\n console.log(\"═\".repeat(70));\n console.log(` Full logs saved to: ${logger.logFile}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n }\n }),\n );\n\n yield* Deferred.await(shutdown);\n });\n\nconst runApp = (\n orchestrator: AppOrchestrator,\n services: Map<string, ServiceDescriptor>,\n runtimeConfig: RuntimeConfig,\n) => {\n let requestShutdown: (() => void) | null = null;\n let signalCount = 0;\n let forceExitTimer: ReturnType<typeof setTimeout> | null = null;\n\n const forceExit = () => {\n console.log(\"\\n[Dev] Force exit\");\n process.exit(0);\n };\n\n const program = Effect.scoped(\n runDevSession(orchestrator, (shutdown) => {\n requestShutdown = shutdown;\n }),\n ).pipe(\n Effect.provide(ServiceDescriptorMapLive(services)),\n Effect.provide(DevRuntimeConfigLive(runtimeConfig)),\n Effect.provide(NodeContext.layer),\n Effect.catchAllDefect((defect) =>\n Effect.sync(() => {\n console.error(\"[Dev] Unhandled defect in orchestrator:\", defect);\n }),\n ),\n );\n\n const handleSignal = () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n console.log(\"\\n[Dev] Shutting down...\");\n forceExitTimer = setTimeout(forceExit, 5000);\n requestShutdown?.();\n };\n\n process.on(\"SIGINT\", handleSignal);\n process.on(\"SIGTERM\", handleSignal);\n\n Effect.runPromiseExit(program).then((exit) => {\n if (forceExitTimer) clearTimeout(forceExitTimer);\n process.exit(Exit.isSuccess(exit) ? 0 : 0);\n });\n};\n\nexport const devApp = runApp;\n\nexport const startApp = runApp;\n"],"mappings":";;;;;;;;;;;;AA0BA,MAAM,qBAAqB;CACzB;CACA;CACA;CACD;AAED,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;CACA;CACD;AAED,MAAM,oBAAoB,QAAgB,MAAc,YAA+B;AACrF,KAAI,QAAQ,IAAI,UAAU,UAAU,QAAQ,IAAI,UAAU,IAAK,QAAO;AACtE,KAAI,WAAW,UAAU;AACvB,MAAI,QAAS,QAAO;AACpB,SAAO,kBAAkB,MAAM,YAAY,QAAQ,KAAK,KAAK,CAAC;;AAEhE,QAAO,CAAC,mBAAmB,MAAM,YAAY,QAAQ,KAAK,KAAK,CAAC;;AAGlE,MAAM,+BAAwC;AAC5C,QAAO,QAAQ,MAAM,UAAU,QAAQ,QAAQ,OAAO,UAAU;;AAGlE,MAAM,gBAAgB;CAAC;CAAU;CAAM;CAAQ;CAAO;CAAU;CAAc;CAAO;AAErF,MAAM,eAAe,aAAiC;AACpD,QAAO,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,MAAM;EAClC,MAAM,OAAO,EAAE,WAAW,UAAU,GAChC,cAAc,QAAQ,SAAS,GAC/B,cAAc,QAAQ,EAAE;EAC5B,MAAM,OAAO,EAAE,WAAW,UAAU,GAChC,cAAc,QAAQ,SAAS,GAC/B,cAAc,QAAQ,EAAE;AAC5B,MAAI,SAAS,MAAM,SAAS,GAAI,QAAO;AACvC,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO,OAAO;GACd;;AAGJ,SAAS,cAAc,OAAyB;CAC9C,MAAM,KAAK,IAAI,KAAK,MAAM,UAAU,CAAC,aAAa;CAClD,MAAM,SAAS,MAAM,UAAU,QAAQ;AACvC,QAAO,IAAI,GAAG,KAAK,MAAM,OAAO,KAAK,OAAO,IAAI,MAAM;;AAGxD,MAAa,iBACX,cACA,oBAEAA,cAAO,IAAI,aAAa;CACtB,MAAM,YAAYC,+BAAgB;CAClC,MAAM,WAAW,OAAOC;CACxB,MAAM,kBAAkB,YAAY,aAAa,SAAS;CAC1D,MAAM,mBAAmCC,sCACvC,iBACA,UACA,aAAa,KACd;AAED,KAAI,QAAQ,IAAI,UAAU,UAAU,QAAQ,IAAI,UAAU,KAAK;AAC7D,UAAQ,MAAM,0CAA0C,aAAa,SAAS,KAAK,KAAK,CAAC;AACzF,UAAQ,MAAM,oCAAoC,gBAAgB,KAAK,KAAK,CAAC;AAC7E,UAAQ,MAAM,kCAAkC,CAAC,GAAG,SAAS,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC;AAChF,UAAQ,MACN,qCACA,iBAAiB,KAAK,MAAM,GAAG,EAAE,KAAK,GAAG,EAAE,SAAS,CAAC,KAAK,KAAK,CAChE;;CAGH,MAAM,SAAS,OAAOH,cAAO,cAC3BI,iCAAgB,WAAW,aAAa,YAAY,CACrD;CAED,MAAM,WAAW,OAAOC,gBAAS,MAAY;AAE7C,yBAAwB;AACtB,EAAKL,cAAO,WAAWK,gBAAS,QAAQ,UAAU,OAAU,CAAC;GAC7D;CAEF,MAAM,UAAsB,EAAE;CAC9B,IAAI,OAA6B;CACjC,IAAI,mBAAmB;CAEvB,MAAM,iCAAiC;AACrC,qBAAmB;AACnB,EAAKL,cAAO,WAAWK,gBAAS,QAAQ,UAAU,OAAU,CAAC;;AAI/D,QADuB,aAAa,eAAe,wBAAwB,GAEvEC,+BACE,kBACA,aAAa,aACb,aAAa,WACP,KAAKN,cAAO,WAAWK,gBAAS,QAAQ,UAAU,OAAU,CAAC,EACnE,yBACD,GACDE,2CACE,kBACA,aAAa,aACb,aAAa,WACP,KAAKP,cAAO,WAAWK,gBAAS,QAAQ,UAAU,OAAU,CAAC,CACpE;CAEL,MAAM,YAA8B;EAClC,WAAW,MAAM,QAAQ,YAAY;AACnC,SAAM,cAAc,MAAM,QAAQ,QAAQ;;EAE5C,QAAQ,MAAM,MAAM,YAAY;GAC9B,MAAM,QAAkB;IACtB,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,QAAQ,SAAS;IACtC,QAAQ;IACR;IACA,WAAW,KAAK,KAAK;IACrB;IACD;AACD,WAAQ,KAAK,MAAM;AACnB,OAAI,iBAAiB,MAAM,MAAM,QAAQ,CACvC,OAAM,OAAO,MAAM,MAAM,QAAQ;AAEnC,OAAI,CAAC,aAAa,OAChB,CAAK,OAAO,MAAM,MAAM;;EAG7B;CAED,MAAM,gBAAgB,QAAgB;AAEpC,SAAOG,oCAAe,KAAK,WADN,QAAQ,SAAS,aAAa,OAAO,OACP,CAAC,KAClDR,cAAO,UAAU,QACfA,cAAO,WAAW;AAChB,aAAU,MAAM,KAAK,oBAAoB,OAAO,KAAK;AACrD,aAAU,SAAS,KAAK,QAAQ;IAChC,CACH,EACDA,cAAO,eACLA,cAAO,QAAQ;GACb,MAAM;GACN,KAAK;GACL,MAAMA,cAAO;GACb,cAAcA,cAAO;GACrB,aAAaA,cAAO;GACrB,CAAyB,CAC3B,CACF;;CAGH,MAAM,cAAc,aAClBA,cAAO,QAAQ,UAAU,cAAc,EAAE,aAAa,aAAa,CAAC;CAEtE,MAAM,cAAc,MAAc,WAChC,OAAO,aAAa,KAAKA,cAAO,eAAeA,cAAO,KAAK,CAAC;CAE9D,MAAM,kBAAkB,gBAAgB,QAAQ,QAAQ,QAAQ,OAAO;CACvE,MAAM,eAAe,gBAAgB,QAAQ,QAAQ,QAAQ,OAAO;CAEpE,MAAM,iBAAiB,OAAO,WAAW,gBAAgB;AAEzD,QAAOA,cAAO,QACZ,eAAe,KAAK,QAAQ,WAAW;EACrC;EACA,KAAK,gBAAgB,UAAU,OAAO;EACvC,EAAE,GACF,EAAE,QAAQ,UAAU,WAAW,KAAK,OAAO,EAC5C,EAAE,aAAa,aAAa,CAC7B;CAED,MAAM,cAAc,OAAO,WAAW,aAAa;AAEnD,QAAOA,cAAO,QACZ,YAAY,KAAK,QAAQ,WAAW;EAAE;EAAQ,KAAK,aAAa,UAAU,OAAO;EAAM,EAAE,GACxF,EAAE,QAAQ,UAAU,WAAW,KAAK,OAAO,EAC5C,EAAE,aAAa,aAAa,CAC7B;CAED,MAAM,aAAa,CAAC,GAAG,gBAAgB,GAAG,YAAY;AAEtD,QAAOA,cAAO,mBACZA,cAAO,IAAI,aAAa;AACtB,SAAOA,cAAO,QAAQ,aAAa,MAAM,EAAE,KAAK,KAAKA,cAAO,OAAO,EAAE,EACnE,aAAa,aACd,CAAC;AAEF,SAAOA,cAAO,MAAM,aAAa;AAEjC,QAAM,SAAS;AAEf,MAAI,kBAAkB;AACpB,WAAQ,IAAI,KAAK;AACjB,WAAQ,IAAI,IAAI,OAAO,GAAG,CAAC;AAC3B,WAAQ,IAAI,mBAAmB,aAAa,cAAc;AAC1D,WAAQ,IAAI,cAAc,IAAI,KAAK,QAAQ,IAAI,aAAa,KAAK,KAAK,CAAC,CAAC,aAAa,GAAG;AACxF,WAAQ,IAAI,oBAAoB,QAAQ,SAAS;AACjD,WAAQ,IAAI,IAAI,OAAO,GAAG,CAAC;AAC3B,WAAQ,IAAI,GAAG;AACf,QAAK,MAAM,SAAS,QAClB,SAAQ,IAAI,cAAc,MAAM,CAAC;AAEnC,WAAQ,IAAI,GAAG;AACf,WAAQ,IAAI,IAAI,OAAO,GAAG,CAAC;AAC3B,WAAQ,IAAI,yBAAyB,OAAO,UAAU;AACtD,WAAQ,IAAI,IAAI,OAAO,GAAG,CAAC;AAC3B,WAAQ,IAAI,GAAG;;GAEjB,CACH;AAED,QAAOK,gBAAS,MAAM,SAAS;EAC/B;AAEJ,MAAM,UACJ,cACA,UACA,kBACG;CACH,IAAI,kBAAuC;CAC3C,IAAI,cAAc;CAClB,IAAI,iBAAuD;CAE3D,MAAM,kBAAkB;AACtB,UAAQ,IAAI,qBAAqB;AACjC,UAAQ,KAAK,EAAE;;CAGjB,MAAM,UAAUL,cAAO,OACrB,cAAc,eAAe,aAAa;AACxC,oBAAkB;GAClB,CACH,CAAC,KACAA,cAAO,QAAQS,oDAAyB,SAAS,CAAC,EAClDT,cAAO,QAAQU,gDAAqB,cAAc,CAAC,EACnDV,cAAO,QAAQW,kCAAY,MAAM,EACjCX,cAAO,gBAAgB,WACrBA,cAAO,WAAW;AAChB,UAAQ,MAAM,2CAA2C,OAAO;GAChE,CACH,CACF;CAED,MAAM,qBAAqB;AACzB;AACA,MAAI,cAAc,GAAG;AACnB,cAAW;AACX;;AAEF,UAAQ,IAAI,2BAA2B;AACvC,mBAAiB,WAAW,WAAW,IAAK;AAC5C,qBAAmB;;AAGrB,SAAQ,GAAG,UAAU,aAAa;AAClC,SAAQ,GAAG,WAAW,aAAa;AAEnC,eAAO,eAAe,QAAQ,CAAC,MAAM,SAAS;AAC5C,MAAI,eAAgB,cAAa,eAAe;AAChD,UAAQ,KAAKY,YAAK,UAAU,KAAK,GAAG,IAAI,EAAE;GAC1C;;AAGJ,MAAa,SAAS;AAEtB,MAAa,WAAW"}
|
package/dist/dev-session.mjs
CHANGED
|
@@ -60,6 +60,12 @@ const runDevSession = (orchestrator, onShutdownReady) => Effect.gen(function* ()
|
|
|
60
60
|
const services = yield* ServiceDescriptorMap;
|
|
61
61
|
const orderedPackages = sortByOrder(orchestrator.packages);
|
|
62
62
|
const initialProcesses = getProcessStates(orderedPackages, services, orchestrator.port);
|
|
63
|
+
if (process.env.DEBUG === "true" || process.env.DEBUG === "1") {
|
|
64
|
+
console.error("[DEBUG session] orchestrator.packages:", orchestrator.packages.join(", "));
|
|
65
|
+
console.error("[DEBUG session] orderedPackages:", orderedPackages.join(", "));
|
|
66
|
+
console.error("[DEBUG session] services keys:", [...services.keys()].join(", "));
|
|
67
|
+
console.error("[DEBUG session] initialProcesses:", initialProcesses.map((p) => `${p.name}=${p.source}`).join(", "));
|
|
68
|
+
}
|
|
63
69
|
const logger = yield* Effect.promise(() => createDevLogger(configDir, orchestrator.description));
|
|
64
70
|
const shutdown = yield* Deferred.make();
|
|
65
71
|
onShutdownReady?.(() => {
|
package/dist/dev-session.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-session.mjs","names":[],"sources":["../src/dev-session.ts"],"sourcesContent":["import * as NodeContext from \"@effect/platform-node/NodeContext\";\nimport { Deferred, Effect, Exit } from \"effect\";\nimport {\n type DevViewHandle,\n type LogEntry,\n type ProcessState,\n renderDevView,\n} from \"./components/dev-view\";\nimport { renderStreamingView } from \"./components/streaming-view\";\nimport { getProjectRoot } from \"./config\";\nimport { createDevLogger } from \"./dev-logs\";\nimport {\n getProcessStates,\n makeDevProcess,\n type ProcessCallbacks,\n type ProcessHandle,\n} from \"./orchestrator\";\nimport {\n type AppOrchestrator,\n DevRuntimeConfigLive,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n ServiceDescriptorMapLive,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nconst LOG_NOISE_PATTERNS = [\n /\\[ Federation Runtime \\] Version .* from (host|ui) of shared singleton module/,\n /Executing an Effect versioned \\d+\\.\\d+\\.\\d+ with a Runtime of version/,\n /you may want to dedupe the effect dependencies/,\n];\n\nconst SSR_LOG_ALLOWLIST = [\n /\\bready\\s+built in\\b/i,\n /\\bcompiled\\b.*successfully/i,\n /\\berror\\b/i,\n /\\bfailed\\b/i,\n /\\bexception\\b/i,\n];\n\nconst shouldDisplayLog = (source: string, line: string, isError?: boolean): boolean => {\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") return true;\n if (source === \"ui-ssr\") {\n if (isError) return true;\n return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));\n }\n return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));\n};\n\nconst isInteractiveSupported = (): boolean => {\n return process.stdin.isTTY === true && process.stdout.isTTY === true;\n};\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"auth\", \"api\", \"plugin\", \"host-build\", \"host\"];\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\nfunction formatLogLine(entry: LogEntry): string {\n const ts = new Date(entry.timestamp).toISOString();\n const prefix = entry.isError ? \"ERR\" : \"OUT\";\n return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport const runDevSession = (\n orchestrator: AppOrchestrator,\n onShutdownReady?: (requestShutdown: () => void) => void,\n) =>\n Effect.gen(function* () {\n const configDir = getProjectRoot();\n const services = yield* ServiceDescriptorMap;\n const orderedPackages = sortByOrder(orchestrator.packages);\n const initialProcesses: ProcessState[] = getProcessStates(\n orderedPackages,\n services,\n orchestrator.port,\n );\n\n const logger = yield* Effect.promise(() =>\n createDevLogger(configDir, orchestrator.description),\n );\n\n const shutdown = yield* Deferred.make<void>();\n\n onShutdownReady?.(() => {\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n });\n\n const allLogs: LogEntry[] = [];\n let view: DevViewHandle | null = null;\n let shouldExportLogs = false;\n\n const requestShutdownAndExport = () => {\n shouldExportLogs = true;\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n };\n\n const useInteractive = orchestrator.interactive ?? isInteractiveSupported();\n view = useInteractive\n ? renderDevView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n requestShutdownAndExport,\n )\n : renderStreamingView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n );\n\n const callbacks: ProcessCallbacks = {\n onStatus: (name, status, message) => {\n view?.updateProcess(name, status, message);\n },\n onLog: (name, line, isError) => {\n const entry: LogEntry = {\n id: `${Date.now()}-${allLogs.length + 1}`,\n source: name,\n line,\n timestamp: Date.now(),\n isError,\n };\n allLogs.push(entry);\n if (shouldDisplayLog(name, line, isError)) {\n view?.addLog(name, line, isError);\n }\n if (!orchestrator.noLogs) {\n void logger.write(entry);\n }\n },\n };\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(pkg, callbacks, portOverride).pipe(\n Effect.tapError((err) =>\n Effect.sync(() => {\n callbacks.onLog(pkg, `Failed to start: ${err}`, true);\n callbacks.onStatus(pkg, \"error\");\n }),\n ),\n Effect.catchAll(() =>\n Effect.succeed({\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle),\n ),\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (_pkg: string, handle: ProcessHandle) =>\n handle.waitForReady.pipe(Effect.catchAll(() => Effect.void));\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const allHandles = [...nonHostHandles, ...hostHandles];\n\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n yield* Effect.forEach(allHandles, (h) => h.kill.pipe(Effect.ignore), {\n concurrency: \"unbounded\",\n });\n\n yield* Effect.sleep(\"200 millis\");\n\n view?.unmount();\n\n if (shouldExportLogs) {\n console.log(\"\\n\");\n console.log(\"═\".repeat(70));\n console.log(` SESSION LOGS: ${orchestrator.description}`);\n console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);\n console.log(` Total entries: ${allLogs.length}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n for (const entry of allLogs) {\n console.log(formatLogLine(entry));\n }\n console.log(\"\");\n console.log(\"═\".repeat(70));\n console.log(` Full logs saved to: ${logger.logFile}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n }\n }),\n );\n\n yield* Deferred.await(shutdown);\n });\n\nconst runApp = (\n orchestrator: AppOrchestrator,\n services: Map<string, ServiceDescriptor>,\n runtimeConfig: RuntimeConfig,\n) => {\n let requestShutdown: (() => void) | null = null;\n let signalCount = 0;\n let forceExitTimer: ReturnType<typeof setTimeout> | null = null;\n\n const forceExit = () => {\n console.log(\"\\n[Dev] Force exit\");\n process.exit(0);\n };\n\n const program = Effect.scoped(\n runDevSession(orchestrator, (shutdown) => {\n requestShutdown = shutdown;\n }),\n ).pipe(\n Effect.provide(ServiceDescriptorMapLive(services)),\n Effect.provide(DevRuntimeConfigLive(runtimeConfig)),\n Effect.provide(NodeContext.layer),\n Effect.catchAllDefect((defect) =>\n Effect.sync(() => {\n console.error(\"[Dev] Unhandled defect in orchestrator:\", defect);\n }),\n ),\n );\n\n const handleSignal = () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n console.log(\"\\n[Dev] Shutting down...\");\n forceExitTimer = setTimeout(forceExit, 5000);\n requestShutdown?.();\n };\n\n process.on(\"SIGINT\", handleSignal);\n process.on(\"SIGTERM\", handleSignal);\n\n Effect.runPromiseExit(program).then((exit) => {\n if (forceExitTimer) clearTimeout(forceExitTimer);\n process.exit(Exit.isSuccess(exit) ? 0 : 0);\n });\n};\n\nexport const devApp = runApp;\n\nexport const startApp = runApp;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dev-session.mjs","names":[],"sources":["../src/dev-session.ts"],"sourcesContent":["import * as NodeContext from \"@effect/platform-node/NodeContext\";\nimport { Deferred, Effect, Exit } from \"effect\";\nimport {\n type DevViewHandle,\n type LogEntry,\n type ProcessState,\n renderDevView,\n} from \"./components/dev-view\";\nimport { renderStreamingView } from \"./components/streaming-view\";\nimport { getProjectRoot } from \"./config\";\nimport { createDevLogger } from \"./dev-logs\";\nimport {\n getProcessStates,\n makeDevProcess,\n type ProcessCallbacks,\n type ProcessHandle,\n} from \"./orchestrator\";\nimport {\n type AppOrchestrator,\n DevRuntimeConfigLive,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n ServiceDescriptorMapLive,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nconst LOG_NOISE_PATTERNS = [\n /\\[ Federation Runtime \\] Version .* from (host|ui) of shared singleton module/,\n /Executing an Effect versioned \\d+\\.\\d+\\.\\d+ with a Runtime of version/,\n /you may want to dedupe the effect dependencies/,\n];\n\nconst SSR_LOG_ALLOWLIST = [\n /\\bready\\s+built in\\b/i,\n /\\bcompiled\\b.*successfully/i,\n /\\berror\\b/i,\n /\\bfailed\\b/i,\n /\\bexception\\b/i,\n];\n\nconst shouldDisplayLog = (source: string, line: string, isError?: boolean): boolean => {\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") return true;\n if (source === \"ui-ssr\") {\n if (isError) return true;\n return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));\n }\n return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));\n};\n\nconst isInteractiveSupported = (): boolean => {\n return process.stdin.isTTY === true && process.stdout.isTTY === true;\n};\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"auth\", \"api\", \"plugin\", \"host-build\", \"host\"];\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\nfunction formatLogLine(entry: LogEntry): string {\n const ts = new Date(entry.timestamp).toISOString();\n const prefix = entry.isError ? \"ERR\" : \"OUT\";\n return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport const runDevSession = (\n orchestrator: AppOrchestrator,\n onShutdownReady?: (requestShutdown: () => void) => void,\n) =>\n Effect.gen(function* () {\n const configDir = getProjectRoot();\n const services = yield* ServiceDescriptorMap;\n const orderedPackages = sortByOrder(orchestrator.packages);\n const initialProcesses: ProcessState[] = getProcessStates(\n orderedPackages,\n services,\n orchestrator.port,\n );\n\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") {\n console.error(\"[DEBUG session] orchestrator.packages:\", orchestrator.packages.join(\", \"));\n console.error(\"[DEBUG session] orderedPackages:\", orderedPackages.join(\", \"));\n console.error(\"[DEBUG session] services keys:\", [...services.keys()].join(\", \"));\n console.error(\n \"[DEBUG session] initialProcesses:\",\n initialProcesses.map((p) => `${p.name}=${p.source}`).join(\", \"),\n );\n }\n\n const logger = yield* Effect.promise(() =>\n createDevLogger(configDir, orchestrator.description),\n );\n\n const shutdown = yield* Deferred.make<void>();\n\n onShutdownReady?.(() => {\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n });\n\n const allLogs: LogEntry[] = [];\n let view: DevViewHandle | null = null;\n let shouldExportLogs = false;\n\n const requestShutdownAndExport = () => {\n shouldExportLogs = true;\n void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n };\n\n const useInteractive = orchestrator.interactive ?? isInteractiveSupported();\n view = useInteractive\n ? renderDevView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n requestShutdownAndExport,\n )\n : renderStreamingView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n );\n\n const callbacks: ProcessCallbacks = {\n onStatus: (name, status, message) => {\n view?.updateProcess(name, status, message);\n },\n onLog: (name, line, isError) => {\n const entry: LogEntry = {\n id: `${Date.now()}-${allLogs.length + 1}`,\n source: name,\n line,\n timestamp: Date.now(),\n isError,\n };\n allLogs.push(entry);\n if (shouldDisplayLog(name, line, isError)) {\n view?.addLog(name, line, isError);\n }\n if (!orchestrator.noLogs) {\n void logger.write(entry);\n }\n },\n };\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(pkg, callbacks, portOverride).pipe(\n Effect.tapError((err) =>\n Effect.sync(() => {\n callbacks.onLog(pkg, `Failed to start: ${err}`, true);\n callbacks.onStatus(pkg, \"error\");\n }),\n ),\n Effect.catchAll(() =>\n Effect.succeed({\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle),\n ),\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (_pkg: string, handle: ProcessHandle) =>\n handle.waitForReady.pipe(Effect.catchAll(() => Effect.void));\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const allHandles = [...nonHostHandles, ...hostHandles];\n\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n yield* Effect.forEach(allHandles, (h) => h.kill.pipe(Effect.ignore), {\n concurrency: \"unbounded\",\n });\n\n yield* Effect.sleep(\"200 millis\");\n\n view?.unmount();\n\n if (shouldExportLogs) {\n console.log(\"\\n\");\n console.log(\"═\".repeat(70));\n console.log(` SESSION LOGS: ${orchestrator.description}`);\n console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);\n console.log(` Total entries: ${allLogs.length}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n for (const entry of allLogs) {\n console.log(formatLogLine(entry));\n }\n console.log(\"\");\n console.log(\"═\".repeat(70));\n console.log(` Full logs saved to: ${logger.logFile}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n }\n }),\n );\n\n yield* Deferred.await(shutdown);\n });\n\nconst runApp = (\n orchestrator: AppOrchestrator,\n services: Map<string, ServiceDescriptor>,\n runtimeConfig: RuntimeConfig,\n) => {\n let requestShutdown: (() => void) | null = null;\n let signalCount = 0;\n let forceExitTimer: ReturnType<typeof setTimeout> | null = null;\n\n const forceExit = () => {\n console.log(\"\\n[Dev] Force exit\");\n process.exit(0);\n };\n\n const program = Effect.scoped(\n runDevSession(orchestrator, (shutdown) => {\n requestShutdown = shutdown;\n }),\n ).pipe(\n Effect.provide(ServiceDescriptorMapLive(services)),\n Effect.provide(DevRuntimeConfigLive(runtimeConfig)),\n Effect.provide(NodeContext.layer),\n Effect.catchAllDefect((defect) =>\n Effect.sync(() => {\n console.error(\"[Dev] Unhandled defect in orchestrator:\", defect);\n }),\n ),\n );\n\n const handleSignal = () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n console.log(\"\\n[Dev] Shutting down...\");\n forceExitTimer = setTimeout(forceExit, 5000);\n requestShutdown?.();\n };\n\n process.on(\"SIGINT\", handleSignal);\n process.on(\"SIGTERM\", handleSignal);\n\n Effect.runPromiseExit(program).then((exit) => {\n if (forceExitTimer) clearTimeout(forceExitTimer);\n process.exit(Exit.isSuccess(exit) ? 0 : 0);\n });\n};\n\nexport const devApp = runApp;\n\nexport const startApp = runApp;\n"],"mappings":"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"}
|
package/dist/plugin.cjs
CHANGED
|
@@ -628,6 +628,12 @@ var plugin_default = (0, every_plugin.createPlugin)({
|
|
|
628
628
|
proxy
|
|
629
629
|
});
|
|
630
630
|
const packages = [...services.keys()];
|
|
631
|
+
if (node_process.default.env.DEBUG === "true" || node_process.default.env.DEBUG === "1") {
|
|
632
|
+
console.error("[DEBUG dev] services keys:", packages.join(", "));
|
|
633
|
+
console.error("[DEBUG dev] services sources:", packages.map((k) => `${k}=${services.get(k)?.source ?? "?"}`).join(", "));
|
|
634
|
+
console.error("[DEBUG dev] runtimeConfig.plugins keys:", Object.keys(runtimeConfig.plugins ?? {}).join(", "));
|
|
635
|
+
console.error("[DEBUG dev] runtimeConfig.plugins sources:", Object.entries(runtimeConfig.plugins ?? {}).map(([k, v]) => `${k}=${v.source}`).join(", "));
|
|
636
|
+
}
|
|
631
637
|
const displayEnv = {};
|
|
632
638
|
if (services.get("api")?.proxy) {
|
|
633
639
|
const proxyUrl = resolveProxyUrl(deps.bosConfig);
|